00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef __CS_BITARRAY_H__
00028 #define __CS_BITARRAY_H__
00029
00034 #include "csextern.h"
00035 #include "csutil/allocator.h"
00036 #include "csutil/bitops.h"
00037 #include "csutil/comparator.h"
00038 #include "csutil/hash.h"
00039
00040 #include "csutil/metautils.h"
00041 #include "csutil/compileassert.h"
00042
00043 #if defined(CS_COMPILER_MSVC) && (CS_PROCESSOR_SIZE == 64)
00044
00045
00046
00047 typedef uint64 csBitArrayStorageType;
00048 #else
00049
00050 typedef unsigned long csBitArrayStorageType;
00051 #endif
00052 const size_t csBitArrayDefaultInlineBits =
00053 sizeof (csBitArrayStorageType) * 8;
00054
00055
00057 template<typename BitArray>
00058 class csComparatorBitArray
00059 {
00060 public:
00061 static int Compare (BitArray const& key1, BitArray const& key2)
00062 {
00063 csBitArrayStorageType const* p0 = key1.GetStore();
00064 csBitArrayStorageType const* p1 = key2.GetStore();
00065 size_t compareNum = MIN (key1.mLength, key2.mLength);
00066 size_t i = 0;
00067 for (; i < compareNum; i++)
00068 if (p0[i] != p1[i])
00069 return (int)p0[i] - (int)p1[i];
00070 if (key1.mLength > key2.mLength)
00071 {
00072 for (; i < key1.mLength; i++)
00073 if (p0[i] != 0)
00074 return (int)p0[i];
00075 }
00076 else
00077 {
00078 for (; i < key2.mLength; i++)
00079 if (p1[i] != 0)
00080 return -((int)p1[i]);
00081 }
00082 return 0;
00083 }
00084 };
00085
00086
00088 template<typename BitArray>
00089 class csHashComputerBitArray
00090 {
00091 public:
00092 static uint ComputeHash (BitArray const& key)
00093 {
00094 const size_t uintCount = sizeof (csBitArrayStorageType) / sizeof (uint);
00095 uint ui[uintCount];
00096 uint hash = 0;
00097 csBitArrayStorageType const* p = key.GetStore();
00098
00099
00100
00101 for (size_t i = 0; i < key.mLength; i++)
00102 {
00103 memcpy (ui, &p[i], sizeof (ui));
00104 for (size_t j = 0; j < uintCount; j++)
00105 hash += ui[j];
00106 }
00107 return hash;
00108 }
00109 };
00110
00130 template<int InlinedBits = csBitArrayDefaultInlineBits,
00131 typename Allocator = CS::Memory::AllocatorMalloc>
00132 class csBitArrayTweakable
00133 {
00134 public:
00135 typedef csBitArrayTweakable<InlinedBits, Allocator> ThisType;
00136 typedef Allocator AllocatorType;
00137
00138 protected:
00139 template<typename BitArray> friend class csComparatorBitArray;
00140 template<typename BitArray> friend class csHashComputerBitArray;
00141
00142 enum
00143 {
00144 cellSize = csBitArrayDefaultInlineBits,
00145 cellCount = (InlinedBits + (cellSize-1)) / cellSize,
00146
00147 cellMask = (cellSize - 1),
00148 cellShift = CS::Meta::Log2<cellSize>::value
00149 };
00150 CS_COMPILE_ASSERT(CS::Meta::IsLog2<cellSize>::value);
00151
00152 struct Storage : public Allocator
00153 {
00154 union
00155 {
00156 csBitArrayStorageType* heapStore;
00157 csBitArrayStorageType inlineStore[cellCount];
00158 };
00159 Storage()
00160 {
00161 memset (&inlineStore, 0,
00162 MAX(sizeof (heapStore), sizeof (inlineStore)));
00163 }
00164 };
00165 Storage storage;
00167 size_t mLength;
00168 size_t mNumBits;
00169
00171 static size_t GetIndex (size_t bit_num)
00172 {
00173 return bit_num >> cellShift;
00174 }
00175
00177 static size_t GetOffset (size_t bit_num)
00178 {
00179 return bit_num & cellMask;
00180 }
00181
00183 bool UseInlineStore () const
00184 {
00185 return mLength <= cellCount;
00186 }
00187
00192 csBitArrayStorageType const* GetStore() const
00193 {
00194 return UseInlineStore () ? storage.inlineStore : storage.heapStore;
00195 }
00196
00201 csBitArrayStorageType* GetStore()
00202 {
00203 return UseInlineStore () ? storage.inlineStore : storage.heapStore;
00204 }
00205
00207 void Trim()
00208 {
00209 size_t extra_bits = mNumBits % cellSize;
00210 if (mLength > 0 && extra_bits != 0)
00211 GetStore()[mLength - 1] &= ~((~(csBitArrayStorageType)0) << extra_bits);
00212 }
00213
00218 void SetSizeInternal (size_t newSize)
00219 {
00220 size_t newLength;
00221 if (newSize == 0)
00222 newLength = 0;
00223 else
00224 newLength = 1 + GetIndex (newSize - 1);
00225
00226 if (newLength != mLength)
00227 {
00228
00229 csBitArrayStorageType* newStore;
00230 if (newLength <= cellCount)
00231 newStore = storage.inlineStore;
00232 else
00233 newStore = (csBitArrayStorageType*)storage.Alloc (
00234 newLength * sizeof (csBitArrayStorageType));
00235
00236 if (newLength > 0)
00237 {
00238 if (mLength > 0)
00239 {
00240 csBitArrayStorageType* oldStore = GetStore();
00241 if (newStore != oldStore)
00242 {
00243 memcpy (newStore, oldStore,
00244 (MIN (mLength, newLength)) * sizeof (csBitArrayStorageType));
00245 if (newLength > mLength)
00246 memset(newStore + mLength, 0,
00247 (newLength - mLength) * sizeof (csBitArrayStorageType));
00248 if (!UseInlineStore ())
00249 storage.Free (oldStore);
00250 }
00251 }
00252 else
00253 memset (newStore, 0, newLength * sizeof (csBitArrayStorageType));
00254 }
00255 mLength = newLength;
00256 if (!UseInlineStore()) storage.heapStore = newStore;
00257 }
00258
00259 mNumBits = newSize;
00260 }
00261
00262 public:
00266 class BitProxy
00267 {
00268 private:
00269 csBitArrayTweakable& mArray;
00270 size_t mPos;
00271 public:
00273 BitProxy (csBitArrayTweakable& array, size_t pos): mArray(array), mPos(pos)
00274 {}
00275
00277 BitProxy &operator= (bool value)
00278 {
00279 mArray.Set (mPos, value);
00280 return *this;
00281 }
00282
00284 BitProxy &operator= (const BitProxy &that)
00285 {
00286 mArray.Set (mPos, that.mArray.IsBitSet (that.mPos));
00287 return *this;
00288 }
00289
00291 operator bool() const
00292 {
00293 return mArray.IsBitSet (mPos);
00294 }
00295
00300 bool Flip()
00301 {
00302 mArray.FlipBit (mPos);
00303 return mArray.IsBitSet (mPos);
00304 }
00305 };
00306 friend class BitProxy;
00307
00311 csBitArrayTweakable () : mLength(0), mNumBits(0)
00312 {
00313 SetSize (0);
00314 }
00315
00319 explicit csBitArrayTweakable (size_t size) : mLength(0), mNumBits(0)
00320 {
00321 SetSize (size);
00322 }
00323
00327 csBitArrayTweakable (const csBitArrayTweakable& that) : mLength(0), mNumBits(0)
00328 {
00329 *this = that;
00330 }
00331
00333 ~csBitArrayTweakable()
00334 {
00335 if (!UseInlineStore ())
00336 storage.Free (storage.heapStore);
00337 }
00338
00340 size_t GetSize() const
00341 {
00342 return mNumBits;
00343 }
00344
00349 CS_DEPRECATED_METHOD_MSG("Use GetSize() instead.")
00350 size_t Length () const
00351 {
00352 return GetSize();
00353 }
00354
00359 CS_DEPRECATED_METHOD_MSG("Use SetSize() instead.")
00360 void SetLength (size_t newSize)
00361 {
00362 SetSize (newSize);
00363 }
00364
00370 void SetSize (size_t newSize)
00371 {
00372 SetSizeInternal (newSize);
00373 Trim();
00374 }
00375
00376
00377
00378
00379
00381 csBitArrayTweakable& operator=(const csBitArrayTweakable& that)
00382 {
00383 if (this != &that)
00384 {
00385 SetSizeInternal (that.mNumBits);
00386 memcpy (GetStore(), that.GetStore(),
00387 mLength * sizeof (csBitArrayStorageType));
00388 }
00389 return *this;
00390 }
00391
00393 BitProxy operator[] (size_t pos)
00394 {
00395 CS_ASSERT (pos < mNumBits);
00396 return BitProxy(*this, pos);
00397 }
00398
00400 bool operator[] (size_t pos) const
00401 {
00402 return IsBitSet(pos);
00403 }
00404
00406 bool operator==(const csBitArrayTweakable& that) const
00407 {
00408 if (mNumBits != that.mNumBits)
00409 return false;
00410
00411 csBitArrayStorageType const* p0 = GetStore();
00412 csBitArrayStorageType const* p1 = that.GetStore();
00413 for (unsigned i = 0; i < mLength; i++)
00414 if (p0[i] != p1[i])
00415 return false;
00416 return true;
00417 }
00418
00420 bool operator != (const csBitArrayTweakable& that) const
00421 {
00422 return !(*this == that);
00423 }
00424
00426 csBitArrayTweakable& operator &= (const csBitArrayTweakable &that)
00427 {
00428 CS_ASSERT (mNumBits == that.mNumBits);
00429 csBitArrayStorageType* p0 = GetStore();
00430 csBitArrayStorageType const* p1 = that.GetStore();
00431 for (size_t i = 0; i < mLength; i++)
00432 p0[i] &= p1[i];
00433 return *this;
00434 }
00435
00437 csBitArrayTweakable operator |= (const csBitArrayTweakable& that)
00438 {
00439 CS_ASSERT (mNumBits == that.mNumBits);
00440 csBitArrayStorageType* p0 = GetStore();
00441 csBitArrayStorageType const* p1 = that.GetStore();
00442 for (size_t i = 0; i < mLength; i++)
00443 p0[i] |= p1[i];
00444 return *this;
00445 }
00446
00448 csBitArrayTweakable operator ^= (const csBitArrayTweakable& that)
00449 {
00450 CS_ASSERT (mNumBits == that.mNumBits);
00451 csBitArrayStorageType* p0 = GetStore();
00452 csBitArrayStorageType const* p1 = that.GetStore();
00453 for (size_t i = 0; i < mLength; i++)
00454 p0[i] ^= p1[i];
00455 return *this;
00456 }
00457
00459 csBitArrayTweakable operator~() const
00460 {
00461 return csBitArrayTweakable(*this).FlipAllBits();
00462 }
00463
00465 friend csBitArrayTweakable operator& (const csBitArrayTweakable& a1,
00466 const csBitArrayTweakable& a2)
00467 {
00468 return csBitArrayTweakable (a1) &= a2;
00469 }
00470
00472 friend csBitArrayTweakable operator | (const csBitArrayTweakable& a1,
00473 const csBitArrayTweakable& a2)
00474 {
00475 return csBitArrayTweakable (a1) |= a2;
00476 }
00477
00479 friend csBitArrayTweakable operator ^ (const csBitArrayTweakable& a1,
00480 const csBitArrayTweakable& a2)
00481 {
00482 return csBitArrayTweakable (a1) ^= a2;
00483 }
00484
00485
00486
00487
00488
00490 void Clear()
00491 {
00492 memset (GetStore(), 0, mLength * sizeof(csBitArrayStorageType));
00493 }
00494
00496 void SetAll()
00497 {
00498 csBitArrayStorageType* store = GetStore();
00499 for (size_t i = 0; i < mNumBits; i++)
00500 store[GetIndex(i)] = ((csBitArrayStorageType)1) << GetOffset(i);
00501 }
00502
00504 void SetBit (size_t pos)
00505 {
00506 CS_ASSERT (pos < mNumBits);
00507 GetStore()[GetIndex(pos)] |= ((csBitArrayStorageType)1) << GetOffset(pos);
00508 }
00509
00511 void ClearBit (size_t pos)
00512 {
00513 CS_ASSERT (pos < mNumBits);
00514 GetStore()[GetIndex(pos)] &= ~(((csBitArrayStorageType)1) << GetOffset(pos));
00515 }
00516
00518 void FlipBit (size_t pos)
00519 {
00520 CS_ASSERT (pos < mNumBits);
00521 GetStore()[GetIndex(pos)] ^= ((csBitArrayStorageType)1) << GetOffset(pos);
00522 }
00523
00525 void Set (size_t pos, bool val = true)
00526 {
00527 if (val)
00528 SetBit(pos);
00529 else
00530 ClearBit(pos);
00531 }
00532
00534 bool IsBitSet (size_t pos) const
00535 {
00536 CS_ASSERT (pos < mNumBits);
00537 return (GetStore()[GetIndex(pos)]
00538 & (((csBitArrayStorageType)1) << GetOffset(pos))) != 0;
00539 }
00540
00547 bool IsBitSetTolerant (size_t pos) const
00548 {
00549 if (pos >= mNumBits) return false;
00550 return (GetStore()[GetIndex(pos)]
00551 & (((csBitArrayStorageType)1) << GetOffset(pos))) != 0;
00552 }
00553
00555 bool AreSomeBitsSet (size_t pos, size_t count) const
00556 {
00557 CS_ASSERT (pos + count <= mNumBits);
00558 csBitArrayStorageType const* p = GetStore();
00559 while (count > 0)
00560 {
00561 size_t index = GetIndex (pos);
00562 size_t offset = GetOffset (pos);
00563 size_t checkCount = MIN(count, cellSize - offset);
00564 csBitArrayStorageType mask = ((checkCount == cellSize)
00565 ? ~(csBitArrayStorageType)0
00566 : ((((csBitArrayStorageType)1) << checkCount) - 1)) << offset;
00567 if (p[index] & mask)
00568 return true;
00569 pos += checkCount;
00570 count -= checkCount;
00571 }
00572 return false;
00573 }
00574
00576 bool AllBitsFalse() const
00577 {
00578 csBitArrayStorageType const* p = GetStore();
00579 for (size_t i = 0; i < mLength; i++)
00580 if (p[i] != 0)
00581 return false;
00582 return true;
00583 }
00584
00586 csBitArrayTweakable& FlipAllBits()
00587 {
00588 csBitArrayStorageType* p = GetStore();
00589 for (size_t i = 0; i < mLength; i++)
00590 p[i] = ~p[i];
00591 Trim();
00592 return *this;
00593 }
00594
00596 size_t NumBitsSet() const
00597 {
00598 const size_t ui32perStorage =
00599 sizeof (csBitArrayStorageType) / sizeof (uint32);
00600
00601 union
00602 {
00603 csBitArrayStorageType s;
00604 uint32 ui32[ui32perStorage];
00605 } v;
00606
00607 const csBitArrayStorageType* p = GetStore();
00608 size_t num = 0;
00609 for (size_t i = 0; i < mLength; i++)
00610 {
00611 v.s = p[i];
00612 for (size_t j = 0; j < ui32perStorage; j++)
00613 num += CS::Utility::BitOps::ComputeBitsSet (v.ui32[j]);
00614 }
00615
00616 return num;
00617 }
00618
00623 size_t GetFirstBitSet() const
00624 {
00625 const size_t ui32perStorage =
00626 sizeof (csBitArrayStorageType) / sizeof (uint32);
00627
00628 union
00629 {
00630 csBitArrayStorageType s;
00631 uint32 ui32[ui32perStorage];
00632 } v;
00633
00634 const csBitArrayStorageType* p = GetStore();
00635 size_t ofs = 0, result;
00636 for (size_t i = 0; i < mLength; i++)
00637 {
00638 v.s = p[i];
00639 for (size_t j = 0; j < ui32perStorage; j++)
00640 {
00641 if (CS::Utility::BitOps::ScanBitForward (v.ui32[j], result))
00642 {
00643 size_t r = ofs + result;
00644 if (r >= mNumBits) return csArrayItemNotFound;
00645 return r;
00646 }
00647 ofs += 32;
00648 }
00649 }
00650 return csArrayItemNotFound;
00651 }
00656 size_t GetFirstBitUnset() const
00657 {
00658 const size_t ui32perStorage =
00659 sizeof (csBitArrayStorageType) / sizeof (uint32);
00660
00661 union
00662 {
00663 csBitArrayStorageType s;
00664 uint32 ui32[ui32perStorage];
00665 } v;
00666
00667 const csBitArrayStorageType* p = GetStore();
00668 size_t ofs = 0;
00669 unsigned long result;
00670 for (size_t i = 0; i < mLength; i++)
00671 {
00672 v.s = p[i];
00673 for (size_t j = 0; j < ui32perStorage; j++)
00674 {
00675 if (CS::Utility::BitOps::ScanBitForward (~v.ui32[j], result))
00676 {
00677 size_t r = ofs + result;
00678 if (r >= mNumBits) return csArrayItemNotFound;
00679 return r;
00680 }
00681 ofs += 32;
00682 }
00683 }
00684 return csArrayItemNotFound;
00685 }
00690 size_t GetLastBitSet() const
00691 {
00692 const size_t ui32perStorage =
00693 sizeof (csBitArrayStorageType) / sizeof (uint32);
00694
00695 union
00696 {
00697 csBitArrayStorageType s;
00698 uint32 ui32[ui32perStorage];
00699 } v;
00700
00701 const csBitArrayStorageType* p = GetStore();
00702 size_t ofs, result;
00703 ofs = 32 * (mLength*ui32perStorage-1);
00704 for (size_t i = mLength; i-- > 0;)
00705 {
00706 v.s = p[i];
00707 for (size_t j = ui32perStorage; j-- > 0; )
00708 {
00709 if (CS::Utility::BitOps::ScanBitForward (v.ui32[j], result))
00710 {
00711 size_t r = ofs + result;
00712 if (r >= mNumBits) return csArrayItemNotFound;
00713 return r;
00714 }
00715 ofs -= 32;
00716 }
00717 }
00718 return csArrayItemNotFound;
00719 }
00724 size_t GetLastBitUnset() const
00725 {
00726 const size_t ui32perStorage =
00727 sizeof (csBitArrayStorageType) / sizeof (uint32);
00728
00729 union
00730 {
00731 csBitArrayStorageType s;
00732 uint32 ui32[ui32perStorage];
00733 } v;
00734
00735 const csBitArrayStorageType* p = GetStore();
00736 size_t ofs, result;
00737 ofs = 32 * (mLength*ui32perStorage-1);
00738 for (size_t i = mLength; i-- > 0;)
00739 {
00740 v.s = p[i];
00741 for (size_t j = ui32perStorage; j-- > 0; )
00742 {
00743 if (CS::Utility::BitOps::ScanBitForward (~v.ui32[j], result))
00744 {
00745 size_t r = ofs + result;
00746 if (r >= mNumBits) return csArrayItemNotFound;
00747 return r;
00748 }
00749 ofs -= 32;
00750 }
00751 }
00752 return csArrayItemNotFound;
00753 }
00754
00759 void Delete(size_t pos, size_t count)
00760 {
00761 if (count > 0)
00762 {
00763 size_t dst = pos;
00764 size_t src = pos + count;
00765 CS_ASSERT(src <= mNumBits);
00766 size_t ntail = mNumBits - src;
00767 while (ntail-- > 0)
00768 Set(dst++, IsBitSet(src++));
00769 SetSize(mNumBits - count);
00770 }
00771 }
00772
00777 csBitArrayTweakable Slice(size_t pos, size_t count) const
00778 {
00779 CS_ASSERT(pos + count <= mNumBits);
00780 csBitArrayTweakable a (count);
00781 for (size_t i = pos, o = 0; i < pos + count; i++)
00782 if (IsBitSet(i))
00783 a.SetBit(o++);
00784 return a;
00785 }
00786
00788
00789 csBitArrayStorageType* GetArrayBits() { return GetStore(); }
00790 const csBitArrayStorageType* GetArrayBits() const { return GetStore(); }
00792
00794
00797 class SetBitIterator
00798 {
00799 public:
00800 SetBitIterator (const SetBitIterator& other)
00801 : bitArray (other.bitArray), pos (other.pos), offset (other.offset),
00802 cachedStore (other.cachedStore)
00803 {}
00804
00806 size_t Next ()
00807 {
00808 while (offset < 8*sizeof(csBitArrayStorageType))
00809 {
00810 if ((cachedStore & 0x1) != 0)
00811 {
00812 const size_t result = (pos-1)*sizeof(csBitArrayStorageType)*8 + offset;
00813
00814 ++offset;
00815 cachedStore >>= 1;
00816 if (!cachedStore)
00817 GetNextCacheItem ();
00818
00819 return result;
00820 }
00821 else
00822 {
00823 ++offset;
00824 cachedStore >>= 1;
00825 if (!cachedStore)
00826 GetNextCacheItem ();
00827 }
00828 }
00829 CS_ASSERT_MSG ("Invalid iteration", false);
00830 return 0;
00831 }
00832
00834 bool HasNext () const
00835 {
00836 return cachedStore != 0;
00837 }
00838
00840 void Reset ()
00841 {
00842 pos = 0;
00843 GetNextCacheItem ();
00844 }
00845
00846 protected:
00847 SetBitIterator (const ThisType& bitArray)
00848 : bitArray (bitArray), pos (0), offset (0), cachedStore (0)
00849 {
00850 Reset ();
00851 }
00852
00853 friend class csBitArrayTweakable<InlinedBits, Allocator>;
00854
00855 void GetNextCacheItem ()
00856 {
00857 offset = 0;
00858 while (pos < bitArray.mLength)
00859 {
00860 cachedStore = bitArray.GetStore ()[pos++];
00861 if (cachedStore)
00862 return;
00863 }
00864 cachedStore = 0;
00865 }
00866
00867 const ThisType& bitArray;
00868 size_t pos, offset;
00869 csBitArrayStorageType cachedStore;
00870 };
00871 friend class SetBitIterator;
00872
00873 SetBitIterator GetSetBitIterator () const
00874 {
00875 return SetBitIterator (*this);
00876 }
00878
00887 uint8* Serialize (size_t& numBytes) const
00888 {
00889 if (mNumBits == 0)
00890 {
00891 numBytes = 0;
00892 return 0;
00893 }
00894
00895 struct SerializeHelper
00896 {
00897 uint8* buf;
00898 size_t bufSize, bufUsed;
00899
00900 SerializeHelper () : buf (0), bufSize (0), bufUsed (0) {}
00901 void PushByte (uint8 b)
00902 {
00903 if (bufUsed >= bufSize)
00904 {
00905 bufSize += 4;
00906 buf = (uint8*)cs_realloc (buf, bufSize);
00907 }
00908 buf[bufUsed++] = b;
00909 }
00910 void TruncZeroes ()
00911 {
00912 while ((bufUsed > 0) && (buf[bufUsed-1] == 0))
00913 bufUsed--;
00914 }
00915 } serHelper;
00916
00917
00918 {
00919 size_t remainder = mNumBits;
00920
00921 while (remainder >= 128)
00922 {
00923 uint8 b = (remainder & 0x7f) | 0x80;
00924 serHelper.PushByte (b);
00925 remainder >>= 7;
00926 }
00927 serHelper.PushByte (uint8 (remainder));
00928 }
00929
00930 const size_t ui8Count = sizeof (csBitArrayStorageType) / sizeof (uint8);
00931 uint8 ui8[ui8Count];
00932 csBitArrayStorageType const* p = GetStore();
00933 for (size_t i = 0; i < mLength; i++)
00934 {
00935 memcpy (ui8, &p[i], sizeof (ui8));
00936 #ifdef CS_LITTLE_ENDIAN
00937 for (size_t j = 0; j < ui8Count; j++)
00938 #else
00939 for (size_t j = ui8Count; j-- > 0; )
00940 #endif
00941 {
00942 serHelper.PushByte (ui8[j]);
00943 }
00944 }
00945
00946 serHelper.TruncZeroes();
00947 numBytes = serHelper.bufUsed;
00948 return serHelper.buf;
00949 }
00954 static ThisType Unserialize (uint8* bytes, size_t numBytes)
00955 {
00956 if ((bytes == 0) || (numBytes == 0))
00957 return ThisType();
00958
00959 size_t bufPos = 0;
00960
00961
00962 size_t numBits = 0;
00963 int shift = 0;
00964 while (bufPos < numBytes)
00965 {
00966 uint8 b = bytes[bufPos++];
00967 numBits |= (b & 0x7f) << shift;
00968 if ((b & 0x80) == 0) break;
00969 shift += 7;
00970 }
00971
00972 ThisType newArray (numBits);
00973
00974
00975 csBitArrayStorageType* p = newArray.GetStore();
00976 size_t storeIndex = 0;
00977 while (bufPos < numBytes)
00978 {
00979 const size_t ui8Count = sizeof (csBitArrayStorageType) / sizeof (uint8);
00980 uint8 ui8[ui8Count];
00981 memset (ui8, 0, sizeof (ui8));
00982 #ifdef CS_LITTLE_ENDIAN
00983 for (size_t j = 0; j < ui8Count; j++)
00984 #else
00985 for (size_t j = ui8Count; j-- > 0; )
00986 #endif
00987 {
00988 ui8[j] = bytes[bufPos++];
00989 if (bufPos >= numBytes) break;
00990 }
00991 memcpy (p + (storeIndex++), ui8, sizeof (ui8));
00992 }
00993
00994 return newArray;
00995 }
00997 };
00998
01003 class csBitArray : public csBitArrayTweakable<>
01004 {
01005 public:
01007 csBitArray () { }
01009 explicit csBitArray (size_t size) : csBitArrayTweakable<> (size) { }
01011 csBitArray (const csBitArray& that) : csBitArrayTweakable<> (that) { }
01012
01014 template<int A, typename B>
01015 csBitArray& operator=(const csBitArrayTweakable<A, B>& that)
01016 {
01017 if (this != &that)
01018 {
01019 SetSize (that.GetSize());
01020 memcpy (GetStore(), that.GetArrayBits(),
01021 mLength * sizeof (csBitArrayStorageType));
01022 }
01023 return *this;
01024 }
01025
01026 };
01027
01028
01033 template<>
01034 class csComparator<csBitArray, csBitArray> :
01035 public csComparatorBitArray<csBitArray> { };
01036
01037
01042 template<>
01043 class csHashComputer<csBitArray> :
01044 public csHashComputerBitArray<csBitArray> { };
01045
01046
01047 #endif // __CS_BITARRAY_H__