gtkIOStream  1.7.0
GTK+ << C++ IOStream operators for GTK+. Now with ORBing, numerical computation, audio client and more ...
BitStream.H
Go to the documentation of this file.
1 /* Copyright 2000-2018 Matt Flax <flatmax@flatmax.org>
2  This file is part of GTK+ IOStream class set
3 
4  GTK+ IOStream is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  GTK+ IOStream is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You have received a copy of the GNU General Public License
15  along with GTK+ IOStream
16  */
17 
18 /*
19 Author: Matt Flax <flatmax@flatmax.org>
20 Date: 2013.08.23
21 */
22 
23 #ifndef BITSTREAM_H_
24 #define BITSTREAM_H_
25 
26 #include <vector>
27 #include <math.h>
28 #include <algorithm>
29 #include <limits.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <iostream>
33 
34 #if __BYTE_ORDER != __LITTLE_ENDIAN
35 #error "iobitstream not tested on big endian systems"
36 #endif
37 
38 #include <assert.h>
39 
83 class BitStream {
84 protected:
85  typedef unsigned int VTYPE;
86 
90  void testMask(unsigned int mSize) const {
91 #ifndef NDEBUG
92  testMask(mSize, genMask(mSize));
93 #endif
94  }
95 
100  void testMask(unsigned int mSize, VTYPE compareAgainst) const {
101 #ifndef NDEBUG
102  VTYPE maskCheck=0;
103  for (int j=0; j<mSize; j++)
104  maskCheck|=(maskCheck<<1|1);
105  if (maskCheck!=compareAgainst) {
106  fprintf(stderr,"BitStream::testMask(%d) failed\n",mSize);
107  fprintf(stderr,"BitStream::compare against 0x%x\n",compareAgainst);
108  fprintf(stderr,"BitStream::compare maskcheck 0x%x\n",maskCheck);
109  assert("BitStream : testMask is failing");
110  abort();
111  }
112 #endif
113  }
114 
115 private:
116  std::vector<VTYPE> data;
117  int freeBits;
118 
120  static const unsigned char revChars[];
121 
129  BitStream &push_backVType(const VTYPE *tempBits, int N, const int sizeOfT);
130 
134  unsigned int VTYPEBits() const {
135  return sizeof(VTYPE)*CHAR_BIT;
136  }
137 
141  unsigned int takenBits() const {
142  return (size()>0) ? VTYPEBits()-freeBits : 0;
143  }
144 
150  VTYPE maskBitsToRight(const unsigned int M, const VTYPE &bits) const {
151  if (M>sizeof(VTYPE)*CHAR_BIT)
152  assert("BitStream::maskBitsToRight : you can't shift right more bits then the word size. M > sizeof(VTYPE)*8");
153  return ((genMask(M)<<(VTYPEBits()-M))&bits)>>(VTYPEBits()-M);
154  }
155 
162  VTYPE maskOffsetBitsToRight(const unsigned int M, const unsigned int offset, const VTYPE &bits) const {
163  if (M+offset>sizeof(VTYPE)*CHAR_BIT)
164  assert("BitStream::maskOffsetBitsToRight : you can't shift right more bits then the word size. M+offset > sizeof(VTYPE)*CHAR_BIT");
165  return ((genMask(M)<<(VTYPEBits()-M-offset))&bits)>>(VTYPEBits()-M-offset);
166  }
167 
173  VTYPE maskBitsToLeft(const unsigned int M, const VTYPE bits) const {
174  if (M>sizeof(VTYPE)*CHAR_BIT)
175  assert("BitStream::maskBitsToLeft : you can't shift left more bits then the word size. M > sizeof(VTYPE)*8");
176  return (genMask(M)&bits)<<(VTYPEBits()-M);
177  }
178 
185  void reverseBits(unsigned char *bits, const unsigned int N) const {
186  // switch each char ...
187  for (int i=0; i<N/2; i++) {
188  char lastChar=revChars[bits[N-1-i]];
189  bits[N-1-i]=revChars[bits[i]];
190  bits[i]=lastChar;
191  }
192  if (N%2) // the case where the number of char is odd
193  bits[N/2]=revChars[bits[N/2]];
194  }
195 
201  VTYPE shiftLeftSubword(std::vector<VTYPE>::iterator firstWord, std::vector<VTYPE>::iterator lastWord, const unsigned int N);
202 
208  VTYPE shiftRightSubword(std::vector<VTYPE>::iterator firstWord, std::vector<VTYPE>::iterator lastWord, const unsigned int N);
209 
210 protected:
214 #ifndef __MINGW32__
215  VTYPE genMask(int M) const {
216 #ifndef NDEBUG // if debugging, test the mask by default
217  testMask(M, (VTYPE)((unsigned long )pow(2.,(float)M)-1));
218 #endif
219  return (VTYPE)((unsigned long )pow(2.,(float)M)-1);
220  }
221 #else // mingw seems to have trouble with the unsigned long
222  VTYPE genMask(int M) const {
223 #ifndef NDEBUG // if debugging, test the mask by default
224  testMask(M, (VTYPE)((unsigned long long )pow(2.,(float)M)-1));
225 #endif
226  return (VTYPE)((unsigned long long)pow(2.,(float)M)-1);
227  }
228 #endif
229 
230 public:
231 
232  BitStream();
233  virtual ~BitStream();
234 
238  std::vector<VTYPE>::size_type size() const;
239 
243  float byteSize() const;
244 
251  template<typename T>
252  T reverseBits(T bits) const {
253  unsigned int N=sizeof(T)*CHAR_BIT;
254  return reverseBits(bits, N);
255  }
256 
264  template<typename T>
265  T reverseBits(T bits, unsigned int N) const {
266  unsigned int charCnt=sizeof(T);
267  if (N>charCnt*CHAR_BIT) N=charCnt*CHAR_BIT;
268  reverseBits((unsigned char *)&bits, charCnt);
269  bits>>=charCnt*CHAR_BIT-N; // roll the word so that there aren't any empty spaces in the LSB
270  return bits;
271  }
272 
278  template<typename T>
280  int N=sizeof(T)*CHAR_BIT;
281  return push_back(bits, N);
282  }
283 
291  template<typename T>
292  BitStream &push_back(const T bits, const int N) {
293  if (N>0) {
294  VTYPE *tempBits=(VTYPE*)&bits;
295  return push_backVType(tempBits, N, sizeof(T));
296  }
297  return *this;
298  }
299 
307  template<typename T>
308  T pop_back(const unsigned int N) {
309  unsigned int NN=N;
310  T bits=0;
311 
312  if (NN && (size()>0)) {
313  //if (NN>sizeof(T)*CHAR_BIT) NN=sizeof(T)*CHAR_BIT;
314  if (takenBits()>=NN) { // if we have enough bits loaded in the last word, the acquire from there
315  bits=maskBitsToRight(takenBits(), data[data.size()-1])&genMask(NN);
316  freeBits+=NN;
317  if (freeBits==VTYPEBits()) { // if we have an completely empty last word, then remove it
318  data.resize(data.size()-1);
319  freeBits-=VTYPEBits();
320  }
321  } else { // handle the case where the takenBits are less then the number requested
322  unsigned int tb=takenBits();
323  NN-=tb; // start with the available bits
324  bits=pop_back<T>(tb);
325  T newBits=pop_back<T>(NN);
326  bits|=(genMask(NN)&newBits)<<tb;
327  }
328  }
329  return bits;
330  }
331 
339  template<typename T>
340  T pop_front(const unsigned int N) {
341  rotateL(N); // rotate so that the required bits are at the end of the strea,
342  return pop_back<T>(N); // pop the back of the stream returning those bits
343  }
344 
349  BitStream &rotateL(const unsigned int N);
350 
355  BitStream &rotateR(const unsigned int N);
356 
361  std::ostream& hexDump(std::ostream& stream);
362 
369  friend std::ostream& operator<<(std::ostream& stream, const BitStream& bitStream);
370 
373  void clear();
374 
379  int reserve(std::vector<VTYPE>::size_type N);
380 
384  std::vector<VTYPE>::size_type capacity() const;
385 
388  void dump(void);
389 
393  void dumpHex(void);
394 
401  template<typename T>
402  T getBits(std::vector<VTYPE>::size_type i, unsigned int N) const {
403  if ((i+N)>size()) // if none of the requested bits are available, then assert
404  assert("BitStream::operator[] : you requested an index which is out of range. The bitstream is smaller then your starting point and the size of your requested type.");
405  unsigned int whichWord=i/VTYPEBits(); // the word to extract the data from.
406  unsigned int wordLoc=i-whichWord*VTYPEBits(); // the MSB to get from the word
407  unsigned int M=std::min<unsigned int>(N,VTYPEBits()-wordLoc);
408  T ret=(T)0.;
409  while (N>0) { // indicate that some bits were retrieved and keep going until complete
410  ret|=maskOffsetBitsToRight(M, wordLoc, data[whichWord++]); // next word's data from the (possibly offset) MSB location shifted to the LSB location
411  M=std::min<unsigned int>(N-=M,VTYPEBits()); // find how many to retrieve from the next word
412  ret<<=M; // ensure there is enough room in T for the left over bits.
413  wordLoc=0;
414  }
415  return ret;
416  }
417 
418 
424  template<typename T>
425  T operator[](std::vector<VTYPE>::size_type i) const {
426  return getBits<T>(i, sizeof(T)*CHAR_BIT);
427  }
428 
434  template<typename T>
435  std::vector<std::vector<VTYPE>::size_type> find(T toFind, const unsigned int N) const {
436  BitStream toFindRef; // construct a vector to use for searching
437  toFindRef.push_back(toFind, N);
438  return find(toFindRef, N);
439  }
440 
446  std::vector<std::vector<VTYPE>::size_type> find(BitStream toFind, const unsigned int N) const;
447 };
448 
449 #endif // BITSTREAM_H_
void testMask(unsigned int mSize) const
Definition: BitStream.H:90
unsigned int takenBits() const
Definition: BitStream.H:141
T reverseBits(T bits, unsigned int N) const
Definition: BitStream.H:265
VTYPE shiftRightSubword(std::vector< VTYPE >::iterator firstWord, std::vector< VTYPE >::iterator lastWord, const unsigned int N)
Definition: BitStream.C:126
int N
BitStream & operator<<(T bits)
Definition: BitStream.H:279
virtual ~BitStream()
Destructor.
Definition: BitStream.C:35
void clear()
Definition: BitStream.C:182
std::ostream & hexDump(std::ostream &stream)
Definition: BitStream.C:174
std::vector< VTYPE > data
The array to hold the bitstream.
Definition: BitStream.H:116
T pop_back(const unsigned int N)
Definition: BitStream.H:308
void testMask(unsigned int mSize, VTYPE compareAgainst) const
Definition: BitStream.H:100
BitStream & rotateR(const unsigned int N)
Definition: BitStream.C:145
T pop_front(const unsigned int N)
Definition: BitStream.H:340
T operator[](std::vector< VTYPE >::size_type i) const
Definition: BitStream.H:425
void reverseBits(unsigned char *bits, const unsigned int N) const
Definition: BitStream.H:185
std::vector< VTYPE >::size_type capacity() const
Definition: BitStream.C:199
VTYPE shiftLeftSubword(std::vector< VTYPE >::iterator firstWord, std::vector< VTYPE >::iterator lastWord, const unsigned int N)
Definition: BitStream.C:80
void dump(void)
Definition: BitStream.C:218
T getBits(std::vector< VTYPE >::size_type i, unsigned int N) const
Definition: BitStream.H:402
static const unsigned char revChars[]
Characters reversed. 8 bit reversals.
Definition: BitStream.H:120
VTYPE maskOffsetBitsToRight(const unsigned int M, const unsigned int offset, const VTYPE &bits) const
Definition: BitStream.H:162
BitStream & push_back(const T bits, const int N)
Definition: BitStream.H:292
VTYPE genMask(int M) const
Definition: BitStream.H:215
VTYPE maskBitsToLeft(const unsigned int M, const VTYPE bits) const
Definition: BitStream.H:173
BitStream()
Constructor.
Definition: BitStream.C:29
unsigned int VTYPE
Use this type for the basic stream type.
Definition: BitStream.H:85
T reverseBits(T bits) const
Definition: BitStream.H:252
int freeBits
The number of free bits in the array.
Definition: BitStream.H:117
void dumpHex(void)
Definition: BitStream.C:232
int reserve(std::vector< VTYPE >::size_type N)
Definition: BitStream.C:187
std::vector< VTYPE >::size_type size() const
Definition: BitStream.C:39
BitStream & push_backVType(const VTYPE *tempBits, int N, const int sizeOfT)
Definition: BitStream.C:47
BitStream & rotateL(const unsigned int N)
Definition: BitStream.C:97
float byteSize() const
Definition: BitStream.C:43
VTYPE maskBitsToRight(const unsigned int M, const VTYPE &bits) const
Definition: BitStream.H:150
std::vector< std::vector< VTYPE >::size_type > find(T toFind, const unsigned int N) const
Definition: BitStream.H:435
unsigned int VTYPEBits() const
Definition: BitStream.H:134
gtkIOStream: /tmp/gtkiostream/include/BitStream.H Source File
GTK+ IOStream  Beta