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 "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

Generated for Crystal Space by doxygen 1.4.6