Crystal Space: csutil/array.h Source File (Crystal Space Public API Reference)

| ## Public API Reference

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# 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