array.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. * Copyright (c) 2012-2014 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/taylor001/crown/blob/master/LICENSE
  4. */
  5. #pragma once
  6. #include "assert.h"
  7. #include "macros.h"
  8. #include "container_types.h"
  9. #include "allocator.h"
  10. #include <cstring> // memcpy
  11. namespace crown
  12. {
  13. /// Functions to manipulate Array.
  14. ///
  15. /// @ingroup Containers
  16. namespace array
  17. {
  18. /// Returns whether the array @a a is empty.
  19. template <typename T> bool empty(const Array<T>& a);
  20. /// Returns the number of items in the array @a a.
  21. template <typename T> uint32_t size(const Array<T>& a);
  22. /// Returns the maximum number of items the array @a a can hold.
  23. template <typename T> uint32_t capacity(const Array<T>& a);
  24. /// Resizes the array @a a to the given @a size.
  25. /// @note
  26. /// Old items will be copied to the newly created array.
  27. /// If the new capacity is smaller than the previous one, the
  28. /// array will be truncated.
  29. template <typename T> void resize(Array<T>& a, uint32_t size);
  30. /// Reserves space in the array @a a for at least @a capacity items.
  31. template <typename T> void reserve(uint32_t capacity);
  32. /// Sets the capacity of array @a a.
  33. template <typename T> void set_capacity(Array<T>& a, uint32_t capacity);
  34. /// Grows the array @a a to contain at least @a min_capacity items.
  35. template <typename T> void grow(Array<T>& a, uint32_t min_capacity);
  36. /// Condenses the array @a a so that its capacity matches the actual number
  37. /// of items in the array.
  38. template <typename T> void condense(Array<T>& a);
  39. /// Appends an item to the array @a a and returns its index.
  40. template <typename T> uint32_t push_back(Array<T>& a, const T& item);
  41. /// Removes the last item from the array @a a.
  42. template <typename T> void pop_back(Array<T>& a);
  43. /// Appends @a count @a items to the array @a a and returns the number
  44. /// of items in the array after the append operation.
  45. template <typename T> uint32_t push(Array<T>& a, const T* items, uint32_t count);
  46. /// Clears the content of the array @a a.
  47. /// @note
  48. /// Does not free memory nor call destructors, it only zeroes
  49. /// the number of items in the array.
  50. template <typename T> void clear(Array<T>& a);
  51. template <typename T> T* begin(Array<T>& a);
  52. template <typename T> const T* begin(const Array<T>& a);
  53. template <typename T> T* end(Array<T>& a);
  54. template <typename T> const T* end(const Array<T>& a);
  55. template <typename T> T& front(Array<T>& a);
  56. template <typename T> const T& front(const Array<T>& a);
  57. template <typename T> T& back(Array<T>& a);
  58. template <typename T> const T& back(const Array<T>& a);
  59. } // namespace array
  60. namespace array
  61. {
  62. template <typename T>
  63. inline bool empty(const Array<T>& a)
  64. {
  65. return a._size == 0;
  66. }
  67. template <typename T>
  68. inline uint32_t size(const Array<T>& a)
  69. {
  70. return a._size;
  71. }
  72. template <typename T>
  73. inline uint32_t capacity(const Array<T>& a)
  74. {
  75. return a._capacity;
  76. }
  77. template <typename T>
  78. inline void resize(Array<T>& a, uint32_t size)
  79. {
  80. if (size > a._capacity)
  81. set_capacity(a, size);
  82. a._size = size;
  83. }
  84. template <typename T>
  85. inline void reserve(Array<T>& a, uint32_t capacity)
  86. {
  87. if (capacity > a._capacity)
  88. grow(a, capacity);
  89. }
  90. template <typename T>
  91. inline void set_capacity(Array<T>& a, uint32_t capacity)
  92. {
  93. if (capacity == a._capacity)
  94. return;
  95. if (capacity < a._size)
  96. resize(a, capacity);
  97. if (capacity > 0)
  98. {
  99. T* tmp = a._array;
  100. a._capacity = capacity;
  101. a._array = (T*)a._allocator->allocate(capacity * sizeof(T), CE_ALIGNOF(T));
  102. memcpy(a._array, tmp, a._size * sizeof(T));
  103. if (tmp)
  104. a._allocator->deallocate(tmp);
  105. }
  106. }
  107. template <typename T>
  108. inline void grow(Array<T>& a, uint32_t min_capacity)
  109. {
  110. uint32_t new_capacity = a._capacity * 2 + 1;
  111. if (new_capacity < min_capacity)
  112. new_capacity = min_capacity;
  113. set_capacity(a, new_capacity);
  114. }
  115. template <typename T>
  116. inline void condense(Array<T>& a)
  117. {
  118. resize(a, a._size);
  119. }
  120. template <typename T>
  121. inline uint32_t push_back(Array<T>& a, const T& item)
  122. {
  123. if (a._capacity == a._size)
  124. grow(a, 0);
  125. a._array[a._size] = item;
  126. return a._size++;
  127. }
  128. template <typename T>
  129. inline void pop_back(Array<T>& a)
  130. {
  131. CE_ASSERT(a._size > 0, "The array is empty");
  132. --a._size;
  133. }
  134. template <typename T>
  135. inline uint32_t push(Array<T>& a, const T* items, uint32_t count)
  136. {
  137. if (a._capacity <= a._size + count)
  138. grow(a, a._size + count);
  139. memcpy(&a._array[a._size], items, sizeof(T) * count);
  140. a._size += count;
  141. return a._size;
  142. }
  143. template <typename T>
  144. inline void clear(Array<T>& a)
  145. {
  146. a._size = 0;
  147. }
  148. template <typename T>
  149. inline const T* begin(const Array<T>& a)
  150. {
  151. return a._array;
  152. }
  153. template <typename T>
  154. inline T* begin(Array<T>& a)
  155. {
  156. return a._array;
  157. }
  158. template <typename T>
  159. inline const T* end(const Array<T>& a)
  160. {
  161. return a._array + a._size;
  162. }
  163. template <typename T>
  164. inline T* end(Array<T>& a)
  165. {
  166. return a._array + a._size;
  167. }
  168. template <typename T>
  169. inline T& front(Array<T>& a)
  170. {
  171. CE_ASSERT(a._size > 0, "The array is empty");
  172. return a._array[0];
  173. }
  174. template <typename T>
  175. inline const T& front(const Array<T>& a)
  176. {
  177. CE_ASSERT(a._size > 0, "The array is empty");
  178. return a._array[0];
  179. }
  180. template <typename T>
  181. inline T& back(Array<T>& a)
  182. {
  183. CE_ASSERT(a._size > 0, "The array is empty");
  184. return a._array[a._size - 1];
  185. }
  186. template <typename T>
  187. inline const T& back(const Array<T>& a)
  188. {
  189. CE_ASSERT(a._size > 0, "The array is empty");
  190. return a._array[a._size - 1];
  191. }
  192. } // namespace array
  193. template <typename T>
  194. inline Array<T>::Array(Allocator& a)
  195. : _allocator(&a)
  196. , _capacity(0)
  197. , _size(0)
  198. , _array(NULL)
  199. {
  200. }
  201. template <typename T>
  202. inline Array<T>::Array(Allocator& a, uint32_t capacity)
  203. : _allocator(&a)
  204. , _capacity(0)
  205. , _size(0)
  206. , _array(NULL)
  207. {
  208. array::resize(*this, capacity);
  209. }
  210. template <typename T>
  211. inline Array<T>::Array(const Array<T>& other)
  212. : _allocator(other._allocator)
  213. , _capacity(0)
  214. , _size(0)
  215. , _array(NULL)
  216. {
  217. *this = other;
  218. }
  219. template <typename T>
  220. inline Array<T>::~Array()
  221. {
  222. if (_array)
  223. _allocator->deallocate(_array);
  224. }
  225. template <typename T>
  226. inline T& Array<T>::operator[](uint32_t index)
  227. {
  228. CE_ASSERT(index < _size, "Index out of bounds");
  229. return _array[index];
  230. }
  231. template <typename T>
  232. inline const T& Array<T>::operator[](uint32_t index) const
  233. {
  234. CE_ASSERT(index < _size, "Index out of bounds");
  235. return _array[index];
  236. }
  237. template <typename T>
  238. inline Array<T>& Array<T>::operator=(const Array<T>& other)
  239. {
  240. const uint32_t size = other._size;
  241. array::resize(*this, size);
  242. memcpy(_array, other._array, sizeof(T) * size);
  243. return *this;
  244. }
  245. } // namespace crown