## 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 "comparator.h"
    00029
    00030 // Hack: Work around problems caused by #defining 'new'.
    00031 #if defined(CS_EXTENSIVE_MEMDEBUG) || defined(CS_MEMORY_TRACKER)
    00032 # undef new
    00033 #endif
    00034 #include <new>
    00035
    00036 #if defined(CS_MEMORY_TRACKER)
    00037 #include "csutil/memdebug.h"
    00038 #include "csutil/snprintf.h"
    00039 #include <typeinfo>
    00040 #endif
    00041
    00045 // Define CSARRAY_INHIBIT_TYPED_KEYS if the compiler is too old or too buggy to
    00046 // properly support templated functions within a templated class.  When this is
    00047 // defined, rather than using a properly typed "key" argument, search methods
    00048 // fall back to dealing with opaque void* for the "key" argument.  Note,
    00049 // however, that this fact is completely hidden from the client; the client
    00050 // simply creates csArrayCmp<> functors using correct types for the keys
    00051 // regardless of whether the compiler actually supports this feature.  (The
    00052 // MSVC6 compiler, for example, does support templated functions within a
    00053 // template class but crashes and burns horribly when a function pointer or
    00054 // functor is thrown into the mix; thus this should be defined for MSVC6.)
    00055 #if !defined(CSARRAY_INHIBIT_TYPED_KEYS)
    00056
    00066 template <class T, class K>
    00067 class csArrayCmp
    00068 {
    00069 public:
    00075   typedef int(*CF)(T const&, K const&);
    00077   csArrayCmp(K const& k, CF c = DefaultCompare) : key(k), cmp(c) {}
    00079   csArrayCmp(csArrayCmp const& o) : key(o.key), cmp(o.cmp) {}
    00081   csArrayCmp& operator=(csArrayCmp const& o)
    00082     { key = o.key; cmp = o.cmp; return *this; }
    00091   int operator()(T const& r) const { return cmp(r, key); }
    00093   operator CF() const { return cmp; }
    00095   operator K const&() const { return key; }
    00106   static int DefaultCompare(T const& r, K const& k)
    00107     { return csComparator<T,K>::Compare(r,k); }
    00108 private:
    00109   K key;
    00110   CF cmp;
    00111 };
    00112
    00113 #define csArrayTemplate(K) template <class K>
    00114 #define csArrayCmpDecl(T1,T2) csArrayCmp<T1,T2>
    00115 #define csArrayCmpInvoke(C,R) C(R)
    00116
    00117 #else // CSARRAY_INHIBIT_TYPED_KEYS
    00118
    00119 class csArrayCmpAbstract
    00120 {
    00121 public:
    00122   typedef int(*CF)(void const*, void const*);
    00123   virtual int operator()(void const*) const = 0;
    00124   virtual operator CF() const = 0;
    00125 };
    00126
    00127 template <class T, class K>
    00128 class csArrayCmp : public csArrayCmpAbstract
    00129 {
    00130 public:
    00131   typedef int(*CFTyped)(T const&, K const&);
    00132   csArrayCmp(K const& k, CFTyped c = DefaultCompare) : key(k), cmp(CF(c)) {}
    00133   csArrayCmp(csArrayCmp const& o) : key(o.key), cmp(o.cmp) {}
    00134   csArrayCmp& operator=(csArrayCmp const& o)
    00135     { key = o.key; cmp = o.cmp; return *this; }
    00136   virtual int operator()(void const* p) const { return cmp(p, &key); }
    00137   virtual operator CF() const { return cmp; }
    00138   operator K const&() const { return key; }
    00139   static int DefaultCompare(T const& r, K const& k)
    00140     { return csComparator<T,K>::Compare(r,k); }
    00141 private:
    00142   K key;
    00143   CF cmp;
    00144 };
    00145
    00146 #define csArrayTemplate(K)
    00147 #define csArrayCmpDecl(T1,T2) csArrayCmpAbstract const&
    00148 #define csArrayCmpInvoke(C,R) C(&(R))
    00149
    00150 #endif // CSARRAY_INHIBIT_TYPED_KEYS
    00151
    00155 template <class T>
    00156 class csArrayElementHandler
    00157 {
    00158 public:
    00159   static void Construct (T* address)
    00160   {
    00161     new (CS_STATIC_CAST(void*,address)) T();
    00162   }
    00163
    00164   static void Construct (T* address, T const& src)
    00165   {
    00166     new (CS_STATIC_CAST(void*,address)) T(src);
    00167   }
    00168
    00169   static void Destroy (T* address)
    00170   {
    00171     address->~T();
    00172   }
    00173
    00174   static void InitRegion (T* address, size_t count)
    00175   {
    00176     for (size_t i = 0 ; i < count ; i++)
    00177       Construct (address + i);
    00178   }
    00179 };
    00180
    00184 template <class T>
    00185 class csArrayMemoryAllocator
    00186 {
    00187 public:
    00188   static T* Alloc (size_t count)
    00189   {
    00190     return (T*)malloc (count * sizeof(T));
    00191   }
    00192
    00193   static void Free (T* mem)
    00194   {
    00195     free (mem);
    00196   }
    00197
    00198   // The 'relevantcount' parameter should be the number of items
    00199   // in the old array that are initialized.
    00200   static T* Realloc (T* mem, size_t relevantcount, size_t oldcount,
    00201     size_t newcount)
    00202   {
    00203     (void)relevantcount; (void)oldcount;
    00204     return (T*)realloc (mem, newcount * sizeof(T));
    00205   }
    00206
    00207   // Move memory.
    00208   static void MemMove (T* mem, size_t dest, size_t src, size_t count)
    00209   {
    00210     memmove (mem + dest, mem + src, count * sizeof(T));
    00211   }
    00212 };
    00213
    00222 template <class T, class ElementHandler = csArrayElementHandler<T> >
    00223 class csSafeCopyArrayMemoryAllocator
    00224 {
    00225 public:
    00226   static T* Alloc (size_t count)
    00227   {
    00228     return (T*)malloc (count * sizeof(T));
    00229   }
    00230
    00231   static void Free (T* mem)
    00232   {
    00233     free (mem);
    00234   }
    00235
    00236   static T* Realloc (T* mem, size_t relevantcount, size_t oldcount,
    00237     size_t newcount)
    00238   {
    00239     if (newcount <= oldcount)
    00240     {
    00241       // Realloc is safe.
    00242       T* newmem = (T*)realloc (mem, newcount * sizeof (T));
    00243       CS_ASSERT (newmem == mem);
    00244       return newmem;
    00245     }
    00246
    00247     T* newmem = Alloc (newcount);
    00248     size_t i;
    00249     for (i = 0 ; i < relevantcount ; i++)
    00250     {
    00251       ElementHandler::Construct (newmem + i, mem[i]);
    00252       ElementHandler::Destroy (mem + i);
    00253     }
    00254     Free (mem);
    00255     return newmem;
    00256   }
    00257
    00258   static void MemMove (T* mem, size_t dest, size_t src, size_t count)
    00259   {
    00260     size_t i;
    00261     if (dest < src)
    00262     {
    00263       for (i = 0 ; i < count ; i++)
    00264       {
    00265         ElementHandler::Construct (mem + dest + i, mem[src + i]);
    00266         ElementHandler::Destroy (mem + src + i);
    00267       }
    00268     }
    00269     else
    00270     {
    00271       i = count;
    00272       while (i > 0)
    00273       {
    00274         i--;
    00275         ElementHandler::Construct (mem + dest + i, mem[src + i]);
    00276         ElementHandler::Destroy (mem + src + i);
    00277       }
    00278     }
    00279   }
    00280 };
    00281
    00286 const size_t csArrayItemNotFound = (size_t)-1;
    00287
    00296 template <class T,
    00297         class ElementHandler = csArrayElementHandler<T>,
    00298         class MemoryAllocator = csArrayMemoryAllocator<T> >
    00299 class csArray
    00300 {
    00301 private:
    00302   size_t count;
    00303   size_t capacity;
    00304   size_t threshold;
    00305   T* root;
    00306 #ifdef CS_MEMORY_TRACKER
    00307   csMemTrackerInfo* mti;
    00308   void UpdateMti (int dn, int curcapacity)
    00309   {
    00310     if (!mti)
    00311     {
    00312       if (!curcapacity) return;
    00313       char buf[1024];
    00314       strcpy (buf, "csArray<");
    00315       size_t l = strlen (typeid (T).name ());
    00316       if (l > 1000) l = 1000;
    00317       strncat (buf, typeid (T).name (), l);
    00318       strcat (buf, ">");
    00319       mti = mtiRegisterAlloc (1 * sizeof (T), buf);
    00320       if (!mti) return;
    00321       curcapacity--;
    00322       if (curcapacity)
    00323         mtiUpdateAmount (mti, curcapacity, curcapacity * sizeof (T));
    00324       return;
    00325     }
    00326     mtiUpdateAmount (mti, dn, dn * sizeof (T));
    00327   }
    00328 #endif
    00329
    00330 protected:
    00335   void InitRegion (size_t start, size_t count)
    00336   {
    00337     ElementHandler::InitRegion (root+start, count);
    00338   }
    00339
    00340 private:
    00342   void CopyFrom (const csArray& source)
    00343   {
    00344     if (&source != this)
    00345     {
    00346       DeleteAll ();
    00347       threshold = source.threshold;
    00348       SetSizeUnsafe (source.Length ());
    00349       for (size_t i=0 ; i<source.Length() ; i++)
    00350         ElementHandler::Construct (root + i, source[i]);
    00351     }
    00352   }
    00353
    00355   void InternalSetCapacity (size_t n)
    00356   {
    00357     if (root == 0)
    00358     {
    00359       root = MemoryAllocator::Alloc (n);
    00360 #ifdef CS_MEMORY_TRACKER
    00361       UpdateMti (n, n);
    00362 #endif
    00363     }
    00364     else
    00365     {
    00366       root = MemoryAllocator::Realloc (root, count, capacity, n);
    00367 #ifdef CS_MEMORY_TRACKER
    00368       UpdateMti (n-capacity, n);
    00369 #endif
    00370     }
    00371     capacity = n;
    00372   }
    00373
    00378   void AdjustCapacity (size_t n)
    00379   {
    00380     if (n > capacity || (capacity > threshold && n < capacity - threshold))
    00381     {
    00382       InternalSetCapacity (((n + threshold - 1) / threshold ) * threshold);
    00383     }
    00384   }
    00385
    00392   void SetSizeUnsafe (size_t n)
    00393   {
    00394     if (n > capacity)
    00395       AdjustCapacity (n);
    00396     count = n;
    00397   }
    00398
    00399 public:
    00411   static int DefaultCompare(T const& r1, T const& r2)
    00412   {
    00413     return csComparator<T,T>::Compare(r1,r2);
    00414   }
    00415
    00421   csArray (size_t in_capacity = 0, size_t in_threshold = 0)
    00422   {
    00423 #ifdef CS_MEMORY_TRACKER
    00424     mti = 0;
    00425 #endif
    00426     count = 0;
    00427     capacity = (in_capacity > 0 ? in_capacity : 0);
    00428     threshold = (in_threshold > 0 ? in_threshold : 16);
    00429     if (capacity != 0)
    00430     {
    00431       root = MemoryAllocator::Alloc (capacity);
    00432 #ifdef CS_MEMORY_TRACKER
    00433       UpdateMti (capacity, capacity);
    00434 #endif
    00435     }
    00436     else
    00437     {
    00438       root = 0;
    00439     }
    00440   }
    00441
    00443   ~csArray ()
    00444   {
    00445     DeleteAll ();
    00446   }
    00447
    00449   csArray (const csArray& source)
    00450   {
    00451 #ifdef CS_MEMORY_TRACKER
    00452     mti = 0;
    00453 #endif
    00454     root = 0;
    00455     capacity = 0;
    00456     count = 0;
    00457     CopyFrom (source);
    00458   }
    00459
    00461   csArray<T,ElementHandler>& operator= (const csArray& other)
    00462   {
    00463     CopyFrom (other);
    00464     return *this;
    00465   }
    00466
    00468   size_t GetSize () const
    00469   {
    00470     return count;
    00471   }
    00472
    00477   size_t Length () const
    00478   {
    00479     return GetSize();
    00480   }
    00481
    00483   size_t Capacity () const
    00484   {
    00485     return capacity;
    00486   }
    00487
    00494   void TransferTo (csArray& destination)
    00495   {
    00496     if (&destination != this)
    00497     {
    00498       destination.DeleteAll ();
    00499       destination.root = root;
    00500       destination.count = count;
    00501       destination.capacity = capacity;
    00502       destination.threshold = threshold;
    00503 #ifdef CS_MEMORY_TRACKER
    00504       destination.mti = mti;
    00505       mti = 0;
    00506 #endif
    00507       root = 0;
    00508       capacity = count = 0;
    00509     }
    00510   }
    00511
    00521   void SetSize (size_t n, T const& what)
    00522   {
    00523     if (n <= count)
    00524     {
    00525       Truncate (n);
    00526     }
    00527     else
    00528     {
    00529       size_t old_len = Length ();
    00530       SetSizeUnsafe (n);
    00531       for (size_t i = old_len ; i < n ; i++)
    00532         ElementHandler::Construct (root + i, what);
    00533     }
    00534   }
    00535
    00543   void SetSize (size_t n)
    00544   {
    00545     if (n <= count)
    00546     {
    00547       Truncate (n);
    00548     }
    00549     else
    00550     {
    00551       size_t old_len = Length ();
    00552       SetSizeUnsafe (n);
    00553       ElementHandler::InitRegion (root + old_len, n-old_len);
    00554     }
    00555   }
    00556
    00562   void SetLength (size_t n, T const& what) { SetSize(n, what); }
    00563   void SetLength (size_t n) { SetSize(n); }
    00566
    00567   T& Get (size_t n)
    00568   {
    00569     CS_ASSERT (n < count);
    00570     return root[n];
    00571   }
    00572
    00574   T const& Get (size_t n) const
    00575   {
    00576     CS_ASSERT (n < count);
    00577     return root[n];
    00578   }
    00579
    00585   T& GetExtend (size_t n)
    00586   {
    00587     if (n >= count)
    00588       SetSize (n+1);
    00589     return root[n];
    00590   }
    00591
    00593   T& operator [] (size_t n)
    00594   {
    00595     return Get(n);
    00596   }
    00597
    00599   T const& operator [] (size_t n) const
    00600   {
    00601     return Get(n);
    00602   }
    00603
    00605   void Put (size_t n, T const& what)
    00606   {
    00607     if (n >= count)
    00608       SetSize (n+1);
    00609     ElementHandler::Destroy (root + n);
    00610     ElementHandler::Construct (root + n, what);
    00611   }
    00612
    00620   csArrayTemplate(K)
    00621   size_t FindKey (csArrayCmpDecl(T,K) comparekey) const
    00622   {
    00623     for (size_t i = 0 ; i < Length () ; i++)
    00624       if (csArrayCmpInvoke(comparekey, root[i]) == 0)
    00625         return i;
    00626     return csArrayItemNotFound;
    00627   }
    00628
    00633   size_t Push (T const& what)
    00634   {
    00635     if (((&what >= root) && (&what < root + Length())) &&
    00636       (capacity < count + 1))
    00637     {
    00638       /*
    00639         Special case: An element from this very array is pushed, and a
    00640         reallocation is needed. This could cause the passed ref to the
    00641         element to be pushed to be read from deleted memory. Work
    00642         around this.
    00643        */
    00644       size_t whatIndex = &what - root;
    00645       SetSizeUnsafe (count + 1);
    00646       ElementHandler::Construct (root + count - 1, root[whatIndex]);
    00647     }
    00648     else
    00649     {
    00650       SetSizeUnsafe (count + 1);
    00651       ElementHandler::Construct (root + count - 1, what);
    00652     }
    00653     return count - 1;
    00654   }
    00655
    00660   size_t PushSmart (T const& what)
    00661   {
    00662     size_t const n = Find (what);
    00663     return (n == csArrayItemNotFound) ? Push (what) : n;
    00664   }
    00665
    00667   T Pop ()
    00668   {
    00669     CS_ASSERT (count > 0);
    00670     T ret(root [count - 1]);
    00671     ElementHandler::Destroy (root + count - 1);
    00672     SetSizeUnsafe (count - 1);
    00673     return ret;
    00674   }
    00675
    00677   T const& Top () const
    00678   {
    00679     CS_ASSERT (count > 0);
    00680     return root [count - 1];
    00681   }
    00682
    00684   T& Top ()
    00685   {
    00686     CS_ASSERT (count > 0);
    00687     return root [count - 1];
    00688   }
    00689
    00691   bool Insert (size_t n, T const& item)
    00692   {
    00693     if (n <= count)
    00694     {
    00695       SetSizeUnsafe (count + 1); // Increments 'count' as a side-effect.
    00696       size_t const nmove = (count - n - 1);
    00697       if (nmove > 0)
    00698         MemoryAllocator::MemMove (root, n+1, n, nmove);
    00699       ElementHandler::Construct (root + n, item);
    00700       return true;
    00701     }
    00702     else
    00703       return false;
    00704   }
    00705
    00709   csArray<T> Section (size_t low, size_t high) const
    00710   {
    00711     CS_ASSERT (high < count && high >= low);
    00712     csArray<T> sect (high - low + 1);
    00713     for (size_t i = low; i <= high; i++) sect.Push (root[i]);
    00714     return sect;
    00715   }
    00716
    00722   csArrayTemplate(K)
    00723   size_t FindSortedKey (csArrayCmpDecl(T,K) comparekey,
    00724                         size_t* candidate = 0) const
    00725   {
    00726     size_t m = 0, l = 0, r = Length ();
    00727     while (l < r)
    00728     {
    00729       m = (l + r) / 2;
    00730       int cmp = csArrayCmpInvoke(comparekey, root[m]);
    00731       if (cmp == 0)
    00732       {
    00733         if (candidate) *candidate = csArrayItemNotFound;
    00734         return m;
    00735       }
    00736       else if (cmp < 0)
    00737         l = m + 1;
    00738       else
    00739         r = m;
    00740     }
    00741     if (candidate) *candidate = m;
    00742     return csArrayItemNotFound;
    00743   }
    00744
    00751   size_t InsertSorted (const T& item,
    00752     int (*compare)(T const&, T const&) = DefaultCompare,
    00753     size_t* equal_index = 0)
    00754   {
    00755     size_t m = 0, l = 0, r = Length ();
    00756     while (l < r)
    00757     {
    00758       m = (l + r) / 2;
    00759       int cmp = compare (root [m], item);
    00760
    00761       if (cmp == 0)
    00762       {
    00763         if (equal_index) *equal_index = m;
    00764         Insert (++m, item);
    00765         return m;
    00766       }
    00767       else if (cmp < 0)
    00768         l = m + 1;
    00769       else
    00770         r = m;
    00771     }
    00772     if ((m + 1) == r)
    00773       m++;
    00774     if (equal_index) *equal_index = csArrayItemNotFound;
    00775     Insert (m, item);
    00776     return m;
    00777   }
    00778
    00785   size_t Find (T const& which) const
    00786   {
    00787     for (size_t i = 0 ; i < Length () ; i++)
    00788       if (root[i] == which)
    00789         return i;
    00790     return csArrayItemNotFound;
    00791   }
    00792
    00794   size_t Contains(T const& which) const
    00795   { return Find(which); }
    00796
    00803   size_t GetIndex (const T* which) const
    00804   {
    00805     CS_ASSERT (which >= root);
    00806     CS_ASSERT (which < (root + count));
    00807     return which-root;
    00808   }
    00809
    00813   void Sort (int (*compare)(T const&, T const&) = DefaultCompare)
    00814   {
    00815     qsort (root, Length(), sizeof(T),
    00816       (int (*)(void const*, void const*))compare);
    00817   }
    00818
    00822   void DeleteAll ()
    00823   {
    00824     if (root)
    00825     {
    00826       size_t i;
    00827       for (i = 0 ; i < count ; i++)
    00828         ElementHandler::Destroy (root + i);
    00829       MemoryAllocator::Free (root);
    00830 #     ifdef CS_MEMORY_TRACKER
    00831       UpdateMti (-capacity, 0);
    00832 #     endif
    00833       root = 0;
    00834       capacity = count = 0;
    00835     }
    00836   }
    00837
    00849   void Truncate (size_t n)
    00850   {
    00851     CS_ASSERT(n <= count);
    00852     if (n < count)
    00853     {
    00854       for (size_t i = n; i < count; i++)
    00855         ElementHandler::Destroy (root + i);
    00856       SetSizeUnsafe(n);
    00857     }
    00858   }
    00859
    00865   void Empty ()
    00866   {
    00867     Truncate (0);
    00868   }
    00869
    00875   bool IsEmpty() const
    00876   {
    00877     return GetSize() == 0;
    00878   }
    00879
    00886   void SetCapacity (size_t n)
    00887   {
    00888     if (n > Length ())
    00889       InternalSetCapacity (n);
    00890   }
    00891
    00899   void SetMinimalCapacity (size_t n)
    00900   {
    00901     if (n < Capacity ()) return;
    00902     if (n > Length ())
    00903       InternalSetCapacity (n);
    00904   }
    00905
    00911   void ShrinkBestFit ()
    00912   {
    00913     if (count == 0)
    00914     {
    00915       DeleteAll ();
    00916     }
    00917     else if (count != capacity)
    00918     {
    00919       root = MemoryAllocator::Realloc (root, count, capacity, count);
    00920 #ifdef CS_MEMORY_TRACKER
    00921       UpdateMti (count-capacity, count);
    00922 #endif
    00923       capacity = count;
    00924     }
    00925   }
    00926
    00935   bool DeleteIndex (size_t n)
    00936   {
    00937     if (n < count)
    00938     {
    00939       size_t const ncount = count - 1;
    00940       size_t const nmove = ncount - n;
    00941       ElementHandler::Destroy (root + n);
    00942       if (nmove > 0)
    00943         MemoryAllocator::MemMove (root, n, n+1, nmove);
    00944       SetSizeUnsafe (ncount);
    00945       return true;
    00946     }
    00947     else
    00948       return false;
    00949   }
    00950
    00960   bool DeleteIndexFast (size_t n)
    00961   {
    00962     if (n < count)
    00963     {
    00964       size_t const ncount = count - 1;
    00965       size_t const nmove = ncount - n;
    00966       ElementHandler::Destroy (root + n);
    00967       if (nmove > 0)
    00968         MemoryAllocator::MemMove (root, n, ncount, 1);
    00969       SetSizeUnsafe (ncount);
    00970       return true;
    00971     }
    00972     else
    00973       return false;
    00974   }
    00975
    00980   void DeleteRange (size_t start, size_t end)
    00981   {
    00982     if (start >= count) return;
    00983     // Treat 'csArrayItemNotFound' as invalid indices, do nothing.
    00984     // @@@ Assert that?
    00985     if (end == csArrayItemNotFound) return;
    00986     if (start == csArrayItemNotFound) return;//start = 0;
    00987     if (end >= count) end = count - 1;
    00988     size_t i;
    00989     for (i = start ; i <= end ; i++)
    00990       ElementHandler::Destroy (root + i);
    00991
    00992     size_t const range_size = end - start + 1;
    00993     size_t const ncount = count - range_size;
    00994     size_t const nmove = count - end - 1;
    00995     if (nmove > 0)
    00996       MemoryAllocator::MemMove (root, start, start + range_size, nmove);
    00997     SetSizeUnsafe (ncount);
    00998   }
    00999
    01005   bool Delete (T const& item)
    01006   {
    01007     size_t const n = Find (item);
    01008     if (n != csArrayItemNotFound)
    01009       return DeleteIndex (n);
    01010     return false;
    01011   }
    01012
    01026   bool DeleteFast (T const& item)
    01027   {
    01028     size_t const n = Find (item);
    01029     if (n != csArrayItemNotFound)
    01030       return DeleteIndexFast (n);
    01031     return false;
    01032   }
    01033
    01035   class Iterator
    01036   {
    01037   public:
    01039     Iterator(Iterator const& r) :
    01040       currentelem(r.currentelem), array(r.array) {}
    01041
    01043     Iterator& operator=(Iterator const& r)
    01044     { currentelem = r.currentelem; array = r.array; return *this; }
    01045
    01047     bool HasNext()
    01048     { return currentelem < array.Length(); }
    01049
    01051     const T& Next()
    01052     { return array.Get(currentelem++); }
    01053
    01055     void Reset()
    01056     { currentelem = 0; }
    01057
    01058   protected:
    01059     Iterator(const csArray<T, ElementHandler>& newarray)
    01060         : currentelem(0), array(newarray) {}
    01061     friend class csArray<T, ElementHandler>;
    01062
    01063   private:
    01064     size_t currentelem;
    01065     const csArray<T, ElementHandler>& array;
    01066   };
    01067
    01069   Iterator GetIterator() const
    01070   { return Iterator(*this); }
    01071
    01073   bool operator== (const csArray& other) const
    01074   {
    01075     if (other.GetSize() != GetSize()) return false;
    01076     for (size_t i = 0; i < GetSize(); i++)
    01077       if (Get (i) != other[i]) return false;
    01078     return true;
    01079   }
    01080 };
    01081
    01087 template <class T>
    01088 class csSafeCopyArray
    01089         : public csArray<T,
    01090                 csArrayElementHandler<T>,
    01091                 csSafeCopyArrayMemoryAllocator<T> >
    01092 {
    01093 public:
    01098   csSafeCopyArray (size_t limit = 0, size_t threshold = 0)
    01099         : csArray<T, csArrayElementHandler<T>,
    01100                      csSafeCopyArrayMemoryAllocator<T> > (limit, threshold)
    01101   {
    01102   }
    01103 };
    01104
    01105 #if defined(CS_EXTENSIVE_MEMDEBUG) || defined(CS_MEMORY_TRACKER)
    01106 # define new CS_EXTENSIVE_MEMDEBUG_NEW
    01107 #endif
    01108
    01111 #endif