AI_Array.h

Go to the documentation of this file.
00001 #ifndef AI_ARRAY_H
00002 #define AI_ARRAY_H
00003 
00004 #include "../AI_Global.h"
00005 
00006 
00007 //------------------------------------------------------------------------------
00026 //#include "kernel/ntypes.h"
00027 
00028 //------------------------------------------------------------------------------
00029 template<class TYPE> class AI_Array
00030 {
00031 public:
00032     typedef TYPE* iterator;
00033 
00035     enum
00036     {
00037         DoubleGrowSize = (1<<0),    // when set, grow size doubles each turn
00038     };
00039 
00041     AI_Array();
00043     AI_Array(int initialSize, int initialGrow);
00045     AI_Array(int initialSize, int initialGrow, TYPE initialValue);
00047     AI_Array(const AI_Array<TYPE>& rhs);
00049     ~AI_Array();
00051     AI_Array<TYPE>& operator=(const AI_Array<TYPE>& rhs);
00053     TYPE& operator[](int index) const;
00055     //bool operator==(const AI_Array<TYPE>& rhs) const;
00056 
00058     void SetFlags(int f);
00060     int GetFlags() const;
00062     void SetFixedSize(int size);
00064     TYPE& PushBack(const TYPE& elm);
00066     TYPE& PushBack(void);
00068     void PopBack(void);
00070     void PopBack(int num);
00072     void Append(const TYPE& elm);
00074     iterator Reserve(int num);
00076     int Size() const;
00078     int AllocSize() const;
00080     TYPE& Set(int index, const TYPE& elm);
00082     TYPE& At(int index);
00084     TYPE& Front() const;
00086     TYPE& Back() const;
00088     bool Empty() const;
00090     void Erase(int index);
00092     void EraseQuick(int index);
00094     iterator Erase(iterator iter);
00096     iterator EraseQuick(iterator iter);
00098     void Insert(int index, const TYPE& elm);
00100     void Clear();
00102     void Reset();
00104     iterator Begin() const;
00106     iterator End() const;
00108     iterator Find(const TYPE& elm) const;
00110     int FindIndex(const TYPE& elm) const;
00112     void Fill(int first, int num, const TYPE& elm);
00114     void Reallocate(int initialSize, int grow);
00115 
00116 private:
00118     void CheckIndex(int);
00120     void Destroy(TYPE* elm);
00122     void Copy(const AI_Array<TYPE>& src);
00124     void Delete();
00126     void Grow();
00128     void GrowTo(int newAllocSize);
00130     void Move(int fromIndex, int toIndex);
00132     void MoveQuick(int fromIndex, int toIndex);
00133 
00134     int growSize;           // grow by this number of elements if array exhausted
00135     int allocSize;          // number of elements allocated
00136     int numElements;        // number of elements in array
00137     int flags;
00138     TYPE* elements;         // pointer to element array
00139 };
00140 
00141 //------------------------------------------------------------------------------
00144 template<class TYPE>
00145 AI_Array<TYPE>::AI_Array() :
00146     growSize(16),
00147     allocSize(0),
00148     numElements(0),
00149     flags(0)
00150 {
00151     this->elements = 0;
00152 }
00153 
00154 //------------------------------------------------------------------------------
00158 template<class TYPE>
00159 AI_Array<TYPE>::AI_Array(int initialSize, int grow) :
00160     growSize(grow),
00161     allocSize(initialSize),
00162     numElements(0),
00163     flags(0)
00164 {
00165     ai_assert(initialSize >= 0);
00166     if (initialSize > 0)
00167     {
00168         this->elements = ai_new_array(TYPE,this->allocSize);
00169     }
00170     else
00171     {
00172         this->elements = 0;
00173     }
00174 }
00175 
00176 //------------------------------------------------------------------------------
00180 template<class TYPE>
00181 AI_Array<TYPE>::AI_Array(int initialSize, int grow, TYPE initialValue) :
00182     growSize(grow),
00183     allocSize(initialSize),
00184     numElements(initialSize),
00185     flags(0)
00186 {
00187     ai_assert(initialSize >= 0);
00188     if (initialSize > 0)
00189     {
00190         this->elements = ai_new_array(TYPE, this->allocSize);
00191         int i;
00192         for (i = 0; i < initialSize; i++)
00193         {
00194             this->elements[i] = initialValue;
00195         }
00196     }
00197     else
00198     {
00199         this->elements = 0;
00200     }
00201 }
00202 
00203 //------------------------------------------------------------------------------
00206 template<class TYPE>
00207 void
00208 AI_Array<TYPE>::Copy(const AI_Array<TYPE>& src)
00209 {
00210     ai_assert(0 == this->elements);
00211 
00212     this->growSize    = src.growSize;
00213     this->allocSize   = src.allocSize;
00214     this->numElements = src.numElements;
00215     this->flags       = src.flags;
00216     if (this->allocSize > 0)
00217     {
00218         this->elements = ai_new_array(TYPE, this->allocSize);
00219         int i;
00220         for (i = 0; i < this->numElements; i++)
00221         {
00222             this->elements[i] = src.elements[i];
00223         }
00224     }
00225 }
00226 
00227 //------------------------------------------------------------------------------
00230 template<class TYPE>
00231 void
00232 AI_Array<TYPE>::Delete()
00233 {
00234     this->growSize = 0;
00235     this->allocSize = 0;
00236     this->numElements = 0;
00237     this->flags = 0;
00238     if (this->elements)
00239     {
00240         ai_delete_array(this->elements);
00241         this->elements = 0;
00242     }
00243 }
00244 
00245 //------------------------------------------------------------------------------
00248 template<class TYPE>
00249 void
00250 AI_Array<TYPE>::Destroy(TYPE* elm)
00251 {
00252     elm->~TYPE();
00253 }
00254 
00255 //------------------------------------------------------------------------------
00258 template<class TYPE>
00259 AI_Array<TYPE>::AI_Array(const AI_Array<TYPE>& rhs) :
00260     growSize(0),
00261     allocSize(0),
00262     numElements(0),
00263     elements(0),
00264     flags(0)
00265 {
00266     this->Copy(rhs);
00267 }
00268 
00269 //------------------------------------------------------------------------------
00272 template<class TYPE>
00273 AI_Array<TYPE>::~AI_Array()
00274 {
00275     this->Delete();
00276 }
00277 
00278 //------------------------------------------------------------------------------
00281 template<class TYPE>
00282 void
00283 AI_Array<TYPE>::SetFlags(int f)
00284 {
00285     this->flags = f;
00286 }
00287 
00288 //------------------------------------------------------------------------------
00291 template<class TYPE>
00292 int
00293 AI_Array<TYPE>::GetFlags() const
00294 {
00295     return this->flags;
00296 }
00297 
00298 //------------------------------------------------------------------------------
00301 template<class TYPE>
00302 void
00303 AI_Array<TYPE>::Reallocate(int initialSize, int grow)
00304 {
00305     this->Delete();
00306     this->growSize    = grow;
00307     this->allocSize   = initialSize;
00308     this->numElements = 0;
00309     if (initialSize > 0)
00310     {
00311         this->elements = ai_new_array(TYPE, initialSize);
00312     }
00313     else
00314     {
00315         this->elements = 0;
00316     }
00317 }
00318 
00319 //------------------------------------------------------------------------------
00325 template<class TYPE>
00326 void
00327 AI_Array<TYPE>::SetFixedSize(int size)
00328 {
00329     this->Reallocate(size, 0);
00330     this->numElements = size;
00331 }
00332 
00333 //------------------------------------------------------------------------------
00336 template<class TYPE>
00337 AI_Array<TYPE>&
00338 AI_Array<TYPE>::operator=(const AI_Array<TYPE>& rhs)
00339 {
00340     this->Delete();
00341     this->Copy(rhs);
00342     return *this;
00343 }
00344 
00345 //------------------------------------------------------------------------------
00348 template<class TYPE>
00349 void
00350 AI_Array<TYPE>::GrowTo(int newAllocSize)
00351 {
00352     TYPE* newArray = ai_new_array(TYPE, newAllocSize);
00353 
00354     if (this->elements)
00355     {
00356         // copy over contents
00357         int i;
00358         for (i = 0; i < this->numElements; i++)
00359         {
00360             newArray[i] = this->elements[i];
00361         }
00362 
00363         // discard old array and update contents
00364         ai_delete_array(this->elements);
00365     }
00366     this->elements  = newArray;
00367     this->allocSize = newAllocSize;
00368 }
00369 
00370 //------------------------------------------------------------------------------
00373 template<class TYPE>
00374 void
00375 AI_Array<TYPE>::Grow()
00376 {
00377     ai_assert(this->growSize > 0);
00378     int growToSize;
00379     if ((DoubleGrowSize & this->flags) != 0)
00380     {
00381         // double growth behaviour
00382         if (0 == this->allocSize)
00383         {
00384             growToSize = growSize;
00385         }
00386         else
00387         {
00388             growToSize = 2 * this->allocSize;
00389         }
00390     }
00391     else
00392     {
00393         // classic linear growth behaviour
00394         growToSize = this->allocSize + this->growSize;
00395     }
00396     this->GrowTo(growToSize);
00397 }
00398 
00399 //------------------------------------------------------------------------------
00405 template<class TYPE>
00406 void
00407 AI_Array<TYPE>::Move(int fromIndex, int toIndex)
00408 {
00409     ai_assert(this->elements);
00410     ai_assert(fromIndex < this->numElements);
00411 
00412     // nothing to move?
00413     if (fromIndex == toIndex)
00414     {
00415         return;
00416     }
00417 
00418     // compute number of elements to move
00419     int num = this->numElements - fromIndex;
00420 
00421     // check if array needs to grow
00422     int neededSize = toIndex + num;
00423     while (neededSize > this->allocSize)
00424     {
00425         this->Grow();
00426     }
00427 
00428     if (fromIndex > toIndex)
00429     {
00430         // this is a backward move
00431         int i;
00432         for (i = 0; i < num; i++)
00433         {
00434             this->elements[toIndex + i] = this->elements[fromIndex + i];
00435         }
00436 
00437         // destroy remaining elements
00438         for (i = (fromIndex + i) - 1; i < this->numElements; i++)
00439         {
00440             this->Destroy(&(this->elements[i]));
00441         }
00442     }
00443     else
00444     {
00445         // this is a forward move
00446         int i;
00447         for (i = num - 1; i >= 0; --i)
00448         {
00449             this->elements[toIndex + i] = this->elements[fromIndex + i];
00450         }
00451 
00452         // destroy freed elements
00453         for (i = fromIndex; i < toIndex; i++)
00454         {
00455             this->Destroy(&(this->elements[i]));
00456         }
00457     }
00458 
00459     // adjust array size
00460     this->numElements = toIndex + num;
00461 }
00462 
00463 //------------------------------------------------------------------------------
00468 template<class TYPE>
00469 void
00470 AI_Array<TYPE>::MoveQuick(int fromIndex, int toIndex)
00471 {
00472     ai_assert(this->elements);
00473     ai_assert(fromIndex < this->numElements);
00474 
00475     // compute number of elements to move
00476     int num = this->numElements - fromIndex;
00477 
00478     // nothing to move?
00479     if (fromIndex == toIndex)
00480     {
00481         return;
00482     }
00483 
00484     // do a direct memory move
00485     memmove(&(this->elements[toIndex]), &(this->elements[fromIndex]), num * sizeof(TYPE));
00486 
00487     // adjust array size
00488     this->numElements = toIndex + num;
00489 }
00490 
00491 //------------------------------------------------------------------------------
00494 template<class TYPE>
00495 TYPE&
00496 AI_Array<TYPE>::PushBack(const TYPE& elm)
00497 {
00498     // grow allocated space if exhausted
00499     if (this->numElements == this->allocSize)
00500     {
00501         this->Grow();
00502     }
00503     ai_assert(this->elements);
00504     this->elements[this->numElements] = elm;
00505     return this->elements[this->numElements++];
00506 }
00507 
00508 //------------------------------------------------------------------------------
00511 template<class TYPE>
00512 TYPE&
00513 AI_Array<TYPE>::PushBack(void)
00514 {
00515     // grow allocated space if exhausted
00516     if (this->numElements == this->allocSize)
00517     {
00518         this->Grow();
00519     }
00520     ai_assert(this->elements);
00521     return this->elements[this->numElements++];
00522 }
00523 
00524 
00525 //------------------------------------------------------------------------------
00528 template<class TYPE>
00529 void
00530 AI_Array<TYPE>::PopBack(void)
00531 {
00532     if (this->numElements > 0)
00533     {
00534         this->numElements--;
00535     }
00536 }
00537 
00538 
00539 //------------------------------------------------------------------------------
00542 template<class TYPE>
00543 void
00544 AI_Array<TYPE>::PopBack(int num)
00545 {
00546     ai_assert(num>0);
00547     if (this->numElements > num)
00548     {
00549         this->numElements-=num;
00550     }
00551     else
00552     {
00553         Reset();
00554     }
00555 }
00556 
00557 //------------------------------------------------------------------------------
00560 template<class TYPE>
00561 void
00562 AI_Array<TYPE>::Append(const TYPE& elm)
00563 {
00564     // grow allocated space if exhausted
00565     if (this->numElements == this->allocSize)
00566     {
00567         this->Grow();
00568     }
00569     ai_assert(this->elements);
00570     this->elements[this->numElements++] = elm;
00571 }
00572 
00573 //------------------------------------------------------------------------------
00579 template<class TYPE>
00580 typename AI_Array<TYPE>::iterator
00581 AI_Array<TYPE>::Reserve(int num)
00582 {
00583     ai_assert(num > 0);
00584     int maxElement = this->numElements + num;
00585     while (maxElement >= this->allocSize)
00586     {
00587         this->Grow();
00588     }
00589     ai_assert(this->elements);
00590     iterator iter = this->elements + this->numElements;
00591     this->numElements += num;
00592     return iter;
00593 }
00594 
00595 //------------------------------------------------------------------------------
00600 template<class TYPE>
00601 void
00602 AI_Array<TYPE>::CheckIndex(int index)
00603 {
00604     if (index >= this->numElements)
00605     {
00606         // grow array if necessary
00607         if (index >= this->allocSize)
00608         {
00609             ai_assert(this->growSize > 0);
00610             this->GrowTo(index + this->growSize);
00611         }
00612         // update number of contained elements
00613         this->numElements = index + 1;
00614     }
00615 }
00616 
00617 //------------------------------------------------------------------------------
00620 template<class TYPE>
00621 TYPE&
00622 AI_Array<TYPE>::Set(int index, const TYPE& elm)
00623 {
00624     this->CheckIndex(index);
00625     this->elements[index] = elm;
00626     return this->elements[index];
00627 }
00628 
00629 //------------------------------------------------------------------------------
00632 template<class TYPE>
00633 int
00634 AI_Array<TYPE>::Size() const
00635 {
00636     return this->numElements;
00637 }
00638 
00639 //------------------------------------------------------------------------------
00642 template<class TYPE>
00643 int
00644 AI_Array<TYPE>::AllocSize() const
00645 {
00646     return this->allocSize;
00647 }
00648 
00649 //------------------------------------------------------------------------------
00654 template<class TYPE>
00655 TYPE&
00656 AI_Array<TYPE>::At(int index)
00657 {
00658     this->CheckIndex(index);
00659     return this->elements[index];
00660 }
00661 
00662 //------------------------------------------------------------------------------
00667 template<class TYPE>
00668 TYPE&
00669 AI_Array<TYPE>::operator[](int index) const
00670 {
00671     ai_assert(this->elements && (index >= 0) && (index < this->numElements));
00672     return this->elements[index];
00673 }
00674 
00675 //------------------------------------------------------------------------------
00678 template<class TYPE>
00679 TYPE&
00680 AI_Array<TYPE>::Front() const
00681 {
00682     ai_assert(this->elements && (this->numElements > 0));
00683     return this->elements[0];
00684 }
00685 
00686 //------------------------------------------------------------------------------
00689 template<class TYPE>
00690 TYPE&
00691 AI_Array<TYPE>::Back() const
00692 {
00693     ai_assert(this->elements && (this->numElements > 0));
00694     return this->elements[this->numElements - 1];
00695 }
00696 
00697 //------------------------------------------------------------------------------
00700 template<class TYPE>
00701 bool
00702 AI_Array<TYPE>::Empty() const
00703 {
00704     return (this->numElements == 0);
00705 }
00706 
00707 //------------------------------------------------------------------------------
00710 template<class TYPE>
00711 void
00712 AI_Array<TYPE>::Erase(int index)
00713 {
00714     ai_assert(this->elements && (index >= 0) && (index < this->numElements));
00715     if (index == (this->numElements - 1))
00716     {
00717         // special case: last element
00718         this->Destroy(&(this->elements[index]));
00719         this->numElements--;
00720     }
00721     else
00722     {
00723         this->Move(index + 1, index);
00724     }
00725 }
00726 
00727 //------------------------------------------------------------------------------
00732 template<class TYPE>
00733 void
00734 AI_Array<TYPE>::EraseQuick(int index)
00735 {
00736     ai_assert(this->elements && (index >= 0) && (index < this->numElements));
00737     if (index == (this->numElements - 1))
00738     {
00739         // special case: last element
00740         this->numElements--;
00741     }
00742     else
00743     {
00744         this->MoveQuick(index + 1, index);
00745     }
00746 }
00747 
00748 //------------------------------------------------------------------------------
00751 template<class TYPE>
00752 typename AI_Array<TYPE>::iterator
00753 AI_Array<TYPE>::Erase(typename AI_Array<TYPE>::iterator iter)
00754 {
00755     ai_assert(this->elements && (iter >= this->elements) && (iter < (this->elements + this->numElements)));
00756     this->Erase( (int)(iter - this->elements) );
00757     return iter;
00758 }
00759 
00760 //------------------------------------------------------------------------------
00765 template<class TYPE>
00766 typename AI_Array<TYPE>::iterator
00767 AI_Array<TYPE>::EraseQuick(typename AI_Array<TYPE>::iterator iter)
00768 {
00769     ai_assert(this->elements && (iter >= this->elements) && (iter < (this->elements + this->numElements)));
00770     this->EraseQuick( (int)(iter - this->elements) );
00771     return iter;
00772 }
00773 
00774 
00775 //------------------------------------------------------------------------------
00778 template<class TYPE>
00779 void
00780 AI_Array<TYPE>::Insert(int index, const TYPE& elm)
00781 {
00782     ai_assert((index >= 0) && (index <= this->numElements));
00783     if (index == this->numElements)
00784     {
00785         // special case: append element to back
00786         this->PushBack(elm);
00787     }
00788     else
00789     {
00790         this->Move(index, index + 1);
00791         this->elements[index] = elm;
00792     }
00793 }
00794 
00795 //------------------------------------------------------------------------------
00800 template<class TYPE>
00801 void
00802 AI_Array<TYPE>::Clear()
00803 {
00804     int i;
00805     for (i = 0; i < this->numElements; i++)
00806     {
00807         this->Destroy(&(this->elements[i]));
00808     }
00809     this->numElements = 0;
00810 }
00811 
00812 //------------------------------------------------------------------------------
00817 template<class TYPE>
00818 void
00819 AI_Array<TYPE>::Reset()
00820 {
00821     this->numElements = 0;
00822 }
00823 
00824 //------------------------------------------------------------------------------
00827 template<class TYPE>
00828 typename AI_Array<TYPE>::iterator
00829 AI_Array<TYPE>::Begin() const
00830 {
00831     return this->elements;
00832 }
00833 
00834 //------------------------------------------------------------------------------
00837 template<class TYPE>
00838 typename AI_Array<TYPE>::iterator
00839 AI_Array<TYPE>::End() const
00840 {
00841     return this->elements + this->numElements;
00842 }
00843 
00844 //------------------------------------------------------------------------------
00852 template<class TYPE>
00853 typename AI_Array<TYPE>::iterator
00854 AI_Array<TYPE>::Find(const TYPE& elm) const
00855 {
00856     int index;
00857     for (index = 0; index < this->numElements; index++)
00858     {
00859         if (this->elements[index] == elm)
00860         {
00861             return &(this->elements[index]);
00862         }
00863     }
00864     return 0;
00865 }
00866 
00867 //------------------------------------------------------------------------------
00875 template<class TYPE>
00876 int
00877 AI_Array<TYPE>::FindIndex(const TYPE& elm) const
00878 {
00879     int index;
00880     for (index = 0; index < this->numElements; index++)
00881     {
00882         if (this->elements[index] == elm)
00883         {
00884             return index;
00885         }
00886     }
00887     return -1;
00888 }
00889 
00890 //------------------------------------------------------------------------------
00899 template<class TYPE>
00900 void
00901 AI_Array<TYPE>::Fill(int first, int num, const TYPE& elm)
00902 {
00903     if ((first + num) > this->numElements)
00904     {
00905         this->GrowTo(first + num);
00906     }
00907     int i;
00908     for (i = first; i < (first + num); i++)
00909     {
00910         this->elements[i] = elm;
00911     }
00912 }
00913 
00914 //------------------------------------------------------------------------------
00915 
00916 //------------------------------------------------------------------------------
00923 template<class TYPE> 
00924 inline bool
00925 operator==(const AI_Array<TYPE> &left, const AI_Array<TYPE> &right)
00926 {
00927     return ( left.Size()==right.Size() &&
00928              ::memcmp(left.Begin(), right.Begin(), left.End() - left.Begin()) );
00929              
00930 }
00931 
00932 #endif