FDO API Reference Feature Data Objects

Array.h

Go to the documentation of this file.
00001 #ifndef _ARRAY_H_
00002 #define _ARRAY_H_
00003 // 
00004 
00005 //
00006 // Copyright (C) 2004-2006  Autodesk, Inc.
00007 // 
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of version 2.1 of the GNU Lesser
00010 // General Public License as published by the Free Software Foundation.
00011 // 
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 // Lesser General Public License for more details.
00016 // 
00017 // You should have received a copy of the GNU Lesser General Public
00018 // License along with this library; if not, write to the Free Software
00019 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 //
00021 
00022 #ifdef _WIN32
00023 #pragma once
00024 #endif
00025 
00026 #include <Common/ArrayHelper.h>
00027 
00028 
00029 // Template for dynamic array.  It supports:
00030 //  - shared ownership, via reference counting
00031 //  - single allocation on heap for entire structure (no internal indirection)
00032 //  - dynamic growth with infrequent reallocation
00033 //  - hiding "new" and "delete" from callers that may have redefined these operators
00034 //
00035 // This class integrates its own needed member variables within
00036 // the array itself.  This approach is very space efficient, as 
00037 // it avoids the overhead of a level of indirection; there is no
00038 // pointer to an internal, owned array.
00039 //
00040 // The tradeoffs to get these features are:
00041 //  - any method call that could cause re-allocation is static, 
00042 //    returning a (possibly new) location for the array object
00043 //  - one cannot call re-allocating methods if the object is shared
00044 //  - this class must never contain virtual methods (thus does its own reference counting)
00045 //  - the allocation mechanism delegates to a helper class
00046 //  - it is not typesafe for objects that cannot safely be moved around
00047 //    in memory or which have non-empty destructors (it is safe for basic
00048 //    types and most structs).
00049 //
00050 // Example:
00051 //      FdoIntArray* ints = FdoIntArray::Create();
00052 //      ints = FdoIntArray::Append(ints, 7);
00053 //      FdoInt32 moreInts [] = { 8, 9 };
00054 //      FdoInt32 numMoreInts = sizeof(moreInts)/sizeof(moreInts[0]);
00055 //      ints = FdoIntArray::Append(ints, numMoreInts, moreInts);
00056 //      int element = (*ints)[1];
00057 //      cout << "The second element is " << element << endl;
00058 //      FDO_SAFE_RELEASE(ints);
00059 
00060 /// \brief
00061 /// Abstract template class for defining dynamic arrays.
00062 /// 
00063 /// <span class="red_text"><b>WARNING:</b></span> This array uses a single memory allocation to store array elements
00064 /// and may re-allocate that memory when the array size needs to change.
00065 /// Therefore, do not keep pointers to array elements and avoid using 
00066 /// for objects which cannot be safely moved around in memory or which have
00067 /// non-empty destructors.
00068 template <typename T> class FdoArray
00069 {
00070 public:
00071 
00072     /// \brief
00073     /// Create an empty array
00074     /// 
00075     /// \return
00076     /// Returns a FdoArray pointer
00077     /// 
00078     static FdoArray<T> * Create();
00079     /// \brief
00080     /// Create a dynamic array preallocated to a specific size
00081     /// 
00082     /// \param initialAlloc 
00083     /// Input initial size of the array
00084     /// 
00085     /// \return
00086     /// Returns a FdoArray pointer
00087     /// 
00088     static FdoArray<T> * Create(FdoInt32 initialAlloc);
00089     /// \brief
00090     /// Create a dynamic array from a pointer to a fixed array
00091     /// 
00092     /// \param elements 
00093     /// Input pointer to array of elements
00094     /// \param initialNumElements 
00095     /// Input number of elements to be added
00096     /// 
00097     /// \return
00098     /// Returns a FdoArray pointer
00099     /// 
00100     static FdoArray<T> * Create(const T* elements, FdoInt32 initialNumElements);
00101 
00102     /// \brief
00103     /// Increase the reference count.
00104     /// 
00105     /// \return
00106     /// Returns the new reference count. For debugging use only.
00107     /// 
00108     inline FdoInt32 AddRef() { return ++((FdoArrayHelper::GenericArray*)this)->m_metadata.refCount; }
00109     /// \brief
00110     /// Decrease the reference count.
00111     /// 
00112     /// \return
00113     /// Returns the new reference count. For debugging use only.
00114     /// 
00115     inline FdoInt32 Release() { if (0 != --((FdoArrayHelper::GenericArray*)this)->m_metadata.refCount ) return ((FdoArrayHelper::GenericArray*)this)->m_metadata.refCount; Dispose(); return 0; }
00116 
00117     /// \brief
00118     /// Retrieves the reference count.
00119     /// 
00120     /// \return
00121     /// Returns the existing reference count value.
00122     /// 
00123     inline FdoInt32 GetRefCount() { return ((FdoArrayHelper::GenericArray*)this)->m_metadata.refCount; }
00124 
00125     /// \brief
00126     /// Gets the number of items in the array.
00127     /// 
00128     /// \return
00129     /// Returns number of items in the array
00130     /// 
00131     FdoInt32 GetCount() const { return ((FdoArrayHelper::GenericArray*)this)->m_metadata.size; }
00132     /// \brief
00133     /// Get a pointer to the data in the array.
00134     /// 
00135     /// \return
00136     /// Returns a pointer to the data
00137     /// 
00138     T* GetData() { return (T*)(((FdoArrayHelper::GenericArray*)this)->GetData()); }
00139     /// \brief
00140     /// Get a pointer to the data in the array.
00141     /// 
00142     /// \return
00143     /// Returns a pointer to the data
00144     /// 
00145     const T* GetData() const {return (const T*)(((FdoArrayHelper::GenericArray*)this)->GetData()); }
00146 
00147     /// \brief
00148     ///  Resize the array.
00149     /// 
00150     /// \return
00151     /// Returns the new array pointer.
00152     /// 
00153     static FdoArray<T> * SetSize(FdoArray<T> * array, FdoInt32 numElements);
00154 
00155     /// \brief
00156     /// Adds the specified array of items to the end of the array. Returns a new array pointer.
00157     /// 
00158     /// \param array 
00159     /// Input array pointer
00160     /// \param numElements 
00161     /// Input number of items to be added
00162     /// \param elements 
00163     /// Input pointer to array to append
00164     /// 
00165     /// \return
00166     /// Returns the new array pointer.
00167     /// 
00168     static FdoArray<T> * Append(FdoArray<T> * array, FdoInt32 numElements, T * elements);
00169     /// \brief
00170     /// Adds the specified item to the end of the array. Returns a new array pointer.
00171     /// 
00172     /// \param array 
00173     /// Input array pointer
00174     /// \param element 
00175     /// Input item to be appended to array
00176     /// 
00177     /// \return
00178     /// Returns the new array pointer.
00179     /// 
00180     static FdoArray<T> * Append(FdoArray<T> * array, T element);
00181     /// \brief
00182     /// Removes all items from the array.
00183     /// 
00184     /// \return
00185     /// Returns nothing
00186     /// 
00187     void Clear();
00188 
00189     /// \brief
00190     /// Provide index operator [] access to array members.
00191     /// 
00192     /// \param i 
00193     /// Input index to access
00194     /// 
00195     /// \return
00196     /// Returns the value of the specified item in the array.
00197     /// 
00198     const T& operator[](int i) const { return GetValue(i); }
00199     /// \brief
00200     /// Provide index operator [] access to array members.
00201     /// 
00202     /// \param i 
00203     /// Input index to access
00204     /// 
00205     /// \return
00206     /// Returns the value of the specified item in the array.
00207     /// 
00208     T& operator[](int i) { return GetValue(i); }
00209 
00210 protected:
00211     /// Constructor
00212     FdoArray() {}
00213 
00214     static FdoArray<T> * AllocMore(FdoArray<T> * array, FdoInt32 atLeastThisMuch, bool exactly);
00215     static FdoArray<T> * SetAlloc(FdoArray<T> * array, FdoInt32 numElements);
00216 
00217     /// Access elements
00218     const T& GetValue(FdoInt32 i) const;
00219     T& GetValue(FdoInt32 i);
00220     void SetValue(FdoInt32 i, T newElement);
00221 
00222     /// the rest of FdoIDisposable
00223     void Dispose();
00224 };
00225 
00226 template <class T>
00227 inline
00228 FdoArray<T> * FdoArray<T>::Create()
00229 {
00230     return AllocMore(0, 0, true);
00231 }
00232 
00233 template <class T>
00234 inline
00235 FdoArray<T> * FdoArray<T>::Create(FdoInt32 initialAlloc)
00236 {
00237     return AllocMore(0, initialAlloc, true);
00238 }
00239 
00240 template <class T>
00241 inline
00242 FdoArray<T> * FdoArray<T>::Create(const T* elements, FdoInt32 initialNumElements)
00243 {
00244     FdoArray<T> * array = AllocMore(0, initialNumElements, true);
00245     if (array != NULL)
00246         array = (FdoArray<T> *)FdoArrayHelper::Append((FdoArrayHelper::GenericArray*) array, initialNumElements, (FdoByte*) elements, sizeof(T));
00247     return array;
00248 }
00249 
00250 template <class T>
00251 inline
00252 FdoArray<T> * FdoArray<T>::Append(FdoArray<T> * array, FdoInt32 numElements, T * elements)
00253 {
00254     array = (FdoArray<T> *)FdoArrayHelper::Append((FdoArrayHelper::GenericArray*) array, numElements, (FdoByte*) elements, sizeof(T));
00255     return array;
00256 }
00257 
00258 template <class T>
00259 inline
00260 FdoArray<T> * FdoArray<T>::Append(FdoArray<T> * array, T element)
00261 {
00262     if ( ((FdoArrayHelper::GenericArray*)array)->m_metadata.size == ((FdoArrayHelper::GenericArray*)array)->m_metadata.alloc )
00263     {
00264         array = (FdoArray<T> *)FdoArrayHelper::AllocMore((FdoArrayHelper::GenericArray*) array, 1, false /*exactly*/, sizeof(T));
00265     }
00266     array->GetValue((((FdoArrayHelper::GenericArray*)array)->m_metadata.size)++) = element;
00267     return array;
00268 }
00269 
00270 template <class T>
00271 inline
00272 void FdoArray<T>::Clear()
00273 {
00274     /// since no memory reallocation we can avoid input/output of array class pointer
00275     SetSize(this, 0);
00276 }
00277 
00278 template <class T>
00279 inline
00280 FdoArray<T> * FdoArray<T>::SetSize(FdoArray<T> * array, FdoInt32 numElements)
00281 {
00282     array = (FdoArray<T> *)FdoArrayHelper::SetSize((FdoArrayHelper::GenericArray*) array, numElements, sizeof(T));
00283     return array;
00284 }
00285 
00286 template <class T>
00287 inline
00288 FdoArray<T> * FdoArray<T>::SetAlloc(FdoArray<T> * array, FdoInt32 numElements)
00289 {
00290     array = (FdoArray<T> *)FdoArrayHelper::SetAlloc((FdoArrayHelper::GenericArray*) array, numElements, sizeof(T));
00291     return array;
00292 }
00293 
00294 //
00295 // Allocate some more memory for the array.
00296 // If the given array is NULL, a new array of zero size 
00297 // but the requested allocation is returned.
00298 // The returned array will always have at least one new
00299 // free element allocated. Thus, passing atLeastThisMuch < 1, 
00300 // while not an error, still results in some new storage.
00301 //
00302 template <class T>
00303 inline
00304 FdoArray<T> * FdoArray<T>::AllocMore(FdoArray<T> * array, FdoInt32 atLeastThisMuch, bool exactly)
00305 {
00306     array = (FdoArray<T> *)FdoArrayHelper::AllocMore((FdoArrayHelper::GenericArray*) array, atLeastThisMuch, exactly, sizeof(T));
00307     return array;
00308 }
00309 
00310 template <class T>
00311 inline
00312 void FdoArray<T>::Dispose()
00313 {
00314     FdoArrayHelper::DisposeOfArray((FdoArrayHelper::GenericArray*) this, sizeof(T));
00315 }
00316 
00317 template <class T>
00318 inline
00319 const T& FdoArray<T>::GetValue(FdoInt32 i) const 
00320 {
00321     if (i >= GetCount() || i < 0)
00322         throw FdoException::Create(FdoException::NLSGetMessage(FDO_NLSID(FDO_5_INDEXOUTOFBOUNDS)));
00323 
00324     return *(this->GetData()+i); 
00325 }
00326 
00327 template <class T>
00328 inline
00329 T& FdoArray<T>::GetValue(FdoInt32 i) 
00330 {
00331     if (i >= GetCount() || i < 0)
00332         throw FdoException::Create(FdoException::NLSGetMessage(FDO_NLSID(FDO_5_INDEXOUTOFBOUNDS)));
00333 
00334     return *(this->GetData()+i); 
00335 }
00336 
00337 template <class T>
00338 inline
00339 void FdoArray<T>::SetValue(FdoInt32 i, T newElement) 
00340 {
00341     if (i >= GetCount() || i < 0)
00342         throw FdoException::Create(FdoException::NLSGetMessage(FDO_NLSID(FDO_5_INDEXOUTOFBOUNDS)));
00343 
00344     *(this->GetData()+i) = newElement;
00345 }
00346 
00347 /// \brief
00348 /// Dynamic array of bytes (FdoByte).
00349 typedef FdoArray<FdoByte>   FdoByteArray;
00350 
00351 /// \brief
00352 /// Dynamic array of doubles (FdoDouble).
00353 typedef FdoArray<FdoDouble> FdoDoubleArray;
00354 
00355 /// \brief
00356 /// Dynamic array of integers (FdoInt32).
00357 typedef FdoArray<FdoInt32>  FdoIntArray;
00358 //typedef FdoArray<FdoString> FdoStringArray;
00359 #endif
00360 
00361 

Comments or suggestions? Send us feedback.