mi32/simplear.h

Go to the documentation of this file.
00001 /**
00002  * \file simplear.h <mi32/simplear.h>
00003  * \brief Definitions for SIMPLE_ARRAY template
00004  *
00005  * \if NODOC
00006  * $Id: simplear.h_v 1.52 2007/04/20 22:30:21 dfriberg Exp $
00007  *
00008  * $Log: simplear.h_v $
00009  * Revision 1.52  2007/04/20 22:30:21  dfriberg
00010  * Set num items to 0 in destructor
00011  *
00012  * Revision 1.51  2006/12/04 18:33:49  mju
00013  * Use string hdr for memmove.
00014  *
00015  * Revision 1.50  2006/08/17 20:48:04  scowan
00016  * Copy ctor will now set the items ptr to null before copy.
00017  *
00018  * Revision 1.49  2006/07/27 14:16:16  mju
00019  * Support reference counting.
00020  *
00021  * Revision 1.48  2006/05/25 16:51:15  dwilliss
00022  * Gave Locate an optional parameter to return -1 if not found.  Defaults
00023  * to previous behaviour which is to return the position one before where
00024  * it would be if not found
00025  *
00026  * Revision 1.47  2006/01/26 15:48:18  mju
00027  * Use template method for array operators so not ambiguous.
00028  *
00029  * Revision 1.46  2005/07/14 17:38:16  mju
00030  * Hdr changes.
00031  *
00032  * Revision 1.45  2005/05/19 16:55:34  mju
00033  * Add sortRange.
00034  *
00035  * Revision 1.44  2004/04/16 21:50:03  scowan
00036  * Added locate method.
00037  *
00038  * Revision 1.43  2004/04/01 21:33:44  mju
00039  * Add GetLast and RemoveLast methods.
00040  *
00041  * Revision 1.42  2003/09/22 19:09:40  dwilliss
00042  * Version of array index operator that takes long for SUN64 to avoid gcc
00043  * error
00044  *
00045  * Revision 1.41  2003/09/15 13:49:56  fileserver!dwilliss
00046  * Doxygen
00047  *
00048  * Revision 1.40  2003/07/28 13:41:45  mju
00049  * Remove deprecated methods.
00050  *
00051  * Revision 1.39  2003/07/25 20:58:42  mju
00052  * Add Assign() method, deprecate old SetItems().
00053  * Add SetItems variant which does not shrink array.
00054  *
00055  * Revision 1.38  2003/06/24 21:47:30  scowan
00056  * Compiler optimization error also in remove fast method.
00057  *
00058  * Revision 1.37  2003/06/18 14:27:26  mju
00059  * Fix compiler optimization bug in RemoveItem by decrement numitems before memmove.
00060  *
00061  * Revision 1.36  2003/06/17 21:49:27  mju
00062  * *** empty log message ***
00063  *
00064  * Revision 1.35  2003/04/09 19:12:52  dwilliss
00065  * Don't use _T in templates.  Mac's ctype defines a global _T
00066  *
00067  * Revision 1.34  2002/10/03 16:49:19  mju
00068  * Remove allocincrement stuff and deprecate method to set.
00069  *
00070  * Revision 1.33  2002/09/30 17:32:57  mju
00071  * Remove redundant swapitems methods as is equivalent to Reverse().
00072  *
00073  * Revision 1.32  2002/09/12 14:54:24  scowan
00074  * Added has item method.
00075  *
00076  * Revision 1.31  2002/07/05 21:53:53  scowan
00077  * resize memset in case _CT is an object with deprecated memset stuff.
00078  *
00079  * Revision 1.30  2002/06/20 15:51:51  scowan
00080  * Prevent ABR.
00081  *
00082  * Revision 1.29  2002/04/02 18:24:29  mju
00083  * Add IsEmpty() method.
00084  * Clarify what will be cleared when 'clear' set to true in Resize().
00085  *
00086  * Revision 1.27  2001/12/18 17:40:31  scowan
00087  * Set allocincrement in constructors.
00088  *
00089  * Revision 1.26  2001/10/30 16:52:50  dwilliss
00090  * Documented what the CompFunc for Sort() is expected to return
00091  *
00092  * Revision 1.25  2001/09/07 17:15:22  scowan
00093  * Change sort compare function to return int.
00094  *
00095  * Revision 1.24  2001/05/24 20:50:34  scowan
00096  * Adjuect some method names.
00097  *
00098  * Revision 1.23  2001/05/24 18:00:09  scowan
00099  * Added multiple helper methods.
00100  *
00101  * Revision 1.22  2001/02/06 17:35:26  mju
00102  * Add ReserveExc and AppendExc methods.
00103  *
00104  * Revision 1.21  2001/01/30 15:01:10  mju
00105  * Add Get/SetItem methods as array/cast operators confused if array type is pointer.
00106  *
00107  * Revision 1.20  2000/12/04 16:31:25  mju
00108  * Fix genitor 'end ignore' tag.
00109  *
00110  * Revision 1.19  2000/10/13 16:45:07  dwilliss
00111  * Added array operater overloads taking long on Mac only to avoid stupid
00112  * ambiguous function overload error
00113  *
00114  * Revision 1.18  2000/08/23 15:53:16  scowan
00115  * Do an bouns check on Clear Items().
00116  *
00117  * Revision 1.17  2000/08/18 14:41:03  scowan
00118  * Removed additional array operators because the other platforms went Huh!?!?
00119  * Stupid VC6.0.
00120  *
00121  * Revision 1.16  2000/08/17 16:01:00  scowan
00122  * Added unsigned int versions of array operator methods, was causeing a
00123  * strange error to occur if an unsigned int was used to access a simple array
00124  * entry.
00125  *
00126  * Revision 1.15  2000/08/09 13:46:54  mju
00127  * Add Append() methods using C-style array and SIMPLE_ARRAY.
00128  *
00129  * Revision 1.14  2000/08/02 21:43:38  mju
00130  * Change Resize() to only clear new entries if keepold 'true'.
00131  *
00132  * Revision 1.13  2000/08/01 14:04:54  dwilliss
00133  * Added a Copy() method.
00134  * Fixed error in methods taking/returning SIMPLE_ARRAY.  Needs to specify
00135  *   the template type.
00136  *
00137  * Revision 1.12  2000/07/27 17:18:14  mju
00138  * Retire SetNumItems().
00139  *
00140  * Revision 1.11  2000/07/27 15:40:36  dwilliss
00141  * Wrote Attach()/Detach() methods
00142  *
00143  * Revision 1.10  2000/07/26 16:08:36  dwilliss
00144  * Fixed compile error in Free()
00145  *
00146  * Revision 1.9  2000/07/21 22:25:36  scowan
00147  * Added Free() method
00148  *
00149  * Revision 1.8  2000/07/18 20:56:57  mju
00150  * Add Resize() and deprecate SetNumItems().
00151  *
00152  * Revision 1.7  2000/06/22 14:52:55  mju
00153  * Fix ClearItems to not clear past ending item.
00154  *
00155  * Revision 1.5  2000/06/21 16:39:24  scowan
00156  * Set items must return a value error fix.
00157  *
00158  * Revision 1.3  2000/06/21 15:23:31  scowan
00159  * Added swap bytes method.
00160  *
00161  * Revision 1.2  2000/05/11 20:33:22  mju
00162  * Change GetSizeInBytes to return required size, not allocated size.
00163  * Add Swap() method.
00164  *
00165  * Revision 1.1  2000/05/10 13:26:15  mju
00166  * Initial revision
00167  *
00168  * \endif
00169 **/
00170 
00171 #ifndef  INC_MI32_SIMPLEAR_H
00172 #define  INC_MI32_SIMPLEAR_H
00173 
00174 #ifndef  INC_MI32_MEMALLOC_H
00175 #include <mi32/memalloc.h>    // For MmAlloc/Realloc/Free defns
00176 #endif
00177 
00178 #ifndef  INC_MI32_SORT_H
00179 #include <mi32/sort.h>
00180 #endif
00181 
00182 #ifndef  INC_MI32_MEMBUF_H
00183 #include <mi32/membuf.h>      // For SwapBytes() defn
00184 #endif
00185 
00186 #ifndef  INC_MEMORY_H
00187 #include <memory.h>           // memcpy()
00188 #define  INC_MEMORY_H
00189 #endif
00190 
00191 #ifndef  INC_STRING_H
00192 #include <string.h>           // memmove
00193 #define  INC_STRING_H
00194 #endif
00195 
00196 //! Simple array template.
00197 //!
00198 //! This template is designed to contain an array of items which can be allocated
00199 //! using MmAlloc/MmRealloc.  The primary purpose of this template is to replace
00200 //! allocated arrays where direct access to both array elements and the ability
00201 //! to access a pointer to the first element (as for a C array) is required.
00202 //! Do not use this template with classes which require constructors or have
00203 //! virtual methods or which do not have compiler-generated assignment operators.
00204 //!
00205 //! For maximum efficiency, only minimal validation of access to array elements is performed.
00206 //! No initialization of array items is performed by the template.
00207 //!
00208 //! For doubles and objects based on doubles, use DOUBLE_ARRAY<> in mi32/doublear.h
00209 //!
00210 //! Instances of this class are passed to DLLs, so do not add or remove members.
00211 
00212 template <class _CT> class SIMPLE_ARRAY {
00213    public:
00214 
00215       //! Default constructor, creates empty array.
00216       SIMPLE_ARRAY (
00217          ):
00218          m_items(0),
00219          m_numitems(0),
00220          m_numalloc(0),
00221          m_RefCount(1)
00222          { }
00223 
00224       //! Copy constructor.
00225       SIMPLE_ARRAY (
00226          const SIMPLE_ARRAY<_CT>& rhs
00227          ):
00228          m_items(0),       //!< If rhs.m_numalloc == 0, then we will not get an invalid pointer
00229          m_RefCount(1)
00230          {
00231          MmAllocExc((void**)&m_items,rhs.m_numalloc*sizeof(_CT));
00232          m_numalloc = rhs.m_numalloc;
00233          memcpy(m_items,rhs.m_items,rhs.m_numitems*sizeof(_CT));
00234          m_numitems = rhs.m_numitems;
00235          }
00236 
00237       //! Destructor.
00238       ~SIMPLE_ARRAY (
00239          ) {
00240          if (m_items != 0) {
00241             free(m_items);
00242             m_numitems = 0;
00243             }
00244          }
00245 
00246       //! Assignment.
00247       SIMPLE_ARRAY<_CT>& operator= (
00248          const SIMPLE_ARRAY<_CT>& rhs
00249          ) {
00250          if (this != &rhs) {
00251             if (m_numalloc < rhs.m_numalloc) {
00252                //! Free the old array instead of using realloc to avoid expensive copy.
00253                MmFree(m_items);
00254                MmAllocExc((void**)&m_items,rhs.m_numalloc*sizeof(_CT));
00255                m_numalloc = rhs.m_numalloc;
00256                }
00257             memcpy(m_items,rhs.m_items,rhs.m_numitems*sizeof(_CT));
00258             m_numitems = rhs.m_numitems;
00259             }
00260          return (*this);
00261          }
00262 
00263       //! Equality operator.
00264       bool operator== (
00265          const SIMPLE_ARRAY<_CT>& rhs
00266          ) const {
00267          if (m_numitems != rhs.m_numitems) return (false);
00268          if (m_numitems == 0) return (true);
00269          return (memcmp(m_items,rhs.m_items,m_numitems*sizeof(_CT)) == 0);
00270          }
00271 
00272       //! Inequality operator.
00273       bool operator!= (
00274          const SIMPLE_ARRAY<_CT>& rhs
00275          ) const {
00276          return (!operator==(rhs));
00277          }
00278 
00279       //! Cast to const array of template type.
00280       operator const _CT*(
00281          ) const {
00282          return (m_items);
00283          }
00284 
00285       //! Cast to array of template type.
00286       operator _CT*(
00287          ) {
00288          return (m_items);
00289          }
00290 
00291       //! Read (const) access to array element.
00292       //!
00293       //! @note Does not verify that index is within valid range.
00294       template <typename _IDXTYPE> const _CT& operator[] (
00295          _IDXTYPE index
00296          ) const {
00297          return (m_items[index]);
00298          }
00299 
00300       //! Write (non-const) access to array element.
00301       //!
00302       //! @note Does not verify that index is within valid range.
00303       template <typename _IDXTYPE> _CT& operator[] (
00304          _IDXTYPE index
00305          ) {
00306          return (m_items[index]);
00307          }
00308 
00309       //! Increment reference count.
00310       void AddRef (
00311          ) { ++m_RefCount; }
00312 
00313       //! Append item to end of array, extending if necessary.
00314       ERRVALUE Append (
00315          const _CT& item
00316          ) {
00317          if (m_numitems >= m_numalloc) {
00318             int err;
00319             if ((err = Reserve(MAX(16,2*m_numitems))) < 0) return (err);
00320             }
00321          m_items[m_numitems++] = item;
00322          return (0);
00323          }
00324 
00325       //! Append items from C array, reserving space if needed.
00326       ERRVALUE Append (
00327          const _CT *items,                //!< Items to append
00328          int numitems                     //!< Number of items to append
00329          ) {
00330          int err;
00331          if ((err = Reserve(m_numitems+numitems)) < 0) return (err);
00332          memcpy(m_items+m_numitems,items,numitems*sizeof(_CT));
00333          m_numitems += numitems;
00334          return (0);
00335          }
00336 
00337       //! Append items from SIMPLE_ARRAY reserving space if needed.
00338       ERRVALUE Append (
00339          const SIMPLE_ARRAY<_CT>& rhs
00340          ) {
00341          int err;
00342          if ((err = Reserve(m_numitems+rhs.m_numitems)) < 0) return (err);
00343          memcpy(m_items+m_numitems,rhs.m_items,rhs.m_numitems*sizeof(_CT));
00344          m_numitems += rhs.m_numitems;
00345          return (0);
00346          }
00347 
00348       //! Append item to end of array, extending if necessary.
00349       //! Throws exception if out of memory.
00350       void AppendExc (
00351          const _CT& item
00352          ) {
00353          if (m_numitems >= m_numalloc) {
00354             ReserveExc(MAX(16,2*m_numitems));
00355             }
00356          m_items[m_numitems++] = item;
00357          return;
00358          }
00359 
00360       //! Append items from C array, reserving space if needed.
00361       //! Throws exception if out of memory.
00362       void AppendExc (
00363          const _CT *items,                //!< Items to append
00364          int numitems                     //!< Number of items to append
00365          ) {
00366          ReserveExc(m_numitems+numitems);
00367          memcpy(m_items+m_numitems,items,numitems*sizeof(_CT));
00368          m_numitems += numitems;
00369          return;
00370          }
00371 
00372       //! Append items from SIMPLE_ARRAY reserving space if needed.
00373       //! Throws exception if out of memory.
00374       void AppendExc (
00375          const SIMPLE_ARRAY<_CT>& rhs
00376          ) {
00377          ReserveExc(m_numitems+rhs.m_numitems);
00378          memcpy(m_items+m_numitems,rhs.m_items,rhs.m_numitems*sizeof(_CT));
00379          m_numitems += rhs.m_numitems;
00380          return;
00381          }
00382 
00383       //! Append item to end of array if unique, extending if necessary.
00384       ERRVALUE AppendUnique (
00385          const _CT& item
00386          ) {
00387          INT32 j;
00388          for (j = 0;(j < m_numitems);++j) {
00389             if (m_items[j] == item) break;
00390             }
00391          return ((j == m_numitems) ? Append(item) : 0);
00392          }
00393 
00394       //! Append item to end of array if unique, extending if necessary.
00395       //! Throws exception if out of memory.
00396       void AppendUniqueExc (
00397          const _CT& item
00398          ) {
00399          INT32 j;
00400          for (j = 0;(j < m_numitems);++j) {
00401             if (m_items[j] == item) break;
00402             }
00403          if (j == m_numitems) AppendExc(item);
00404          return;
00405          }
00406 
00407       //! Assign from C array, reserving space if needed.
00408       //! Resizes the array to the specified number of items.
00409       ERRVALUE Assign (
00410          const _CT *items,                //!< Items to copy to array
00411          int numitems                     //!< Number of items to copy
00412          ) {
00413          int err;
00414          if ((err = Reserve(numitems)) < 0) return (err);
00415          memcpy(m_items,items,numitems*sizeof(_CT));
00416          m_numitems = numitems;
00417          return (0);
00418          }
00419 
00420       //! Attach a buffer to the SIMPLE_ARRAY.
00421       //! After passing a buffer to Attach(), the SIMPLE_ARRAY "<b>owns</b>" the
00422       //! buffer and will free it in its destructor.  
00423       //! @param items Reference to a pointer to the templated data type.
00424       //! The reason it's a reference is that after recording the pointer,
00425       //! Attach() will set <i>your</i> pointer to 0.  This will prevent you
00426       //! from accidently freeing a pointer you no longer own.  If you want
00427       //! it back, call the Detach() method
00428       void Attach (
00429          _CT *& items,                 
00430          int numitems               //!< Number of items in array
00431          ) {
00432          Free();
00433          m_items = items;
00434          m_numitems = m_numalloc = numitems;
00435          items = 0;
00436          return;
00437          }
00438 
00439 
00440       //! Clear the array, does not free resources.
00441       void Clear (
00442          ) {
00443          m_numitems = 0;
00444          return;
00445          }
00446 
00447       //! Clear items in the array
00448       void ClearItems (
00449          int start = 0,
00450          int end = -1                  //!< Default -1, use number of items
00451          ) {
00452          if (end < start) end = m_numitems - 1;
00453          if (end >= start) {     //! Start might be larger than end
00454             memset(m_items + start, 0, (end - start + 1) * sizeof(_CT));
00455             }
00456          return;
00457          }
00458 
00459 
00460       //! Copy the contents of another SIMPLE_ARRAY.
00461       //! Same as assignment, but returns an error code instead of throwing an exception.
00462       ERRVALUE Copy (
00463          const SIMPLE_ARRAY<_CT>& rhs
00464          ) {
00465          if (this != &rhs) {
00466             if (m_numalloc < rhs.m_numalloc) {
00467                //! Free the old array instead of using realloc to avoid expensive copy.
00468                MmFree(m_items);
00469                ERRVALUE err = MmAlloc((void**)&m_items,rhs.m_numalloc*sizeof(_CT));
00470                if (err < 0) return (err);
00471                m_numalloc = rhs.m_numalloc;
00472                }
00473             memcpy(m_items,rhs.m_items,rhs.m_numitems*sizeof(_CT));
00474             m_numitems = rhs.m_numitems;
00475             }
00476          return (0);
00477          }
00478 
00479       //! Detach the buffer from the SIMPLE_ARRAY.
00480       //!
00481       //! This turns ownership of the buffer over to the caller, who is then
00482       //! responsibile for seeing that it gets disposed of.
00483       //! After calling Detach(), the SIMPLE_ARRAY will behave as if it had
00484       //! just been constructed.  In other words, it will be a NULL pointer
00485       //! pointing to 0 items.
00486       //! This means that if you want to know how many items are in the
00487       //! array returned, you'd better find out @{before} you call Detach()!
00488       _CT* Detach (
00489          ) {
00490          _CT* ret = m_items;
00491          m_numalloc = m_numitems = 0;
00492          m_items = 0;
00493          return (ret);
00494          }
00495 
00496       //! Free the array.
00497       void Free (
00498          ) {
00499          m_numalloc = m_numitems = 0;
00500          MmFree(m_items);
00501          return;
00502          }
00503 
00504       //! Get array item, does not verify index range.
00505       const _CT& GetItem (
00506          int index
00507          ) const { return (m_items[index]); }
00508 
00509       //! Get last item in array.
00510       //! Does not verify that array is non-empty.
00511       const _CT& GetLast (
00512          ) const { return (m_items[m_numitems-1]); }
00513 
00514       //! Get maximum number of items in array.
00515       int GetMaxItems (
00516          ) const { return (m_numalloc); }
00517 
00518       //! Get number of items in array.
00519       int GetNumItems (
00520          ) const { return (m_numitems); }
00521 
00522       //! Get current reference count.
00523       UINT32 GetRefCount (
00524          ) const { return (m_RefCount); }
00525 
00526       //! Get size of array required to hold current number of items in bytes.
00527       int GetSizeInBytes (
00528          ) const { return (m_numitems*sizeof(_CT)); }
00529 
00530       //! Determine if an item exists in the array.
00531       //! Item must have a valid operator==()
00532       //! @return 'True' if item found
00533       bool HasItem (
00534          const _CT& item
00535          ) const {
00536          for (INT32 i = 0;(i < m_numitems);++i) {
00537             if (m_items[i] == item) return (true);
00538             }
00539          return (false);
00540          }
00541 
00542       //! Insert multiple items into the array
00543       void InsertItems (
00544          int start,
00545          int num = 1
00546          ) {
00547          ReserveExc(m_numitems+num);
00548          memmove(&m_items[start + num], &m_items[start], (m_numitems - start) * sizeof(_CT));
00549          m_numitems += num;
00550          return;
00551          }
00552 
00553       //! Determine if array is empty.
00554       bool IsEmpty (
00555          ) const { return (GetNumItems() == 0); }
00556 
00557       //! Binary search for an entry or the place where the entry should be
00558       //! _Pr is a functor that returns -1 if 1st item < 2nd, 1 if 1st > 2nd, 0 if 1st == 2nd
00559       //! 'item' is the first parameter passed to the _Pr functor
00560       //! @return Position that is equal or immediately less than 'item', or GetNumItems() if item > all list items
00561       template<class _Pr1>
00562       INT32 Locate (
00563          const _CT& item,
00564          _Pr1 _Pr,
00565          bool bReturnNegativeOneIfNotFound = false
00566          ) const {
00567          if (m_numitems == 0) return (bReturnNegativeOneIfNotFound ? -1 : 0);
00568          INT32 l = 0, r = m_numitems-1, q;
00569          do {
00570             q = (l+r)/2;
00571             int test = _Pr(item, m_items[q]);
00572             if (test == 0) return (q);
00573             if (test < 0) {
00574                r = q - 1;
00575                q = r;
00576                }
00577             else {
00578                l = q + 1;
00579                q = l;
00580                }
00581             } while (l <= r);
00582          return (bReturnNegativeOneIfNotFound ? -1 : q);
00583          }
00584 
00585       //! Decrement reference count, delete if zero.
00586       void Release (
00587          ) { if (--m_RefCount == 0) delete this; }
00588 
00589       //! Remove duplicate entries in the list, assume not sorted    
00590       void RemoveDuplicates (
00591          ) {
00592          for (INT32 i = 0;(i < m_numitems);++i) {
00593             for (INT32 k = i+1;(k < m_numitems);++k) {
00594                if (m_items[i] == m_items[k]) {
00595                   m_items[k] = m_items[m_numitems-1];
00596                   m_numitems --;
00597                   k --;
00598                   }
00599                }
00600             }
00601          return;
00602          }     
00603 
00604       //! Remove an item by placing the end item in its place.
00605       void RemoveFast (
00606          INT32 item
00607          ) {
00608          if (item >= 0 && item < m_numitems) {
00609             m_numitems --;
00610             m_items[item] = m_items[m_numitems];
00611             }
00612          return;
00613          }
00614 
00615       //! Remove item at specified index, maintaining order.
00616       //! Note that this is inefficient for large arrays.
00617       void RemoveItem (
00618          INT32 item
00619          ) {
00620          if (item < m_numitems && item >= 0) {
00621             --m_numitems;
00622             if (item < m_numitems) { memmove(&m_items[item], &m_items[item+1], (m_numitems - item) * sizeof(_CT)); }
00623             }
00624          return;
00625          }
00626 
00627       //! Remove last item(s) from array.
00628       void RemoveLast (
00629          INT32 count = 1                           //!< Number of items to remove
00630          ) {
00631          if (count > m_numitems)
00632             m_numitems = 0;
00633          else
00634             m_numitems -= count;
00635          return;
00636          }
00637 
00638       //! Remove items matching the item passed in.  _CT must have a operator==() defined
00639       //! Maintains item order
00640       //! @return 'True' if one or more items was removed
00641       bool RemoveMatchingItems (
00642          const _CT& item
00643          ) {
00644          INT32 i, num;
00645          for (num = i = 0;(i < m_numitems); ++i) {
00646             if (m_items[i] != item) {
00647                if (num < i) m_items[num] = m_items[i];      // Avoid expensive copy if not needed
00648                num ++;
00649                }
00650             }
00651          bool retval = (m_numitems != num);
00652          m_numitems = num;
00653          return (retval);
00654          }
00655 
00656       //! Reserve space in array for up to specified number of items.
00657       ERRVALUE Reserve (
00658          int newmaxitems,                 //!< New maximum number of items
00659          bool clear = false               //!< Clear the array by resetting number of items to 0
00660          ) {
00661          if (clear) m_numitems = 0;
00662          if (newmaxitems > m_numalloc) {
00663             int err;
00664             if (m_numitems == 0) {
00665                //! Free the old array to avoid expensive copy in reallocation
00666                MmFree(m_items);
00667                }
00668             if ((err = MmRealloc((void**)&m_items,newmaxitems*sizeof(_CT))) < 0) return (err);
00669             m_numalloc = newmaxitems;
00670             }
00671          return (0);
00672          }
00673 
00674       //! Reserve space in array for up to specified number of items.
00675       //! Throws exception if out of memory.
00676       void ReserveExc (
00677          int newmaxitems,                 //!< New maximum number of items
00678          bool clear = false               //!< Clear the array by resetting number of items to 0
00679          ) {
00680          if (clear) m_numitems = 0;
00681          if (newmaxitems > m_numalloc) {
00682             if (m_numitems == 0) {
00683                //! Free the old array to avoid expensive copy in reallocation
00684                MmFree(m_items);
00685                }
00686             MmReallocExc((void**)&m_items,newmaxitems*sizeof(_CT));
00687             m_numalloc = newmaxitems;
00688             }
00689          return;
00690          }
00691 
00692       //! Resize array to specified number of items.
00693       //! If the new size is larger than the previous size and the array is
00694       //! not cleared the new array entries will have indeterminant values.
00695       ERRVALUE Resize (
00696          int numitems,                    //!< New number of items desired
00697          bool keepold = true,             //!< Keep old array entries
00698          bool clear = false               //!< Clear new array items to zeros
00699          ) {
00700          int err;
00701          if ((err = Reserve(numitems,!keepold)) < 0) return (err);
00702          if (clear && numitems > m_numitems) memset(static_cast<void*>(m_items+m_numitems),0,(numitems-m_numitems)*sizeof(_CT));
00703          m_numitems = numitems;
00704          return (0);
00705          }
00706 
00707       //! Reverse order of items in array.
00708       void Reverse (
00709          ) {
00710          for (int i = 0; (i < m_numitems/2); ++i) {
00711             _CT temp(m_items[i]);
00712             m_items[i] = m_items[m_numitems-i-1];
00713             m_items[m_numitems-i-1] = temp;
00714             }
00715          return;
00716          }
00717 
00718       //! Set single item, does not verify index range.
00719       void SetItem (
00720          int index,                       //!< Item index, must be in range from 0 to NumItems-1
00721          const _CT& item                     //!< Item value to set
00722          ) {
00723          m_items[index] = item;
00724          }
00725 
00726       //! Set array items from C array, expanding if needed.
00727       //! Will not reduce the number of items in the array.
00728       ERRVALUE SetItems (
00729          int firstitem,                   //!< First array item to replace
00730          const _CT *items,                //!< Items to copy to array
00731          int numitems                     //!< Number of items to copy
00732          ) {
00733          int err;
00734          if ((err = Reserve(firstitem+numitems)) < 0) return (err);
00735          memcpy(m_items+firstitem,items,numitems*sizeof(_CT));
00736          if (m_numitems < firstitem + numitems) m_numitems = firstitem + numitems;
00737          return (0);
00738          }
00739 
00740       //! Sort the items in the array.
00741       //! CompFunc should return 1 if the first item sorts before the 2nd item
00742       //! Otherwise, return 0.
00743       void Sort (
00744          int (*CompFunc)(_CT*, _CT*, void*),
00745          void *data = 0
00746          ) {
00747          // Compare function cannot return 'bool', must be 'int'.
00748          heapsort(m_items, m_numitems, sizeof(_CT), reinterpret_cast<int (*)(void*, void*, void*)>(CompFunc), data);
00749          }
00750          
00751       //! Sort the items in the array.
00752       //! CompFunc should return 1 if the first item sorts before the 2nd item
00753       //! Otherwise, return 0.
00754       void SortRange (
00755          int (*CompFunc)(_CT*, _CT*, void*),
00756          int firstidx,
00757          int numitems,
00758          void *data = 0
00759          ) {
00760          if (numitems <= 0 || firstidx < 0 || firstidx + numitems > m_numitems) return;
00761          heapsort(m_items + firstidx, numitems, sizeof(_CT), reinterpret_cast<int (*)(void*, void*, void*)>(CompFunc), data);
00762          }
00763          
00764       //! Swap (exchange) two SIMPLE_ARRAYs.
00765       //! This exchanges the internal buffers so minimal copying is performed for efficiency.
00766       void Swap (
00767          SIMPLE_ARRAY<_CT>& rhs
00768          ) {
00769          _CT *t_items = m_items;
00770          m_items = rhs.m_items;
00771          rhs.m_items = t_items;
00772          int t_numitems = m_numitems;
00773          m_numitems = rhs.m_numitems;
00774          rhs.m_numitems = t_numitems;
00775          int t_numalloc = m_numalloc;
00776          m_numalloc = rhs.m_numalloc;
00777          rhs.m_numalloc = t_numalloc;
00778          }
00779 
00780       //! Swap bytes in a SIMPLE_ARRAY, assume that there is an overload to swap a _CT
00781       void SwapBytes (
00782          ) {
00783          for (int i = 0;(i < m_numitems);++i) ::SwapBytes(m_items[i]);
00784          }
00785 
00786    private:
00787       #ifndef GENERATING_DOXYGEN_OUTPUT
00788       _CT *m_items;                       //!< The actual array
00789       int m_numitems;                     //!< Number of valid items
00790       int m_numalloc;                     //!< Number of items allocated
00791       UINT32 m_RefCount;
00792       #endif // GENERATING_DOXYGEN_OUTPUT
00793 
00794    };
00795 
00796 #endif   //!< INC_MI32_SIMPLEAR_H

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