smallvec_type.hpp

Go to the documentation of this file.
00001 /* $Id: smallvec_type.hpp 24452 2012-08-01 19:07:04Z rubidium $ */
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 
00153   inline const T *Find(const T &item) const
00154   {
00155     const T *pos = this->Begin();
00156     const T *end = this->End();
00157     while (pos != end && *pos != item) pos++;
00158     return pos;
00159   }
00160 
00167   inline T *Find(const T &item)
00168   {
00169     T *pos = this->Begin();
00170     const T *end = this->End();
00171     while (pos != end && *pos != item) pos++;
00172     return pos;
00173   }
00174 
00181   inline int FindIndex(const T &item)
00182   {
00183     int index = 0;
00184     T *pos = this->Begin();
00185     const T *end = this->End();
00186     while (pos != end && *pos != item) {
00187       pos++;
00188       index++;
00189     }
00190     return pos == end ? -1 : index;
00191   }
00192 
00199   inline bool Contains(const T &item) const
00200   {
00201     return this->Find(item) != this->End();
00202   }
00203 
00209   inline void Erase(T *item)
00210   {
00211     assert(item >= this->Begin() && item < this->End());
00212     *item = this->data[--this->items];
00213   }
00214 
00221   inline bool Include(const T &item)
00222   {
00223     bool is_member = this->Contains(item);
00224     if (!is_member) *this->Append() = item;
00225     return is_member;
00226   }
00227 
00231   inline uint Length() const
00232   {
00233     return this->items;
00234   }
00235 
00241   inline const T *Begin() const
00242   {
00243     return this->data;
00244   }
00245 
00251   inline T *Begin()
00252   {
00253     return this->data;
00254   }
00255 
00261   inline const T *End() const
00262   {
00263     return &this->data[this->items];
00264   }
00265 
00271   inline T *End()
00272   {
00273     return &this->data[this->items];
00274   }
00275 
00282   inline const T *Get(uint index) const
00283   {
00284     /* Allow access to the 'first invalid' item */
00285     assert(index <= this->items);
00286     return &this->data[index];
00287   }
00288 
00295   inline T *Get(uint index)
00296   {
00297     /* Allow access to the 'first invalid' item */
00298     assert(index <= this->items);
00299     return &this->data[index];
00300   }
00301 
00308   inline const T &operator[](uint index) const
00309   {
00310     assert(index < this->items);
00311     return this->data[index];
00312   }
00313 
00320   inline T &operator[](uint index)
00321   {
00322     assert(index < this->items);
00323     return this->data[index];
00324   }
00325 };
00326 
00327 
00338 template <typename T, uint S>
00339 class AutoFreeSmallVector : public SmallVector<T, S> {
00340 public:
00341   ~AutoFreeSmallVector()
00342   {
00343     this->Clear();
00344   }
00345 
00349   inline void Clear()
00350   {
00351     for (uint i = 0; i < this->items; i++) {
00352       free(this->data[i]);
00353     }
00354 
00355     this->items = 0;
00356   }
00357 };
00358 
00369 template <typename T, uint S>
00370 class AutoDeleteSmallVector : public SmallVector<T, S> {
00371 public:
00372   ~AutoDeleteSmallVector()
00373   {
00374     this->Clear();
00375   }
00376 
00380   inline void Clear()
00381   {
00382     for (uint i = 0; i < this->items; i++) {
00383       delete this->data[i];
00384     }
00385 
00386     this->items = 0;
00387   }
00388 };
00389 
00390 typedef AutoFreeSmallVector<char*, 4> StringList; 
00391 
00392 #endif /* SMALLVEC_TYPE_HPP */