csutil/array.h
Go to the documentation of this file.00001 /* 00002 Crystal Space Generic Array Template 00003 Copyright (C) 2003 by Matze Braun 00004 Copyright (C) 2003 by Jorrit Tyberghein 00005 Copyright (C) 2003,2004 by Eric Sunshine 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 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 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public 00018 License along with this library; if not, write to the Free 00019 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00020 */ 00021 #ifndef __CSUTIL_ARRAY_H__ 00022 #define __CSUTIL_ARRAY_H__ 00023 00028 #include "csutil/allocator.h" 00029 #include "csutil/comparator.h" 00030 #include "csutil/customallocated.h" 00031 00032 #include "csutil/custom_new_disable.h" 00033 00034 #if defined(CS_MEMORY_TRACKER) 00035 #include "csutil/memdebug.h" 00036 #include "csutil/snprintf.h" 00037 #include <typeinfo> 00038 #endif 00039 00052 template <class T, class K> 00053 class csArrayCmp 00054 { 00055 public: 00061 typedef int(*CF)(T const&, K const&); 00063 csArrayCmp(K const& k, CF c = DefaultCompare) : key(k), cmp(c) {} 00065 csArrayCmp(csArrayCmp const& o) : key(o.key), cmp(o.cmp) {} 00067 csArrayCmp& operator=(csArrayCmp const& o) 00068 { key = o.key; cmp = o.cmp; return *this; } 00077 int operator()(T const& r) const { return cmp(r, key); } 00079 operator CF() const { return cmp; } 00081 operator K const&() const { return key; } 00092 static int DefaultCompare(T const& r, K const& k) 00093 { return csComparator<T,K>::Compare(r,k); } 00094 private: 00095 K key; 00096 CF cmp; 00097 }; 00098 00102 template <class T> 00103 class csArrayElementHandler 00104 { 00105 public: 00107 static void Construct (T* address) 00108 { 00109 new (static_cast<void*> (address)) T(); 00110 } 00111 00113 static void Construct (T* address, T const& src) 00114 { 00115 new (static_cast<void*> (address)) T(src); 00116 } 00117 00119 static void Destroy (T* address) 00120 { 00121 address->~T(); 00122 } 00123 00125 static void InitRegion (T* address, size_t count) 00126 { 00127 for (size_t i = 0 ; i < count ; i++) 00128 Construct (address + i); 00129 } 00130 00132 template<typename Allocator> 00133 static T* ResizeRegion (Allocator& alloc, T* mem, size_t relevantcount, 00134 size_t oldcount, size_t newcount) 00135 { 00136 (void)relevantcount; 00137 T* newp = (T*)alloc.Realloc (mem, newcount * sizeof(T)); 00138 if (newp != 0) return newp; 00139 // Realloc() failed - allocate a new block 00140 newp = (T*)alloc.Alloc (newcount * sizeof(T)); 00141 if (newcount < oldcount) 00142 memcpy (newp, mem, newcount * sizeof(T)); 00143 else 00144 memcpy (newp, mem, oldcount * sizeof(T)); 00145 alloc.Free (mem); 00146 return newp; 00147 } 00148 00150 static void MoveElements (T* mem, size_t dest, size_t src, size_t count) 00151 { 00152 memmove (mem + dest, mem + src, count * sizeof(T)); 00153 } 00154 }; 00155 00164 template <class T> 00165 class csArraySafeCopyElementHandler 00166 { 00167 public: 00168 static void Construct (T* address) 00169 { 00170 new (static_cast<void*> (address)) T(); 00171 } 00172 00173 static void Construct (T* address, T const& src) 00174 { 00175 new (static_cast<void*> (address)) T(src); 00176 } 00177 00178 static void Destroy (T* address) 00179 { 00180 address->~T(); 00181 } 00182 00183 static void InitRegion (T* address, size_t count) 00184 { 00185 for (size_t i = 0 ; i < count ; i++) 00186 Construct (address + i); 00187 } 00188 00194 template<typename Allocator> 00195 static T* ResizeRegion (Allocator& alloc, T* mem, size_t relevantcount, 00196 size_t oldcount, size_t newcount) 00197 { 00198 if (newcount <= oldcount) 00199 { 00200 // Realloc is safe. 00201 T* newmem = (T*)alloc.Realloc (mem, newcount * sizeof (T)); 00202 if (newmem != 0) 00203 { 00204 CS_ASSERT (newmem == mem); 00205 return newmem; 00206 } 00207 // else Realloc() failed (probably not supported) - allocate a new block 00208 } 00209 00210 T* newmem = (T*)alloc.Alloc (newcount * sizeof (T)); 00211 size_t i; 00212 for (i = 0 ; i < relevantcount ; i++) 00213 { 00214 Construct (newmem + i, mem[i]); 00215 Destroy (mem + i); 00216 } 00217 alloc.Free (mem); 00218 return newmem; 00219 } 00220 00226 static void MoveElements (T* mem, size_t dest, size_t src, size_t count) 00227 { 00228 size_t i; 00229 if (dest < src) 00230 { 00231 for (i = 0 ; i < count ; i++) 00232 { 00233 Construct (mem + dest + i, mem[src + i]); 00234 Destroy (mem + src + i); 00235 } 00236 } 00237 else 00238 { 00239 i = count; 00240 while (i > 0) 00241 { 00242 i--; 00243 Construct (mem + dest + i, mem[src + i]); 00244 Destroy (mem + src + i); 00245 } 00246 } 00247 } 00248 }; 00249 00250 00255 class csArrayThresholdVariable 00256 { 00257 size_t threshold; 00258 public: 00260 csArrayThresholdVariable (size_t in_threshold = 0) 00261 { threshold = (in_threshold > 0 ? in_threshold : 16); } 00263 size_t GetThreshold() const { return threshold; } 00264 }; 00265 00270 template<int N> 00271 class csArrayThresholdFixed 00272 { 00273 public: 00275 csArrayThresholdFixed (size_t x = 0) 00276 { (void)x; } 00278 size_t GetThreshold() const { return N; } 00279 // Work around VC7 bug apparently incorrectly copying this empty class 00280 csArrayThresholdFixed& operator= (const csArrayThresholdFixed&) 00281 { return *this; } 00282 }; 00283 00291 template<typename Threshold = csArrayThresholdVariable> 00292 class csArrayCapacityLinear : public Threshold 00293 { 00294 public: 00296 00297 csArrayCapacityLinear () : Threshold () {} 00298 csArrayCapacityLinear (const Threshold& threshold) : Threshold (threshold) 00299 {} 00301 00307 csArrayCapacityLinear (const size_t x) : Threshold (x) 00308 {} 00309 00315 bool IsCapacityExcessive (size_t capacity, size_t count) const 00316 { 00317 return (capacity > this->GetThreshold() 00318 && count < capacity - this->GetThreshold()); 00319 } 00325 size_t GetCapacity (size_t count) const 00326 { 00327 return ((count + this->GetThreshold() - 1) / this->GetThreshold()) * 00328 this->GetThreshold(); 00329 } 00330 }; 00331 00332 // Alias for csArrayCapacityLinear<csArrayThresholdVariable> to keep 00333 // SWIG generated Java classes (and thus filenames) short enough for Windows. 00334 // Note that a typedef wont work because SWIG would expand it. 00335 struct csArrayCapacityDefault : 00336 public csArrayCapacityLinear<csArrayThresholdVariable> 00337 { 00338 csArrayCapacityDefault () : 00339 csArrayCapacityLinear<csArrayThresholdVariable> () {} 00340 csArrayCapacityDefault (const csArrayThresholdVariable& threshold) : 00341 csArrayCapacityLinear<csArrayThresholdVariable> (threshold) {} 00342 csArrayCapacityDefault (const size_t x) : 00343 csArrayCapacityLinear<csArrayThresholdVariable> (x) {} 00344 } ; 00345 00350 const size_t csArrayItemNotFound = (size_t)-1; 00351 00360 template <class T, 00361 class ElementHandler = csArrayElementHandler<T>, 00362 class MemoryAllocator = CS::Memory::AllocatorMalloc, 00363 class CapacityHandler = csArrayCapacityDefault> 00364 class csArray : public CS::Memory::CustomAllocated 00365 { 00366 public: 00367 typedef csArray<T, ElementHandler, MemoryAllocator, CapacityHandler> ThisType; 00368 typedef T ValueType; 00369 typedef ElementHandler ElementHandlerType; 00370 typedef MemoryAllocator AllocatorType; 00371 typedef CapacityHandler CapacityHandlerType; 00372 00373 private: 00374 size_t count; 00379 struct ArrayCapacity : public CapacityHandler 00380 { 00381 size_t c; 00382 ArrayCapacity (size_t in_capacity) 00383 { c = (in_capacity > 0 ? in_capacity : 0); } 00384 ArrayCapacity (size_t in_capacity, const CapacityHandler& ch) : 00385 CapacityHandler (ch) 00386 { c = (in_capacity > 0 ? in_capacity : 0); } 00387 void CopyFrom (const CapacityHandler& source) 00388 { 00389 CapacityHandler::operator= (source); 00390 } 00391 }; 00392 ArrayCapacity capacity; 00393 CS::Memory::AllocatorPointerWrapper<T, MemoryAllocator> root; 00394 00395 protected: 00400 void InitRegion (size_t start, size_t count) 00401 { 00402 ElementHandler::InitRegion (root.p+start, count); 00403 } 00404 00409 void SetData (T* data) { root.p = data; } 00410 private: 00412 void CopyFrom (const csArray& source) 00413 { 00414 capacity.CopyFrom (source.capacity); 00415 SetSizeUnsafe (source.GetSize ()); 00416 for (size_t i=0 ; i<source.GetSize () ; i++) 00417 ElementHandler::Construct (root.p + i, source[i]); 00418 } 00419 00421 void InternalSetCapacity (size_t n) 00422 { 00423 if (root.p == 0) 00424 { 00425 root.p = (T*)root.Alloc (n * sizeof (T)); 00426 } 00427 else 00428 { 00429 root.p = ElementHandler::ResizeRegion (root, root.p, count, capacity.c, n); 00430 } 00431 capacity.c = n; 00432 } 00433 00438 void AdjustCapacity (size_t n) 00439 { 00440 if (n > capacity.c || capacity.IsCapacityExcessive (capacity.c, n)) 00441 { 00442 InternalSetCapacity (capacity.GetCapacity (n)); 00443 } 00444 } 00445 00452 void SetSizeUnsafe (size_t n) 00453 { 00454 if (n > capacity.c) 00455 AdjustCapacity (n); 00456 count = n; 00457 } 00458 00459 public: 00471 static int DefaultCompare(T const& r1, T const& r2) 00472 { 00473 return csComparator<T,T>::Compare(r1,r2); 00474 } 00475 00482 csArray (size_t in_capacity = 0, 00483 const CapacityHandler& ch = CapacityHandler()) : count (0), 00484 capacity (in_capacity, ch) 00485 { 00486 #ifdef CS_MEMORY_TRACKER 00487 root.SetMemTrackerInfo (typeid(*this).name()); 00488 #endif 00489 if (capacity.c != 0) 00490 { 00491 root.p = (T*)root.Alloc (capacity.c * sizeof (T)); 00492 } 00493 else 00494 { 00495 root.p = 0; 00496 } 00497 } 00502 csArray (size_t in_capacity, 00503 const MemoryAllocator& alloc, 00504 const CapacityHandler& ch) : count (0), 00505 capacity (in_capacity, ch), root (alloc) 00506 { 00507 #ifdef CS_MEMORY_TRACKER 00508 root.SetMemTrackerInfo (typeid(*this).name()); 00509 #endif 00510 if (capacity.c != 0) 00511 { 00512 root.p = (T*)root.Alloc (capacity.c * sizeof (T)); 00513 } 00514 else 00515 { 00516 root.p = 0; 00517 } 00518 } 00519 00521 ~csArray () 00522 { 00523 DeleteAll (); 00524 } 00525 00527 csArray (const csArray& source) : count (0), capacity (0), root (0) 00528 { 00529 #ifdef CS_MEMORY_TRACKER 00530 root.SetMemTrackerInfo (typeid(*this).name()); 00531 #endif 00532 CopyFrom (source); 00533 } 00534 00536 csArray<T,ElementHandler,MemoryAllocator,CapacityHandler>& operator= ( 00537 const csArray& other) 00538 { 00539 if (&other != this) 00540 { 00541 DeleteAll (); 00542 CopyFrom (other); 00543 } 00544 return *this; 00545 } 00546 00548 size_t GetSize () const 00549 { 00550 return count; 00551 } 00552 00554 size_t Capacity () const 00555 { 00556 return capacity.c; 00557 } 00558 00565 // @@@ FIXME: What about custom allocators? 00566 void TransferTo (csArray& destination) 00567 { 00568 if (&destination != this) 00569 { 00570 destination.DeleteAll (); 00571 destination.root.p = root.p; 00572 destination.count = count; 00573 destination.capacity = capacity; 00574 root.p = 0; 00575 capacity.c = count = 0; 00576 } 00577 } 00578 00588 void SetSize (size_t n, T const& what) 00589 { 00590 if (n <= count) 00591 { 00592 Truncate (n); 00593 } 00594 else 00595 { 00596 size_t old_len = GetSize (); 00597 SetSizeUnsafe (n); 00598 for (size_t i = old_len ; i < n ; i++) 00599 ElementHandler::Construct (root.p + i, what); 00600 } 00601 } 00602 00610 void SetSize (size_t n) 00611 { 00612 if (n <= count) 00613 { 00614 Truncate (n); 00615 } 00616 else 00617 { 00618 size_t old_len = GetSize (); 00619 SetSizeUnsafe (n); 00620 ElementHandler::InitRegion (root.p + old_len, n-old_len); 00621 } 00622 } 00623 00624 00626 T& Get (size_t n) 00627 { 00628 CS_ASSERT (n < count); 00629 return root.p[n]; 00630 } 00631 00633 T const& Get (size_t n) const 00634 { 00635 CS_ASSERT (n < count); 00636 return root.p[n]; 00637 } 00638 00644 T& GetExtend (size_t n) 00645 { 00646 if (n >= count) 00647 SetSize (n+1); 00648 return root.p[n]; 00649 } 00650 00656 T& GetExtend (size_t n, T const& what) 00657 { 00658 if (n >= count) 00659 SetSize (n+1, what); 00660 return root.p[n]; 00661 } 00662 00664 T& operator [] (size_t n) 00665 { 00666 return Get(n); 00667 } 00668 00670 T const& operator [] (size_t n) const 00671 { 00672 return Get(n); 00673 } 00674 00676 void Put (size_t n, T const& what) 00677 { 00678 if (n >= count) 00679 SetSize (n+1); 00680 ElementHandler::Destroy (root.p + n); 00681 ElementHandler::Construct (root.p + n, what); 00682 } 00683 00691 template <class K> 00692 size_t FindKey (csArrayCmp<T,K> comparekey) const 00693 { 00694 for (size_t i = 0 ; i < GetSize () ; i++) 00695 if (comparekey (root.p[i]) == 0) 00696 return i; 00697 return csArrayItemNotFound; 00698 } 00699 00704 size_t Push (T const& what) 00705 { 00706 if (((&what >= root.p) && (&what < root.p + GetSize())) && 00707 (capacity.c < count + 1)) 00708 { 00709 /* 00710 Special case: An element from this very array is pushed, and a 00711 reallocation is needed. This could cause the passed ref to the 00712 element to be pushed to be read from deleted memory. Work 00713 around this. 00714 */ 00715 size_t whatIndex = &what - root.p; 00716 SetSizeUnsafe (count + 1); 00717 ElementHandler::Construct (root.p + count - 1, root.p[whatIndex]); 00718 } 00719 else 00720 { 00721 SetSizeUnsafe (count + 1); 00722 ElementHandler::Construct (root.p + count - 1, what); 00723 } 00724 return count - 1; 00725 } 00726 00731 size_t PushSmart (T const& what) 00732 { 00733 size_t const n = Find (what); 00734 return (n == csArrayItemNotFound) ? Push (what) : n; 00735 } 00736 00738 T Pop () 00739 { 00740 CS_ASSERT (count > 0); 00741 T ret(root.p [count - 1]); 00742 ElementHandler::Destroy (root.p + count - 1); 00743 SetSizeUnsafe (count - 1); 00744 return ret; 00745 } 00746 00748 T const& Top () const 00749 { 00750 CS_ASSERT (count > 0); 00751 return root.p [count - 1]; 00752 } 00753 00755 T& Top () 00756 { 00757 CS_ASSERT (count > 0); 00758 return root.p [count - 1]; 00759 } 00760 00762 bool Insert (size_t n, T const& item) 00763 { 00764 if (n <= count) 00765 { 00766 SetSizeUnsafe (count + 1); // Increments 'count' as a side-effect. 00767 size_t const nmove = (count - n - 1); 00768 if (nmove > 0) 00769 ElementHandler::MoveElements (root.p, n+1, n, nmove); 00770 ElementHandler::Construct (root.p + n, item); 00771 return true; 00772 } 00773 else 00774 return false; 00775 } 00776 00780 csArray<T> Section (size_t low, size_t high) const 00781 { 00782 CS_ASSERT (high < count && high >= low); 00783 csArray<T> sect (high - low + 1); 00784 for (size_t i = low; i <= high; i++) sect.Push (root.p[i]); 00785 return sect; 00786 } 00787 00793 template <class K> 00794 size_t FindSortedKey (csArrayCmp<T,K> comparekey, 00795 size_t* candidate = 0) const 00796 { 00797 size_t m = 0, l = 0, r = GetSize (); 00798 while (l < r) 00799 { 00800 m = (l + r) / 2; 00801 int cmp = comparekey (root.p[m]); 00802 if (cmp == 0) 00803 { 00804 if (candidate) *candidate = csArrayItemNotFound; 00805 return m; 00806 } 00807 else if (cmp < 0) 00808 l = m + 1; 00809 else 00810 r = m; 00811 } 00812 if ((m + 1) == r) 00813 m++; 00814 if (candidate) *candidate = m; 00815 return csArrayItemNotFound; 00816 } 00817 00828 size_t InsertSorted (const T& item, 00829 int (*compare)(T const&, T const&) = DefaultCompare, 00830 size_t* equal_index = 0) 00831 { 00832 size_t m = 0, l = 0, r = GetSize (); 00833 while (l < r) 00834 { 00835 m = (l + r) / 2; 00836 int cmp = compare (root.p [m], item); 00837 00838 if (cmp == 0) 00839 { 00840 if (equal_index) *equal_index = m; 00841 Insert (++m, item); 00842 return m; 00843 } 00844 else if (cmp < 0) 00845 l = m + 1; 00846 else 00847 r = m; 00848 } 00849 if ((m + 1) == r) 00850 m++; 00851 if (equal_index) *equal_index = csArrayItemNotFound; 00852 Insert (m, item); 00853 return m; 00854 } 00855 00862 size_t Find (T const& which) const 00863 { 00864 for (size_t i = 0 ; i < GetSize () ; i++) 00865 if (root.p[i] == which) 00866 return i; 00867 return csArrayItemNotFound; 00868 } 00869 00871 size_t Contains(T const& which) const 00872 { return Find(which); } 00873 00880 size_t GetIndex (const T* which) const 00881 { 00882 CS_ASSERT (which >= root.p); 00883 CS_ASSERT (which < (root.p + count)); 00884 return which-root.p; 00885 } 00886 00890 void Sort (int (*compare)(T const&, T const&) = DefaultCompare) 00891 { 00892 qsort (root.p, GetSize (), sizeof(T), 00893 (int (*)(void const*, void const*))compare); 00894 } 00895 00899 void DeleteAll () 00900 { 00901 if (root.p) 00902 { 00903 size_t i; 00904 for (i = 0 ; i < count ; i++) 00905 ElementHandler::Destroy (root.p + i); 00906 root.Free (root.p); 00907 root.p = 0; 00908 capacity.c = count = 0; 00909 } 00910 } 00911 00923 void Truncate (size_t n) 00924 { 00925 CS_ASSERT(n <= count); 00926 if (n < count) 00927 { 00928 for (size_t i = n; i < count; i++) 00929 ElementHandler::Destroy (root.p + i); 00930 SetSizeUnsafe(n); 00931 } 00932 } 00933 00939 void Empty () 00940 { 00941 Truncate (0); 00942 } 00943 00949 bool IsEmpty() const 00950 { 00951 return GetSize() == 0; 00952 } 00953 00960 void SetCapacity (size_t n) 00961 { 00962 if (n > GetSize ()) 00963 InternalSetCapacity (n); 00964 } 00965 00973 void SetMinimalCapacity (size_t n) 00974 { 00975 if (n < Capacity ()) return; 00976 if (n > GetSize ()) 00977 InternalSetCapacity (n); 00978 } 00979 00985 void ShrinkBestFit () 00986 { 00987 if (count == 0) 00988 { 00989 DeleteAll (); 00990 } 00991 else if (count != capacity.c) 00992 { 00993 root.p = ElementHandler::ResizeRegion (root, root.p, count, capacity.c, count); 00994 capacity.c = count; 00995 } 00996 } 00997 01006 bool DeleteIndex (size_t n) 01007 { 01008 if (n < count) 01009 { 01010 size_t const ncount = count - 1; 01011 size_t const nmove = ncount - n; 01012 ElementHandler::Destroy (root.p + n); 01013 if (nmove > 0) 01014 ElementHandler::MoveElements (root.p, n, n+1, nmove); 01015 SetSizeUnsafe (ncount); 01016 return true; 01017 } 01018 else 01019 return false; 01020 } 01021 01031 bool DeleteIndexFast (size_t n) 01032 { 01033 if (n < count) 01034 { 01035 size_t const ncount = count - 1; 01036 size_t const nmove = ncount - n; 01037 ElementHandler::Destroy (root.p + n); 01038 if (nmove > 0) 01039 ElementHandler::MoveElements (root.p, n, ncount, 1); 01040 SetSizeUnsafe (ncount); 01041 return true; 01042 } 01043 else 01044 return false; 01045 } 01046 01053 bool DeleteRange (size_t start, size_t end) 01054 { 01055 if (start >= count) return false; 01056 // Treat 'csArrayItemNotFound' as invalid indices, do nothing. 01057 if (end == csArrayItemNotFound) return false; 01058 if (start == csArrayItemNotFound) return false;//start = 0; 01059 if (end >= count) end = count - 1; 01060 size_t i; 01061 for (i = start ; i <= end ; i++) 01062 ElementHandler::Destroy (root.p + i); 01063 01064 size_t const range_size = end - start + 1; 01065 size_t const ncount = count - range_size; 01066 size_t const nmove = count - end - 1; 01067 if (nmove > 0) 01068 ElementHandler::MoveElements (root.p, start, start + range_size, nmove); 01069 SetSizeUnsafe (ncount); 01070 return true; 01071 } 01072 01078 bool Delete (T const& item) 01079 { 01080 size_t const n = Find (item); 01081 if (n != csArrayItemNotFound) 01082 return DeleteIndex (n); 01083 return false; 01084 } 01085 01087 class Iterator 01088 { 01089 public: 01091 Iterator(Iterator const& r) : 01092 currentelem(r.currentelem), array(r.array) {} 01093 01095 Iterator& operator=(Iterator const& r) 01096 { currentelem = r.currentelem; array = r.array; return *this; } 01097 01099 bool HasNext() const 01100 { return currentelem < array.GetSize (); } 01101 01103 T& Next() 01104 { return array.Get(currentelem++); } 01105 01107 void Reset() 01108 { currentelem = 0; } 01109 01110 protected: 01111 Iterator(csArray<T, ElementHandler, MemoryAllocator, CapacityHandler>& newarray) 01112 : currentelem(0), array(newarray) {} 01113 friend class csArray<T, ElementHandler, MemoryAllocator, CapacityHandler>; 01114 01115 private: 01116 size_t currentelem; 01117 csArray<T, ElementHandler, MemoryAllocator, CapacityHandler>& array; 01118 }; 01119 01121 class ConstIterator 01122 { 01123 public: 01125 ConstIterator(ConstIterator const& r) : 01126 currentelem(r.currentelem), array(r.array) {} 01127 01129 ConstIterator& operator=(ConstIterator const& r) 01130 { currentelem = r.currentelem; array = r.array; return *this; } 01131 01133 bool HasNext() const 01134 { return currentelem < array.GetSize (); } 01135 01137 const T& Next() 01138 { return array.Get(currentelem++); } 01139 01141 void Reset() 01142 { currentelem = 0; } 01143 01144 protected: 01145 ConstIterator(const csArray<T, ElementHandler, MemoryAllocator, CapacityHandler>& newarray) 01146 : currentelem(0), array(newarray) {} 01147 friend class csArray<T, ElementHandler, MemoryAllocator, CapacityHandler>; 01148 01149 private: 01150 size_t currentelem; 01151 const csArray<T, ElementHandler, MemoryAllocator, CapacityHandler>& array; 01152 }; 01153 01155 Iterator GetIterator() 01156 { return Iterator(*this); } 01157 01159 ConstIterator GetIterator() const 01160 { return ConstIterator(*this); } 01161 01163 bool operator== (const csArray& other) const 01164 { 01165 if (other.GetSize() != GetSize()) return false; 01166 for (size_t i = 0; i < GetSize(); i++) 01167 if (Get (i) != other[i]) return false; 01168 return true; 01169 } 01170 01171 bool operator!= (const csArray& other) const { return !(*this==other); } 01172 01174 const MemoryAllocator& GetAllocator() const 01175 { 01176 return root; 01177 } 01178 }; 01179 01185 template <class T> 01186 class csSafeCopyArray 01187 : public csArray<T, 01188 csArraySafeCopyElementHandler<T> > 01189 { 01190 public: 01195 csSafeCopyArray (size_t limit = 0, size_t threshold = 0) 01196 : csArray<T, csArraySafeCopyElementHandler<T> > (limit, threshold) 01197 { 01198 } 01199 }; 01200 01201 #include "csutil/custom_new_enable.h" 01202 01205 #endif
Generated for Crystal Space 1.4.0 by doxygen 1.5.8