Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

Collection.hpp

Go to the documentation of this file.
00001 #ifndef COLLECTION_HPP__
00002 #define COLLECTION_HPP__
00003 
00004 #include "TObjArray.h"
00005 #include <iterator>
00006 
00007 namespace cafe {
00008 
00022     template<class T>
00023     class Collection {
00024     public:
00025         typedef T      value_type;
00026         typedef size_t size_type;
00027         typedef T*     pointer_type;
00028         typedef T&     reference_type;
00029         typedef const T* const_pointer_type;
00030         typedef const T& const_reference_type;
00031     public:
00034         Collection(TObjArray *data)
00035             : _data(0)
00036         {
00037             if (data)
00038                 _data = (new array_holder(data, false));
00039             else
00040                 _data = (new array_holder(new TObjArray(), true));
00041         }
00042 
00045         Collection(const Collection<T>& other)
00046             : _data(other._data)
00047         {
00048             _data->inc();
00049         }
00052         Collection(void)
00053             : _data (new array_holder(new TObjArray(), true))
00054         {}
00055 
00057         virtual ~Collection() {
00058             _data->decAndDeleteIf();
00059         }
00060 
00062         Collection<T>& operator=(const Collection<T>& other) 
00063         {
00064             if(&other != this) {
00065                 _data->decAndDeleteIf();
00066                 _data = other._data;
00067                 _data->inc();
00068             }
00069             return *this;
00070         }
00071 
00075         void push_back (const T& item)
00076         {
00077             assert(item.IsOnHeap());
00078             make_us_owner_of_data();
00079             (*_data)->Add(const_cast<T*>(&item));
00080         }
00081 
00084         void push_back(T *item)
00085         {
00086             make_us_owner_of_data();
00087             (*_data)->Add(item);
00088         }
00089 
00091         const T& operator[](size_t index) const { return *static_cast<T*>((*_data)->At(index)); }
00092 
00094 
00095         class iterator;
00096         class const_iterator;
00097 
00099         iterator begin() { return iterator(*_data, 0); }
00100         const_iterator begin() const { return const_iterator(*_data, 0); }
00101 
00103         iterator end()   { return iterator(*_data, *_data ? (*_data)->GetLast() + 1 : 0); }
00104         const_iterator end()   const { return const_iterator(*_data, (*_data) ? (*_data)->GetLast() + 1 : 0); }
00105 
00107         iterator erase(iterator it) 
00108         { 
00109             int i = it._index;
00110             make_us_owner_of_data();
00111             (*_data)->RemoveAt(i);
00112             (*_data)->Compress();
00113             return iterator((*_data), i);
00114         }
00115 
00117         iterator erase(iterator first, iterator last)
00118         {
00119             int i = first._index;
00120             make_us_owner_of_data();
00121             while(i != last._index) {
00122                 (*_data)->RemoveAt(i);
00123                 ++i;
00124             }
00125             (*_data)->Compress();
00126             return iterator((*_data),first._index);
00127         }
00128 
00130         
00132         size_t size() const { return _data ? (*_data)->GetLast() + 1 : 0; }
00133 
00144         template <typename compare>
00145         void sort(iterator from, iterator to, compare CompFun)
00146         {
00147             make_us_owner_of_data();
00148             full_sort(*(*_data),from._index,to._index,CompFun);
00149             return;
00150         } 
00151 
00152 
00154         class iterator : public std::iterator<std::random_access_iterator_tag, T> {
00155         public:
00156             iterator() : _data(0), _index(0) {}
00157             iterator(const iterator& other) : _data(other._data), _index(other._index) {}
00158             iterator& operator=(const iterator& other)
00159             {
00160                 if(this != &other) {
00161                     _data  = other._data;
00162                     _index = other._index;
00163                 }
00164                 return *this;
00165             }
00166 
00167             reference_type operator*() const { return *static_cast<T*>(_data->At(_index)); }
00168             pointer_type operator->() const { return static_cast<T*>(_data->At(_index)); }
00169 
00170             iterator& operator++()    { _index++; return *this; }
00171             iterator  operator++(int) { iterator  result(*this); _index++; return result; }
00172 
00173             iterator& operator--()    { _index--; return *this; }
00174             iterator  operator--(int) { iterator  result(*this); _index--; return result; }
00175 
00176             iterator operator+(size_t offset) const { return iterator(_data, _index + offset); }
00177             iterator operator-(size_t offset) const { return iterator(_data, _index - offset); }
00178 
00179             // template horror ahead
00180             typename std::iterator<std::random_access_iterator_tag, T>::difference_type 
00181             operator-(const iterator& other) const { return _index - other._index; }
00182 
00183             typename std::iterator<std::random_access_iterator_tag, T>::difference_type 
00184             operator+(const iterator& other) const { return _index + other._index; }
00185 
00186             iterator& operator+=(size_t offset) { _index += offset; return *this; }
00187             iterator& operator-=(size_t offset) { _index -= offset; return *this; }
00188 
00189             bool operator<(const iterator& other)  const{ return _index < other._index; }
00190             bool operator!=(const iterator& other) const { return _index != other._index; }
00191 
00192         private:
00193             friend class Collection;
00194             friend class const_iterator;
00195             iterator(TObjArray* data, int index = 0) : _data(data), _index(index) {}
00196         
00197             const TObjArray *_data;
00198             int             _index;
00199         };
00200 
00202         class const_iterator : public std::iterator<std::random_access_iterator_tag, T> {
00203         public:
00204             const_iterator() : _data(0), _index(0) {}
00205             const_iterator(const const_iterator& other) : _data(other._data), _index(other._index) {}
00206             const_iterator(const iterator& other) : _data(other._data), _index(other._index) {}
00207             const_iterator& operator=(const const_iterator& other)
00208             {
00209                 if(this != &other) {
00210                     _data  = other._data;
00211                     _index = other._index;
00212                 }
00213                 return *this;
00214             }
00215 
00216             const_reference_type operator*() const { return *static_cast<const T*>(_data->At(_index)); }
00217             const_pointer_type operator->() const { return static_cast<const T*>(_data->At(_index)); }
00218 
00219             const_iterator& operator++()    { _index++; return *this; }
00220             const_iterator  operator++(int) { const_iterator  result(*this); _index++; return result; }
00221 
00222             const_iterator& operator--()    { _index--; return *this; }
00223             const_iterator  operator--(int) { const_iterator  result(*this); _index--; return result; }
00224 
00225             const_iterator operator+(size_t offset) const { return const_iterator(_data, _index + offset); }
00226             const_iterator operator-(size_t offset) const { return const_iterator(_data, _index - offset); }
00227 
00228             // template horror ahead
00229             typename std::iterator<std::random_access_iterator_tag, T>::difference_type 
00230             operator-(const const_iterator& other) const { return _index - other._index; }
00231 
00232             typename std::iterator<std::random_access_iterator_tag, T>::difference_type 
00233             operator+(const const_iterator& other) const { return _index + other._index; }
00234 
00235             const_iterator& operator+=(size_t offset) { _index += offset; return *this; }
00236             const_iterator& operator-=(size_t offset) { _index -= offset; return *this; }
00237 
00238             bool operator<(const const_iterator& other)  const{ return _index < other._index; }
00239             bool operator!=(const const_iterator& other) const { return _index != other._index; }
00240 
00241         private:
00242             friend class Collection;
00243             const_iterator(const TObjArray* data, int index = 0) : _data(data), _index(index) {}
00244         
00245             const TObjArray *_data;
00246             int             _index;
00247         };
00248 
00251         class array_holder {
00252         public:
00253             inline array_holder (TObjArray *obj, bool owned)
00254                 : _array (obj), _count(1), _owned(owned)
00255             {}
00256             inline ~array_holder (void) {
00257                 if (_owned) {
00258                     delete _array;
00259                 }
00260             }
00261 
00262             TObjArray * operator->() {return _array;}
00263             operator TObjArray*() {return _array;}
00264             operator bool () {return _array != 0;}
00265 
00266             inline void inc (void) {
00267                 _count++;
00268             }
00269             inline void dec (void) {
00270                 _count--;
00271             }
00272             inline void decAndDeleteIf (void) {
00273                 dec();
00274                 if (!ownersLeft()) {
00275                     delete this;
00276                 }
00277             }
00278             inline bool ownersLeft (void) {
00279                 return _count != 0;
00280             }
00281             inline bool isOwned (void) {
00282                 return _owned;
00283             }
00284         private:
00285             TObjArray *_array;
00286             int        _count;
00287             bool       _owned;
00288         };
00289     private:
00292         array_holder *_data; 
00293 
00296         void make_us_owner_of_data (void)
00297         {
00298             if (_data->isOwned()) {
00299                 return;
00300             }
00301             TObjArray *t = new TObjArray (*(*_data));
00302             _data->decAndDeleteIf();
00303             _data = new array_holder (t, true);
00304         }
00305 
00306         // Sorting routines.
00307         // The insert_sort routine does a simple insertion sort. This is used by the
00308         // full_sort method for small Collections.
00309         template <typename compare>
00310         void insert_sort(TObjArray& array, int const from, int const to, compare CompFun)
00311         {
00312             int j = 0;
00313             TObject* tmp;
00314 
00315             for (int i = from; i != to; ++i) {
00316                 j   = i;
00317                 tmp = array.At(j);
00318                 while ((j>0) &&
00319                        !CompFun(*static_cast<T const*>(array.At(j-1)),*static_cast<T const*>(tmp))) {
00320                     array[j] = array.At(j-1);
00321                     --j;
00322                 } // while
00323                 array[j] = tmp;
00324             } // for
00325             return;
00326         } // insert_sort
00327 
00328         // The partial_quicksort does quicksort for Collections larger than insertSortMax entries.
00329         // It is called by full_sort.
00330         template <typename compare>
00331         void partial_quicksort(TObjArray& array, int indLow, int indHigh, compare CompFun)
00332         {
00333 
00334             const int insertSortMax = 8;
00335             int i = 0;
00336             int j = 0;
00337             int indTurn = 0;
00338             TObject const* turn = NULL;
00339 
00340             if ((indHigh - indLow) > insertSortMax) {
00341                 indTurn = (indLow+indHigh)/2;
00342                 turn = array.At(indTurn);
00343                 i = indLow;
00344                 j = indHigh-1;
00345 
00346                 swap(array,indTurn,indHigh);
00347 
00348                 // This may not be very nice but we'll use an infinite loop
00349                 // which we will exit via breaks.
00350                 while (true) {
00351                     while (!CompFun(*static_cast<T const*>(array.At(i)),*static_cast<T const*>(turn)) &&
00352                            (i<=j)) {
00353                         ++i;
00354                     }
00355                     while (CompFun(*static_cast<T const*>(array.At(j)),*static_cast<T const*>(turn)) &&
00356                            (i<j)) {
00357                         --j;
00358                     }
00359                     if (j<=i) {
00360                         break;
00361                     }
00362                     swap(array,i,j);
00363 
00364                 } // while (infinite loop)
00365                 swap(array,indHigh,j);
00366 
00367                 partial_quicksort(array,indLow,j-1,CompFun);
00368                 partial_quicksort(array,j+1,indHigh,CompFun);
00369             } // if (insert_sort or quicksort)
00370 
00371             return;
00372         } 
00373 
00374         // This is the sorting routine for Collections. It does insertion sort for
00375         // small Collections and quicksort for larger ones.
00376         template <typename compare>
00377         void full_sort(TObjArray& array, int const from, int const to, compare CompFun)
00378         {
00379             // First do a rough sort using partial_quicksort,
00380             // then finish things by sorting the remaining bits
00381             // using insert_sort.
00382             partial_quicksort(array,from,to-1,CompFun);
00383             insert_sort(array,from,to,CompFun);
00384             return;
00385         } 
00386 
00387         // The swap routine is a helper for the sorting methods.
00388         void swap(TObjArray& array, int i, int j)
00389         {
00390             TObject* tmp = array.At(i);
00391             array[i] = array.At(j);
00392             array[j] = tmp;
00393             return;
00394         }
00395 
00396     public:
00397         ClassDef(Collection, 0);
00398     };
00399 
00400 }
00401 
00402 #endif // COLLECTION_HPP__

Generated on Tue Mar 28 10:13:03 2006 for CAF by doxygen 1.3.4