Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

477 lines
7.9 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. bitarray.cxx
  6. Abstract:
  7. Common utils.
  8. Author:
  9. Steve Kiraly (SteveKi) 01-12-97
  10. Revision History:
  11. --*/
  12. #include "spllibp.hxx"
  13. #pragma hdrstop
  14. /********************************************************************
  15. Bit Array class
  16. ********************************************************************/
  17. TBitArray::
  18. TBitArray(
  19. IN UINT nBits,
  20. IN UINT uGrowSize
  21. ) : _nBits( nBits ),
  22. _pBits( NULL ),
  23. _uGrowSize( uGrowSize )
  24. {
  25. DBGMSG( DBG_TRACE, ( "TBitArray::ctor\n" ) );
  26. //
  27. // If the initial number of bits is not specified then
  28. // create a default bit array size.
  29. //
  30. if( !_nBits )
  31. {
  32. _nBits = kBitsInType;
  33. }
  34. //
  35. // This could fail, thus leaving the bit array
  36. // in an invalid state, Note _pBits being true is
  37. // the bValid check.
  38. //
  39. _pBits = new Type [ nBitsToType( _nBits ) ];
  40. if( _pBits )
  41. {
  42. //
  43. // The grow size should be at least the
  44. // number of bits in the type.
  45. //
  46. if( _uGrowSize < kBitsInType )
  47. {
  48. _uGrowSize = kBitsInType;
  49. }
  50. //
  51. // Clear all the bits.
  52. //
  53. memset( _pBits, 0, nBitsToType( _nBits ) * sizeof( Type ) );
  54. }
  55. }
  56. TBitArray::
  57. TBitArray(
  58. const TBitArray &rhs
  59. ) : _nBits( kBitsInType ),
  60. _pBits( NULL )
  61. {
  62. DBGMSG( DBG_TRACE, ( "TBitArray::copy_ctor\n" ) );
  63. bClone( rhs );
  64. }
  65. const TBitArray &
  66. TBitArray::
  67. operator =(
  68. const TBitArray &rhs
  69. )
  70. {
  71. DBGMSG( DBG_TRACE, ( "TBitArray::operator =\n" ) );
  72. bClone( rhs );
  73. return *this;
  74. }
  75. TBitArray::
  76. ~TBitArray(
  77. VOID
  78. )
  79. {
  80. DBGMSG( DBG_TRACE, ( "TBitArray::dtor\n" ) );
  81. delete [] _pBits;
  82. }
  83. BOOL
  84. TBitArray::
  85. bValid(
  86. VOID
  87. ) const
  88. {
  89. return _pBits != NULL;
  90. }
  91. BOOL
  92. TBitArray::
  93. bToString(
  94. IN TString &strBits
  95. ) const
  96. {
  97. BOOL bStatus = bValid();
  98. if( bStatus )
  99. {
  100. TString strString;
  101. strBits.bUpdate( NULL );
  102. //
  103. // Get the upper bound bit.
  104. //
  105. UINT uIndex = _nBits - 1;
  106. //
  107. // Print the array in reverse order to make the bit array
  108. // appear as one large binary number.
  109. //
  110. for( UINT i = 0; i < _nBits; i++, uIndex-- )
  111. {
  112. strString.bFormat( TEXT( "%d" ), bRead( uIndex ) );
  113. strBits.bCat( strString );
  114. }
  115. bStatus = strBits.bValid();
  116. }
  117. return bStatus;
  118. }
  119. BOOL
  120. TBitArray::
  121. bRead(
  122. IN UINT Bit
  123. ) const
  124. {
  125. BOOL bStatus = bIsValidBit( Bit );
  126. if( bStatus )
  127. {
  128. bStatus = _pBits[BitToIndex( Bit )] & BitToMask( Bit ) ? TRUE : FALSE;
  129. }
  130. return bStatus;
  131. }
  132. BOOL
  133. TBitArray::
  134. bSet(
  135. IN UINT Bit
  136. )
  137. {
  138. BOOL bStatus = bIsValidBit( Bit );
  139. if( bStatus )
  140. {
  141. _pBits[BitToIndex( Bit )] |= BitToMask( Bit );
  142. }
  143. return bStatus;
  144. }
  145. BOOL
  146. TBitArray::
  147. bReset(
  148. IN UINT Bit
  149. )
  150. {
  151. BOOL bStatus = bIsValidBit( Bit );
  152. if( bStatus )
  153. {
  154. _pBits[BitToIndex( Bit )] &= ~BitToMask( Bit );
  155. }
  156. return bStatus;
  157. }
  158. BOOL
  159. TBitArray::
  160. bToggle(
  161. IN UINT Bit
  162. )
  163. {
  164. BOOL bStatus = bIsValidBit( Bit );
  165. if( bStatus )
  166. {
  167. _pBits[BitToIndex( Bit )] ^= BitToMask( Bit );
  168. }
  169. return bStatus;
  170. }
  171. //
  172. // Add one new bit to the end of the bit array.
  173. // If multiple bits need to be added the user of the
  174. // class should call this routine repeatedly.
  175. //
  176. BOOL
  177. TBitArray::
  178. bAdd(
  179. VOID
  180. )
  181. {
  182. BOOL bStatus = FALSE;
  183. UINT Bit = _nBits + 1;
  184. //
  185. // Check if there is room in the array for one more bit.
  186. //
  187. if( Bit <= nBitsToType( _nBits ) * kBitsInType )
  188. {
  189. //
  190. // Update the current bit count and return true.
  191. //
  192. _nBits = Bit;
  193. bStatus = TRUE;
  194. }
  195. else
  196. {
  197. //
  198. // Grow the bit array.
  199. //
  200. bStatus = bGrow( Bit );
  201. }
  202. return bStatus;
  203. }
  204. VOID
  205. TBitArray::
  206. vSetAll(
  207. VOID
  208. )
  209. {
  210. for( UINT i = 0; i < _nBits; i++ )
  211. {
  212. bSet( i );
  213. }
  214. }
  215. VOID
  216. TBitArray::
  217. vResetAll(
  218. VOID
  219. )
  220. {
  221. for( UINT i = 0; i < _nBits; i++ )
  222. {
  223. bReset( i );
  224. }
  225. }
  226. UINT
  227. TBitArray::
  228. uNumBits(
  229. VOID
  230. ) const
  231. {
  232. return _nBits;
  233. }
  234. BOOL
  235. TBitArray::
  236. bFindNextResetBit(
  237. IN UINT *puNextFreeBit
  238. )
  239. {
  240. BOOL bStatus = bValid();
  241. if( bStatus )
  242. {
  243. BOOL bFound = FALSE;
  244. //
  245. // Locate the first type that contains at least one cleared bit.
  246. //
  247. for( UINT i = 0; i < nBitsToType( _nBits ); i++ )
  248. {
  249. if( _pBits[i] != kBitsInTypeMask )
  250. {
  251. //
  252. // Search for the bit that is cleared.
  253. //
  254. for( UINT j = 0; j < kBitsInType; j++ )
  255. {
  256. if( !( _pBits[i] & BitToMask( j ) ) )
  257. {
  258. *puNextFreeBit = i * kBitsInType + j;
  259. bFound = TRUE;
  260. break;
  261. }
  262. }
  263. }
  264. //
  265. // Free bit found terminate the search.
  266. //
  267. if( bFound )
  268. {
  269. break;
  270. }
  271. }
  272. //
  273. // Free bit was not found then grow the bit array
  274. //
  275. if( !bFound )
  276. {
  277. //
  278. // Assume a new bit will be added.
  279. //
  280. *puNextFreeBit = uNumBits();
  281. //
  282. // Add a new bit.
  283. //
  284. bStatus = bAdd();
  285. }
  286. }
  287. return bStatus;
  288. }
  289. /********************************************************************
  290. Bit Array - private member functions.
  291. ********************************************************************/
  292. BOOL
  293. TBitArray::
  294. bClone(
  295. const TBitArray &rhs
  296. )
  297. {
  298. BOOL bStatus = FALSE;
  299. if( this == &rhs )
  300. {
  301. bStatus = TRUE;
  302. }
  303. else
  304. {
  305. Type *pTempBits = new Type [ nBitsToType( _nBits ) ];
  306. if( pTempBits )
  307. {
  308. memcpy( pTempBits, rhs._pBits, nBitsToType( _nBits ) * sizeof( Type ) );
  309. delete [] _pBits;
  310. _pBits = pTempBits;
  311. _nBits = rhs._nBits;
  312. bStatus = TRUE;
  313. }
  314. }
  315. return bStatus;
  316. }
  317. BOOL
  318. TBitArray::
  319. bGrow(
  320. IN UINT uBits
  321. )
  322. {
  323. DBGMSG( DBG_TRACE, ( "TBitArray::bGrow\n" ) );
  324. BOOL bStatus = FALSE;
  325. UINT uNewBits = uBits + _uGrowSize;
  326. DBGMSG( DBG_TRACE, ( "Grow to size %d Original size %d Buffer pointer %x\n", uNewBits, _nBits, _pBits ) );
  327. //
  328. // We do support reducing the size of the bit array.
  329. //
  330. SPLASSERT( uNewBits > _nBits );
  331. //
  332. // Allocate the enlarged bit array.
  333. //
  334. Type *pNewBits = new Type [ nBitsToType( uNewBits ) ];
  335. if( pNewBits )
  336. {
  337. //
  338. // Clear the new bits.
  339. //
  340. memset( pNewBits, 0, nBitsToType( uNewBits ) * sizeof( Type ) );
  341. //
  342. // Copy the old bits to the new bit array.
  343. //
  344. memcpy( pNewBits, _pBits, nBitsToType( _nBits ) * sizeof( Type ) );
  345. //
  346. // Release the old bit array and save the new pointer and size.
  347. //
  348. delete [] _pBits;
  349. _pBits = pNewBits;
  350. _nBits = uBits;
  351. //
  352. // Success.
  353. //
  354. bStatus = TRUE;
  355. }
  356. DBGMSG( DBG_TRACE, ( "New size %d Buffer pointer %x\n", _nBits, _pBits ) );
  357. return bStatus;
  358. }
  359. UINT
  360. TBitArray::
  361. nBitsToType(
  362. IN UINT uBits
  363. ) const
  364. {
  365. return ( uBits + kBitsInType - 1 ) / kBitsInType;
  366. }
  367. TBitArray::Type
  368. TBitArray::
  369. BitToMask(
  370. IN UINT uBit
  371. ) const
  372. {
  373. return 1 << ( uBit % kBitsInType );
  374. }
  375. UINT
  376. TBitArray::
  377. BitToIndex(
  378. IN UINT uBit
  379. ) const
  380. {
  381. return uBit / kBitsInType;
  382. }
  383. BOOL
  384. TBitArray::
  385. bIsValidBit(
  386. IN UINT uBit
  387. ) const
  388. {
  389. BOOL bStatus = ( uBit < _nBits ) && bValid();
  390. if( !bStatus )
  391. {
  392. DBGMSG( DBG_TRACE, ( "Invalid bit value %d\n", uBit ) );
  393. }
  394. return bStatus;
  395. }