mi32/bitset.h

Go to the documentation of this file.
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

Generated on Thu Apr 26 04:44:52 2007 for TNTsdk by  doxygen 1.5.2