OpenTTD: src/core/smallvec_type.hpp Source File

OpenTTD

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

smallvec_type.hpp
Go to the documentation of this file.
1 /* $Id: smallvec_type.hpp 25043 2013-02-24 16:43:24Z frosch $ */
2
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
9
12 #ifndef SMALLVEC_TYPE_HPP
13 #define SMALLVEC_TYPE_HPP
14
15 #include "alloc_func.hpp"
16 #include "mem_func.hpp"
17
28 template <typename T, uint S>
29 class SmallVector {
30 protected:
31 T *data;
32 uint items;
33 uint capacity;
34
35 public:
36 SmallVector() : data(NULL), items(0), capacity(0) { }
37
42 SmallVector(const SmallVector &other) : data(NULL), items(0), capacity(0)
43 {
44 this->Assign(other);
45 }
46
51 template <uint X>
52 SmallVector(const SmallVector<T, X> &other) : data(NULL), items(0), capacity(0)
53 {
54 this->Assign(other);
55 }
56
61 SmallVector &operator=(const SmallVector &other)
62 {
63 this->Assign(other);
64 return *this;
65 }
66
71 template <uint X>
72 SmallVector &operator=(const SmallVector<T, X> &other)
73 {
74 this->Assign(other);
75 return *this;
76 }
77
78 ~SmallVector()
79 {
80 free(this->data);
81 }
82
86 template <uint X>
87 inline void Assign(const SmallVector<T, X> &other)
88 {
89 if ((const void *)&other == (void *)this) return;
90
91 this->Clear();
92 if (other.Length() > 0) MemCpyT<T>(this->Append(other.Length()), other.Begin(), other.Length());
93 }
94
98 inline void Clear()
99 {
100 /* In fact we just reset the item counter avoiding the need to
101 * probably reallocate the same amount of memory the list was
102 * previously using. */
103 this->items = 0;
104 }
105
109 inline void Reset()
110 {
111 this->items = 0;
112 this->capacity = 0;
113 free(data);
114 data = NULL;
115 }
116
120 inline void Compact()
121 {
122 uint capacity = Align(this->items, S);
123 if (capacity >= this->capacity) return;
124
125 this->capacity = capacity;
126 this->data = ReallocT(this->data, this->capacity);
127 }
128
134 inline T *Append(uint to_add = 1)
135 {
136 uint begin = this->items;
137 this->items += to_add;
138
139 if (this->items > this->capacity) {
140 this->capacity = Align(this->items, S);
141 this->data = ReallocT(this->data, this->capacity);
142 }
143
144 return &this->data[begin];
145 }
146
151 inline void Resize(uint num_items)
152 {
153 this->items = num_items;
154
155 if (this->items > this->capacity) {
156 this->capacity = Align(this->items, S);
157 this->data = ReallocT(this->data, this->capacity);
158 }
159 }
160
167 inline const T *Find(const T &item) const
168 {
169 const T *pos = this->Begin();
170 const T *end = this->End();
171 while (pos != end && *pos != item) pos++;
172 return pos;
173 }
174
181 inline T *Find(const T &item)
182 {
183 T *pos = this->Begin();
184 const T *end = this->End();
185 while (pos != end && *pos != item) pos++;
186 return pos;
187 }
188
195 inline int FindIndex(const T &item) const
196 {
197 int index = 0;
198 const T *pos = this->Begin();
199 const T *end = this->End();
200 while (pos != end && *pos != item) {
201 pos++;
202 index++;
203 }
204 return pos == end ? -1 : index;
205 }
206
213 inline bool Contains(const T &item) const
214 {
215 return this->Find(item) != this->End();
216 }
217
223 inline void Erase(T *item)
224 {
225 assert(item >= this->Begin() && item < this->End());
226 *item = this->data[--this->items];
227 }
228
234 void ErasePreservingOrder(uint pos, uint count = 1)
235 {
236 if (count == 0) return;
237 assert(pos < this->items);
238 assert(pos + count <= this->items);
239 this->items -= count;
240 uint to_move = this->items - pos;
241 if (to_move > 0) MemMoveT(this->data + pos, this->data + pos + count, to_move);
242 }
243
250 inline bool Include(const T &item)
251 {
252 bool is_member = this->Contains(item);
253 if (!is_member) *this->Append() = item;
254 return is_member;
255 }
256
260 inline uint Length() const
261 {
262 return this->items;
263 }
264
270 inline const T *Begin() const
271 {
272 return this->data;
273 }
274
280 inline T *Begin()
281 {
282 return this->data;
283 }
284
290 inline const T *End() const
291 {
292 return &this->data[this->items];
293 }
294
300 inline T *End()
301 {
302 return &this->data[this->items];
303 }
304
311 inline const T *Get(uint index) const
312 {
313 /* Allow access to the 'first invalid' item */
314 assert(index <= this->items);
315 return &this->data[index];
316 }
317
324 inline T *Get(uint index)
325 {
326 /* Allow access to the 'first invalid' item */
327 assert(index <= this->items);
328 return &this->data[index];
329 }
330
337 inline const T &operator[](uint index) const
338 {
339 assert(index < this->items);
340 return this->data[index];
341 }
342
349 inline T &operator[](uint index)
350 {
351 assert(index < this->items);
352 return this->data[index];
353 }
354 };
355
356
367 template <typename T, uint S>
368 class AutoFreeSmallVector : public SmallVector<T, S> {
369 public:
370 ~AutoFreeSmallVector()
371 {
372 this->Clear();
373 }
374
378 inline void Clear()
379 {
380 for (uint i = 0; i < this->items; i++) {
381 free(this->data[i]);
382 }
383
384 this->items = 0;
385 }
386 };
387
398 template <typename T, uint S>
399 class AutoDeleteSmallVector : public SmallVector<T, S> {
400 public:
401 ~AutoDeleteSmallVector()
402 {
403 this->Clear();
404 }
405
409 inline void Clear()
410 {
411 for (uint i = 0; i < this->items; i++) {
412 delete this->data[i];
413 }
414
415 this->items = 0;
416 }
417 };
418
419 typedef AutoFreeSmallVector<char*, 4> StringList;
420
421 #endif /* SMALLVEC_TYPE_HPP */