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 DeleteElem(int where)
00210 {
00211 CLAM_ASSERT(OwnsMemory(),"Array::DeleteElem(): Resize requiered,"
00212 " but this array does not own its memory!");
00213 CLAM_ASSERT(where>-1 ,msgDeleteOutOfRange);
00214 CLAM_ASSERT(where<mSize,msgDeleteOutOfRange);
00215 DeleteElemInDataBuffer(where);
00216 mSize--;
00217 if (mSize<mAllocSize-mStep)
00218 Resize(mSize);
00219 }
00220
00221 Array<T>& operator = (const Array<T>& src)
00222 {
00223
00224 if ( OwnsMemory() )
00225 {
00226 if ( Size() != src.Size() )
00227 Resize( src.Size() );
00228 if ( src.OwnsMemory() )
00229 mStep = src.mStep;
00230 else
00231 mStep = 1;
00232 }
00233 else
00234 {
00235 CLAM_ASSERT( AllocatedSize() >= src.Size(),
00236 "Array::RegionWrite() : source size exceeds the Region bounds" );
00237 CLAM_ASSERT( GetPtr() != NULL,
00238 "Array::operator= : if you want to create a not memory owning array "
00239 "from one that does own memory, use instead Array::SetPtr() method");
00240 }
00241
00242 int tocopy = (src.Size()<Size())?src.Size():Size();
00243 CopyDataBlock(0,tocopy,src.GetPtr());
00244 InitializeCopyDataBlock(tocopy,src.Size(),src.GetPtr());
00245 mSize=src.Size();
00246
00247 return *this;
00248
00249 }
00250
00251 Array<T>& operator += (const Array<T>& src)
00252 {
00253 int start = Size();
00254 Resize(Size()+src.Size());
00255 mSize+=src.Size();
00256 int end = Size();
00257 InitializeCopyDataBlock(start,end,0,src.mpData);
00258 return *this;
00259 }
00260
00261 void Apply( T (*f)(T) )
00262 {
00263 int i;
00264 for (i=0; i<mSize; i++)
00265 (*this)[i] = f( (*this)[i] );
00266 }
00267
00268 void Apply( T (*f)(T,int),int parameter )
00269 {
00270 int i;
00271 for (i=0; i<mSize; i++)
00272 (*this)[i] = f( (*this)[i], parameter );
00273 }
00274
00275 void StoreOn(Storage & storage) const
00276 {
00277 StoreBufferOn((typename TypeInfo<T>::StorableAsLeaf *)NULL, mpData, storage);
00278 }
00279 void LoadFrom(Storage & storage)
00280 {
00281 LoadBufferFrom((typename TypeInfo<T>::StorableAsLeaf *)NULL, mpData, storage);
00282 }
00283
00284
00285
00286 static const char *msgSetSizeOutOfRange;
00287 static const char *msgIndexOutOfRange;
00288 static const char *msgInsertOutOfRange;
00289 static const char *msgDeleteOutOfRange;
00290
00291 private:
00292 inline void ResizeDataBuffer(int new_size);
00293 inline void DestroyDataBuffer(void);
00294 inline void InsertElemInDataBuffer(int position);
00295 inline void DeleteElemInDataBuffer(int position);
00296 inline void InitializeElement(int position);
00297 inline void InitializeDataBlock(int first, int last);
00298 inline void UninitializeDataBlock(int first, int last);
00299 inline void CopyDataBlock(int first, int last, const T* src);
00300 inline void InitializeCopyDataBlock(int first, int last, const T* src);
00301 inline void InitializeCopyDataBlock(int first, int last, int src_first, const T* src);
00302
00303 void StoreBufferOn(StaticFalse* asLeave, const Component * polymorphicSelector, Storage & storage) const
00304 {
00305 if (mSize<=0) return;
00306 const char* className = mpData[0].GetClassName();
00307 const char* label = className? className : "Element";
00308 for (int i=0; i<mSize; i++)
00309 {
00310 XMLComponentAdapter adapter(mpData[i], label, true);
00311 storage.Store(adapter);
00312 }
00313 }
00314 void StoreBufferOn(StaticTrue* asLeave, const void * polymorphicSelector, Storage & storage) const
00315 {
00316 XMLAdapter<unsigned> sizeAdapter(Size(),"size");
00317 storage.Store(sizeAdapter);
00318 XMLArrayAdapter<T> adapter(mpData,mSize);
00319 storage.Store(adapter);
00320 }
00321 void StoreBufferOn(StaticFalse* asLeave, const void * polymorphicSelector, Storage & storage) const
00322 {
00323 CLAM_ASSERT(false,
00324 "Trying to Store an object that is not neither a streamable nor a Component");
00325 }
00326 void LoadBufferFrom(StaticFalse* asLeave, Component * polymorphicSelector, Storage & storage)
00327 {
00328 const char* label = 0;
00329 while (true)
00330 {
00331 T elem;
00332 if (!label)
00333 {
00334 label = elem.GetClassName();
00335 if (!label)
00336 label = "Element";
00337 }
00338 XMLComponentAdapter adapter(elem, label, true);
00339 if (!storage.Load(adapter)) return;
00340 AddElem(elem);
00341 }
00342 }
00343 void LoadBufferFrom(StaticTrue* asLeave, void * polymorphicSelector, Storage & storage)
00344 {
00345 unsigned size;
00346 XMLAdapter<unsigned> sizeAdapter(size,"size");
00347 if (storage.Load(sizeAdapter))
00348 {
00349 Resize(size);
00350 SetSize(size);
00351 XMLArrayAdapter<T> adapter(mpData,mSize);
00352 storage.Load(adapter);
00353
00354 return;
00355 }
00356
00357 while (true) {
00358 T elem;
00359 XMLAdapter<T> adapter(elem);
00360 if ( ! storage.Load(adapter)) return;
00361 AddElem(elem);
00362 }
00363 }
00364 void LoadBufferFrom(StaticFalse* asLeave, void * polymorphicSelector, Storage & storage)
00365 {
00366 CLAM_ASSERT(false,
00367 "Trying to Store an object that is not neither a streamable nor a Component");
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385 bool LoadMemberFrom(StaticTrue* asLeave, void * item, Storage & storage) {
00386 XMLAdapter<T> adapter(*(T*)item);
00387 return storage.Load(adapter);
00388 }
00389 bool LoadMemberFrom(StaticFalse* asLeave, Component * item, Storage & storage) {
00390 const char* className = (item->GetClassName());
00391 const char* label = className? className : "Element";
00392 XMLComponentAdapter adapter(*item, label, true);
00393 return storage.Load(adapter);
00394 }
00395 bool LoadMemberFrom(StaticFalse* asLeave, void * item, Storage & storage) {
00396 CLAM_ASSERT(false, "Trying to Load an object that is not neither a streamable nor a Component");
00397 return false;
00398 }
00399
00400 };
00401
00402
00403
00404
00405 template<class T>
00406 void Array<T>::GiveChunk(int pos, int size, Array<T>& a) const
00407 {
00408 CLAM_ASSERT(pos + size <= mSize,
00409 "Array::GiveChunk(): Chunk out of bounds.");
00410 a.SetPtr(&mpData[pos],size);
00411 }
00412
00413 template<class T>
00414 void Array<T>::CopyChunk(int pos, int size, Array<T>& a) const
00415 {
00416 int last=pos+size;
00417 CLAM_ASSERT(last <= mSize,
00418 "Array::CopyChunk(): Chunk out of bounds.");
00419 CLAM_ASSERT(size <= a.mSize,
00420 "Array::CopyChunk(): destination array does not have enough memory");
00421 for (int i=pos;i<last;i++)
00422 a.mpData[i-pos]=mpData[i];
00423 }
00424
00425 template<class T>
00426 void Array<T>::InitializeElement(int i)
00427 {
00428 new (&mpData[i]) T();
00429 }
00430
00431 template<class T>
00432 void Array<T>::InitializeDataBlock(int first, int last)
00433 {
00434 int i;
00435 for (i = first; i < last; i++)
00436 InitializeElement(i);
00437 }
00438
00439 template<class T>
00440 void Array<T>::UninitializeDataBlock(int first, int last)
00441 {
00442 int i;
00443 for (i = first; i < last; i++)
00444 (&mpData[i])->~T();
00445 }
00446
00447 template<class T>
00448 void Array<T>::CopyDataBlock(int first, int last, const T* src)
00449 {
00450 int i;
00451 for (i=first; i<last ;i++)
00452 mpData[i]=src[i];
00453 }
00454
00455 template<class T>
00456 void Array<T>::InitializeCopyDataBlock(int first, int last, const T* src)
00457 {
00458 int i;
00459 for (i=first; i<last; i++)
00460 new(&mpData[i]) T(src[i]);
00461 }
00462
00463 template<class T>
00464 void Array<T>::InitializeCopyDataBlock(int first, int last, int src_first, const T* src)
00465 {
00466 int i, j = src_first;
00467 for (i=first; i<last; i++)
00468 new (&mpData[i]) T(src[j++]);
00469 }
00470
00471
00472 template<class T>
00473 void Array<T>::DestroyDataBuffer()
00474 {
00475 if (OwnsMemory())
00476 {
00477 UninitializeDataBlock(0,mSize);
00478 free(mpData);
00479 }
00480 mpData=NULL;
00481 }
00482
00484 template<class T>
00485 void Array<T>::ResizeDataBuffer(int new_size)
00486 {
00487 if (new_size == mAllocSize)
00488 return;
00489 T* old_data = mpData;
00490 mpData = (T*) malloc(new_size*sizeof(T));
00491 if (!old_data) return;
00492 int elems = new_size;
00493 if (mSize < elems)
00494 elems = mSize;
00495 InitializeCopyDataBlock(0,elems,old_data);
00496 for (int i=0; i<mSize; i++)
00497 (&old_data[i])->~T();
00498 free(old_data);
00499 }
00500
00508 template<class T>
00509 void Array<T>::InsertElemInDataBuffer(int position)
00510 {
00511 if (mSize>0)
00512 new(&mpData[mSize]) T(mpData[mSize-1]);
00513 for (int i=mSize-1; i>position; i--)
00514 mpData[i] = mpData[i-1];
00515 (&mpData[position])->~T();
00516 }
00517
00524 template<class T>
00525 void Array<T>::DeleteElemInDataBuffer(int position)
00526 {
00527 for (int i=position; i<mSize-1; i++)
00528 mpData[i] = mpData[i+1];
00529 (&mpData[mSize-1])->~T();
00530 }
00531
00532
00533 template <class T> inline Array<T> operator + (
00534 const Array<T>& a,const Array<T>& b)
00535 {
00536 Array<T> ret = a;
00537 ret += b;
00538 return ret;
00539 }
00540
00541 template <class T> inline bool operator == (
00542 const Array<T>& a,const Array<T>& b)
00543 {
00544 if (a.Size()!=b.Size()) return false;
00545 for (int i=0;i<a.Size();i++)
00546 {
00547 if (a[i]!=b[i]) return false;
00548 }
00549 return true;
00550 }
00551
00552
00553
00554 typedef Array<TData> DataArray;
00555
00556 template<class T>
00557 const char* Array<T>::msgSetSizeOutOfRange =
00558 "Array::SetSize(): Argument larger than allocated size\n"
00559 "You can probably fix this calling Resize() befor SetSize().";
00560
00561 template<class T>
00562 const char* Array<T>::msgIndexOutOfRange =
00563 "Array::operator[]: Index out of range\n"
00564 "This may happen if you forgot to call SetSize(...) in your code.\n"
00565 "This is now needed. Just calling Resize() is not enough any more.";
00566
00567 template<class T>
00568 const char* Array<T>::msgInsertOutOfRange =
00569 "Array::InsertElem: Index out of range";
00570
00571 template<class T>
00572 const char* Array<T>::msgDeleteOutOfRange =
00573 "Array::DeleteElem: Index out of range";
00574
00575 }
00576
00577 #endif//_Array_
00578