aboutsummaryrefslogtreecommitdiff
path: root/src/unstable/bitstring.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/unstable/bitstring.cpp')
-rw-r--r--src/unstable/bitstring.cpp479
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
21Bu::BitString::BitString()
22{
23 caData = NULL;
24 cTopByteMask = 0;
25 iBits = iBytes = 0;
26}
27
28Bu::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
39Bu::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
65Bu::BitString::~BitString()
66{
67 if( caData != NULL ) delete[] caData;
68}
69
70Bu::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
87Bu::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
101Bu::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
127Bu::BitString Bu::BitString::operator>>( const long iAmt )
128{
129 if( iAmt == 0 )
130 {
131 return (*this);
132 }
133 return (*this);
134}
135
136void 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
160void 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/*
184long Bu::BitString::bitsToBytes( long iBits )
185{
186 return (iBits/8)+((iBits%8)?(1):(0));
187}
188*/
189void Bu::BitString::fixup()
190{
191 if( caData != NULL )
192 {
193 caData[iBytes-1] &= cTopByteMask;
194 }
195}
196
197void 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
211void Bu::BitString::flipBit( long iBit )
212{
213 caData[iBit/8] ^= (1<<(iBit%8));
214}
215
216bool 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
226long Bu::BitString::getBitLength()
227{
228 return iBits;
229}
230
231long Bu::BitString::getSize()
232{
233 return iBits;
234}
235
236class 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
258long 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/*
272std::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*/
310void Bu::BitString::clear()
311{
312 if( caData != NULL )
313 {
314 memset( caData, 0, iBytes );
315 }
316}
317
318bool Bu::BitString::setBitLength( long iLength, bool bClear )
319{
320 return setSize( iLength, bClear );
321}
322
323bool 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
391void 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
410void 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
422void 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
434long 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
447Bu::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/*
456bool 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
464bool 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}*/