00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef _Array_
00023 #define _Array_
00024
00025 #include <cstdio>
00026 #include <cstdlib>
00027 #include <cstring>
00028 #include <new>
00029 #include "DataTypes.hxx"
00030 #include "Err.hxx"
00031 #include "Assert.hxx"
00032 #include "ErrOutOfMemory.hxx"
00033 #include "Storage.hxx"
00034 #include "Component.hxx"
00035 #include "TypeInfo.hxx"
00036
00037
00038 #include "DynamicType.hxx"
00039
00040
00041 #include "XMLAdapter.hxx"
00042 #include "XMLArrayAdapter.hxx"
00043 #include "XMLComponentAdapter.hxx"
00044
00045 namespace CLAM {
00046
00047
00048
00049 template <class T> class Array:public Component
00050 {
00051 private:
00052 T *mpData;
00053 TSize mAllocSize;
00054 TSize mSize;
00055 int mStep;
00056 public:
00057 Array(TSize size = 0,TSize step = 1)
00058 {
00059 mSize = mAllocSize = 0;
00060 mStep = step;
00061 mpData = NULL;
00062 Resize(size);
00063 SetSize(size);
00064 }
00065
00066 void Init(){
00067 Resize(0);
00068 SetSize(0);}
00069
00070 Array(T* ptr,int size = 0)
00071 {
00072 CLAM_ASSERT( ptr!=NULL,
00073 "Array::Array( T*, int) : you cannot create a not-owning memory array "
00074 "without specifying a valid data pointer. ");
00075 mSize = mAllocSize = size;
00076 mStep = -1;
00077 mpData = ptr;
00078 }
00079
00080 Array(const Array<T> &originalArray)
00081 {
00082 mpData = NULL;
00083 mSize = mAllocSize = mStep = 0;
00084 *this = originalArray;
00085 }
00086
00087 ~Array()
00088 {
00089 DestroyDataBuffer();
00090 mAllocSize=mSize=mStep=0;
00091 }
00092
00093 const char * GetClassName() const {return NULL;}
00094
00095 bool OwnsMemory() const {return mStep>=0; }
00096 bool Empty() const { return mSize==0; }
00097
00098 TSize Size(void) const { return mSize; }
00099 TSize SizeInBytes(void) const { return mSize*sizeof(T); }
00100 TSize AllocatedSize(void) const { return mAllocSize; }
00101 TSize AllocatedSizeInBytes(void) const { return mAllocSize*sizeof(T); }
00102
00103 void SetSize(TSize size)
00104 {
00105 CLAM_ASSERT(size <= AllocatedSize() || !OwnsMemory(), msgSetSizeOutOfRange);
00106 if (OwnsMemory())
00107 {
00108 if (size > mSize)
00109 InitializeDataBlock(mSize,size);
00110 if (size < mSize)
00111 UninitializeDataBlock(size,mSize);
00112 }
00113 mSize = size;
00114 }
00115
00116 void SetStep(TSize step) { mStep = step;}
00117
00118 TSize GetStep() const {return mStep;}
00119
00120 void Resize(TSize newAllocSize)
00121 {
00122 CLAM_ASSERT(OwnsMemory(),
00123 "Array::Resize(): You cannot invoke this method on an array that "
00124 "does not own any memory" );
00125 CLAM_ASSERT( newAllocSize >= 0,
00126 "Array::Resize(): You are trying to allocate a negative amount of "
00127 "space, which is a weird thing to do, isn't it?");
00128
00129
00130
00131 if(newAllocSize>0)
00132 ResizeDataBuffer(newAllocSize);
00133 else
00134 {
00135 if(mpData)
00136 {
00137 DestroyDataBuffer();
00138 mpData=NULL;
00139 }
00140 }
00141
00142 mAllocSize = newAllocSize;
00143
00144 if (mAllocSize<mSize)
00145 mSize = mAllocSize;
00146
00147
00148
00149 CLAM_ASSERT( AllocatedSize()==0 || mpData!=NULL,
00150 "Array::Resize() : Memory Allocation failed!" );
00151 }
00152
00153 const T* GetPtr(void) const { return mpData; }
00154 T* GetPtr(void) { return mpData; }
00155
00156 void SetPtr(T* ptr, int size = 0)
00157 {
00158 CLAM_ASSERT( !OwnsMemory() || mAllocSize == 0,
00159 "Array::SetPtr() : You are not allowed to invoke SetPtr() on"
00160 " an Array that owns memory or is not empty" );
00161
00162 mSize = mAllocSize = size;
00163 mpData = ptr;
00164
00165 if (ptr == 0 && size == 0)
00166 mStep = 1;
00167 else
00168 mStep = -1;
00169 }
00170
00171 inline void GiveChunk(int pos, int size, Array<T>&) const;
00172
00173 inline void CopyChunk(int pos, int size, Array<T>&) const;
00174
00175 const T& operator [](const int& i) const
00176 {
00177 CLAM_DEBUG_ASSERT(i>=0,msgIndexOutOfRange);
00178 CLAM_DEBUG_ASSERT(i<mSize,msgIndexOutOfRange);
00179 return mpData[i];
00180 }
00181
00182 T& operator [](const int& i)
00183 {
00184 CLAM_DEBUG_ASSERT(i>=0,msgIndexOutOfRange);
00185 CLAM_DEBUG_ASSERT(i<mSize,msgIndexOutOfRange);
00186 return mpData[i];
00187 }
00188
00189 void AddElem(const T& elem)
00190 {
00191 CLAM_ASSERT(OwnsMemory(),"Array::AddElem(): Resize requiered,"
00192 " but this array does not own its memory!");
00193 if (mSize>=mAllocSize)
00194 Resize(mAllocSize+mStep);
00195 new(&mpData[mSize]) T(elem);
00196 mSize++;
00197 }
00198 void InsertElem(int where,const T& elem)
00199 {
00200 CLAM_ASSERT(OwnsMemory(),"Array::InsertElem(): Resize requiered,"
00201 " but this array does not own its memory!");
00202 CLAM_ASSERT( (where>=0) && (where<mSize) ,msgInsertOutOfRange);
00203 if (mSize>=mAllocSize)
00204 Resize(mAllocSize+mStep);
00205 InsertElemInDataBuffer(where);
00206 new(&mpData[where]) T(elem);
00207 mSize++;
00208 }
00209 void SetElem(int where,const T& elem)
00210 {
00211 CLAM_DEBUG_ASSERT(where>=0,msgIndexOutOfRange);
00212 CLAM_DEBUG_ASSERT(where<mSize,msgIndexOutOfRange);
00213 mpData[where] = elem;
00214 }
00215 void DeleteElem(int where)
00216 {
00217 CLAM_ASSERT(OwnsMemory(),"Array::DeleteElem(): Resize requiered,"
00218 " but this array does not own its memory!");
00219 CLAM_ASSERT(where>-1 ,msgDeleteOutOfRange);
00220 CLAM_ASSERT(where<mSize,msgDeleteOutOfRange);
00221 DeleteElemInDataBuffer(where);
00222 mSize--;
00223 if (mSize<mAllocSize-mStep)
00224 Resize(mSize);
00225 }
00226
00227 Array<T>& operator = (const Array<T>& src)
00228 {
00229
00230 if ( OwnsMemory() )
00231 {
00232 if ( Size() != src.Size() )
00233 Resize( src.Size() );
00234 if ( src.OwnsMemory() )
00235 mStep = src.mStep;
00236 else
00237 mStep = 1;
00238 }
00239 else
00240 {
00241 CLAM_ASSERT( AllocatedSize() >= src.Size(),
00242 "Array::RegionWrite() : source size exceeds the Region bounds" );
00243 CLAM_ASSERT( GetPtr() != NULL,
00244 "Array::operator= : if you want to create a not memory owning array "
00245 "from one that does own memory, use instead Array::SetPtr() method");
00246 }
00247
00248 int tocopy = (src.Size()<Size())?src.Size():Size();
00249 CopyDataBlock(0,tocopy,src.GetPtr());
00250 InitializeCopyDataBlock(tocopy,src.Size(),src.GetPtr());
00251 mSize=src.Size();
00252
00253 return *this;
00254
00255 }
00256
00257 Array<T>& operator += (const Array<T>& src)
00258 {
00259 int start = Size();
00260 Resize(Size()+src.Size());
00261 mSize+=src.Size();
00262 int end = Size();
00263 InitializeCopyDataBlock(start,end,0,src.mpData);
00264 return *this;
00265 }
00266
00267 void Apply( T (*f)(T) )
00268 {
00269 int i;
00270 for (i=0; i<mSize; i++)
00271 (*this)[i] = f( (*this)[i] );
00272 }
00273
00274 void Apply( T (*f)(T,int),int parameter )
00275 {
00276 int i;
00277 for (i=0; i<mSize; i++)
00278 (*this)[i] = f( (*this)[i], parameter );
00279 }
00280
00281 void StoreOn(Storage & storage) const
00282 {
00283 StoreBufferOn((typename TypeInfo<T>::StorableAsLeaf *)NULL, mpData, storage);
00284 }
00285 void LoadFrom(Storage & storage)
00286 {
00287 LoadBufferFrom((typename TypeInfo<T>::StorableAsLeaf *)NULL, mpData, storage);
00288 }
00289
00290
00291
00292 static const char *msgSetSizeOutOfRange;
00293 static const char *msgIndexOutOfRange;
00294 static const char *msgInsertOutOfRange;
00295 static const char *msgDeleteOutOfRange;
00296
00297 private:
00298 inline void ResizeDataBuffer(int new_size);
00299 inline void DestroyDataBuffer(void);
00300 inline void InsertElemInDataBuffer(int position);
00301 inline void DeleteElemInDataBuffer(int position);
00302 inline void InitializeElement(int position);
00303 inline void InitializeDataBlock(int first, int last);
00304 inline void UninitializeDataBlock(int first, int last);
00305 inline void CopyDataBlock(int first, int last, const T* src);
00306 inline void InitializeCopyDataBlock(int first, int last, const T* src);
00307 inline void InitializeCopyDataBlock(int first, int last, int src_first, const T* src);
00308
00309 void StoreBufferOn(StaticFalse* asLeave, const Component * polymorphicSelector, Storage & storage) const
00310 {
00311 if (mSize<=0) return;
00312 const char* className = mpData[0].GetClassName();
00313 const char* label = className? className : "Element";
00314 for (int i=0; i<mSize; i++)
00315 {
00316 XMLComponentAdapter adapter(mpData[i], label, true);
00317 storage.Store(adapter);
00318 }
00319 }
00320 void StoreBufferOn(StaticTrue* asLeave, const void * polymorphicSelector, Storage & storage) const
00321 {
00322 XMLAdapter<unsigned> sizeAdapter(Size(),"size");
00323 storage.Store(sizeAdapter);
00324 XMLArrayAdapter<T> adapter(mpData,mSize);
00325 storage.Store(adapter);
00326 }
00327 void StoreBufferOn(StaticFalse* asLeave, const void * polymorphicSelector, Storage & storage) const
00328 {
00329 CLAM_ASSERT(false,
00330 "Trying to Store an object that is not neither a streamable nor a Component");
00331 }
00332 void LoadBufferFrom(StaticFalse* asLeave, Component * polymorphicSelector, Storage & storage)
00333 {
00334 const char* label = 0;
00335 while (true)
00336 {
00337 T elem;
00338 if (!label)
00339 {
00340 label = elem.GetClassName();
00341 if (!label)
00342 label = "Element";
00343 }
00344 XMLComponentAdapter adapter(elem, label, true);
00345 if (!storage.Load(adapter)) return;
00346 AddElem(elem);
00347 }
00348 }
00349 void LoadBufferFrom(StaticTrue* asLeave, void * polymorphicSelector, Storage & storage)
00350 {
00351 unsigned size;
00352 XMLAdapter<unsigned> sizeAdapter(size,"size");
00353 if (storage.Load(sizeAdapter))
00354 {
00355 Resize(size);
00356 SetSize(size);
00357 XMLArrayAdapter<T> adapter(mpData,mSize);
00358 storage.Load(adapter);
00359
00360 return;
00361 }
00362
00363 while (true) {
00364 T elem;
00365 XMLAdapter<T> adapter(elem);
00366 if ( ! storage.Load(adapter)) return;
00367 AddElem(elem);
00368 }
00369 }
00370 void LoadBufferFrom(StaticFalse* asLeave, void * polymorphicSelector, Storage & storage)
00371 {
00372 CLAM_ASSERT(false,
00373 "Trying to Store an object that is not neither a streamable nor a Component");
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 bool LoadMemberFrom(StaticTrue* asLeave, void * item, Storage & storage) {
00392 XMLAdapter<T> adapter(*(T*)item);
00393 return storage.Load(adapter);
00394 }
00395 bool LoadMemberFrom(StaticFalse* asLeave, Component * item, Storage & storage) {
00396 const char* className = (item->GetClassName());
00397 const char* label = className? className : "Element";
00398 XMLComponentAdapter adapter(*item, label, true);
00399 return storage.Load(adapter);
00400 }
00401 bool LoadMemberFrom(StaticFalse* asLeave, void * item, Storage & storage) {
00402 CLAM_ASSERT(false, "Trying to Load an object that is not neither a streamable nor a Component");
00403 return false;
00404 }
00405
00406 };
00407
00408
00409
00410
00411 template<class T>
00412 void Array<T>::GiveChunk(int pos, int size, Array<T>& a) const
00413 {
00414 CLAM_ASSERT(pos + size <= mSize,
00415 "Array::GiveChunk(): Chunk out of bounds.");
00416 a.SetPtr(&mpData[pos],size);
00417 }
00418
00419 template<class T>
00420 void Array<T>::CopyChunk(int pos, int size, Array<T>& a) const
00421 {
00422 int last=pos+size;
00423 CLAM_ASSERT(last <= mSize,
00424 "Array::CopyChunk(): Chunk out of bounds.");
00425 CLAM_ASSERT(size <= a.mSize,
00426 "Array::CopyChunk(): destination array does not have enough memory");
00427 for (int i=pos;i<last;i++)
00428 a.mpData[i-pos]=mpData[i];
00429 }
00430
00431 template<class T>
00432 void Array<T>::InitializeElement(int i)
00433 {
00434 new (&mpData[i]) T();
00435 }
00436
00437 template<class T>
00438 void Array<T>::InitializeDataBlock(int first, int last)
00439 {
00440 int i;
00441 for (i = first; i < last; i++)
00442 InitializeElement(i);
00443 }
00444
00445 template<class T>
00446 void Array<T>::UninitializeDataBlock(int first, int last)
00447 {
00448 int i;
00449 for (i = first; i < last; i++)
00450 (&mpData[i])->~T();
00451 }
00452
00453 template<class T>
00454 void Array<T>::CopyDataBlock(int first, int last, const T* src)
00455 {
00456 int i;
00457 for (i=first; i<last ;i++)
00458 mpData[i]=src[i];
00459 }
00460
00461 template<class T>
00462 void Array<T>::InitializeCopyDataBlock(int first, int last, const T* src)
00463 {
00464 int i;
00465 for (i=first; i<last; i++)
00466 new(&mpData[i]) T(src[i]);
00467 }
00468
00469 template<class T>
00470 void Array<T>::InitializeCopyDataBlock(int first, int last, int src_first, const T* src)
00471 {
00472 int i, j = src_first;
00473 for (i=first; i<last; i++)
00474 new (&mpData[i]) T(src[j++]);
00475 }
00476
00477
00478 template<class T>
00479 void Array<T>::DestroyDataBuffer()
00480 {
00481 if (OwnsMemory())
00482 {
00483 UninitializeDataBlock(0,mSize);
00484 free(mpData);
00485 }
00486 mpData=NULL;
00487 }
00488
00490 template<class T>
00491 void Array<T>::ResizeDataBuffer(int new_size)
00492 {
00493 if (new_size == mAllocSize)
00494 return;
00495 T* old_data = mpData;
00496 mpData = (T*) malloc(new_size*sizeof(T));
00497 if (!old_data) return;
00498 int elems = new_size;
00499 if (mSize < elems)
00500 elems = mSize;
00501 InitializeCopyDataBlock(0,elems,old_data);
00502 for (int i=0; i<mSize; i++)
00503 (&old_data[i])->~T();
00504 free(old_data);
00505 }
00506
00514 template<class T>
00515 void Array<T>::InsertElemInDataBuffer(int position)
00516 {
00517 if (mSize>0)
00518 new(&mpData[mSize]) T(mpData[mSize-1]);
00519 for (int i=mSize-1; i>position; i--)
00520 mpData[i] = mpData[i-1];
00521 (&mpData[position])->~T();
00522 }
00523
00530 template<class T>
00531 void Array<T>::DeleteElemInDataBuffer(int position)
00532 {
00533 for (int i=position; i<mSize-1; i++)
00534 mpData[i] = mpData[i+1];
00535 (&mpData[mSize-1])->~T();
00536 }
00537
00538
00539 template <class T> inline Array<T> operator + (
00540 const Array<T>& a,const Array<T>& b)
00541 {
00542 Array<T> ret = a;
00543 ret += b;
00544 return ret;
00545 }
00546
00547 template <class T> inline bool operator == (
00548 const Array<T>& a,const Array<T>& b)
00549 {
00550 if (a.Size()!=b.Size()) return false;
00551 for (int i=0;i<a.Size();i++)
00552 {
00553 if (a[i]!=b[i]) return false;
00554 }
00555 return true;
00556 }
00557
00558
00559
00560 typedef Array<TData> DataArray;
00561
00562 template<class T>
00563 const char* Array<T>::msgSetSizeOutOfRange =
00564 "Array::SetSize(): Argument larger than allocated size\n"
00565 "You can probably fix this calling Resize() befor SetSize().";
00566
00567 template<class T>
00568 const char* Array<T>::msgIndexOutOfRange =
00569 "Array::operator[]: Index out of range\n"
00570 "This may happen if you forgot to call SetSize(...) in your code.\n"
00571 "This is now needed. Just calling Resize() is not enough any more.";
00572
00573 template<class T>
00574 const char* Array<T>::msgInsertOutOfRange =
00575 "Array::InsertElem: Index out of range";
00576
00577 template<class T>
00578 const char* Array<T>::msgDeleteOutOfRange =
00579 "Array::DeleteElem: Index out of range";
00580
00581 }
00582
00583 #endif//_Array_
00584