# smallvec_type.hpp

Go to the documentation of this file.

    00001 /* $Id: smallvec_type.hpp 25043 2013-02-24 16:43:24Z frosch $ */
    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 */