diff options
Diffstat (limited to 'src/unstable/bitstring.cpp')
-rw-r--r-- | src/unstable/bitstring.cpp | 479 |
1 files changed, 479 insertions, 0 deletions
diff --git a/src/unstable/bitstring.cpp b/src/unstable/bitstring.cpp new file mode 100644 index 0000000..bdd1bc2 --- /dev/null +++ b/src/unstable/bitstring.cpp | |||
@@ -0,0 +1,479 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2011 Xagasoft, All rights reserved. | ||
3 | * | ||
4 | * This file is part of the libbu++ library and is released under the | ||
5 | * terms of the license contained in the file LICENSE. | ||
6 | */ | ||
7 | |||
8 | #include "bu/bitstring.h" | ||
9 | #include <stdlib.h> | ||
10 | #include <stdio.h> | ||
11 | #include <string.h> | ||
12 | |||
13 | #include "bu/exceptionbase.h" | ||
14 | |||
15 | #ifdef _WIN32 | ||
16 | #define random() rand() | ||
17 | #endif | ||
18 | |||
19 | #define bitsToBytes( iBits ) (((iBits/8)+((iBits%8)?(1):(0)))); | ||
20 | |||
21 | Bu::BitString::BitString() | ||
22 | { | ||
23 | caData = NULL; | ||
24 | cTopByteMask = 0; | ||
25 | iBits = iBytes = 0; | ||
26 | } | ||
27 | |||
28 | Bu::BitString::BitString( const Bu::BitString &xSrc ) | ||
29 | { | ||
30 | iBits = xSrc.iBits; | ||
31 | iBytes = xSrc.iBytes; | ||
32 | cTopByteMask = xSrc.cTopByteMask; | ||
33 | caData = new unsigned char[iBytes]; | ||
34 | memcpy( caData, xSrc.caData, iBytes ); | ||
35 | |||
36 | fixup(); | ||
37 | } | ||
38 | |||
39 | Bu::BitString::BitString( long iNewBits, bool bFillRandomly ) | ||
40 | { | ||
41 | long j; | ||
42 | iBits = iNewBits; | ||
43 | iBytes = bitsToBytes( iNewBits );//(iNewBits/8)+((iNewBits%8)?(1):(0)); | ||
44 | caData = new unsigned char[iBytes]; | ||
45 | |||
46 | setMask(); | ||
47 | |||
48 | if( bFillRandomly ) | ||
49 | { | ||
50 | // rand() only returns a value up to RAND_MAX (0x7FFF on my system) so | ||
51 | // I'll just use the low order byte) | ||
52 | for( j = 0; j < iBytes; j++ ) | ||
53 | { | ||
54 | caData[j] = (unsigned char)(random() & 0xFF); | ||
55 | } | ||
56 | } | ||
57 | else | ||
58 | { | ||
59 | clear(); | ||
60 | } | ||
61 | |||
62 | fixup(); | ||
63 | } | ||
64 | |||
65 | Bu::BitString::~BitString() | ||
66 | { | ||
67 | if( caData != NULL ) delete[] caData; | ||
68 | } | ||
69 | |||
70 | Bu::BitString &Bu::BitString::operator=( const Bu::BitString &xSrc ) | ||
71 | { | ||
72 | if( caData != NULL ) | ||
73 | { | ||
74 | delete[] caData; | ||
75 | } | ||
76 | iBits = xSrc.iBits; | ||
77 | iBytes = xSrc.iBytes; | ||
78 | cTopByteMask = xSrc.cTopByteMask; | ||
79 | caData = new unsigned char[iBytes]; | ||
80 | memcpy( caData, xSrc.caData, iBytes ); | ||
81 | |||
82 | fixup(); | ||
83 | |||
84 | return *this; | ||
85 | } | ||
86 | |||
87 | Bu::BitString Bu::BitString::operator~() | ||
88 | { | ||
89 | Bu::BitString xRet( *this ); | ||
90 | |||
91 | for( int j = 0; j < xRet.iBytes; j++ ) | ||
92 | { | ||
93 | xRet.caData[j] = ~xRet.caData[j]; | ||
94 | } | ||
95 | |||
96 | xRet.fixup(); | ||
97 | |||
98 | return xRet; | ||
99 | } | ||
100 | |||
101 | Bu::BitString Bu::BitString::operator<<( const long iAmt ) | ||
102 | { | ||
103 | if( iAmt == 0 ) | ||
104 | { | ||
105 | return (*this); | ||
106 | } | ||
107 | //int iByteShift = iAmt/8; | ||
108 | |||
109 | Bu::BitString xSub( getSize() ); | ||
110 | |||
111 | long shft = (iAmt%8); | ||
112 | long base = (iAmt/8); | ||
113 | unsigned char lowmask=0; | ||
114 | for( long j = 0; j < 8-shft; j++ ) | ||
115 | { | ||
116 | lowmask |= (1<<j); | ||
117 | } | ||
118 | for( long j = 0; j < xSub.iBytes; j++ ) | ||
119 | { | ||
120 | xSub.caData[base+j] = ((caData[j]>>shft)&(lowmask)) | ((caData[j+1]<<(8-shft))&(~lowmask)); | ||
121 | } | ||
122 | xSub.fixup(); | ||
123 | |||
124 | return xSub; | ||
125 | } | ||
126 | |||
127 | Bu::BitString Bu::BitString::operator>>( const long iAmt ) | ||
128 | { | ||
129 | if( iAmt == 0 ) | ||
130 | { | ||
131 | return (*this); | ||
132 | } | ||
133 | return (*this); | ||
134 | } | ||
135 | |||
136 | void Bu::BitString::shiftLeft( long iAmt ) | ||
137 | { | ||
138 | if( iAmt == 0 ) | ||
139 | { | ||
140 | return; | ||
141 | } | ||
142 | else if( iAmt < 0 ) | ||
143 | { | ||
144 | shiftRight( -iAmt ); | ||
145 | return; | ||
146 | } | ||
147 | |||
148 | long iByteShift = iAmt/8; | ||
149 | long iBitShift = iAmt%8; | ||
150 | |||
151 | long j; | ||
152 | for( j = iBytes-1; j >= 0; j-- ) | ||
153 | { | ||
154 | caData[j] = (((j-iByteShift)<0)?(0):((caData[j-iByteShift]<<iBitShift))) | (((j-iByteShift-1)<0)?(0):((caData[j-iByteShift-1]>>(8-iBitShift)))); | ||
155 | } | ||
156 | |||
157 | fixup(); | ||
158 | } | ||
159 | |||
160 | void Bu::BitString::shiftRight( long iAmt ) | ||
161 | { | ||
162 | if( iAmt == 0 ) | ||
163 | { | ||
164 | return; | ||
165 | } | ||
166 | else if( iAmt < 0 ) | ||
167 | { | ||
168 | shiftLeft( -iAmt ); | ||
169 | return; | ||
170 | } | ||
171 | |||
172 | long iByteShift = iAmt/8; | ||
173 | long iBitShift = iAmt%8; | ||
174 | |||
175 | long j; | ||
176 | for( j = 0; j < iBytes; j++ ) | ||
177 | { | ||
178 | caData[j] = (((j+iByteShift)>iBytes)?(0):((caData[j+iByteShift]>>iBitShift))) | (((j+iByteShift+1)>iBytes)?(0):((caData[j+iByteShift+1]<<(8-iBitShift)))); | ||
179 | } | ||
180 | |||
181 | fixup(); | ||
182 | } | ||
183 | /* | ||
184 | long Bu::BitString::bitsToBytes( long iBits ) | ||
185 | { | ||
186 | return (iBits/8)+((iBits%8)?(1):(0)); | ||
187 | } | ||
188 | */ | ||
189 | void Bu::BitString::fixup() | ||
190 | { | ||
191 | if( caData != NULL ) | ||
192 | { | ||
193 | caData[iBytes-1] &= cTopByteMask; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | void Bu::BitString::setBit( long iBit, bool bBitState ) | ||
198 | { | ||
199 | if( iBit < 0 || iBit >= iBits ) | ||
200 | throw Bu::ExceptionBase("bit out of range: %d in (0-%d)", iBit, iBits ); | ||
201 | if( bBitState ) | ||
202 | { | ||
203 | caData[iBit/8] |= (1<<(iBit%8)); | ||
204 | } | ||
205 | else | ||
206 | { | ||
207 | caData[iBit/8] &= ~(1<<(iBit%8)); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | void Bu::BitString::flipBit( long iBit ) | ||
212 | { | ||
213 | caData[iBit/8] ^= (1<<(iBit%8)); | ||
214 | } | ||
215 | |||
216 | bool Bu::BitString::getBit( long iBit ) | ||
217 | { | ||
218 | if( iBit >= iBits || iBit < 0 ) return false; | ||
219 | if( (caData[iBit/8] & (1<<(iBit%8))) == 0 ) | ||
220 | { | ||
221 | return false; | ||
222 | } | ||
223 | return true; | ||
224 | } | ||
225 | |||
226 | long Bu::BitString::getBitLength() | ||
227 | { | ||
228 | return iBits; | ||
229 | } | ||
230 | |||
231 | long Bu::BitString::getSize() | ||
232 | { | ||
233 | return iBits; | ||
234 | } | ||
235 | |||
236 | class Bu::BitString Bu::BitString::getSubString( long iLower, long iUpper ) | ||
237 | { | ||
238 | if( iUpper == 0 || iUpper < iLower ) iUpper = iBits; | ||
239 | |||
240 | Bu::BitString xSub( iUpper-iLower+1 ); | ||
241 | |||
242 | long shft = (iLower%8); | ||
243 | long base = (iLower/8); | ||
244 | unsigned char lowmask=0; | ||
245 | for( long j = 0; j < 8-shft; j++ ) | ||
246 | { | ||
247 | lowmask |= (1<<j); | ||
248 | } | ||
249 | for( long j = 0; j < xSub.iBytes; j++ ) | ||
250 | { | ||
251 | xSub.caData[j] = ((caData[base+j]>>shft)&(lowmask)) | ((caData[base+j+1]<<(8-shft))&(~lowmask)); | ||
252 | } | ||
253 | xSub.fixup(); | ||
254 | |||
255 | return xSub; | ||
256 | } | ||
257 | |||
258 | long Bu::BitString::toLong( long iStart, long iSize ) | ||
259 | { | ||
260 | if( iSize < 1 ) iSize = 1; | ||
261 | if( iSize > 32 ) iSize = 32; | ||
262 | if( iStart < 0 ) return 0; | ||
263 | if( iStart+iSize > getSize() ) return 0; | ||
264 | |||
265 | Bu::BitString tmpo; | ||
266 | tmpo = getSubString( iStart, iStart+iSize-1 ); | ||
267 | long x = *((long *)tmpo.caData); | ||
268 | |||
269 | return x; | ||
270 | } | ||
271 | /* | ||
272 | std::string Bu::BitString::toString( bool bAddSpacers ) | ||
273 | { | ||
274 | long iSz = iBits; | ||
275 | if( bAddSpacers ) | ||
276 | { | ||
277 | iSz += (iBits/8); | ||
278 | if( iBits%8 == 0 ) iSz--; | ||
279 | } | ||
280 | std::string xStr; | ||
281 | |||
282 | int bw=0; | ||
283 | int of=0; | ||
284 | for( int j = iBits-1; j >= 0; j-- ) | ||
285 | { | ||
286 | if( getBit( j ) ) | ||
287 | { | ||
288 | xStr += '1'; | ||
289 | } | ||
290 | else | ||
291 | { | ||
292 | xStr += '0'; | ||
293 | } | ||
294 | |||
295 | if( bAddSpacers ) | ||
296 | { | ||
297 | bw++; | ||
298 | if( bw >= 8 && j < iBits-1 ) | ||
299 | { | ||
300 | bw = 0; | ||
301 | of++; | ||
302 | xStr += ' '; | ||
303 | } | ||
304 | } | ||
305 | } | ||
306 | |||
307 | return xStr; | ||
308 | } | ||
309 | */ | ||
310 | void Bu::BitString::clear() | ||
311 | { | ||
312 | if( caData != NULL ) | ||
313 | { | ||
314 | memset( caData, 0, iBytes ); | ||
315 | } | ||
316 | } | ||
317 | |||
318 | bool Bu::BitString::setBitLength( long iLength, bool bClear ) | ||
319 | { | ||
320 | return setSize( iLength, bClear ); | ||
321 | } | ||
322 | |||
323 | bool Bu::BitString::setSize( long iLength, bool bClear ) | ||
324 | { | ||
325 | // First, if there's nothing, then allocate an empty one. | ||
326 | if( caData == NULL ) | ||
327 | { | ||
328 | iBits = iLength; | ||
329 | iBytes = bitsToBytes( iLength ); | ||
330 | caData = new unsigned char[iBytes]; | ||
331 | memset( caData, 0, iBytes ); | ||
332 | return true; | ||
333 | } | ||
334 | |||
335 | // If the new length is the same as the old, don't do anything, but do | ||
336 | // check to see if we should still clear the data. | ||
337 | if( iBits != iLength ) | ||
338 | { | ||
339 | // Ok, we are changing the number if bits, but are we changing the | ||
340 | // number of bytes? | ||
341 | long iNewBytes = bitsToBytes( iLength ); | ||
342 | if( iBytes == iNewBytes ) | ||
343 | { | ||
344 | // No? That makes life easier | ||
345 | iBits = iLength; | ||
346 | setMask(); | ||
347 | if( bClear ) | ||
348 | { | ||
349 | clear(); | ||
350 | } | ||
351 | } | ||
352 | else | ||
353 | { | ||
354 | // Ok, reallocate and copy... | ||
355 | iBits = iLength; | ||
356 | // long iNewBytes = bitsToBytes( iLength ); | ||
357 | if( bClear ) | ||
358 | { | ||
359 | delete[] caData; | ||
360 | caData = new unsigned char[iNewBytes]; | ||
361 | memset( caData, 0, iNewBytes ); | ||
362 | } | ||
363 | else | ||
364 | { | ||
365 | unsigned char *tmp = caData; | ||
366 | caData = new unsigned char[iNewBytes]; | ||
367 | if( iNewBytes < iBytes ) | ||
368 | { | ||
369 | memcpy( caData, tmp, iNewBytes ); | ||
370 | } | ||
371 | else | ||
372 | { | ||
373 | memcpy( caData, tmp, iBytes ); | ||
374 | } | ||
375 | delete[] tmp; | ||
376 | } | ||
377 | iBytes = iNewBytes; | ||
378 | |||
379 | setMask(); | ||
380 | } | ||
381 | |||
382 | } | ||
383 | else if( bClear ) | ||
384 | { | ||
385 | clear(); | ||
386 | } | ||
387 | |||
388 | return true; | ||
389 | } | ||
390 | |||
391 | void Bu::BitString::setMask() | ||
392 | { | ||
393 | // This can either mean that there are a multiple of eight bits or | ||
394 | // zero, if there are zero you're an idiot (zero can't happen, because | ||
395 | // we would allocate an extra byte and never use it) | ||
396 | if( (iBits%8 == 0) ) | ||
397 | { | ||
398 | cTopByteMask = 0xFF; | ||
399 | } | ||
400 | else | ||
401 | { | ||
402 | cTopByteMask = 0; | ||
403 | for( long j = 0; j < (iBits%8); j++ ) | ||
404 | { | ||
405 | cTopByteMask |= (1<<j); | ||
406 | } | ||
407 | } | ||
408 | } | ||
409 | |||
410 | void Bu::BitString::randomize() | ||
411 | { | ||
412 | if( caData != NULL ) | ||
413 | { | ||
414 | for( int j = 0; j < iBytes; j++ ) | ||
415 | { | ||
416 | caData[j] = (unsigned char)(random() & 0xFF); | ||
417 | } | ||
418 | fixup(); | ||
419 | } | ||
420 | } | ||
421 | |||
422 | void Bu::BitString::invert() | ||
423 | { | ||
424 | if( caData != NULL ) | ||
425 | { | ||
426 | for( long j = 0; j < iBytes; j++ ) | ||
427 | { | ||
428 | caData[j] = ~caData[j]; | ||
429 | } | ||
430 | fixup(); | ||
431 | } | ||
432 | } | ||
433 | |||
434 | long Bu::BitString::getHighestOrderBitPos() | ||
435 | { | ||
436 | for( long j = iBits-1; j >= 0; j-- ) | ||
437 | { | ||
438 | if( getBit( j ) ) | ||
439 | { | ||
440 | return j; | ||
441 | } | ||
442 | } | ||
443 | |||
444 | return -1; | ||
445 | } | ||
446 | |||
447 | Bu::String Bu::BitString::toString() | ||
448 | { | ||
449 | Bu::String sRet; | ||
450 | for( int j = iBits-1; j >= 0; j-- ) | ||
451 | sRet.append( getBit( j )?'1':'0' ); | ||
452 | return sRet; | ||
453 | } | ||
454 | |||
455 | /* | ||
456 | bool Bu::BitString::writeToFile( FILE *fh ) | ||
457 | { | ||
458 | fwrite( &iBits, sizeof(long), 1, fh ); | ||
459 | fwrite( caData, sizeof(char), iBytes, fh ); | ||
460 | |||
461 | return true; | ||
462 | } | ||
463 | |||
464 | bool Bu::BitString::readFromFile( FILE *fh ) | ||
465 | { | ||
466 | fread( &iBits, sizeof(long), 1, fh ); | ||
467 | |||
468 | iBytes = bitsToBytes( iBits ); | ||
469 | if( caData ) delete[] caData; | ||
470 | caData = new unsigned char[iBytes]; | ||
471 | |||
472 | fread( caData, sizeof(char), iBytes, fh ); | ||
473 | |||
474 | setMask(); | ||
475 | |||
476 | fixup(); | ||
477 | |||
478 | return true; | ||
479 | }*/ | ||