ScummVM API documentation
vector.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef AGS_STD_VECTOR_H
23 #define AGS_STD_VECTOR_H
24 
25 #include "ags/lib/std/type_traits.h"
26 #include "ags/lib/std/utility.h"
27 #include "common/scummsys.h"
28 #include "common/algorithm.h"
29 #include "common/memory.h"
30 
31 namespace AGS3 {
32 namespace std {
33 
34 template<class In, class Type>
35 Type *uninitialized_move(In first, In last, Type *dst) {
36  while (first != last) {
37  Type &t = *new ((void *)dst++) Type();
38  t = std::move(*first++);
39  }
40 
41  return dst;
42 }
43 
44 template<class T>
45 class vector {
46 public:
47  typedef T *iterator;
48  typedef const T *const_iterator;
50  typedef T value_type;
52  typedef uint size_type;
54 protected:
55  size_type _capacity;
56  size_type _size;
57  T *_storage;
59 public:
61  private:
62  vector<T> *_owner;
63  int _index;
64  public:
65  reverse_iterator(vector<T> *owner, int index) : _owner(owner), _index(index) {
66  }
67  reverse_iterator() : _owner(0), _index(-1) {
68  }
69 
70  T &operator*() {
71  return (*_owner)[_index];
72  }
73 
74  reverse_iterator &operator++() {
75  --_index;
76  return *this;
77  }
78 
79  bool operator==(const reverse_iterator &rhs) {
80  return _owner == rhs._owner && _index == rhs._index;
81  }
82  bool operator!=(const reverse_iterator &rhs) {
83  return !operator==(rhs);
84  }
85  };
86 
88  private:
89  const vector<T> *_owner;
90  int _index;
91  public:
92  const_reverse_iterator(const vector<T> *owner, int index) : _owner(owner), _index(index) {
93  }
94  const_reverse_iterator() : _owner(0), _index(-1) {
95  }
96 
97  const T operator*() const {
98  return (*_owner)[_index];
99  }
100 
101  const_reverse_iterator &operator++() {
102  --_index;
103  return *this;
104  }
105 
106  bool operator==(const const_reverse_iterator &rhs) const {
107  return _owner == rhs._owner && _index == rhs._index;
108  }
109  bool operator!=(const const_reverse_iterator &rhs) const {
110  return !operator==(rhs);
111  }
112  bool operator<(const const_reverse_iterator &rhs) const {
113  return _index > rhs._index;
114  }
115  };
116 public:
117  vector() : _capacity(0), _size(0), _storage(nullptr) {
118  }
119 
124  explicit vector(size_type count) : _size(count) {
125  allocCapacity(count);
126  for (size_type i = 0; i < count; ++i)
127  new ((void *)&_storage[i]) T();
128  }
129 
133  vector(size_type count, const T &value) : _size(count) {
134  allocCapacity(count);
135  Common::uninitialized_fill_n(_storage, count, value);
136  }
137 
141  vector(const vector<T> &array) : _capacity(array._size), _size(array._size), _storage(nullptr) {
142  if (array._storage) {
143  allocCapacity(_size);
144  Common::uninitialized_copy(array._storage, array._storage + _size, _storage);
145  }
146  }
147 
151  vector(vector<T> &&old) : _capacity(old._capacity), _size(old._size), _storage(old._storage) {
152  old._storage = nullptr;
153  old._capacity = 0;
154  old._size = 0;
155  }
156 
167  vector(::std::initializer_list<T> list) : _size(list.size()) {
168  allocCapacity(list.size());
169  if (_storage)
170  Common::uninitialized_copy(list.begin(), list.end(), _storage);
171  }
172 
176  template<class T2>
177  vector(const T2 *array, size_type n) {
178  _size = n;
179  allocCapacity(n);
180  Common::uninitialized_copy(array, array + _size, _storage);
181  }
182 
183  ~vector() {
184  freeStorage(_storage, _size);
185  _storage = nullptr;
186  _capacity = _size = 0;
187  }
188 
190  void push_back(const T &element) {
191  if (_size + 1 <= _capacity)
192  new ((void *)&_storage[_size++]) T(element);
193  else
194  insert_aux(end(), &element, &element + 1);
195  }
196 
197  template<class... Args>
198  void emplace_back(Args... args) {
199  T tmp(args...);
200  push_back(tmp);
201  }
202 
204  void push_back(const vector<T> &array) {
205  if (_size + array.size() <= _capacity) {
206  Common::uninitialized_copy(array.begin(), array.end(), end());
207  _size += array.size();
208  } else
209  insert_aux(end(), array.begin(), array.end());
210  }
211 
212  void insert(const T &element) {
213  this->push_back(element);
214  }
215 
219  void insert(iterator position, const_iterator first, const_iterator last) {
220  int destIndex = position - this->begin();
221  for (; first != last; ++first) {
222  insert_at(destIndex++, *first);
223  }
224  }
225 
227  void pop_back() {
228  assert(_size > 0);
229  _size--;
230  // We also need to destroy the last object properly here.
231  _storage[_size].~T();
232  }
233 
235  const T *data() const {
236  return _storage;
237  }
238 
240  T *data() {
241  return _storage;
242  }
243 
245  T &front() {
246  assert(_size > 0);
247  return _storage[0];
248  }
249 
251  const T &front() const {
252  assert(_size > 0);
253  return _storage[0];
254  }
255 
257  T &back() {
258  assert(_size > 0);
259  return _storage[_size - 1];
260  }
261 
263  const T &back() const {
264  assert(_size > 0);
265  return _storage[_size - 1];
266  }
267 
269  void insert_at(size_type idx, const T &element) {
270  assert(idx <= _size);
271  insert_aux(_storage + idx, &element, &element + 1);
272  }
273 
275  void insert_at(size_type idx, const vector<T> &array) {
276  assert(idx <= _size);
277  insert_aux(_storage + idx, array.begin(), array.end());
278  }
279 
283  void insert(iterator pos, const T &element) {
284  insert_aux(pos, &element, &element + 1);
285  }
286 
288  T remove_at(size_type idx) {
289  assert(idx < _size);
290  T tmp = _storage[idx];
291  Common::copy(_storage + idx + 1, _storage + _size, _storage + idx);
292  _size--;
293  // We also need to destroy the last object properly here.
294  _storage[_size].~T();
295  return tmp;
296  }
297 
298  // TODO: insert, remove, ...
299 
300  T &at(size_t index) {
301  return (*this)[index];
302  }
303  const T &at(size_t index) const {
304  return (*this)[index];
305  }
306 
308  T &operator[](size_type idx) {
309  assert(idx < _size);
310  return _storage[idx];
311  }
312 
314  const T &operator[](size_type idx) const {
315  assert(idx < _size);
316  return _storage[idx];
317  }
318 
321  if (this == &array)
322  return *this;
323 
324  freeStorage(_storage, _size);
325  _size = array._size;
326  allocCapacity(_size);
327  Common::uninitialized_copy(array._storage, array._storage + _size, _storage);
328 
329  return *this;
330  }
331 
334  if (this == &old)
335  return *this;
336 
337  freeStorage(_storage, _size);
338  _capacity = old._capacity;
339  _size = old._size;
340  _storage = old._storage;
341 
342  old._storage = nullptr;
343  old._capacity = 0;
344  old._size = 0;
345 
346  return *this;
347  }
348 
350  size_type size() const {
351  return _size;
352  }
353 
355  void clear() {
356  freeStorage(_storage, _size);
357  _storage = nullptr;
358  _size = 0;
359  _capacity = 0;
360  }
361 
363  iterator erase(iterator pos) {
364  Common::copy(pos + 1, _storage + _size, pos);
365  _size--;
366  // We also need to destroy the last object properly here.
367  _storage[_size].~T();
368  return pos;
369  }
370 
371  iterator erase(iterator first, iterator last) {
372  Common::copy(last, this->_storage + this->_size, first);
373 
374  int count = (last - first);
375  this->_size -= count;
376 
377  // We also need to destroy the objects beyond the new size
378  for (uint idx = this->_size; idx < (this->_size + count); ++idx)
379  this->_storage[idx].~T();
380 
381  return first;
382  }
383 
387  void remove(T element) {
388  for (uint i = 0; i < this->size(); ++i) {
389  if (this->operator[](i) == element) {
390  this->remove_at(i);
391  return;
392  }
393  }
394  }
395 
397  bool empty() const {
398  return (_size == 0);
399  }
400 
402  bool operator==(const vector<T> &other) const {
403  if (this == &other)
404  return true;
405  if (_size != other._size)
406  return false;
407  for (size_type i = 0; i < _size; ++i) {
408  if (_storage[i] != other._storage[i])
409  return false;
410  }
411  return true;
412  }
413 
415  bool operator!=(const vector<T> &other) const {
416  return !(*this == other);
417  }
418 
420  iterator begin() {
421  return _storage;
422  }
423 
425  iterator end() {
426  return _storage + _size;
427  }
428 
430  const_iterator begin() const {
431  return _storage;
432  }
433 
435  const_iterator end() const {
436  return _storage + _size;
437  }
438 
439 
440  void swap(vector &arr) {
441  SWAP(this->_capacity, arr._capacity);
442  SWAP(this->_size, arr._size);
443  SWAP(this->_storage, arr._storage);
444  }
445 
450  void rotate(iterator it) {
451  if (it != end()) {
452  size_t count = it - begin();
453  for (size_t ctr = 0; ctr < count; ++ctr) {
454  push_back(front());
455  remove_at(0);
456  }
457  }
458  }
459 
460  const_iterator cbegin() {
461  return this->begin();
462  }
463  const_iterator cend() {
464  return this->end();
465  }
466  reverse_iterator rbegin() {
467  return reverse_iterator(this, (int)size() - 1);
468  }
469  reverse_iterator rend() {
470  return reverse_iterator(this, -1);
471  }
472  const_reverse_iterator rbegin() const {
473  return const_reverse_iterator(this, (int)size() - 1);
474  }
475  const_reverse_iterator rend() const {
476  return const_reverse_iterator(this, -1);
477  }
478  const_reverse_iterator crbegin() const {
479  return const_reverse_iterator(this, (int)size() - 1);
480  }
481  const_reverse_iterator crend() const {
482  return const_reverse_iterator(this, -1);
483  }
484 
488  void reserve(size_type newCapacity) {
489  if (newCapacity <= _capacity)
490  return;
491 
492  T *oldStorage = _storage;
493  allocCapacity(newCapacity);
494 
495  if (oldStorage) {
496  // Copy old data
497  uninitialized_move(oldStorage, oldStorage + _size, _storage);
498  freeStorage(oldStorage, _size);
499  }
500  }
501 
503  void resize(size_type newSize) {
504  reserve(newSize);
505  for (size_type i = newSize; i < _size; ++i)
506  _storage[i].~T();
507  for (size_type i = _size; i < newSize; ++i)
508  new ((void *)&_storage[i]) T();
509  _size = newSize;
510  }
511 
512  void resize(size_t newSize, const T elem) {
513  size_t oldSize = size();
514  resize(newSize);
515  for (size_t idx = oldSize; idx < newSize; ++idx)
516  this->operator[](idx) = elem;
517  }
518 
522  void assign(const_iterator first, const_iterator last) {
523  resize(distance(first, last)); // FIXME: ineffective?
524  T *dst = _storage;
525  while (first != last)
526  *dst++ = *first++;
527  }
528 
529 protected:
533  static size_type roundUpCapacity(size_type capacity) {
534  size_type capa = 8;
535  while (capa < capacity)
536  capa <<= 1;
537  return capa;
538  }
539 
541  void allocCapacity(size_type capacity) {
542  _capacity = capacity;
543  if (capacity) {
544  _storage = (T *)malloc(sizeof(T) * capacity);
545  if (!_storage)
546  ::error("Common::vector: failure to allocate %u bytes", capacity * (size_type)sizeof(T));
547  } else {
548  _storage = nullptr;
549  }
550  }
551 
553  void freeStorage(T *storage, const size_type elements) {
554  for (size_type i = 0; i < elements; ++i)
555  storage[i].~T();
556  free(storage);
557  }
558 
572  iterator insert_aux(iterator pos, const_iterator first, const_iterator last) {
573  assert(_storage <= pos && pos <= _storage + _size);
574  assert(first <= last);
575  const size_type n = last - first;
576  if (n) {
577  const size_type idx = pos - _storage;
578  if (_size + n > _capacity || (_storage <= first && first <= _storage + _size)) {
579  T *const oldStorage = _storage;
580 
581  // If there is not enough space, allocate more.
582  // Likewise, if this is a self-insert, we allocate new
583  // storage to avoid conflicts.
584  allocCapacity(roundUpCapacity(_size + n));
585 
586  // Copy the data from the old storage till the position where
587  // we insert new data
588  Common::uninitialized_copy(oldStorage, oldStorage + idx, _storage);
589  // Copy the data we insert
590  Common::uninitialized_copy(first, last, _storage + idx);
591  // Afterwards, copy the old data from the position where we
592  // insert.
593  Common::uninitialized_copy(oldStorage + idx, oldStorage + _size, _storage + idx + n);
594 
595  freeStorage(oldStorage, _size);
596  } else if (idx + n <= _size) {
597  // Make room for the new elements by shifting back
598  // existing ones.
599  // 1. Move a part of the data to the uninitialized area
600  Common::uninitialized_copy(_storage + _size - n, _storage + _size, _storage + _size);
601  // 2. Move a part of the data to the initialized area
602  Common::copy_backward(pos, _storage + _size - n, _storage + _size);
603 
604  // Insert the new elements.
605  Common::copy(first, last, pos);
606  } else {
607  // Copy the old data from the position till the end to the new
608  // place.
609  Common::uninitialized_copy(pos, _storage + _size, _storage + idx + n);
610 
611  // Copy a part of the new data to the position inside the
612  // initialized space.
613  Common::copy(first, first + (_size - idx), pos);
614 
615  // Copy a part of the new data to the position inside the
616  // uninitialized space.
617  Common::uninitialized_copy(first + (_size - idx), last, _storage + _size);
618  }
619 
620  // Finally, update the internal state
621  _size += n;
622  }
623  return pos;
624  }
625 };
626 
627 } // namespace std
628 } // namespace AGS3
629 
630 #endif
uint size_type
Definition: vector.h:52
void push_back(const vector< T > &array)
Definition: vector.h:204
vector(vector< T > &&old)
Definition: vector.h:151
void insert(iterator position, const_iterator first, const_iterator last)
Definition: vector.h:219
Definition: vector.h:45
void allocCapacity(size_type capacity)
Definition: vector.h:541
vector(const vector< T > &array)
Definition: vector.h:141
bool operator!=(const vector< T > &other) const
Definition: vector.h:415
const T * const_iterator
Definition: vector.h:48
void reserve(size_type newCapacity)
Definition: vector.h:488
void freeStorage(T *storage, const size_type elements)
Definition: vector.h:553
const_iterator end() const
Definition: vector.h:435
T * data()
Definition: vector.h:240
void insert(iterator pos, const T &element)
Definition: vector.h:283
const_iterator begin() const
Definition: vector.h:430
void SWAP(T &a, T &b)
Definition: util.h:82
bool empty() const
Definition: vector.h:397
vector(size_type count)
Definition: vector.h:124
void rotate(iterator it)
Definition: vector.h:450
void insert_at(size_type idx, const T &element)
Definition: vector.h:269
Type
Definition: system.h:121
size_type size() const
Definition: vector.h:350
T remove_at(size_type idx)
Definition: vector.h:288
vector< T > & operator=(const vector< T > &array)
Definition: vector.h:320
Out copy(In first, In last, Out dst)
Definition: algorithm.h:52
T & front()
Definition: vector.h:245
vector & operator=(vector< T > &&old)
Definition: vector.h:333
const T & front() const
Definition: vector.h:251
iterator begin()
Definition: vector.h:420
const T & back() const
Definition: vector.h:263
size_type _size
Definition: vector.h:56
T value_type
Definition: vector.h:50
void resize(size_type newSize)
Definition: vector.h:503
T & back()
Definition: vector.h:257
constexpr remove_reference_t< T > && move(T &&t) noexcept
Definition: util.h:209
Type * uninitialized_copy(In first, In last, Type *dst)
Definition: memory.h:59
bool operator==(const vector< T > &other) const
Definition: vector.h:402
void push_back(const T &element)
Definition: vector.h:190
const T & operator[](size_type idx) const
Definition: vector.h:314
void assign(const_iterator first, const_iterator last)
Definition: vector.h:522
void insert_at(size_type idx, const vector< T > &array)
Definition: vector.h:275
vector(::std::initializer_list< T > list)
Definition: vector.h:167
void NORETURN_PRE error(MSVC_PRINTF const char *s,...) GCC_PRINTF(1
vector(size_type count, const T &value)
Definition: vector.h:133
iterator erase(iterator pos)
Definition: vector.h:363
void clear()
Definition: vector.h:355
iterator end()
Definition: vector.h:425
T & operator[](size_type idx)
Definition: vector.h:308
vector(const T2 *array, size_type n)
Definition: vector.h:177
Definition: list.h:31
T * iterator
Definition: vector.h:47
void pop_back()
Definition: vector.h:227
static size_type roundUpCapacity(size_type capacity)
Definition: vector.h:533
iterator insert_aux(iterator pos, const_iterator first, const_iterator last)
Definition: vector.h:572
Definition: ags.h:40
Definition: array.h:31
Out copy_backward(In first, In last, Out dst)
Definition: algorithm.h:67
size_type _capacity
Definition: vector.h:55
void uninitialized_fill_n(Type *dst, size_t n, const Value &x)
Definition: memory.h:82
T * _storage
Definition: vector.h:57
const T * data() const
Definition: vector.h:235