OpenTTD
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 
62  {
63  this->Assign(other);
64  return *this;
65  }
66 
71  template <uint X>
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:
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:
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 
420 
421 #endif /* SMALLVEC_TYPE_HPP */