# 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
    00038   template <uint X>
    00039   SmallVector(const SmallVector<T, X> &other) : data(NULL), items(0), capacity(0)
    00040   {
    00041     MemCpyT<T>(this->Append(other.Length()), other.Begin(), other.Length());
    00042   }
    00043
    00044   template <uint X>
    00045   SmallVector &operator=(const SmallVector<T, X> &other)
    00046   {
    00047     this->Reset();
    00048     MemCpyT<T>(this->Append(other.Length()), other.Begin(), other.Length());
    00049     return *this;
    00050   }
    00051
    00052   ~SmallVector()
    00053   {
    00054     free(this->data);
    00055   }
    00056
    00060   FORCEINLINE void Clear()
    00061   {
    00062     /* In fact we just reset the item counter avoiding the need to
    00063      * probably reallocate the same amount of memory the list was
    00064      * previously using. */
    00065     this->items = 0;
    00066   }
    00067
    00071   FORCEINLINE void Reset()
    00072   {
    00073     this->items = 0;
    00074     this->capacity = 0;
    00075     free(data);
    00076     data = NULL;
    00077   }
    00078
    00082   FORCEINLINE void Compact()
    00083   {
    00084     uint capacity = Align(this->items, S);
    00085     if (capacity >= this->capacity) return;
    00086
    00087     this->capacity = capacity;
    00088     this->data = ReallocT(this->data, this->capacity);
    00089   }
    00090
    00096   FORCEINLINE T *Append(uint to_add = 1)
    00097   {
    00098     uint begin = this->items;
    00099     this->items += to_add;
    00100
    00101     if (this->items > this->capacity) {
    00102       this->capacity = Align(this->items, S);
    00103       this->data = ReallocT(this->data, this->capacity);
    00104     }
    00105
    00106     return &this->data[begin];
    00107   }
    00108
    00115   FORCEINLINE const T *Find(const T &item) const
    00116   {
    00117     const T *pos = this->Begin();
    00118     const T *end = this->End();
    00119     while (pos != end && *pos != item) pos++;
    00120     return pos;
    00121   }
    00122
    00129   FORCEINLINE T *Find(const T &item)
    00130   {
    00131     T *pos = this->Begin();
    00132     const T *end = this->End();
    00133     while (pos != end && *pos != item) pos++;
    00134     return pos;
    00135   }
    00136
    00143   FORCEINLINE int FindIndex(const T &item)
    00144   {
    00145     int index = 0;
    00146     T *pos = this->Begin();
    00147     const T *end = this->End();
    00148     while (pos != end && *pos != item) {
    00149       pos++;
    00150       index++;
    00151     }
    00152     return pos == end ? -1 : index;
    00153   }
    00154
    00161   FORCEINLINE bool Contains(const T &item) const
    00162   {
    00163     return this->Find(item) != this->End();
    00164   }
    00165
    00171   FORCEINLINE void Erase(T *item)
    00172   {
    00173     assert(item >= this->Begin() && item < this->End());
    00174     *item = this->data[--this->items];
    00175   }
    00176
    00183   FORCEINLINE bool Include(const T &item)
    00184   {
    00185     bool is_member = this->Contains(item);
    00186     if (!is_member) *this->Append() = item;
    00187     return is_member;
    00188   }
    00189
    00193   FORCEINLINE uint Length() const
    00194   {
    00195     return this->items;
    00196   }
    00197
    00203   FORCEINLINE const T *Begin() const
    00204   {
    00205     return this->data;
    00206   }
    00207
    00213   FORCEINLINE T *Begin()
    00214   {
    00215     return this->data;
    00216   }
    00217
    00223   FORCEINLINE const T *End() const
    00224   {
    00225     return &this->data[this->items];
    00226   }
    00227
    00233   FORCEINLINE T *End()
    00234   {
    00235     return &this->data[this->items];
    00236   }
    00237
    00244   FORCEINLINE const T *Get(uint index) const
    00245   {
    00246     /* Allow access to the 'first invalid' item */
    00247     assert(index <= this->items);
    00248     return &this->data[index];
    00249   }
    00250
    00257   FORCEINLINE T *Get(uint index)
    00258   {
    00259     /* Allow access to the 'first invalid' item */
    00260     assert(index <= this->items);
    00261     return &this->data[index];
    00262   }
    00263
    00270   FORCEINLINE const T &operator[](uint index) const
    00271   {
    00272     assert(index < this->items);
    00273     return this->data[index];
    00274   }
    00275
    00282   FORCEINLINE T &operator[](uint index)
    00283   {
    00284     assert(index < this->items);
    00285     return this->data[index];
    00286   }
    00287 };
    00288
    00289
    00300 template <typename T, uint S>
    00301 class AutoFreeSmallVector : public SmallVector<T, S> {
    00302 public:
    00303   ~AutoFreeSmallVector()
    00304   {
    00305     this->Clear();
    00306   }
    00307
    00311   FORCEINLINE void Clear()
    00312   {
    00313     for (uint i = 0; i < this->items; i++) {
    00314       free(this->data[i]);
    00315     }
    00316
    00317     this->items = 0;
    00318   }
    00319 };
    00320
    00321 typedef AutoFreeSmallVector<char*, 4> StringList;
    00322
    00323 #endif /* SMALLVEC_TYPE_HPP */