mi32/doublear.h

Go to the documentation of this file.
00001 /**
00002  * \file doublear.h <mi32/doublear.h>
00003  * \brief Definitions for DOUBLE_ARRAY template
00004  *
00005  * \if NODOC
00006  * $Id: doublear.h_v 1.30 2004/07/09 14:22:06 mju Exp $
00007  *
00008  * $Log: doublear.h_v $
00009  * Revision 1.30  2004/07/09 14:22:06  mju
00010  * In append need to multiply by item size when reserve.
00011  *
00012  * Revision 1.29  2003/09/15 13:49:56  fileserver!dwilliss
00013  * Doxygen
00014  *
00015  * Revision 1.28  2003/07/31 14:13:24  mju
00016  * Include string.h for memset/memcpy.
00017  *
00018  * Revision 1.27  2003/07/28 13:41:52  mju
00019  * Remove deprecated methods.
00020  *
00021  * Revision 1.26  2003/07/28 13:12:56  mju
00022  * Remove 'allocincrement' stuff, when append resize by doubling allocation.
00023  * Fix deprecated setitems method to not reference firstitem.
00024  *
00025  * Revision 1.25  2003/07/25 20:59:15  mju
00026  * Add Assign(), deprecate old SetItems().
00027  * Add SetItems variant which does not shrink array.
00028  *
00029  * Revision 1.24  2003/04/09 20:14:52  dwilliss
00030  * Don't use _T in template. Mac's ctype.h defines global _T. Thanks Apple!
00031  *
00032  * Revision 1.23  2002/01/02 21:06:14  scowan
00033  * Fixed GetItems().
00034  *
00035  * Revision 1.22  2001/11/06 17:09:05  dwilliss
00036  * Method TransferOwnerFrom() was trying to access non-existant member.
00037  * Should have been m_numitems, not numitems
00038  *
00039  * Revision 1.21  2001/11/01 16:44:15  mju
00040  * Add GetItems() method.
00041  *
00042  * Revision 1.20  2001/06/20 16:25:12  scowan
00043  * More errors.
00044  *
00045  * Revision 1.19  2001/06/20 15:43:10  scowan
00046  * Fixed append.
00047  *
00048  * Revision 1.18  2001/05/24 17:07:37  scowan
00049  * Uses new base mi double array class for storage.
00050  * Now supports Attach and Detach paradigm.
00051  *
00052  * Revision 1.17  2001/02/02 20:52:18  scowan
00053  * Stupid G++ compiler will not let me friend a instantiated template.
00054  *
00055  * Revision 1.16  2001/01/29 23:31:39  scowan
00056  * Attempt to fix UNIX g++ errors.
00057  *
00058  * Revision 1.15  2001/01/26 14:51:13  scowan
00059  * Added new transfer owner from method that is a template.
00060  *
00061  * Revision 1.14  2001/01/19 14:57:22  mju
00062  * Add DeleteItem().
00063  *
00064  * Revision 1.13  2001/01/17 17:33:36  mju
00065  * Add 'addinc' parm to Reserve() and use in Resize().
00066  *
00067  * Revision 1.12  2001/01/05 20:59:10  scowan
00068  * No change.
00069  *
00070  * Revision 1.11  2000/12/04 16:31:19  mju
00071  * Fix genitor 'end ignore' tag.
00072  *
00073  * Revision 1.10  2000/11/17 23:02:00  scowan
00074  * Added transfer method.
00075  *
00076  * Revision 1.9  2000/11/02 15:15:59  mju
00077  * Add ReserveExc/ResizeExc.
00078  *
00079  * Revision 1.8  2000/10/13 22:22:26  scowan
00080  * Added mac array operator overload specific crap.
00081  *
00082  * Revision 1.6  2000/08/17 16:12:45  scowan
00083  * Added unsigned array operators.
00084  *
00085  * Revision 1.4  2000/08/03 22:23:10  scowan
00086  * Added free and updated error reporting.
00087  *
00088  * Revision 1.3  2000/08/02 21:43:56  mju
00089  * Add Resize().
00090  * Fix methods taking DOUBLE_ARRAY<_CT>& parms.
00091  * Retire SetNumItems().
00092  *
00093  * Revision 1.2  2000/06/22 14:52:34  mju
00094  * Fix ClearItems to not clear past specified ending item.
00095  *
00096  * Revision 1.1  2000/06/21 22:59:40  scowan
00097  * Initial revision
00098  *
00099  * \endif
00100 **/
00101 
00102 #ifndef  INC_MI32_DOUBLEAR_H
00103 #define  INC_MI32_DOUBLEAR_H
00104 
00105 #ifndef  INC_MI32_MIODEFNS_H
00106 #include <mi32/miodefns.h>    //! For MmAlloc/Realloc/Free defns
00107 #endif
00108 
00109 #ifndef  INC_MI32_MEMBUF_H
00110 #include <mi32/membuf.h>      //! For SwapBytes() defn
00111 #endif
00112 
00113 #ifndef  INC_STRING_H
00114 #include <string.h>           //! For memset/memcpy
00115 #define  INC_STRING_H
00116 #endif
00117 
00118 #ifndef  INC_MI32_MIDBLARY_H
00119 #include <mi32/midblary.h>    //! For MIDOUBLEARRAY defn
00120 #endif
00121 
00122 //! Double array template.
00123 //!
00124 //! This template is designed to contain an array of items which can be allocated
00125 //! using MmAlloc/MmRealloc.  The primary purpose of this template is to replace
00126 //! allocated arrays where direct access to both array elements and the ability
00127 //! to access a pointer to the first element (as for a C array) is required.
00128 //!
00129 //! For maximum efficiency, only minimal validation of access to array elements is performed.
00130 //! No initialization of array items is performed by the template.
00131 //!
00132 //! This class is also designed to handle the 4 byte off alignment issue in regards to systems
00133 //! that have a 4 byte allocation granularity.
00134 //!
00135 //! Best if used as DOUBLE_ARRAY<double>, DOUBLE_ARRAY<DPOINT2D>, DOUBLE_ARRAY<DPOINT3D>, 
00136 //! DOUBLE_ARRAY<DRECT2D>, and DOUBLE_ARRAY<DRECT3D>
00137 
00138 template <class _CT> class DOUBLE_ARRAY {
00139 
00140    public:
00141 
00142       //! Default constructor.
00143       DOUBLE_ARRAY (
00144          ):
00145          m_data(0),
00146          m_numitems(0),
00147          m_spare(0)
00148          { }
00149 
00150       //! Copy constructor
00151       DOUBLE_ARRAY (
00152          const DOUBLE_ARRAY<_CT>& rhs
00153          ) :
00154          m_items(rhs.m_items),
00155          m_numitems(rhs.m_numitems),
00156          m_spare(0)
00157          {
00158          m_data = reinterpret_cast<_CT*>(m_items.GetPointer());
00159          }
00160 
00161       ~DOUBLE_ARRAY (
00162          ) {}
00163 
00164       //! Assignment.
00165       DOUBLE_ARRAY<_CT>& operator= (
00166          const DOUBLE_ARRAY<_CT>& rhs
00167          ) {
00168          if (this != &rhs) {
00169             m_items = rhs.m_items;
00170             m_numitems = rhs.m_numitems;
00171             m_data = reinterpret_cast<_CT*>(m_items.GetPointer());
00172             }
00173          return (*this);
00174          }
00175 
00176       //! Equality operator.
00177       bool operator== (
00178          const DOUBLE_ARRAY<_CT>& rhs
00179          ) const {
00180          if (m_numitems != rhs.m_numitems) return (false);
00181          if (m_numitems == 0) return (true);
00182          return (memcmp(m_data,m_data,m_numitems*sizeof(_CT)) == 0);
00183          }
00184 
00185       //! Inequality operator.
00186       bool operator!= (
00187          const DOUBLE_ARRAY<_CT>& rhs
00188          ) const {
00189          return (!operator==(rhs));
00190          }
00191 
00192       //! Cast to const array of template type.
00193       operator const _CT*(
00194          ) const {
00195          return (m_data);
00196          }
00197 
00198       //! Cast to array of template type.
00199       operator _CT*(
00200          ) {
00201          return (m_data);
00202          }
00203 
00204       //! Read (const) access to array element.
00205       //!
00206       //! @note Does not verify that index is within valid range.
00207       const _CT& operator[] (
00208          int index
00209          ) const {
00210          return (m_data[index]);
00211          }
00212 
00213       //! Write (non-const) access to array element.
00214       //!
00215       //! @note Does not verify that index is within valid range.
00216       _CT& operator[] (
00217          int index
00218          ) {
00219          return (m_data[index]);
00220          }
00221 
00222       #ifndef GENERATING_DOXYGEN_OUTPUT
00223       #ifdef MAC_NATIVE
00224          //! Fixes ambiguity error on Macintosh.
00225          
00226          //! Read (const) access to array element.
00227          //!
00228          //! @note Does not verify that index is within valid range.
00229          const _CT& operator[] (
00230             long index
00231             ) const {
00232             return (m_data[index]);
00233             }
00234 
00235          //! Write (non-const) access to array element.
00236          //!
00237          //! @note Does not verify that index is within valid range.
00238          _CT& operator[] (
00239             long index
00240             ) {
00241             return (m_data[index]);
00242             }
00243       #endif
00244       #endif //!< GENERATING_DOXYGEN_OUTPUT
00245 
00246       //! Append item to end of array, extending if necessary.
00247       ERRVALUE Append (
00248          const _CT& item
00249          ) {
00250          if (m_numitems >= GetMaxItems()) {
00251             int err;
00252             if ((err = m_items.Reserve(MAX(16,2*m_numitems*sizeof(_CT)), true)) < 0) return (err);
00253             m_data = reinterpret_cast<_CT*>(m_items.GetPointer());
00254             }
00255          m_data[m_numitems++] = item;
00256          return (0);
00257          }
00258          
00259       //! Assign from C array, reserving space if needed.
00260       //! Resizes the array to the specified number of items.
00261       ERRVALUE Assign (
00262          const _CT *items,                //!< Items to copy to array
00263          int numitems                     //!< Number of items to copy
00264          ) {
00265          ERRVALUE err;
00266          if ((err = Reserve(numitems,true)) < 0) return (err);
00267          memcpy(m_data,items,numitems*sizeof(_CT));
00268          m_numitems = numitems;
00269          return (0);
00270          }
00271 
00272       //! Attach a buffer to the DOUBLE_ARRAY.
00273       //! After passing a buffer to Attach(), the DOUBLE_ARRAY "<b>owns</b>" the
00274       //! buffer and will free it in its destructor.  
00275       //! @param items Reference to a pointer to the templated data type.
00276       //! @param numitems The number of items being attached
00277       //!
00278       //! The reason it's a reference is that after recording the pointer,
00279       //! Attach() will set <i>your</i> pointer to 0.  This will prevent you
00280       //! from accidently freeing a pointer you no longer own.  If you want
00281       //! it back, call the Detach() method
00282       void Attach (
00283          MIDOUBLEARRAY& items,
00284          int numitems
00285          ) {
00286          m_items.Attach(items);
00287          m_numitems = numitems;
00288          m_data = reinterpret_cast<_CT*>(m_items.GetPointer());
00289          return;
00290          }
00291          
00292       //! Clear the array, does not free resources.
00293       void Clear (
00294          ) { m_numitems = 0; }
00295 
00296       //! Clear items in the array
00297       void ClearItems (
00298          int start = 0,
00299          int end = -1                  //!< Default -1, use number of items
00300          ) {
00301          if (end < start) end = m_numitems - 1;
00302          memset(m_data + start, 0, (end - start + 1) * sizeof(_CT));
00303          return;
00304          }
00305 
00306       //! Copy the contents of another DOUBLE_ARRAY.
00307       //! Same as assignment, but returns an error code instead of throwing an exception.
00308       ERRVALUE Copy (
00309          const DOUBLE_ARRAY<_CT>& rhs
00310          ) {
00311          if (this != &rhs) {
00312             return (SetItems(rhs, rhs.m_numitems));
00313             }
00314          return (0);
00315          }
00316 
00317       //! Delete item in the array.
00318       //! Use with care as this is not efficient for large arrays.
00319       void DeleteItem (
00320          int index
00321          ) {
00322          if (index >= 0 && index < m_numitems) {
00323             --m_numitems;
00324             if (index < m_numitems) {
00325                memmove(m_data+index,m_data+index+1,(m_numitems-index)*sizeof(_CT));
00326                }
00327             }
00328          return;
00329          }
00330          
00331       //! Detach the buffer from the DOUBLE_ARRAY.
00332       //!
00333       //! This turns ownership of the buffer over to the caller, who is then
00334       //! responsibile for seeing that it gets disposed of.
00335       //! After calling Detach(), the DOUBLE_ARRAY will behave as if it had
00336       //! just been constructed.  In other words, it will be a NULL pointer
00337       //! pointing to 0 items.
00338       //! This means that if you want to know how many items are in the
00339       //! array returned, you'd better find out @{before} you call Detach()!
00340       void Detach (
00341          MIDOUBLEARRAY& items
00342          ) {
00343          items.Attach(m_items);
00344          m_numitems = 0;
00345          m_data = 0;
00346          return;
00347          }
00348          
00349       // See above comment on Attach() for Detach() method bad idea.
00350 
00351       //! Free the array.
00352       void Free (
00353          ) {
00354          m_items.Free();
00355          m_numitems = 0;
00356          m_data = 0;
00357          return;
00358          }
00359 
00360       //! Get items from array.
00361       void GetItems (
00362          _CT *items,                      //!< Buffer to hold items
00363          int numitems,                    //!< Number of items to copy
00364          int firstitem = 0                //!< First array item to retrieve
00365          ) const {
00366          memcpy(items,m_data+firstitem,MIN(m_numitems-firstitem, numitems)*sizeof(_CT));
00367          return;
00368          }
00369 
00370       //! Get maximum number of items in array.
00371       int GetMaxItems (
00372          ) const {
00373          return (m_items.GetNumReserved() / (sizeof(_CT) / sizeof(double)));
00374          }
00375 
00376       //! Get number of items in array.
00377       int GetNumItems (
00378          ) const { return (m_numitems); }
00379 
00380       //! Get size of array required to hold current number of items in bytes.
00381       int GetSizeInBytes (
00382          ) const { return (m_numitems*sizeof(_CT)); }
00383 
00384       //! Reserve space in array for up to specified number of items.
00385       ERRVALUE Reserve (
00386          int newmaxitems,                 //!< New maximum number of items
00387          bool clear = false,              //!< Clear the array by resetting number of items to 0
00388          bool addinc = false              //!< Add alloation increment to requested size if actually need to resize
00389          ) {
00390          if (clear) m_numitems = 0;
00391          if (newmaxitems > GetMaxItems()) {
00392             ERRVALUE err;
00393             if ((err = m_items.Reserve(newmaxitems * sizeof(_CT), true)) < 0) return (err);
00394             m_data = reinterpret_cast<_CT*>(m_items.GetPointer());
00395             }
00396          return (0);
00397          }
00398 
00399       //! Reserve space in array for up to specified number of items, throw exception on failure.
00400       void ReserveExc (
00401          int newmaxitems,                 //!< New maximum number of items
00402          bool clear = false,              //!< Clear the array by resetting number of items to 0
00403          bool addinc = false              //!< Add alloation increment to requested size if actually need to resize
00404          ) {
00405          if (clear) m_numitems = 0;
00406          if (newmaxitems > GetMaxItems()) {
00407             m_items.ReserveExc(newmaxitems * sizeof(_CT), true);
00408             m_data = reinterpret_cast<_CT*>(m_items.GetPointer());
00409             }
00410          return;
00411          }
00412 
00413       //! Resize array to specified number of items.
00414       //! If the new size is larger than the previous size and the array is
00415       //! not cleared the new array entries will have indeterminant values.
00416       ERRVALUE Resize (
00417          int numitems,                    //!< New number of items desired
00418          bool keepold = true,             //!< Keep old array entries
00419          bool clear = false               //!< Clear new entries to zeros, will clear all if keepold is false
00420          ) {
00421          int err;
00422          if ((err = Reserve(numitems,!keepold,true)) < 0) return (err);
00423          if (clear && numitems > m_numitems) memset(m_data+m_numitems,0,(numitems-m_numitems)*sizeof(_CT));
00424          m_numitems = numitems;
00425          return (0);
00426          }
00427 
00428       //! Resize array to specified number of items, throw exception on failure.
00429       //! If the new size is larger than the previous size and the array is
00430       //! not cleared the new array entries will have indeterminant values.
00431       void ResizeExc (
00432          int numitems,                    //!< New number of items desired
00433          bool keepold = true,             //!< Keep old array entries
00434          bool clear = false               //!< Clear new entries to zeros, will clear all if keepold is false
00435          ) {
00436          ReserveExc(numitems,!keepold,true);
00437          if (clear && numitems > m_numitems) memset(m_data+m_numitems,0,(numitems-m_numitems)*sizeof(_CT));
00438          m_numitems = numitems;
00439          return;
00440          }
00441 
00442       //! Reverse order of items in array.
00443       void Reverse (
00444          ) {
00445          for (int i = 0; (i < m_numitems/2); ++i) {
00446             _CT temp(m_data[i]);
00447             m_data[i] = m_data[m_numitems-i-1];
00448             m_data[m_numitems-i-1] = temp;
00449             }
00450          return;
00451          }
00452 
00453       //! Set array items from C array, expanding if needed.
00454       //! Will not reduce the number of items in the array.
00455       ERRVALUE SetItems (
00456          int firstitem,                   //!< First array item to replace
00457          const _CT *items,                //!< Items to copy to array
00458          int numitems                     //!< Number of items to copy
00459          ) {
00460          ERRVALUE err;
00461          if ((err = Reserve(firstitem+numitems,true)) < 0) return (err);
00462          memcpy(m_data+firstitem,items,numitems*sizeof(_CT));
00463          if (m_numitems < firstitem + numitems) m_numitems = firstitem + numitems;
00464          return (0);
00465          }
00466 
00467       //! Swap two DOUBLE_ARRAYs.
00468       void Swap (
00469          DOUBLE_ARRAY<_CT>& rhs
00470          ) {
00471          m_items.Swap(rhs.m_items);
00472          _CT *t_data = m_data;
00473          m_data = rhs.m_data;
00474          rhs.m_data = t_data;
00475          int t_numitems = m_numitems;
00476          m_numitems = rhs.m_numitems;
00477          rhs.m_numitems = t_numitems;
00478          return;
00479          }
00480          
00481       //! Swap bytes in a DOUBLE_ARRAY, assume that there is an overload to swap a _CT
00482       void SwapBytes (
00483          ) { for (int i = 0;(i < m_numitems);++i) ::SwapBytes(m_data[i]); }
00484          
00485       //! Transfer data ownership from 'rhs' to 'this'.
00486       void TransferOwnerFrom (
00487          DOUBLE_ARRAY<_CT>& rhs
00488          ) {
00489          MIDOUBLEARRAY temp;
00490          int numitems = rhs.GetNumItems();
00491          rhs.Detach(temp);
00492          Attach(temp, numitems);
00493          return;
00494          }
00495          
00496       //! Transfer data ownership from 'rhs' to 'this'.
00497       template <class _T2> void TransferOwnerFromExt (
00498          DOUBLE_ARRAY<_T2>& rhs
00499          ) {
00500          MIDOUBLEARRAY temp;
00501          int numitems = rhs.GetNumItems();
00502          rhs.Detach(temp);
00503          
00504          int T1 = sizeof(_CT) / sizeof(double);
00505          int T2 = sizeof(_T2) / sizeof(double);
00506          numitems = (numitems * T2) / T1;
00507          Attach(temp, numitems);
00508          rhs.Clear();
00509          return;
00510          }
00511          
00512    private:
00513       #ifndef GENERATING_DOXYGEN_OUTPUT
00514 
00515       MIDOUBLEARRAY m_items;              //!< The accessed array
00516       _CT* m_data;                        //!< Pointer to the data for fast access
00517       int m_numitems;                     //!< Number of valid items
00518       int m_spare;
00519       #endif // GENERATING_DOXYGEN_OUTPUT
00520    };
00521 
00522 #endif   //!< INC_MI32_DOUBLEAR_H

Generated on Thu Aug 12 06:18:31 2004 for TNTsdk by doxygen 1.3.4-20031026