00001 #ifndef AI_ARRAY_H
00002 #define AI_ARRAY_H
00003
00004 #include "../AI_Global.h"
00005
00006
00007
00026
00027
00028
00029 template<class TYPE> class AI_Array
00030 {
00031 public:
00032 typedef TYPE* iterator;
00033
00035 enum
00036 {
00037 DoubleGrowSize = (1<<0),
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
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;
00135 int allocSize;
00136 int numElements;
00137 int flags;
00138 TYPE* elements;
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
00357 int i;
00358 for (i = 0; i < this->numElements; i++)
00359 {
00360 newArray[i] = this->elements[i];
00361 }
00362
00363
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
00382 if (0 == this->allocSize)
00383 {
00384 growToSize = growSize;
00385 }
00386 else
00387 {
00388 growToSize = 2 * this->allocSize;
00389 }
00390 }
00391 else
00392 {
00393
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
00413 if (fromIndex == toIndex)
00414 {
00415 return;
00416 }
00417
00418
00419 int num = this->numElements - fromIndex;
00420
00421
00422 int neededSize = toIndex + num;
00423 while (neededSize > this->allocSize)
00424 {
00425 this->Grow();
00426 }
00427
00428 if (fromIndex > toIndex)
00429 {
00430
00431 int i;
00432 for (i = 0; i < num; i++)
00433 {
00434 this->elements[toIndex + i] = this->elements[fromIndex + i];
00435 }
00436
00437
00438 for (i = (fromIndex + i) - 1; i < this->numElements; i++)
00439 {
00440 this->Destroy(&(this->elements[i]));
00441 }
00442 }
00443 else
00444 {
00445
00446 int i;
00447 for (i = num - 1; i >= 0; --i)
00448 {
00449 this->elements[toIndex + i] = this->elements[fromIndex + i];
00450 }
00451
00452
00453 for (i = fromIndex; i < toIndex; i++)
00454 {
00455 this->Destroy(&(this->elements[i]));
00456 }
00457 }
00458
00459
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
00476 int num = this->numElements - fromIndex;
00477
00478
00479 if (fromIndex == toIndex)
00480 {
00481 return;
00482 }
00483
00484
00485 memmove(&(this->elements[toIndex]), &(this->elements[fromIndex]), num * sizeof(TYPE));
00486
00487
00488 this->numElements = toIndex + num;
00489 }
00490
00491
00494 template<class TYPE>
00495 TYPE&
00496 AI_Array<TYPE>::PushBack(const TYPE& elm)
00497 {
00498
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
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
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
00607 if (index >= this->allocSize)
00608 {
00609 ai_assert(this->growSize > 0);
00610 this->GrowTo(index + this->growSize);
00611 }
00612
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
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
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
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