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

Generated on Wed May 31 15:26:50 2006 for TNTsdk by  doxygen 1.3.8-20040913