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 00031 #include "csutil/custom_new_disable.h" 00032 00033 #if defined(CS_MEMORY_TRACKER) 00034 #include "csutil/memdebug.h" 00035 #include "csutil/snprintf.h" 00036 #include <typeinfo> 00037 #endif 00038 00051 template <class T, class K> 00052 class csArrayCmp 00053 { 00054 public: 00060 typedef int(*CF)(T const&, K const&); 00062 csArrayCmp(K const& k, CF c = DefaultCompare) : key(k), cmp(c) {} 00064 csArrayCmp(csArrayCmp const& o) : key(o.key), cmp(o.cmp) {} 00066 csArrayCmp& operator=(csArrayCmp const& o) 00067 { key = o.key; cmp = o.cmp; return *this; } 00076 int operator()(T const& r) const { return cmp(r, key); } 00078 operator CF() const { return cmp; } 00080 operator K const&() const { return key; } 00091 static int DefaultCompare(T const& r, K const& k) 00092 { return csComparator<T,K>::Compare(r,k); } 00093 private: 00094 K key; 00095 CF cmp; 00096 }; 00097 00101 template <class T> 00102 class csArrayElementHandler 00103 { 00104 public: 00106 static void Construct (T* address) 00107 { 00108 new (static_cast<void*> (address)) T(); 00109 } 00110 00112 static void Construct (T* address, T const& src) 00113 { 00114 new (static_cast<void*> (address)) T(src); 00115 } 00116 00118 static void Destroy (T* address) 00119 { 00120 address->~T(); 00121 } 00122 00124 static void InitRegion (T* address, size_t count) 00125 { 00126 for (size_t i = 0 ; i < count ; i++) 00127 Construct (address + i); 00128 } 00129 00131 template<typename Allocator> 00132 static T* ResizeRegion (Allocator& alloc, T* mem, size_t relevantcount, 00133 size_t oldcount, size_t newcount) 00134 { 00135 (void)relevantcount; (void)oldcount; 00136 return (T*)alloc.Realloc (mem, newcount * sizeof(T)); 00137 } 00138 00140 static void MoveElements (T* mem, size_t dest, size_t src, size_t count) 00141 { 00142 memmove (mem + dest, mem + src, count * sizeof(T)); 00143 } 00144 }; 00145 00154 template <class T> 00155 class csArraySafeCopyElementHandler 00156 { 00157 public: 00158 static void Construct (T* address) 00159 { 00160 new (static_cast<void*> (address)) T(); 00161 } 00162 00163 static void Construct (T* address, T const& src) 00164 { 00165 new (static_cast<void*> (address)) T(src); 00166 } 00167 00168 static void Destroy (T* address) 00169 { 00170 address->~T(); 00171 } 00172 00173 static void InitRegion (T* address, size_t count) 00174 { 00175 for (size_t i = 0 ; i < count ; i++) 00176 Construct (address + i); 00177 } 00178 00184 template<typename Allocator> 00185 static T* ResizeRegion (Allocator& alloc, T* mem, size_t relevantcount, 00186 size_t oldcount, size_t newcount) 00187 { 00188 if (newcount <= oldcount) 00189 { 00190 // Realloc is safe. 00191 T* newmem = (T*)alloc.Realloc (mem, newcount * sizeof (T)); 00192 CS_ASSERT (newmem == mem); 00193 return newmem; 00194 } 00195 00196 T* newmem = (T*)alloc.Alloc (newcount * sizeof (T)); 00197 size_t i; 00198 for (i = 0 ; i < relevantcount ; i++) 00199 { 00200 Construct (newmem + i, mem[i]); 00201 Destroy (mem + i); 00202 } 00203 alloc.Free (mem); 00204 return newmem; 00205 } 00206 00212 static void MoveElements (T* mem, size_t dest, size_t src, size_t count) 00213 { 00214 size_t i; 00215 if (dest < src) 00216 { 00217 for (i = 0 ; i < count ; i++) 00218 { 00219 Construct (mem + dest + i, mem[src + i]); 00220 Destroy (mem + src + i); 00221 } 00222 } 00223 else 00224 { 00225 i = count; 00226 while (i > 0) 00227 { 00228 i--; 00229 Construct (mem + dest + i, mem[src + i]); 00230 Destroy (mem + src + i); 00231 } 00232 } 00233 } 00234 }; 00235 00236 00241 class csArrayThresholdVariable 00242 { 00243 size_t threshold; 00244 public: 00246 csArrayThresholdVariable (size_t in_threshold = 0) 00247 { threshold = (in_threshold > 0 ? in_threshold : 16); } 00249 size_t GetThreshold() const { return threshold; } 00250 }; 00251 00256 template<int N> 00257 class csArrayThresholdFixed 00258 { 00259 public: 00261 csArrayThresholdFixed (size_t x = 0) 00262 { (void)x; } 00264 size_t GetThreshold() const { return N; } 00265 // Work around VC7 bug apparently incorrectly copying this empty class 00266 csArrayThresholdFixed& operator= (const csArrayThresholdFixed&) 00267 { return *this; } 00268 }; 00269 00277 template<typename Threshold = csArrayThresholdVariable> 00278 class csArrayCapacityLinear : public Threshold 00279 { 00280 public: 00282 00283 csArrayCapacityLinear () : Threshold () {} 00284 csArrayCapacityLinear (const Threshold& threshold) : Threshold (threshold) 00285 {} 00287 00293 csArrayCapacityLinear (const size_t x) : Threshold (x) 00294 {} 00295 00301 bool IsCapacityExcessive (size_t capacity, size_t count) const 00302 { 00303 return (capacity > this->GetThreshold() 00304 && count < capacity - this->GetThreshold()); 00305 } 00311 size_t GetCapacity (size_t count) const 00312 { 00313 return ((count + this->GetThreshold() - 1) / this->GetThreshold()) * 00314 this->GetThreshold(); 00315 } 00316 }; 00317 00318 // Alias for csArrayCapacityLinear<csArrayThresholdVariable> to keep 00319 // SWIG generated Java classes (and thus filenames) short enough for Windows. 00320 // Note that a typedef wont work because SWIG would expand it. 00321 struct csArrayCapacityDefault : 00322 public csArrayCapacityLinear<csArrayThresholdVariable> 00323 { 00324 csArrayCapacityDefault () : 00325 csArrayCapacityLinear<csArrayThresholdVariable> () {} 00326 csArrayCapacityDefault (const csArrayThresholdVariable& threshold) : 00327 csArrayCapacityLinear<csArrayThresholdVariable> (threshold) {} 00328 csArrayCapacityDefault (const size_t x) : 00329 csArrayCapacityLinear<csArrayThresholdVariable> (x) {} 00330 } ; 00331 00336 const size_t csArrayItemNotFound = (size_t)-1; 00337 00346 template <class T, 00347 class ElementHandler = csArrayElementHandler<T>, 00348 class MemoryAllocator = CS::Memory::AllocatorMalloc, 00349 class CapacityHandler = csArrayCapacityDefault> 00350 class csArray 00351 { 00352 public: 00353 typedef csArray<T, ElementHandler, MemoryAllocator, CapacityHandler> ThisType; 00354 typedef T ValueType; 00355 typedef ElementHandler ElementHandlerType; 00356 typedef MemoryAllocator AllocatorType; 00357 typedef CapacityHandler CapacityHandlerType; 00358 00359 private: 00360 size_t count; 00365 struct ArrayCapacity : public CapacityHandler 00366 { 00367 size_t c; 00368 ArrayCapacity (size_t in_capacity) 00369 { c = (in_capacity > 0 ? in_capacity : 0); } 00370 ArrayCapacity (size_t in_capacity, const CapacityHandler& ch) : 00371 CapacityHandler (ch) 00372 { c = (in_capacity > 0 ? in_capacity : 0); } 00373 void CopyFrom (const CapacityHandler& source) 00374 { 00375 CapacityHandler::operator= (source); 00376 } 00377 }; 00378 ArrayCapacity capacity; 00379 CS::Memory::AllocatorPointerWrapper<T, MemoryAllocator> root; 00380 00381 protected: 00386 void InitRegion (size_t start, size_t count) 00387 { 00388 ElementHandler::InitRegion (root.p+start, count); 00389 } 00390 00391 private: 00393 void CopyFrom (const csArray& source) 00394 { 00395 capacity.CopyFrom (source.capacity); 00396 SetSizeUnsafe (source.Length ()); 00397 for (size_t i=0 ; i<source.Length() ; i++) 00398 ElementHandler::Construct (root.p + i, source[i]); 00399 } 00400 00402 void InternalSetCapacity (size_t n) 00403 { 00404 if (root.p == 0) 00405 { 00406 root.p = (T*)root.Alloc (n * sizeof (T)); 00407 } 00408 else 00409 { 00410 root.p = ElementHandler::ResizeRegion (root, root.p, count, capacity.c, n); 00411 } 00412 capacity.c = n; 00413 } 00414 00419 void AdjustCapacity (size_t n) 00420 { 00421 if (n > capacity.c || capacity.IsCapacityExcessive (capacity.c, n)) 00422 { 00423 InternalSetCapacity (capacity.GetCapacity (n)); 00424 } 00425 } 00426 00433 void SetSizeUnsafe (size_t n) 00434 { 00435 if (n > capacity.c) 00436 AdjustCapacity (n); 00437 count = n; 00438 } 00439 00440 public: 00452 static int DefaultCompare(T const& r1, T const& r2) 00453 { 00454 return csComparator<T,T>::Compare(r1,r2); 00455 } 00456 00463 csArray (size_t in_capacity = 0, 00464 const CapacityHandler& ch = CapacityHandler()) : count (0), 00465 capacity (in_capacity, ch) 00466 { 00467 #ifdef CS_MEMORY_TRACKER 00468 root.SetMemTrackerInfo (typeid(*this).name()); 00469 #endif 00470 if (capacity.c != 0) 00471 { 00472 root.p = (T*)root.Alloc (capacity.c * sizeof (T)); 00473 } 00474 else 00475 { 00476 root.p = 0; 00477 } 00478 } 00483 csArray (size_t in_capacity, 00484 const MemoryAllocator& alloc, 00485 const CapacityHandler& ch) : count (0), 00486 capacity (in_capacity, ch), root (alloc) 00487 { 00488 #ifdef CS_MEMORY_TRACKER 00489 root.SetMemTrackerInfo (typeid(*this).name()); 00490 #endif 00491 if (capacity.c != 0) 00492 { 00493 root.p = (T*)root.Alloc (capacity.c * sizeof (T)); 00494 } 00495 else 00496 { 00497 root.p = 0; 00498 } 00499 } 00500 00502 ~csArray () 00503 { 00504 DeleteAll (); 00505 } 00506 00508 csArray (const csArray& source) : count (0), capacity (0), root (0) 00509 { 00510 #ifdef CS_MEMORY_TRACKER 00511 root.SetMemTrackerInfo (typeid(*this).name()); 00512 #endif 00513 CopyFrom (source); 00514 } 00515 00517 csArray<T,ElementHandler,MemoryAllocator,CapacityHandler>& operator= ( 00518 const csArray& other) 00519 { 00520 if (&other != this) 00521 { 00522 DeleteAll (); 00523 CopyFrom (other); 00524 } 00525 return *this; 00526 } 00527 00529 size_t GetSize () const 00530 { 00531 return count; 00532 } 00533 00538 /*CS_DEPRECATED_METHOD_MSG("Use GetSize() instead.")*/ 00539 size_t Length () const 00540 { 00541 return GetSize(); 00542 } 00543 00545 size_t Capacity () const 00546 { 00547 return capacity.c; 00548 } 00549 00556 // @@@ FIXME: What about custom allocators? 00557 void TransferTo (csArray& destination) 00558 { 00559 if (&destination != this) 00560 { 00561 destination.DeleteAll (); 00562 destination.root.p = root.p; 00563 destination.count = count; 00564 destination.capacity = capacity; 00565 root.p = 0; 00566 capacity.c = count = 0; 00567 } 00568 } 00569 00579 void SetSize (size_t n, T const& what) 00580 { 00581 if (n <= count) 00582 { 00583 Truncate (n); 00584 } 00585 else 00586 { 00587 size_t old_len = Length (); 00588 SetSizeUnsafe (n); 00589 for (size_t i = old_len ; i < n ; i++) 00590 ElementHandler::Construct (root.p + i, what); 00591 } 00592 } 00593 00601 void SetSize (size_t n) 00602 { 00603 if (n <= count) 00604 { 00605 Truncate (n); 00606 } 00607 else 00608 { 00609 size_t old_len = Length (); 00610 SetSizeUnsafe (n); 00611 ElementHandler::InitRegion (root.p + old_len, n-old_len); 00612 } 00613 } 00614 00620 /*CS_DEPRECATED_METHOD_MSG("Use SetSize() instead.")*/ 00621 void SetLength (size_t n, T const& what) { SetSize(n, what); } 00622 /*CS_DEPRECATED_METHOD_MSG("Use SetSize() instead.")*/ 00623 void SetLength (size_t n) { SetSize(n); } 00626 00627 T& Get (size_t n) 00628 { 00629 CS_ASSERT (n < count); 00630 return root.p[n]; 00631 } 00632 00634 T const& Get (size_t n) const 00635 { 00636 CS_ASSERT (n < count); 00637 return root.p[n]; 00638 } 00639 00645 T& GetExtend (size_t n) 00646 { 00647 if (n >= count) 00648 SetSize (n+1); 00649 return root.p[n]; 00650 } 00651 00653 T& operator [] (size_t n) 00654 { 00655 return Get(n); 00656 } 00657 00659 T const& operator [] (size_t n) const 00660 { 00661 return Get(n); 00662 } 00663 00665 void Put (size_t n, T const& what) 00666 { 00667 if (n >= count) 00668 SetSize (n+1); 00669 ElementHandler::Destroy (root.p + n); 00670 ElementHandler::Construct (root.p + n, what); 00671 } 00672 00680 template <class K> 00681 size_t FindKey (csArrayCmp<T,K> comparekey) const 00682 { 00683 for (size_t i = 0 ; i < Length () ; i++) 00684 if (comparekey (root.p[i]) == 0) 00685 return i; 00686 return csArrayItemNotFound; 00687 } 00688 00693 size_t Push (T const& what) 00694 { 00695 if (((&what >= root.p) && (&what < root.p + Length())) && 00696 (capacity.c < count + 1)) 00697 { 00698 /* 00699 Special case: An element from this very array is pushed, and a 00700 reallocation is needed. This could cause the passed ref to the 00701 element to be pushed to be read from deleted memory. Work 00702 around this. 00703 */ 00704 size_t whatIndex = &what - root.p; 00705 SetSizeUnsafe (count + 1); 00706 ElementHandler::Construct (root.p + count - 1, root.p[whatIndex]); 00707 } 00708 else 00709 { 00710 SetSizeUnsafe (count + 1); 00711 ElementHandler::Construct (root.p + count - 1, what); 00712 } 00713 return count - 1; 00714 } 00715 00720 size_t PushSmart (T const& what) 00721 { 00722 size_t const n = Find (what); 00723 return (n == csArrayItemNotFound) ? Push (what) : n; 00724 } 00725 00727 T Pop () 00728 { 00729 CS_ASSERT (count > 0); 00730 T ret(root.p [count - 1]); 00731 ElementHandler::Destroy (root.p + count - 1); 00732 SetSizeUnsafe (count - 1); 00733 return ret; 00734 } 00735 00737 T const& Top () const 00738 { 00739 CS_ASSERT (count > 0); 00740 return root.p [count - 1]; 00741 } 00742 00744 T& Top () 00745 { 00746 CS_ASSERT (count > 0); 00747 return root.p [count - 1]; 00748 } 00749 00751 bool Insert (size_t n, T const& item) 00752 { 00753 if (n <= count) 00754 { 00755 SetSizeUnsafe (count + 1); // Increments 'count' as a side-effect. 00756 size_t const nmove = (count - n - 1); 00757 if (nmove > 0) 00758 ElementHandler::MoveElements (root.p, n+1, n, nmove); 00759 ElementHandler::Construct (root.p + n, item); 00760 return true; 00761 } 00762 else 00763 return false; 00764 } 00765 00769 csArray<T> Section (size_t low, size_t high) const 00770 { 00771 CS_ASSERT (high < count && high >= low); 00772 csArray<T> sect (high - low + 1); 00773 for (size_t i = low; i <= high; i++) sect.Push (root.p[i]); 00774 return sect; 00775 } 00776 00782 template <class K> 00783 size_t FindSortedKey (csArrayCmp<T,K> comparekey, 00784 size_t* candidate = 0) const 00785 { 00786 size_t m = 0, l = 0, r = Length (); 00787 while (l < r) 00788 { 00789 m = (l + r) / 2; 00790 int cmp = comparekey (root.p[m]); 00791 if (cmp == 0) 00792 { 00793 if (candidate) *candidate = csArrayItemNotFound; 00794 return m; 00795 } 00796 else if (cmp < 0) 00797 l = m + 1; 00798 else 00799 r = m; 00800 } 00801 if ((m + 1) == r) 00802 m++; 00803 if (candidate) *candidate = m; 00804 return csArrayItemNotFound; 00805 } 00806 00817 size_t InsertSorted (const T& item, 00818 int (*compare)(T const&, T const&) = DefaultCompare, 00819 size_t* equal_index = 0) 00820 { 00821 size_t m = 0, l = 0, r = Length (); 00822 while (l < r) 00823 { 00824 m = (l + r) / 2; 00825 int cmp = compare (root.p [m], item); 00826 00827 if (cmp == 0) 00828 { 00829 if (equal_index) *equal_index = m; 00830 Insert (++m, item); 00831 return m; 00832 } 00833 else if (cmp < 0) 00834 l = m + 1; 00835 else 00836 r = m; 00837 } 00838 if ((m + 1) == r) 00839 m++; 00840 if (equal_index) *equal_index = csArrayItemNotFound; 00841 Insert (m, item); 00842 return m; 00843 } 00844 00851 size_t Find (T const& which) const 00852 { 00853 for (size_t i = 0 ; i < Length () ; i++) 00854 if (root.p[i] == which) 00855 return i; 00856 return csArrayItemNotFound; 00857 } 00858 00860 size_t Contains(T const& which) const 00861 { return Find(which); } 00862 00869 size_t GetIndex (const T* which) const 00870 { 00871 CS_ASSERT (which >= root.p); 00872 CS_ASSERT (which < (root.p + count)); 00873 return which-root.p; 00874 } 00875 00879 void Sort (int (*compare)(T const&, T const&) = DefaultCompare) 00880 { 00881 qsort (root.p, Length(), sizeof(T), 00882 (int (*)(void const*, void const*))compare); 00883 } 00884 00888 void DeleteAll () 00889 { 00890 if (root.p) 00891 { 00892 size_t i; 00893 for (i = 0 ; i < count ; i++) 00894 ElementHandler::Destroy (root.p + i); 00895 root.Free (root.p); 00896 root.p = 0; 00897 capacity.c = count = 0; 00898 } 00899 } 00900 00912 void Truncate (size_t n) 00913 { 00914 CS_ASSERT(n <= count); 00915 if (n < count) 00916 { 00917 for (size_t i = n; i < count; i++) 00918 ElementHandler::Destroy (root.p + i); 00919 SetSizeUnsafe(n); 00920 } 00921 } 00922 00928 void Empty () 00929 { 00930 Truncate (0); 00931 } 00932 00938 bool IsEmpty() const 00939 { 00940 return GetSize() == 0; 00941 } 00942 00949 void SetCapacity (size_t n) 00950 { 00951 if (n > Length ()) 00952 InternalSetCapacity (n); 00953 } 00954 00962 void SetMinimalCapacity (size_t n) 00963 { 00964 if (n < Capacity ()) return; 00965 if (n > Length ()) 00966 InternalSetCapacity (n); 00967 } 00968 00974 void ShrinkBestFit () 00975 { 00976 if (count == 0) 00977 { 00978 DeleteAll (); 00979 } 00980 else if (count != capacity.c) 00981 { 00982 root.p = ElementHandler::ResizeRegion (root, root.p, count, capacity.c, count); 00983 capacity.c = count; 00984 } 00985 } 00986 00995 bool DeleteIndex (size_t n) 00996 { 00997 if (n < count) 00998 { 00999 size_t const ncount = count - 1; 01000 size_t const nmove = ncount - n; 01001 ElementHandler::Destroy (root.p + n); 01002 if (nmove > 0) 01003 ElementHandler::MoveElements (root.p, n, n+1, nmove); 01004 SetSizeUnsafe (ncount); 01005 return true; 01006 } 01007 else 01008 return false; 01009 } 01010 01020 bool DeleteIndexFast (size_t n) 01021 { 01022 if (n < count) 01023 { 01024 size_t const ncount = count - 1; 01025 size_t const nmove = ncount - n; 01026 ElementHandler::Destroy (root.p + n); 01027 if (nmove > 0) 01028 ElementHandler::MoveElements (root.p, n, ncount, 1); 01029 SetSizeUnsafe (ncount); 01030 return true; 01031 } 01032 else 01033 return false; 01034 } 01035 01042 bool DeleteRange (size_t start, size_t end) 01043 { 01044 if (start >= count) return false; 01045 // Treat 'csArrayItemNotFound' as invalid indices, do nothing. 01046 if (end == csArrayItemNotFound) return false; 01047 if (start == csArrayItemNotFound) return false;//start = 0; 01048 if (end >= count) end = count - 1; 01049 size_t i; 01050 for (i = start ; i <= end ; i++) 01051 ElementHandler::Destroy (root.p + i); 01052 01053 size_t const range_size = end - start + 1; 01054 size_t const ncount = count - range_size; 01055 size_t const nmove = count - end - 1; 01056 if (nmove > 0) 01057 ElementHandler::MoveElements (root.p, start, start + range_size, nmove); 01058 SetSizeUnsafe (ncount); 01059 return true; 01060 } 01061 01067 bool Delete (T const& item) 01068 { 01069 size_t const n = Find (item); 01070 if (n != csArrayItemNotFound) 01071 return DeleteIndex (n); 01072 return false; 01073 } 01074 01088 CS_DEPRECATED_METHOD_MSG("'Fast' is illusory. See documentation") 01089 bool DeleteFast (T const& item) 01090 { 01091 size_t const n = Find (item); 01092 if (n != csArrayItemNotFound) 01093 return DeleteIndexFast (n); 01094 return false; 01095 } 01096 01098 class Iterator 01099 { 01100 public: 01102 Iterator(Iterator const& r) : 01103 currentelem(r.currentelem), array(r.array) {} 01104 01106 Iterator& operator=(Iterator const& r) 01107 { currentelem = r.currentelem; array = r.array; return *this; } 01108 01110 bool HasNext() const 01111 { return currentelem < array.Length(); } 01112 01114 T& Next() 01115 { return array.Get(currentelem++); } 01116 01118 void Reset() 01119 { currentelem = 0; } 01120 01121 protected: 01122 Iterator(csArray<T, ElementHandler>& newarray) 01123 : currentelem(0), array(newarray) {} 01124 friend class csArray<T, ElementHandler>; 01125 01126 private: 01127 size_t currentelem; 01128 csArray<T, ElementHandler>& array; 01129 }; 01130 01132 class ConstIterator 01133 { 01134 public: 01136 ConstIterator(ConstIterator const& r) : 01137 currentelem(r.currentelem), array(r.array) {} 01138 01140 ConstIterator& operator=(ConstIterator const& r) 01141 { currentelem = r.currentelem; array = r.array; return *this; } 01142 01144 bool HasNext() const 01145 { return currentelem < array.Length(); } 01146 01148 const T& Next() 01149 { return array.Get(currentelem++); } 01150 01152 void Reset() 01153 { currentelem = 0; } 01154 01155 protected: 01156 ConstIterator(const csArray<T, ElementHandler>& newarray) 01157 : currentelem(0), array(newarray) {} 01158 friend class csArray<T, ElementHandler>; 01159 01160 private: 01161 size_t currentelem; 01162 const csArray<T, ElementHandler>& array; 01163 }; 01164 01166 Iterator GetIterator() 01167 { return Iterator(*this); } 01168 01170 ConstIterator GetIterator() const 01171 { return ConstIterator(*this); } 01172 01174 bool operator== (const csArray& other) const 01175 { 01176 if (other.GetSize() != GetSize()) return false; 01177 for (size_t i = 0; i < GetSize(); i++) 01178 if (Get (i) != other[i]) return false; 01179 return true; 01180 } 01181 01182 bool operator!= (const csArray& other) const { return !(*this==other); } 01183 01185 const MemoryAllocator& GetAllocator() const 01186 { 01187 return root; 01188 } 01189 }; 01190 01196 template <class T> 01197 class csSafeCopyArray 01198 : public csArray<T, 01199 csArraySafeCopyElementHandler<T> > 01200 { 01201 public: 01206 csSafeCopyArray (size_t limit = 0, size_t threshold = 0) 01207 : csArray<T, csArraySafeCopyElementHandler<T> > (limit, threshold) 01208 { 01209 } 01210 }; 01211 01212 #include "csutil/custom_new_enable.h" 01213 01216 #endif
Generated for Crystal Space by doxygen 1.4.7