smallvec_type.hpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #ifndef SMALLVEC_TYPE_HPP
00013 #define SMALLVEC_TYPE_HPP
00014 
00015 #include "alloc_func.hpp"
00016 #include "mem_func.hpp"
00017 
00028 template <typename T, uint S>
00029 class SmallVector {
00030 protected:
00031   T *data;       
00032   uint items;    
00033   uint capacity; 
00034 
00035 public:
00036   SmallVector() : data(NULL), items(0), capacity(0) { }
00037 
00042   SmallVector(const SmallVector &other) : data(NULL), items(0), capacity(0)
00043   {
00044     this->Assign(other);
00045   }
00046 
00051   template <uint X>
00052   SmallVector(const SmallVector<T, X> &other) : data(NULL), items(0), capacity(0)
00053   {
00054     this->Assign(other);
00055   }
00056 
00061   SmallVector &operator=(const SmallVector &other)
00062   {
00063     this->Assign(other);
00064     return *this;
00065   }
00066 
00071   template <uint X>
00072   SmallVector &operator=(const SmallVector<T, X> &other)
00073   {
00074     this->Assign(other);
00075     return *this;
00076   }
00077 
00078   ~SmallVector()
00079   {
00080     free(this->data);
00081   }
00082 
00086   template <uint X>
00087   inline void Assign(const SmallVector<T, X> &other)
00088   {
00089     if ((const void *)&other == (void *)this) return;
00090 
00091     this->Clear();
00092     if (other.Length() > 0) MemCpyT<T>(this->Append(other.Length()), other.Begin(), other.Length());
00093   }
00094 
00098   inline void Clear()
00099   {
00100     /* In fact we just reset the item counter avoiding the need to
00101      * probably reallocate the same amount of memory the list was
00102      * previously using. */
00103     this->items = 0;
00104   }
00105 
00109   inline void Reset()
00110   {
00111     this->items = 0;
00112     this->capacity = 0;
00113     free(data);
00114     data = NULL;
00115   }
00116 
00120   inline void Compact()
00121   {
00122     uint capacity = Align(this->items, S);
00123     if (capacity >= this->capacity) return;
00124 
00125     this->capacity = capacity;
00126     this->data = ReallocT(this->data, this->capacity);
00127   }
00128 
00134   inline T *Append(uint to_add = 1)
00135   {
00136     uint begin = this->items;
00137     this->items += to_add;
00138 
00139     if (this->items > this->capacity) {
00140       this->capacity = Align(this->items, S);
00141       this->data = ReallocT(this->data, this->capacity);
00142     }
00143 
00144     return &this->data[begin];
00145   }
00146 
00151   inline void Resize(uint num_items)
00152   {
00153     this->items = num_items;
00154 
00155     if (this->items > this->capacity) {
00156       this->capacity = Align(this->items, S);
00157       this->data = ReallocT(this->data, this->capacity);
00158     }
00159   }
00160 
00167   inline const T *Find(const T &item) const
00168   {
00169     const T *pos = this->Begin();
00170     const T *end = this->End();
00171     while (pos != end && *pos != item) pos++;
00172     return pos;
00173   }
00174 
00181   inline T *Find(const T &item)
00182   {
00183     T *pos = this->Begin();
00184     const T *end = this->End();
00185     while (pos != end && *pos != item) pos++;
00186     return pos;
00187   }
00188 
00195   inline int FindIndex(const T &item) const
00196   {
00197     int index = 0;
00198     const T *pos = this->Begin();
00199     const T *end = this->End();
00200     while (pos != end && *pos != item) {
00201       pos++;
00202       index++;
00203     }
00204     return pos == end ? -1 : index;
00205   }
00206 
00213   inline bool Contains(const T &item) const
00214   {
00215     return this->Find(item) != this->End();
00216   }
00217 
00223   inline void Erase(T *item)
00224   {
00225     assert(item >= this->Begin() && item < this->End());
00226     *item = this->data[--this->items];
00227   }
00228 
00234   void ErasePreservingOrder(uint pos, uint count = 1)
00235   {
00236     if (count == 0) return;
00237     assert(pos < this->items);
00238     assert(pos + count <= this->items);
00239     this->items -= count;
00240     uint to_move = this->items - pos;
00241     if (to_move > 0) MemMoveT(this->data + pos, this->data + pos + count, to_move);
00242   }
00243 
00250   inline bool Include(const T &item)
00251   {
00252     bool is_member = this->Contains(item);
00253     if (!is_member) *this->Append() = item;
00254     return is_member;
00255   }
00256 
00260   inline uint Length() const
00261   {
00262     return this->items;
00263   }
00264 
00270   inline const T *Begin() const
00271   {
00272     return this->data;
00273   }
00274 
00280   inline T *Begin()
00281   {
00282     return this->data;
00283   }
00284 
00290   inline const T *End() const
00291   {
00292     return &this->data[this->items];
00293   }
00294 
00300   inline T *End()
00301   {
00302     return &this->data[this->items];
00303   }
00304 
00311   inline const T *Get(uint index) const
00312   {
00313     /* Allow access to the 'first invalid' item */
00314     assert(index <= this->items);
00315     return &this->data[index];
00316   }
00317 
00324   inline T *Get(uint index)
00325   {
00326     /* Allow access to the 'first invalid' item */
00327     assert(index <= this->items);
00328     return &this->data[index];
00329   }
00330 
00337   inline const T &operator[](uint index) const
00338   {
00339     assert(index < this->items);
00340     return this->data[index];
00341   }
00342 
00349   inline T &operator[](uint index)
00350   {
00351     assert(index < this->items);
00352     return this->data[index];
00353   }
00354 };
00355 
00356 
00367 template <typename T, uint S>
00368 class AutoFreeSmallVector : public SmallVector<T, S> {
00369 public:
00370   ~AutoFreeSmallVector()
00371   {
00372     this->Clear();
00373   }
00374 
00378   inline void Clear()
00379   {
00380     for (uint i = 0; i < this->items; i++) {
00381       free(this->data[i]);
00382     }
00383 
00384     this->items = 0;
00385   }
00386 };
00387 
00398 template <typename T, uint S>
00399 class AutoDeleteSmallVector : public SmallVector<T, S> {
00400 public:
00401   ~AutoDeleteSmallVector()
00402   {
00403     this->Clear();
00404   }
00405 
00409   inline void Clear()
00410   {
00411     for (uint i = 0; i < this->items; i++) {
00412       delete this->data[i];
00413     }
00414 
00415     this->items = 0;
00416   }
00417 };
00418 
00419 typedef AutoFreeSmallVector<char*, 4> StringList; 
00420 
00421 #endif /* SMALLVEC_TYPE_HPP */