KSquare Utilities
BitString.cpp
Go to the documentation of this file.
1 /* BitString.cpp -- Bit String management Class
2  * Copyright (C) 1994-2011 Kurt Kramer
3  * For conditions of distribution and use, see copyright notice in KKB.h
4  */
5 #include "FirstIncludes.h"
6 #include <stdio.h>
7 #include <fstream>
8 #include <string>
9 #include <iostream>
10 #include <vector>
11 #include <string.h>
12 #include "MemoryDebug.h"
13 using namespace std;
14 
15 #include "BitString.h"
16 #include "GlobalGoalKeeper.h"
17 #include "KKBaseTypes.h"
18 #include "KKException.h"
19 #include "XmlStream.h"
20 using namespace KKB;
21 
22 
23 // Bit 0 1 2 3 4 5 6 7
24 uchar BitString::bitMasks[8] = { 1, 2, 4, 8, 16, 32, 64, 128};
25 
26 uchar BitString::bitMasksRev[8] = {255-1, 255-2, 255-4, 255-8, 255-16, 255-32, 255-64, 255-128};
27 
28 uchar* BitString::bitCounts = NULL;
29 
30 
31 /**
32  *@brief Initializes static array 'bitCounts' which maintains the number of bits in the binary representation of 0 - 255.
33  *@details The purpose of 'bitCounts' is to make the computation of total number of bits in a bit string stored in 'str' as fast as possible.
34  */
35 void BitString::BuildBitCounts ()
36 {
37  if (bitCounts)
38  return;
39 
40  bitCounts = new uchar[256];
41 
42  kkint32 byte = 0;
43  for (byte = 0; byte < 256; byte++)
44  {
45  bitCounts[byte] = 0;
46  kkint32 x = byte;
47  while (x > 0)
48  {
49  if ((x % 2) == 1)
50  bitCounts[byte]++;
51  x = x / 2;
52  }
53  }
54 } /* BuildBitCounts */
55 
56 
57 
59  bitLen (0),
60  byteLen (0)
61 {
62  byteLen = ((bitLen - 1) / 8) + 1;
63  str = NULL;
64 }
65 
66 
67 
69  bitLen (_bitLen),
70  byteLen (0)
71 {
72  byteLen = ((bitLen - 1) / 8) + 1;
73  str = new uchar[byteLen];
74  memset (str, 0, byteLen);
75 }
76 
77 
79  bitLen (bs.bitLen),
80  byteLen (bs.byteLen),
81  str (NULL)
82 {
83  uchar* str;
84  str = new uchar[byteLen];
85  memcpy (str, bs.str, byteLen);
86 }
87 
88 
90  kkuint16* bitNums,
91  kkuint32 bitNumsLen
92  ):
93  bitLen (_bitLen),
94  byteLen (0),
95  str (NULL)
96 {
97  byteLen = ((bitLen - 1) / 8) + 1;
98  str = new uchar[byteLen];
99  memset (str, 0, byteLen);
100  kkuint32 x;
101  for (x = 0; x < bitNumsLen; x++)
102  {
103  if (bitNums[x] >= bitLen)
104  {
105  KKStr msg (128);
106  msg << "BitString Constructing from list of numbers: bitNums[" << x << "] = [" << bitNums[x] << "] which is >= bitLen[" << bitLen << "].";
107  cerr << std::endl << std::endl << "BitString ***ERROR*** " << msg << std::endl << std::endl;
108  throw KKException (msg);
109  }
110  Set (bitNums[x]);
111  }
112 }
113 
114 
115 
117 {
118  delete str;
119  str = NULL;
120 }
121 
122 
123 
125 {
126  return new BitString (*this);
127 }
128 
129 
130 
131 void BitString::CalcByteAndBitOffsets (kkuint32 bitNum,
132  kkint32& byteOffset,
133  uchar& bitOffset
134  ) const
135 {
136  byteOffset = bitNum / 8;
137  bitOffset = bitNum % 8;
138 } /* CalcByteAndBitOffsets */
139 
140 
141 
143 {
144  BuildBitCounts ();
145 
146  kkuint32 count = 0;
147  kkuint32 byteOffset = 0;
148 
149  for (byteOffset = 0; byteOffset < byteLen; byteOffset++)
150  count += bitCounts[str[byteOffset]];
151 
152  return count;
153 } /* Count */
154 
155 
156 
157 
158 bool BitString::Test (kkuint32 bitNum) const
159 {
160  kkint32 byteOffset;
161  uchar bitOffset;
162 
163  CalcByteAndBitOffsets (bitNum, byteOffset, bitOffset);
164 
165  bool bit = ((str[byteOffset] & bitMasks[bitOffset]) != 0);
166 
167  return bit;
168 } /* IsSet */
169 
170 
171 
172 
173 void BitString::Set ()
174 {
175  memset (str, 255, byteLen);
176 } /* Set */
177 
178 
179 
180 
181 
182 void BitString::Set (kkuint32 bitNum)
183 {
184  if (bitNum >= bitLen)
185  {
186  // Index violation.
187  cerr << std::endl
188  << "BitString::Set Invalid Index[" << bitNum << "] BitString::bitLen[" << bitLen << "]." << std::endl
189  << std::endl;
190  exit (-1);
191  }
192 
193  kkint32 byteOffset;
194  uchar bitOffset;
195 
196  CalcByteAndBitOffsets (bitNum, byteOffset, bitOffset);
197 
198  uchar& br = str[byteOffset];
199 
200  br = (br | bitMasks[bitOffset]);
201 } /* Set */
202 
203 
204 
205 
206 
207 void BitString::ReSet ()
208 {
209  memset (str, 0, byteLen);
210 }
211 
212 
213 
214 
215 void BitString::ReSet (kkuint32 bitNum)
216 {
217  if (bitNum >= bitLen)
218  {
219  // Index violation.
220  cerr << std::endl
221  << "BitString::Set Invalid Index[" << bitNum << "] BitString::bitLen[" << bitLen << "]." << std::endl
222  << std::endl;
223  exit (-1);
224  }
225 
226  kkint32 byteOffset;
227  uchar bitOffset;
228 
229  CalcByteAndBitOffsets (bitNum, byteOffset, bitOffset);
230 
231  uchar& br = str[byteOffset];
232 
233  br = (br & bitMasksRev[bitOffset]);
234 } /* ReSet */
235 
236 
237 
238 
239 void BitString::PopulateVectorBool (VectorBool& boolVector) const
240 {
241  boolVector.erase (boolVector.begin (), boolVector.end ());
242 
243  kkuint32 byteOffset = 0;
244  kkuint32 numOfBits = 0;
245  kkuint32 x;
246 
247  for (byteOffset = 0; byteOffset < byteLen; byteOffset++)
248  {
249  uchar br = str[byteOffset];
250  if (byteOffset < (byteLen - 1))
251  numOfBits = 8;
252  else
253  numOfBits = bitLen % 8;
254 
255  for (x = 0; x < numOfBits; x++)
256  {
257  boolVector.push_back ((br % 2) == 1);
258  br = br / 2;
259  }
260  }
261 } /* PopulateVectorBool */
262 
263 
264 
265 
266 void BitString::ListOfSetBits16 (VectorUint16& setBits) const
267 {
268  if (bitLen > 65535)
269  {
270  KKStr msg (50);
271  msg << "BitString::ListOfSetBits BitLen[" << bitLen << "] of this instance of BitString exceeds capacity of 'VectorUint16'.";
272  cerr << std::endl << "BitString::ListOfSetBits ***ERROR*** " << msg << std::endl << std::endl;
273  throw KKException (msg);
274  }
275 
276  setBits.clear ();
277 
278  kkuint32 byteOffset = 0;
279  kkuint32 numOfBits = 0;
280  kkuint32 bitNum = 0;
281 
282  for (byteOffset = 0; byteOffset < byteLen; byteOffset++)
283  {
284  uchar br = str[byteOffset];
285  if (br == 0)
286  {
287  bitNum = bitNum + 8;
288  continue;
289  }
290  else
291  {
292  if (byteOffset < (byteLen - 1))
293  numOfBits = 8;
294  else
295  {
296  numOfBits = bitLen % 8;
297  if (numOfBits == 0)
298  numOfBits = 8;
299  }
300 
301  kkuint32 x;
302  for (x = 0; x < numOfBits; x++)
303  {
304  if ((br % 2) == 1)
305  {
306  setBits.push_back ((kkuint16)bitNum);
307  }
308 
309  br = br / 2;
310  bitNum++;
311  }
312  }
313  }
314 } /* ListOfSetBits16 */
315 
316 
317 void BitString::ListOfSetBits32 (VectorUint32& setBits) const
318 {
319  setBits.clear ();
320 
321  kkuint32 byteOffset = 0;
322  kkuint32 numOfBits = 0;
323  kkuint32 bitNum = 0;
324 
325  for (byteOffset = 0; byteOffset < byteLen; byteOffset++)
326  {
327  uchar br = str[byteOffset];
328  if (br == 0)
329  {
330  bitNum = bitNum + 8;
331  continue;
332  }
333  else
334  {
335  if (byteOffset < (byteLen - 1))
336  numOfBits = 8;
337  else
338  {
339  numOfBits = bitLen % 8;
340  if (numOfBits == 0)
341  numOfBits = 8;
342  }
343 
344  kkuint32 x;
345  for (x = 0; x < numOfBits; x++)
346  {
347  if ((br % 2) == 1)
348  {
349  setBits.push_back (bitNum);
350  }
351 
352  br = br / 2;
353  bitNum++;
354  }
355  }
356  }
357 } /* ListOfSetBits32 */
358 
359 
360 
362 {
363  KKStr hexStr (byteLen * 2); // There will be 2 hex characters for every byte in bit string
364 
365  static char hexChars[] = {'0', '1', '2', '3', '4', '5', '6', '7','8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
366 
367  kkuint32 byteOffset = 0;
368  kkint32 high4Bits;
369  kkint32 low4Bits;
370 
371  for (byteOffset = 0; byteOffset < byteLen; byteOffset++)
372  {
373  high4Bits = str[byteOffset] / 16;
374  low4Bits = str[byteOffset] % 16;
375 
376  hexStr.Append (hexChars[low4Bits]);
377  hexStr.Append (hexChars[high4Bits]);
378  }
379 
380  return hexStr;
381 } /* HexStr */
382 
383 
384 
385 kkint32 BitString::HexCharToInt (uchar hexChar)
386 {
387  if ((hexChar >= '0') && (hexChar <= '9'))
388  return (kkint32 (hexChar) - kkint32 ('0'));
389 
390  hexChar = (char)toupper (hexChar);
391  if ((hexChar < 'A') || (hexChar > 'F'))
392  return -1;
393 
394  return (10 + (kkint32 (hexChar) - kkint32 ('A')));
395 } /* HexCharToInt */
396 
397 
398 
400  bool& validHexStr
401  )
402 {
403  BitString bs (hexStr.Len () * 4);
404  kkint32 byteNum = 0;
405  kkint32 hexStrLen = hexStr.Len ();
406  kkint32 high4Bits = 0;
407  kkint32 low4Bits = 0;
408  kkint32 x = 0;
409 
410  validHexStr = true;
411 
412  while (x < hexStrLen)
413  {
414  low4Bits = HexCharToInt (hexStr[x]);
415  x++;
416  if (low4Bits < 0)
417  validHexStr = false;
418 
419  if (x < hexStrLen)
420  {
421  high4Bits = HexCharToInt (hexStr[x]);
422  x++;
423  if (high4Bits < 0)
424  validHexStr = false;
425  }
426  else
427  {
428  high4Bits = 0;
429  }
430 
431  bs.str[byteNum] = (uchar)low4Bits + (uchar)high4Bits * 16;
432  byteNum++;
433  }
434 
435  return bs;
436 } /* FromHexStr */
437 
438 
439 
440 
442 {
443  delete str;
444 
445  bitLen = right.bitLen;
446  byteLen = right.byteLen;
447  str = new uchar[byteLen];
448 
449  kkuint32 x;
450  for (x = 0; x < byteLen; x++)
451  str[x] = right.str[x];
452 
453  return *this;
454 } /* operator= */
455 
456 
457 
458 
460 {
461  kkuint32 shortestByteLen = Min (byteLen, right.byteLen);
462 
463  kkuint32 x;
464 
465  for (x = 0; x < shortestByteLen; x++)
466  {
467  str[x] = str[x] | right.str[x];
468  }
469 
470  return *this;
471 } /* operator|= */
472 
473 
474 
476 {
477  operator|= (right);
478  return *this;
479 } /* operator+= */
480 
481 
482 
483 
485 {
486  kkuint32 shortestByteLen = Min (byteLen, right.byteLen);
487 
488  kkuint32 x;
489 
490  for (x = 0; x < shortestByteLen; x++)
491  {
492  str[x] = str[x] & right.str[x];
493  }
494  for (x = shortestByteLen; x < byteLen; ++x)
495  {
496  str[x] = 0;
497  }
498 
499  return *this;
500 } /* operator&= */
501 
502 
503 
505 {
506  operator&= (right);
507  return *this;
508 } /* operator*= */
509 
510 
511 
512 kkint32 BitString::Compare (const BitString& right) const
513 {
514  kkuint32 shortestByteLen = Min (byteLen, right.byteLen);
515 
516  kkuint32 x = 0;
517 
518  while (x < shortestByteLen)
519  {
520  if (str[x] < right.str[x])
521  return -1;
522 
523  else if (str[x] > right.str[x])
524  return 1;
525 
526  else
527  x++;
528  }
529 
530  if (x >= byteLen)
531  {
532  if (x >= right.byteLen)
533  return 0;
534  else
535  return -1;
536  }
537  else
538  {
539  return 1;
540  }
541 } /* Compare */
542 
543 
544 
545 bool BitString::operator== (const BitString& right) const
546 {
547  return (Compare (right) == 0);
548 } /* operator== */
549 
550 
551 
552 bool BitString::operator!= (const BitString& right) const
553 {
554  return (Compare (right) != 0);
555 } /* operator!= */
556 
557 
558 
559 bool BitString::operator> (const BitString& right) const
560 {
561  return (Compare (right) > 0);
562 } /* operator> */
563 
564 
565 
566 bool BitString::operator>= (const BitString& right) const
567 {
568  return (Compare (right) >= 0);
569 } /* operator>= */
570 
571 
572 
573 bool BitString::operator< (const BitString& right) const
574 {
575  return (Compare (right) < 0);
576 } /* operator< */
577 
578 
579 
581 {
582  kkuint32 shortestByteLen = Min (byteLen, right.byteLen);
583  kkuint32 longestByteLen = Max (byteLen, right.byteLen);
584 
585  kkuint32 x;
586 
587  for (x = 0; x < shortestByteLen; x++)
588  str[x] = str[x] ^ right.str[x];
589 
590  for (x = shortestByteLen; x < longestByteLen; x++)
591  str[x] = 0;
592 
593  return *this;
594 }
595 
596 
597 
598 BitString BitString::operator^ (const BitString& right) /* bitwise exclusive-or */
599 {
600  kkuint32 shortestByteLen = Min (byteLen, right.byteLen);
601  kkuint32 longestByteLen = Max (byteLen, right.byteLen);
602 
603  kkuint32 x;
604 
605  BitString result (Max (bitLen, right.bitLen));
606 
607  for (x = 0; x < shortestByteLen; x++)
608  result.str[x] = str[x] ^ right.str[x];
609 
610  for (x = shortestByteLen; x < longestByteLen; x++)
611  result.str[x] = 0;
612 
613  return result;
614 }
615 
616 
617 
619  XmlTagConstPtr tag,
620  VolConstBool& cancelFlag,
621  RunLog& log
622  )
623 {
624  kkint32 bitIndex = 0;
625  XmlTokenPtr t = s.GetNextToken (cancelFlag, log);
626  while (t && (!cancelFlag))
627  {
628  if (typeid (*t) == typeid (XmlContent))
629  {
630  XmlContentPtr c = dynamic_cast<XmlContentPtr> (t);
631  if (c && c->Content ())
632  {
633  KKStrConstPtr text = c->Content ();
634  /** TODO decode text block into list of bits. */
635  //ParseClassIndexList (*text, log);
636  delete text;
637  text = NULL;
638  }
639  }
640  delete t;
641  t = s.GetNextToken (cancelFlag, log);
642  }
643  delete t;
644  t = NULL;
645 } /* ReadXML */
646 
647 
648 
649 
650 void BitString::WriteXML (const KKStr& varName,
651  ostream& o
652  ) const
653 {
654  XmlTag startTag ("BitString", XmlTag::TagTypes::tagStart);
655  if (!varName.Empty ())
656  startTag.AddAtribute ("VarName", varName);
657  startTag.WriteXML (o);
659  XmlTag endTag ("BitString", XmlTag::TagTypes::tagEnd);
660  endTag.WriteXML (o);
661  o << endl;
662 }
663 
664 
665 XmlFactoryMacro(BitString)
KKStr(kkint32 size)
Creates a KKStr object that pre-allocates space for &#39;size&#39; characters.
Definition: KKStr.cpp:655
XmlTag(const KKStr &_name, TagTypes _tagType)
Definition: XmlStream.cpp:586
kkuint32 Count() const
Returns number of bits set to &#39;1&#39;.
Definition: BitString.cpp:142
BitString & operator&=(const BitString &right)
Performs a bitwise AND against the left operand.
Definition: BitString.cpp:484
std::vector< kkuint32 > VectorUint32
Vector of unsigned 32 bit integers.
Definition: KKBaseTypes.h:145
__int32 kkint32
Definition: KKBaseTypes.h:88
void ReSet(kkuint32 bitNum)
Set the bit indicated by &#39;bitNum&#39; to &#39;0&#39;.
Definition: BitString.cpp:215
virtual BitString * Duplicate() const
Definition: BitString.cpp:124
static BitString FromHexStr(const KKStr &hexStr, bool &validHexStr)
Create a bit-string from a Hex String.
Definition: BitString.cpp:399
void Set()
Set all bits to &#39;1&#39;.
Definition: BitString.cpp:173
virtual void ReadXML(XmlStream &s, XmlTagConstPtr tag, VolConstBool &cancelFlag, RunLog &log)
Definition: BitString.cpp:618
KKStr HexStr() const
Returns a Hex-String representation.
Definition: BitString.cpp:361
void ReSet()
Set all bits to &#39;0&#39;.
Definition: BitString.cpp:207
virtual void WriteXML(const KKStr &varName, std::ostream &o) const
Definition: BitString.cpp:650
bool operator!=(const BitString &right) const
Definition: BitString.cpp:552
void PopulateVectorBool(VectorBool &boolVector) const
Populates a boolean vector where each element reflects whether the corresponding bit is set...
Definition: BitString.cpp:239
BitString & operator^=(const BitString &right)
Performs a bitwise XOR against the left operand.
Definition: BitString.cpp:580
unsigned __int16 kkuint16
16 bit unsigned integer.
Definition: KKBaseTypes.h:86
XmlContent * XmlContentPtr
Definition: XmlStream.h:24
bool operator>(const BitString &right) const
Definition: BitString.cpp:559
BitString & operator|=(const BitString &right)
Performs a bitwise OR against the left operand.
Definition: BitString.cpp:459
BitString operator^(const BitString &right)
Performs a bitwise XOR between two operands returning a new BitString.
Definition: BitString.cpp:598
BitString & operator+=(const BitString &right)
Performs a bitwise OR against the left operand.
Definition: BitString.cpp:475
bool Test(kkuint32 bitNum) const
Definition: BitString.cpp:158
XmlToken * XmlTokenPtr
Definition: XmlStream.h:18
unsigned __int32 kkuint32
Definition: KKBaseTypes.h:89
std::vector< bool > VectorBool
Definition: KKBaseTypes.h:135
bool operator==(const BitString &right) const
Definition: BitString.cpp:545
Allows you to manage very long bit strings.
Definition: BitString.h:31
kkuint32 Len() const
Returns the number of characters in the string.
Definition: KKStr.h:366
KKTHread * KKTHreadPtr
void Append(char ch)
Definition: KKStr.cpp:1863
BitString(const BitString &b)
Copy constructor.
Definition: BitString.cpp:78
void AddAtribute(const KKStr &attributeName, const KKStr &attributeValue)
Definition: XmlStream.cpp:602
bool Empty() const
Definition: KKStr.h:241
Manages the reading and writing of objects in a simple XML format. For a class to be supported by Xml...
Definition: XmlStream.h:46
BitString & operator=(const BitString &right)
Definition: BitString.cpp:441
unsigned char uchar
Unsigned character.
Definition: KKBaseTypes.h:77
static KKStr Concat(const std::vector< std::string > &values)
Concatenates the list of &#39;std::string&#39; strings.
Definition: KKStr.cpp:1082
void ListOfSetBits16(VectorUint16 &setBits) const
Definition: BitString.cpp:266
void Set(kkuint32 bitNum)
Set the bit indicated by &#39;bitNum&#39; to &#39;1&#39;.
Definition: BitString.cpp:182
BitString()
Instantiates a empty bit-string of length 0; needed for ReadXML.
Definition: BitString.cpp:58
BitString & operator*=(const BitString &right)
Performs a bitwise AND against the left operand.
Definition: BitString.cpp:504
static void WriteXml(const KKStr &s, std::ostream &o)
Definition: XmlStream.cpp:853
BitString(kkuint32 _bitLen, kkuint16 *_bitNums, kkuint32 _bitNumsLen)
Construct a BitString of length _bitLen with bits indicated by &#39;_bitNums&#39; set to &#39;1&#39;.
Definition: BitString.cpp:89
char operator[](kkint32 i) const
Definition: KKStr.cpp:3413
void WriteXML(std::ostream &o)
Definition: XmlStream.cpp:723
KKStrPtr const Content() const
Definition: XmlStream.h:338
bool operator<(const BitString &right) const
Definition: BitString.cpp:573
Used for logging messages.
Definition: RunLog.h:49
BitString(kkuint32 _bitLen)
Construct a bit string of length _binLen with all bits set to &#39;0&#39;.
Definition: BitString.cpp:68
virtual XmlTokenPtr GetNextToken(VolConstBool &cancelFlag, RunLog &log)
Definition: XmlStream.cpp:116
KKException(const KKStr &_exceptionStr)
Definition: KKException.cpp:45
std::vector< kkuint16 > VectorUint16
Vector of unsigned 16 bit integers.
Definition: KKBaseTypes.h:141
void ListOfSetBits32(VectorUint32 &setBits) const
Definition: BitString.cpp:317
bool operator>=(const BitString &right) const
Definition: BitString.cpp:566
#define XmlFactoryMacro(NameOfClass)
Definition: XmlStream.h:688
volatile const bool VolConstBool
Definition: KKBaseTypes.h:163