# smallvec_type.hpp

Go to the documentation of this file.

    00001 /* $Id: smallvec_type.hpp 18996 2010-02-03 21:45:48Z 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 "math_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   ~SmallVector()
    00039   {
    00040     free(this->data);
    00041   }
    00042
    00046   FORCEINLINE void Clear()
    00047   {
    00048     /* In fact we just reset the item counter avoiding the need to
    00049      * probably reallocate the same amount of memory the list was
    00050      * previously using. */
    00051     this->items = 0;
    00052   }
    00053
    00057   FORCEINLINE void Reset()
    00058   {
    00059     this->items = 0;
    00060     this->capacity = 0;
    00061     free(data);
    00062     data = NULL;
    00063   }
    00064
    00068   FORCEINLINE void Compact()
    00069   {
    00070     uint capacity = Align(this->items, S);
    00071     if (capacity >= this->capacity) return;
    00072
    00073     this->capacity = capacity;
    00074     this->data = ReallocT(this->data, this->capacity);
    00075   }
    00076
    00082   FORCEINLINE T *Append(uint to_add = 1)
    00083   {
    00084     uint begin = this->items;
    00085     this->items += to_add;
    00086
    00087     if (this->items > this->capacity) {
    00088       this->capacity = Align(this->items, S);
    00089       this->data = ReallocT(this->data, this->capacity);
    00090     }
    00091
    00092     return &this->data[begin];
    00093   }
    00094
    00101   FORCEINLINE const T *Find(const T &item) const
    00102   {
    00103     const T *pos = this->Begin();
    00104     const T *end = this->End();
    00105     while (pos != end && *pos != item) pos++;
    00106     return pos;
    00107   }
    00108
    00115   FORCEINLINE T *Find(const T &item)
    00116   {
    00117     T *pos = this->Begin();
    00118     const T *end = this->End();
    00119     while (pos != end && *pos != item) pos++;
    00120     return pos;
    00121   }
    00122
    00129   FORCEINLINE int FindIndex(const T &item)
    00130   {
    00131     int index = 0;
    00132     T *pos = this->Begin();
    00133     const T *end = this->End();
    00134     while (pos != end && *pos != item) {
    00135       pos++;
    00136       index++;
    00137     }
    00138     return pos == end ? -1 : index;
    00139   }
    00140
    00147   FORCEINLINE bool Contains(const T &item) const
    00148   {
    00149     return this->Find(item) != this->End();
    00150   }
    00151
    00157   FORCEINLINE void Erase(T *item)
    00158   {
    00159     assert(item >= this->Begin() && item < this->End());
    00160     *item = this->data[--this->items];
    00161   }
    00162
    00169   FORCEINLINE bool Include(const T &item)
    00170   {
    00171     bool is_member = this->Contains(item);
    00172     if (!is_member) *this->Append() = item;
    00173     return is_member;
    00174   }
    00175
    00179   FORCEINLINE uint Length() const
    00180   {
    00181     return this->items;
    00182   }
    00183
    00189   FORCEINLINE const T *Begin() const
    00190   {
    00191     return this->data;
    00192   }
    00193
    00199   FORCEINLINE T *Begin()
    00200   {
    00201     return this->data;
    00202   }
    00203
    00209   FORCEINLINE const T *End() const
    00210   {
    00211     return &this->data[this->items];
    00212   }
    00213
    00219   FORCEINLINE T *End()
    00220   {
    00221     return &this->data[this->items];
    00222   }
    00223
    00230   FORCEINLINE const T *Get(uint index) const
    00231   {
    00232     /* Allow access to the 'first invalid' item */
    00233     assert(index <= this->items);
    00234     return &this->data[index];
    00235   }
    00236
    00243   FORCEINLINE T *Get(uint index)
    00244   {
    00245     /* Allow access to the 'first invalid' item */
    00246     assert(index <= this->items);
    00247     return &this->data[index];
    00248   }
    00249
    00256   FORCEINLINE const T &operator[](uint index) const
    00257   {
    00258     assert(index < this->items);
    00259     return this->data[index];
    00260   }
    00261
    00268   FORCEINLINE T &operator[](uint index)
    00269   {
    00270     assert(index < this->items);
    00271     return this->data[index];
    00272   }
    00273 };
    00274
    00275
    00286 template <typename T, uint S>
    00287 class AutoFreeSmallVector : public SmallVector<T, S> {
    00288 public:
    00289   ~AutoFreeSmallVector()
    00290   {
    00291     this->Clear();
    00292   }
    00293
    00297   FORCEINLINE void Clear()
    00298   {
    00299     for (uint i = 0; i < this->items; i++) {
    00300       free(this->data[i]);
    00301     }
    00302
    00303     this->items = 0;
    00304   }
    00305 };
    00306
    00307 typedef AutoFreeSmallVector<char*, 4> StringList;
    00308
    00309 #endif /* SMALLVEC_TYPE_HPP */