00001 /** 00002 * \file mi32/bitset.h 00003 * \brief Definitions for BITSET classes. 00004 * 00005 * This class is designed so that an access violation beyond 00006 * the array size results in a bit setting of 'false'. 00007 * 00008 * \if NODOC 00009 * $Id: bitset.h_v 1.60 2006/03/08 20:43:10 dwilliss Exp $ 00010 * 00011 * $Log: bitset.h_v $ 00012 * Revision 1.60 2006/03/08 20:43:10 dwilliss 00013 * missed a ctor 00014 * 00015 * Revision 1.59 2006/03/08 17:55:43 dwilliss 00016 * Make ctors non-inline to see if that will solve a problem I'm having. 00017 * Unfortunately, have to recompile everything to know for sure. 00018 * 00019 * Revision 1.58 2005/11/14 20:29:45 mju 00020 * Put most of implementations in misystem dll as many inlines were too large. 00021 * 00022 * Revision 1.57 2005/03/01 14:15:43 mju 00023 * Use 'value' in hasMultiple. 00024 * 00025 * Revision 1.56 2005/02/28 21:47:27 mju 00026 * Add HasValue, HasMultiple, CountValues. 00027 * 00028 * Revision 1.55 2004/02/24 18:50:44 mju 00029 * In unowned assign, check for null array. 00030 * 00031 * Revision 1.54 2004/02/04 15:02:16 scowan 00032 * Handle ctor with legacy bit array of null. 00033 * 00034 * Revision 1.53 2003/12/24 21:22:15 scowan 00035 * Fixed vc7 warning. 00036 * 00037 * Revision 1.52 2003/11/17 17:30:22 dwilliss 00038 * Gave the iterator a default constructor so you could declare it outside 00039 * a loop and assign it inside a loop. 00040 * 00041 * Revision 1.51 2003/10/01 22:10:50 dwilliss 00042 * *** empty log message *** 00043 * 00044 * Revision 1.50 2003/09/25 21:29:07 dwilliss 00045 * Don't capitalize enum any more. Genitor needed it, doxygen doesn't like it. 00046 * 00047 * Revision 1.49 2003/09/15 13:49:56 fileserver!dwilliss 00048 * Doxygen 00049 * 00050 * Revision 1.48 2003/06/24 15:59:05 mju 00051 * Add SET_OPERATION enum. 00052 * 00053 * Revision 1.47 2003/01/23 21:23:56 scowan 00054 * Fixed unsigned / signed comparison warnings. 00055 * 00056 * Revision 1.46 2003/01/23 18:23:10 scowan 00057 * Added private array methods to disallow array access to the bitset. 00058 * 00059 * Revision 1.45 2002/11/20 23:52:31 dwilliss 00060 * Fixed problem in SetRange/ClearRange if the whole range fell within a single 00061 * byte 00062 * 00063 * Revision 1.43 2002/09/12 21:27:59 mju 00064 * Alloc copy/assign of bitset_unowned. 00065 * 00066 * Revision 1.42 2002/08/19 15:01:10 scowan 00067 * Fixed g++3.1 warnings. 00068 * 00069 * Revision 1.41 2002/02/27 16:26:49 scowan 00070 * Fixed issues with get range. 00071 * 00072 * Revision 1.40 2002/02/26 15:03:01 scowan 00073 * Fixed stupid warning. 00074 * 00075 * Revision 1.39 2002/01/30 23:20:12 scowan 00076 * Fixed problems with GetRange. 00077 * 00078 * Revision 1.38 2002/01/29 21:37:32 scowan 00079 * Fixed infinite loop. 00080 * 00081 * Revision 1.37 2002/01/28 21:34:59 scowan 00082 * Added a Get Range method. 00083 * 00084 * Revision 1.36 2002/01/25 23:34:02 scowan 00085 * Added bitset shared class. 00086 * 00087 * Revision 1.35 2001/09/17 14:11:04 mju 00088 * Fix Set/ClearRange, was writing 1 byte too far. 00089 * 00090 * Revision 1.34 2001/08/13 15:05:45 scowan 00091 * Fixed ABR in operator++(). 00092 * 00093 * Revision 1.33 2000/11/28 21:15:00 scowan 00094 * Attach() and Detach() methods added. 00095 * 00096 * Revision 1.32 2000/10/05 16:57:23 mju 00097 * make bitset_unowned::begin/end const. 00098 * 00099 * Revision 1.31 2000/09/20 21:48:14 mju 00100 * In op++ check index past end before access. 00101 * 00102 * Revision 1.30 2000/07/20 20:33:49 mju 00103 * Fix SetRange() where end of range was < 8 would cause ABW. 00104 * 00105 * Revision 1.29 2000/07/10 19:34:20 mju 00106 * Fix Set/ClearRange(). 00107 * 00108 * Revision 1.28 2000/07/10 14:42:29 mju 00109 * Add Set/ClearRange methods. 00110 * 00111 * Revision 1.27 2000/06/20 14:15:35 mju 00112 * Fix bitwise operators comparison for same size. 00113 * 00114 * Revision 1.26 2000/06/19 17:32:31 scowan 00115 * *** empty log message *** 00116 * 00117 * Revision 1.25 2000/06/09 14:27:19 mju 00118 * Add BITSET copy ctor too so compiler doesn't generate an incorrect one. 00119 * 00120 * Revision 1.24 2000/06/09 14:25:23 mju 00121 * Add bitset assignment from BITSET as Unix compilers complain otherwise. 00122 * 00123 * Revision 1.23 2000/06/08 20:45:24 mju 00124 * Implement BITSET_UNOWNED so can use old-style bitarrays without copy. 00125 * Change to use UINT8* so can safely cast to old-style bit arrays. 00126 * Change iterator to allow iteration through 'false' entries too. 00127 * Rename Clear as ClearAll. 00128 * Rename FlipBit as Invert. 00129 * Add Set(entry), Clear(entry), and InvertAll. 00130 * Add bitwise operators between bit sets. 00131 * 00132 * Revision 1.21 2000/06/07 16:03:45 scowan 00133 * Fixed Begin(). 00134 * 00135 * Revision 1.20 2000/06/05 13:23:08 mju 00136 * Must define loop vars outside of loop if reference after end of loop. 00137 * 00138 * Revision 1.19 2000/06/02 22:53:34 scowan 00139 * Added new SETITERATOR nested class to iterate through set items. 00140 * 00141 * Revision 1.18 2000/05/31 22:10:45 mju 00142 * Don't include stdincls, include only those headers needed. 00143 * Use inclusion guards. 00144 * 00145 * \endif 00146 ***/ 00147 00148 #ifndef INC_MI32_BITSET_H 00149 #define INC_MI32_BITSET_H 00150 00151 #ifndef INC_MI32_STDDEFNS_H 00152 #include <mi32/stddefns.h> 00153 #endif 00154 00155 #ifndef INC_MEMORY_H 00156 #include <memory.h> // Includes defn for memset() 00157 #define INC_MEMORY_H 00158 #endif 00159 00160 00161 #ifdef MISYSTEMDLL 00162 #define CLASSLIBEXPORT MI_DLLCLASSEXPORT 00163 #else 00164 #define CLASSLIBEXPORT MI_DLLCLASSIMPORT 00165 #endif 00166 00167 00168 #ifndef GENERATING_DOXYGEN_OUTPUT 00169 class BITSET_SHARED; 00170 #endif // GENERATING_DOXYGEN_OUTPUT 00171 00172 00173 enum SET_OPERATION { 00174 SET_OPERATION_Null = 0, 00175 SET_OPERATION_Clear = 1, 00176 SET_OPERATION_Set = 2, 00177 SET_OPERATION_Negate = 3, 00178 SET_OPERATION_Copy = 4, 00179 SET_OPERATION_Union = 5, 00180 SET_OPERATION_Add = SET_OPERATION_Union, 00181 SET_OPERATION_Subtract = 6, 00182 SET_OPERATION_ExUnion = 7, 00183 SET_OPERATION_Intersection = 8, 00184 }; 00185 00186 00187 //===================================================================================================================== 00188 //! Base bit set class for case where actual array is "owned" by 00189 //! something other than the class. 00190 class CLASSLIBEXPORT BITSET_UNOWNED { 00191 00192 protected: //! Placed here so that ITERATOR class can have access to them 00193 UINT8 *m_Array; //!< Memory containing the bit array 00194 UINT32 m_NumEntries; //!< Actual number of bits used 00195 UINT32 m_ArraySize; //!< Array size in bytes 00196 00197 public: 00198 00199 class ITERATOR; 00200 friend class ITERATOR; 00201 00202 //! Iterator to step forward through all selected items in a BITSET. 00203 class CLASSLIBEXPORT ITERATOR { 00204 public: 00205 00206 //! Default constructor (leaves the bitset unattache). 00207 ITERATOR (); 00208 00209 //! Dereference operator, returns item number set. 00210 UINT32 operator* ( 00211 ) const { 00212 return (m_SetItemIndex); 00213 } 00214 00215 //! Cast operator to UINT32. 00216 operator UINT32 ( 00217 ) const { 00218 return (m_SetItemIndex); 00219 } 00220 00221 //! Pre-increment operator. 00222 ITERATOR& operator++ ( 00223 ); 00224 00225 //! Equality operator. 00226 bool operator== ( 00227 const ITERATOR& rhs 00228 ) const { 00229 return (m_BitSet == rhs.m_BitSet && (m_SetItemIndex == rhs.m_SetItemIndex || (m_SetItemIndex >= m_BitSet->m_NumEntries && rhs.m_SetItemIndex >= m_BitSet->m_NumEntries))); 00230 } 00231 00232 //! Inequality operator. 00233 bool operator!= ( 00234 const ITERATOR& rhs 00235 ) const { 00236 return (!(*this == rhs)); 00237 } 00238 00239 protected: 00240 #ifndef GENERATING_DOXYGEN_OUTPUT 00241 const BITSET_UNOWNED* GetBitSet () const { return m_BitSet; } 00242 #endif 00243 00244 private: 00245 #ifndef GENERATING_DOXYGEN_OUTPUT 00246 const BITSET_UNOWNED* m_BitSet; 00247 UINT32 m_SetItemIndex; 00248 UINT8 m_TestBit; 00249 UINT8 m_SkipByte; 00250 00251 // Construct for "begin". 00252 ITERATOR ( 00253 const BITSET_UNOWNED* BitSet, 00254 bool testvalue 00255 ); 00256 00257 // Construct for "end". 00258 ITERATOR ( 00259 const BITSET_UNOWNED* BitSet 00260 ) : 00261 m_BitSet(BitSet), 00262 m_SetItemIndex(BitSet->GetNumEntries()), 00263 m_TestBit(0), 00264 m_SkipByte(0) 00265 { 00266 } 00267 00268 friend class BITSET_UNOWNED; 00269 #endif // GENERATING_DOXYGEN_OUTPUT 00270 }; 00271 00272 00273 //! Default constructor. 00274 BITSET_UNOWNED ( 00275 ); 00276 00277 //! Constructor to convert old bit-array's into BITSET_UNOWNEDs. 00278 BITSET_UNOWNED ( 00279 UINT8 *set, //!< Old bit array set 00280 UINT32 NumEntries //!< Number of items in old bit array, not size in bytes 00281 ); 00282 00283 //! Destructor. 00284 virtual ~BITSET_UNOWNED ( 00285 ); 00286 00287 //! Conversion to old bit-array style for legacy code. 00288 operator UINT8* ( 00289 ) { 00290 return (m_Array); 00291 } 00292 00293 //! Conversion to old bit-array style for legacy code. 00294 operator const UINT8* ( 00295 ) const { 00296 return (m_Array); 00297 } 00298 00299 //! Bitwise AND. 00300 //! If the bit sets are not the same size the set will be unaltered. 00301 BITSET_UNOWNED& operator&= ( 00302 const BITSET_UNOWNED& rhs 00303 ); 00304 00305 //! Bitwise OR. 00306 //! If the bit sets are not the same size the set will be unaltered. 00307 BITSET_UNOWNED& operator|= ( 00308 const BITSET_UNOWNED& rhs 00309 ); 00310 00311 //! Bitwise XOR. 00312 //! If the bit sets are not the same size the set will be unaltered. 00313 BITSET_UNOWNED& operator^= ( 00314 const BITSET_UNOWNED& rhs 00315 ); 00316 00317 //! Assign from old type bit arrays. 00318 virtual ERRVALUE Assign ( 00319 UINT8 *set, //!< Pointer to old bit-array 00320 UINT32 NumEntries //!< Number of items in old bit array 00321 ); 00322 00323 //! Initialize iterator with first set or unset item in the bit set. 00324 //! Returns iterator to first set entry, otherwise the last+1 item if no matching item. 00325 ITERATOR Begin ( 00326 bool value = true //!< Value to iterate through 00327 ) const { 00328 return (ITERATOR(this, value)); 00329 } 00330 00331 //! Clear value at specified position. 00332 void Clear ( 00333 UINT32 posn 00334 ) { 00335 if (posn < m_NumEntries) { 00336 m_Array[posn/8] &= ~(1 << (posn & 7)); 00337 } 00338 return; 00339 } 00340 00341 //! Clear bit array with false. 00342 //! Makes all the entries in the bit set 'false'. 00343 void ClearAll ( 00344 ) { 00345 if (m_ArraySize > 0) memset(m_Array, 0, m_ArraySize); 00346 return; 00347 } 00348 00349 //! Set range of entries to "false". 00350 void ClearRange ( 00351 UINT32 min, 00352 UINT32 max 00353 ); 00354 00355 //! Transfer value from source to dest entry. 00356 //! Replaces putbit(set, DestPosn, getbit(set, SourcePosn)). 00357 void CopyBit ( 00358 UINT32 DestPosn, //!< where setting goes to 00359 UINT32 SourcePosn //!< where setting comes from 00360 ); 00361 00362 //! Count the values in the set. 00363 //! Iterates through the set, so should not be used in time-critical code. 00364 INT32 CountValues ( 00365 bool value = true 00366 ) const; 00367 00368 //! Initialize iterator with last+1 item in the bit set. 00369 //! Returns iterator to last+1 item 00370 ITERATOR End ( 00371 ) const { 00372 return (ITERATOR(this)); 00373 } 00374 00375 //! Retrieve value at the requested position, true or false. 00376 //! Returns 'false' if the position given is outside the range of the BITSET 00377 bool GetBit ( 00378 UINT32 posn //!< position where value is retrieved from 00379 ) const { 00380 if (posn >= m_NumEntries) return (false); 00381 return ((m_Array[posn/8] & (1 << (posn & 7))) != 0); 00382 } 00383 00384 //! Return the number of valid entries. 00385 UINT32 GetNumEntries ( 00386 ) const { 00387 return (m_NumEntries); 00388 } 00389 00390 //! Get a range of entries that are set continuously in the bitset 00391 //! @return 'True' if a true range, 'false' if a false range 00392 bool GetRange ( 00393 UINT32 StartPosn, //!< Staring position 00394 UINT32 MaxEnd, //!< Maximum ending position 00395 UINT32& EndPosn //!< Ending position (inclusive) RETURNED 00396 ) const; 00397 00398 //! Does bit set have any entries? 00399 bool HasEntries ( 00400 ) const { 00401 return (m_NumEntries > 0); 00402 } 00403 00404 //! Determine if has multiple entries with specified value. 00405 bool HasMultiple ( 00406 bool value 00407 ) const; 00408 00409 //! Determine if has at least one entry with specified value; 00410 bool HasValue ( 00411 bool value 00412 ) const { return (Begin(value) != End()); } 00413 00414 //! Invert value at specified position. 00415 void Invert ( 00416 UINT32 posn //!< Position to be inverted 00417 ) { 00418 if (posn >= m_NumEntries) return; 00419 m_Array[posn/8] ^= 1 << (posn & 7); 00420 return; 00421 } 00422 00423 //! Invert all entries in bit set. 00424 void InvertAll ( 00425 ); 00426 00427 //! Set range of entries to inverse 00428 void InvertRange ( 00429 UINT32 min, 00430 UINT32 max 00431 ); 00432 00433 //! Set a value at the requested position to "true". 00434 //! Does nothing if the position given is outside range. 00435 void Set ( 00436 UINT32 posn //!< Position to set 00437 ) { 00438 if (posn < m_NumEntries) { 00439 m_Array[posn/8] |= 1 << (posn & 7); 00440 } 00441 return; 00442 } 00443 00444 //! Set all entries to true, opposite of ClearAll(). 00445 //! Turn all bit positions to true. 00446 void SetAll ( 00447 ); 00448 00449 //! Set a value at the requested position, true or false. 00450 //! Does nothing if the position given is outside range. 00451 void SetBit ( 00452 UINT32 posn, //!< Position where value is set 00453 bool value //!< Value to be set at position 00454 ) { 00455 if (posn >= m_NumEntries) return; 00456 if (value) { 00457 m_Array[posn/8] |= 1 << (posn & 7); 00458 } 00459 else { 00460 m_Array[posn/8] &= ~(1 << (posn & 7)); 00461 } 00462 return; 00463 } 00464 00465 //! Set range of entries to "true". 00466 void SetRange ( 00467 UINT32 min, 00468 UINT32 max 00469 ); 00470 00471 private: 00472 #ifndef GENERATING_DOXYGEN_OUTPUT 00473 // Disallowed operations. 00474 const UINT8& operator[](int) const; 00475 UINT8& operator[](int); 00476 #endif // GENERATING_DOXYGEN_OUTPUT 00477 00478 }; 00479 00480 //===================================================================================================================== 00481 //! Bit set. 00482 class CLASSLIBEXPORT BITSET : public BITSET_UNOWNED { 00483 00484 public: 00485 00486 //! Default constructor. 00487 BITSET ( 00488 ); 00489 00490 //! Copy constructor. 00491 BITSET ( 00492 const BITSET& rhs 00493 ); 00494 00495 //! Construct from BITSET_UNOWNED. 00496 BITSET ( 00497 const BITSET_UNOWNED& rhs 00498 ); 00499 00500 //! Constructor to convert old bit-array's into BITSETs. 00501 BITSET ( 00502 UINT8 *set, //!< Old bit array set 00503 UINT32 NumEntries //!< Number of items in old bit array, not size in bytes 00504 ); 00505 00506 //! Destructor. 00507 virtual ~BITSET ( 00508 ); 00509 00510 //! Assignment from BITSET. 00511 BITSET& operator= ( 00512 const BITSET& rhs 00513 ); 00514 00515 //! Assignment from BITSET_UNOWNED. 00516 BITSET& operator= ( 00517 const BITSET_UNOWNED& rhs 00518 ); 00519 00520 //! Assign from old type bit arrays. 00521 virtual ERRVALUE Assign ( 00522 UINT8 *set, //!< Pointer to old bit-array 00523 UINT32 NumEntries //!< Number of items in old bit array 00524 ); 00525 00526 //! Attach a old bit array to the BITSET 00527 //! 00528 //! After passing a buffer to Attach(), the BITSET \b "owns" the 00529 //! buffer and will free it in its destructor. 00530 //! 00531 //! @param items Reference to a pointer to the other bit array. 00532 //! The reason it's a reference is that after recording the pointer, 00533 //! Attach() will set <i>your</i> pointer to 0. This will prevent you 00534 //! from accidently freeing a pointer you no longer own. If you want 00535 //! it back, call the Detach() method 00536 //! 00537 void Attach ( 00538 UINT8*& items, 00539 int numitems //!< Number of items in array 00540 ); 00541 00542 //! Detach the buffer from the BITSET 00543 //! This turns ownership of the buffer over to the caller, who is then 00544 //! responsibile for seeing that it gets disposed of. 00545 //! After calling Detach(), the BITSET will behave as if it had 00546 //! just been constructed. In other words, it will be a NULL pointer 00547 //! pointing to 0 items. 00548 //! This means that if you want to know how many items are in the 00549 //! array returned, you'd better find out @{before} you call Detach()! 00550 UINT8* Detach ( 00551 ); 00552 00553 //! Erase BITSET internals, same as calling destructor. 00554 void Free ( 00555 ); 00556 00557 //! Resize BITSET to a new number of entries. 00558 ERRVALUE Resize ( 00559 UINT32 NumEntries //!< Number of elements to resize to 00560 ); 00561 00562 private: 00563 #ifndef GENERATING_DOXYGEN_OUTPUT 00564 friend class BITSET_SHARED; 00565 #endif // GENERATING_DOXYGEN_OUTPUT 00566 }; 00567 00568 00569 //===================================================================================================================== 00570 //! Shared Bit set. 00571 class CLASSLIBEXPORT BITSET_SHARED : public BITSET_UNOWNED { 00572 00573 private: 00574 #ifndef GENERATING_DOXYGEN_OUTPUT 00575 struct BITSET_COUNT { 00576 mutable UINT32 m_RefCount; 00577 BITSET m_Bitset; 00578 BITSET_COUNT () : m_RefCount(1) {} 00579 BITSET_COUNT (const BITSET_UNOWNED& rhs) : m_RefCount(1), m_Bitset(rhs) {} 00580 BITSET_COUNT (UINT8 *set, UINT32 NumEntries) : m_RefCount(1), m_Bitset(set, NumEntries) {} 00581 ERRVALUE Resize (UINT32 NumEntries) {return (m_Bitset.Resize(NumEntries));} 00582 }; 00583 00584 BITSET_COUNT* m_SharedBitset; 00585 #endif // GENERATING_DOXYGEN_OUTPUT 00586 00587 public: 00588 00589 //! Default constructor. 00590 BITSET_SHARED ( 00591 ); 00592 00593 //! Copy constructor. 00594 BITSET_SHARED ( 00595 const BITSET_SHARED& rhs 00596 ); 00597 00598 //! Construct from BITSET_UNOWNED. 00599 BITSET_SHARED ( 00600 const BITSET_UNOWNED& rhs 00601 ); 00602 00603 //! Constructor to convert old bit-array's into BITSETs. 00604 BITSET_SHARED ( 00605 UINT8 *set, //!< Old bit array set 00606 UINT32 NumEntries //!< Number of items in old bit array, not size in bytes 00607 ); 00608 00609 //! Destructor. 00610 virtual ~BITSET_SHARED ( 00611 ); 00612 00613 //! Assignment from BITSET_SHARED. 00614 BITSET_SHARED& operator= ( 00615 const BITSET_SHARED& rhs 00616 ); 00617 00618 //! Assignment from BITSET_UNOWNED. 00619 BITSET_SHARED& operator= ( 00620 const BITSET_UNOWNED& rhs 00621 ); 00622 00623 //! Assign from old type bit arrays. 00624 virtual ERRVALUE Assign ( 00625 UINT8 *set, //!< Pointer to old bit-array 00626 UINT32 NumEntries //!< Number of items in old bit array 00627 ); 00628 00629 //! Attach a old bit array to the BITSET 00630 //! 00631 //! After passing a buffer to Attach(), the BITSET @b "owns" the 00632 //! buffer and will free it in its destructor. 00633 //! 00634 //! @param items Reference to a pointer to the other bit array. 00635 //! The reason it's a reference is that after recording the pointer, 00636 //! Attach() will set <i>your</i> pointer to 0. This will prevent you 00637 //! from accidently freeing a pointer you no longer own. If you want 00638 //! it back, call the Detach() method 00639 //! 00640 void Attach ( 00641 UINT8*& items, 00642 int numitems //!< Number of items in array 00643 ); 00644 00645 // Detach() method cannot work here!! 00646 00647 //! Erase BITSET internals, same as calling destructor. 00648 void Free ( 00649 ); 00650 00651 //! Resize BITSET_SHARED to a new number of entries. 00652 ERRVALUE Resize ( 00653 UINT32 NumEntries //!< Number of elements to resize to 00654 ); 00655 00656 private: 00657 #ifndef GENERATING_DOXYGEN_OUTPUT 00658 void AttachPointers (); 00659 void DecrementCount (); 00660 #endif // GENERATING_DOXYGEN_OUTPUT 00661 00662 }; 00663 00664 //===================================================================================================================== 00665 00666 #undef CLASSLIBEXPORT 00667 00668 #endif // INC_MI32_BITSET_H
1.5.2