gtkIOStream  1.7.0
GTK+ << C++ IOStream operators for GTK+. Now with ORBing, numerical computation, audio client and more ...
BitStream.C
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 #include "BitStream.H"
24 #include <bitset>
25 #include <Debug.H>
26 
27 const unsigned char BitStream::revChars[]= {0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255};
28 
30  freeBits=0; // start with empty, no bits free
31  // check the extreme mask generation of all the bits
33 }
34 
36  //dtor
37 }
38 
39 std::vector<BitStream::VTYPE>::size_type BitStream::size() const {
40  return data.size()*sizeof(data[0])*CHAR_BIT-freeBits;
41 }
42 
43 float BitStream::byteSize() const {
44  return (float)size()/(float)CHAR_BIT;
45 }
46 
47 BitStream &BitStream::push_backVType(const VTYPE *tempBits, int N, const int sizeOfT) {
48 // std::cout<<"BitStream::push_backVType N "<<N<<" sizeOfT "<<sizeOfT<<std::endl;
49  if (sizeOfT>sizeof(VTYPE)) { // first handle the case where the bits type is larger in size then the VTYPE
50  if (fmod(sizeOfT,sizeof(VTYPE))>0.)
51  assert("BitStream::push_back sizeof(T)/sizeof(VTYPE) should be zero : This means that your specified type is larger then the BitStream base type and is not an integer multiple of the BitStream base type. This shouldn't be possible.");
52  for (int i=0; i<sizeOfT/sizeof(VTYPE); i++) { // break up the larger type into multiples of VTYPE
53  int NN=-((sizeOfT*CHAR_BIT-N)-(i+1)*sizeof(VTYPE)*CHAR_BIT);
54  if (NN>0) {
55  push_back(tempBits[sizeOfT/sizeof(VTYPE)-i-1], NN);
56  N-=NN;
57  }
58  }
59  }
60  if (N>sizeOfT*CHAR_BIT) { // handle the case where more bits are specified then exist in the given type.
61  push_back((VTYPE)0,N-sizeOfT*CHAR_BIT);
62  N-=N-sizeOfT*CHAR_BIT;
63  }
64  if (N<=freeBits) { // if we have enough free bits to pack these new bits, then simply do so.
65  VTYPE mask=(VTYPE)pow(2.,(float)freeBits)-1;
66  data[data.size()-1]|=((*tempBits)<<(freeBits-N))&mask;
67  freeBits-=N;
68  } else { // if there aren't enough free bits, create some ...
69  if (data.size()) {
70  VTYPE mask=(VTYPE)pow(2.,(float)freeBits)-1;
71  data[data.size()-1]|=(VTYPE)(*tempBits>>(N-=freeBits))&mask;
72  }
73  data.push_back((VTYPE)0.);
74  freeBits=sizeof(VTYPE)*CHAR_BIT;
75  return push_backVType(tempBits, N, sizeOfT);
76  }
77  return *this;
78 }
79 
80 BitStream::VTYPE BitStream::shiftLeftSubword(std::vector<VTYPE>::iterator firstWord, std::vector<VTYPE>::iterator lastWord, const unsigned int N) {
81  if (N==0)
82  return (VTYPE)0;
83  if (N>=VTYPEBits())
84  assert("BitStream::shiftLeftSubword : You are trying to shift left too many bits > sizeof(VTYPE)*8\n");
85 
86  VTYPE bitReg=maskBitsToRight(N, *firstWord); // bitReg holds N bits from the MSBs of the first word in the LSB location
87  VTYPE notMask=~genMask(N); // the last N LSBs are zeros, the rest are ones
88  for (; firstWord!=lastWord; ++firstWord) {
89  VTYPE nextBits=maskBitsToRight(N, *(firstWord+1)); // get the first N bits from the next word.
90  *firstWord=((*firstWord)<<N)&notMask; // rotate the current word and clear the N LSBs
91  *firstWord|=nextBits; // inject the N LSBs from the next word
92  }
93  *lastWord=((*lastWord)<<N)&notMask; // rotate the last word and clear the N LSBs
94  return bitReg;
95 }
96 
97 BitStream &BitStream::rotateL(const unsigned int N) {
98  if (data.size()) { // only rotate if there is data to rotate.
99  unsigned int cycleCnt=N/size(); // remove any full cycles
100  // find how many non-whole word bits require rotation
101  int wholeWordN=N-freeBits-cycleCnt*size(); // whole words occur once freeBits have been shifted.
102  unsigned int wholeWords = (wholeWordN<0)?0:wholeWordN/VTYPEBits(); // find the number of whole words, guard the case where freeBits > N-cycleCnt*size(), which means no whole words, rather then a negative number
103  unsigned int M = N-cycleCnt*size(); // set the number of bits to shift, remove any full cycles
104 
105  if (wholeWords) { // this will shift by wholeWords
106  rotate(data.begin(), data.begin()+wholeWords, data.end()); // rotate the wholeWords
107  if (freeBits) { // account for any freeBits in the last word
108  VTYPE bitReg=shiftLeftSubword(data.end()-(wholeWords+1), data.end()-1, freeBits);
109  data[data.size()-(wholeWords+1)]=(data[data.size()-(wholeWords+1)]&genMask(freeBits))|((bitReg<<freeBits)&~genMask(freeBits)); // position the first shiftBits to be in the correct last location and add to the last word
110  }
111  M-=wholeWords*VTYPEBits(); // remove the number of bits shifted
112  }
113  while (M>takenBits()) { // if we are trying to shift data which will roll off the end and be lost, then shift twice so as not to lose data
114  unsigned int shiftBits=std::min<unsigned int>(M, takenBits());
115  M-=shiftBits;
116  rotateL(shiftBits);
117  }
118  if (M) { // if we still have something left to shift, it will be less then a whole word
119  VTYPE bitReg=shiftLeftSubword(data.begin(), data.end()-1, M);
120  data[data.size()-1]=(data[data.size()-1]&~genMask(freeBits+M))|(bitReg<<freeBits); // position the first M to be in the correct last location and add to the last word
121  }
122  }
123  return *this;
124 }
125 
126 BitStream::VTYPE BitStream::shiftRightSubword(std::vector<VTYPE>::iterator firstWord, std::vector<VTYPE>::iterator lastWord, const unsigned int N) {
127  if (N==0)
128  return (VTYPE)0;
129  if (N>=VTYPEBits())
130  assert("BitStream::shiftRightSubword : You are trying to shift right too many bits > sizeof(VTYPE)*CHAR_BIT\n");
131  if (N>=takenBits())
132  assert("BitStream::shiftRightSubword : You are trying to shift more bits then are present, ensure N <= takenBits()\n");
133 
134  VTYPE bitReg=maskOffsetBitsToRight(N, takenBits()-N,*lastWord)<<(VTYPEBits()-N);
135  VTYPE mask=genMask(VTYPEBits()-N); // the last N LSBs are zeros, the rest are ones
136  for (; lastWord!=firstWord; --lastWord) {
137  VTYPE nextBits=maskBitsToLeft(N, *(lastWord-1)); // get the least significant N bits from the next word in the MSB location
138  *lastWord=((*lastWord)>>N)&mask; // rotate the current word and clear the N MSBs
139  *lastWord|=nextBits; // inject the N LSBs from the next word
140  }
141  *firstWord=((*firstWord)>>N)&mask; // rotate the first word and clear the N MSBs
142  return bitReg;
143 }
144 
145 BitStream &BitStream::rotateR(const unsigned int N) {
146  if (data.size()) { // only rotate if there is data to rotate.
147  unsigned int cycleCnt=N/size(); // remove any full cycles
148  unsigned int M = N-cycleCnt*size(); // set the number of bits to shift, remove any full cycles
149  // find how many non-whole word bits require rotation
150  int wholeWordN=N-freeBits-cycleCnt*size(); // whole words occur once freeBits have been shifted.
151  unsigned int wholeWords = (wholeWordN<0)?0:wholeWordN/VTYPEBits(); // find the number of whole words, guard the case where freeBits > N-cycleCnt*size(), which means no whole words, rather then a negative number
152 
153  if (wholeWords) { // this will shift by wholeWords
154  rotate(data.begin(), data.end()-wholeWords, data.end()); // rotate the wholeWords
155  if (freeBits) { // account for any freeBits in the last word
156  VTYPE bitReg=shiftRightSubword(data.begin(), data.begin()+wholeWords-1, freeBits);
157  data[0]=(data[0]&genMask(takenBits()))|maskBitsToLeft(freeBits, data[data.size()-1]);
158  }
159  M-=wholeWords*VTYPEBits(); // remove the number of bits shifted
160  }
161  while (M>takenBits()) { // if we are trying to shift data which will roll off the end and be lost, then shift twice so as not to loose data
162  // TODO : this is inefficient if there is only 1 or a few bits stored in the last word, as it will be executed many times
163  unsigned int shiftBits=std::min<unsigned int>(M, takenBits());
164  M-=shiftBits;
165  rotateR(shiftBits);
166  }
167  if (M) { // if we still have something left to shift, it will be less then a whole word
168  VTYPE bitReg=shiftRightSubword(data.begin(), data.end()-1, M); // shift right
169  data[0]=(data[0]&genMask(VTYPEBits()-M))|bitReg; // add the last M bits to the beginning of the first word
170  }
171  }
172 }
173 
174 std::ostream& BitStream::hexDump(std::ostream& stream) {
175  stream<<std::hex;
176  for (std::vector<VTYPE>::iterator word=data.begin(); word!=data.end(); ++word)
177  stream<<*word;
178  stream<<std::dec;
179  return stream;
180 }
181 
183  data.clear();
184  freeBits=0;
185 }
186 
187 int BitStream::reserve(std::vector<BitStream::VTYPE>::size_type N) {
188  if (capacity()<N)
189 #ifndef __MINGW32__
190  data.reserve((unsigned long)ceil((double)N/(double)VTYPEBits()));
191 #else
192  data.reserve((unsigned long long)ceil((double)N/(double)VTYPEBits()));
193 #endif
194  if (capacity()<N)
195  return Debug().evaluateError(MALLOC_ERROR);
196  return NO_ERROR;
197 }
198 
199 std::vector<BitStream::VTYPE>::size_type BitStream::capacity() const {
200  return data.capacity()*VTYPEBits();
201 }
202 
203 
204 std::ostream& operator<<(std::ostream& stream, const BitStream& bitStream) {
205  const int N=sizeof(BitStream::VTYPE)*CHAR_BIT; // work with char
206  const int M=(int)fmod(bitStream.size(),N); // the initial bit count short of N
207  for (unsigned int i=0; i<bitStream.size()/N; i++)
208  stream<<std::bitset<N>(bitStream.operator[]<BitStream::VTYPE>(i*N));
209  if (M) {
210  std::bitset<N> bits(std::bitset<N>(bitStream.operator[]<BitStream::VTYPE>(bitStream.size()-M)));
211  bits>>=N-M;
212  for (int i=0; i<M; i++)
213  stream<<bits[M-i-1];
214  }
215  return stream;
216 }
217 
218 void BitStream::dump(void) {
219  const int N=sizeof(BitStream::VTYPE)*CHAR_BIT; // work with char
220  const int M=(int)fmod(size(),N); // the initial bit count short of N
221  for (int i=0; i<size()/N; i++)
222  printf("%lu ",((std::bitset<N>)data[i]).to_ulong());
223  if (M) {
224  std::bitset<N> bits(data[size()/N]);
225  bits>>=N-M;
226  for (int i=0; i<M; i++)
227  printf("%d", bits[M-i-1]==1);
228  }
229  printf("\n");
230 }
231 
232 void BitStream::dumpHex(void) {
233  const int N=sizeof(BitStream::VTYPE)*CHAR_BIT; // work with char
234  const int M=(int)fmod(size(),N); // the initial bit count short of N
235  for (int i=0; i<size()/N; i++)
236  printf("%x ",data[i]);
237  if (M) {
238  printf("%x ",data[size()/N]);
239 
240  }
241  printf("\n");
242 }
243 
244 std::vector<std::vector<BitStream::VTYPE>::size_type> BitStream::find(BitStream toFind, const unsigned int N) const {
245  std::vector<std::vector<VTYPE>::size_type> indexes; // the vector of matching indexes
246  if (N>0 && toFind.size()>0)
247  for (int j=0; j<size()-toFind.size(); j++) { // step through each of the vector's elements
248  unsigned int M=N;
249  while (M>0) {
250  // go through all of the bits from this location, comparing for equality
251  unsigned int K=std::min<unsigned int>(VTYPEBits(), M);
252  if (getBits<VTYPE>(j+N-M, K)!=toFind.getBits<VTYPE>(N-M, K))
253  break;
254  M-=K;
255  }
256  if (M<=0) // if we have found one, add it to the list
257  indexes.push_back(j);
258  }
259  return indexes;
260 }
void testMask(unsigned int mSize) const
Definition: BitStream.H:90
unsigned int takenBits() const
Definition: BitStream.H:141
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
virtual int evaluateError(int errorNum)
Definition: Debug.H:132
BitStream & rotateR(const unsigned int N)
Definition: BitStream.C:145
#define NO_ERROR
There is no error.
Definition: Debug.H:33
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
#define MALLOC_ERROR
Error when trying to allocate memory.
Definition: Debug.H:113
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
Definition: Debug.H:112
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/src/BitStream.C Source File
GTK+ IOStream  Beta