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

Generated on Tue Dec 14 13:18:20 2004 for TNTsdk by  doxygen 1.3.8-20040913