CrystalSpace

Public API Reference

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