array.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  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. {
  82. set_capacity(a, size);
  83. }
  84. a._size = size;
  85. }
  86. template <typename T>
  87. inline void reserve(Array<T>& a, uint32_t capacity)
  88. {
  89. if (capacity > a._capacity)
  90. {
  91. grow(a, capacity);
  92. }
  93. }
  94. template <typename T>
  95. inline void set_capacity(Array<T>& a, uint32_t capacity)
  96. {
  97. if (capacity == a._capacity)
  98. {
  99. return;
  100. }
  101. if (capacity < a._size)
  102. {
  103. resize(a, capacity);
  104. }
  105. if (capacity > 0)
  106. {
  107. T* tmp = a._array;
  108. a._capacity = capacity;
  109. a._array = (T*)a._allocator->allocate(capacity * sizeof(T), CE_ALIGNOF(T));
  110. memcpy(a._array, tmp, a._size * sizeof(T));
  111. if (tmp)
  112. {
  113. a._allocator->deallocate(tmp);
  114. }
  115. }
  116. }
  117. template <typename T>
  118. inline void grow(Array<T>& a, uint32_t min_capacity)
  119. {
  120. uint32_t new_capacity = a._capacity * 2 + 1;
  121. if (new_capacity < min_capacity)
  122. {
  123. new_capacity = min_capacity;
  124. }
  125. set_capacity(a, new_capacity);
  126. }
  127. template <typename T>
  128. inline void condense(Array<T>& a)
  129. {
  130. resize(a, a._size);
  131. }
  132. template <typename T>
  133. inline uint32_t push_back(Array<T>& a, const T& item)
  134. {
  135. if (a._capacity == a._size)
  136. {
  137. grow(a, 0);
  138. }
  139. a._array[a._size] = item;
  140. return a._size++;
  141. }
  142. template <typename T>
  143. inline void pop_back(Array<T>& a)
  144. {
  145. CE_ASSERT(a._size > 0, "The array is empty");
  146. a._size--;
  147. }
  148. template <typename T>
  149. inline uint32_t push(Array<T>& a, const T* items, uint32_t count)
  150. {
  151. if (a._capacity <= a._size + count)
  152. {
  153. grow(a, a._size + count);
  154. }
  155. memcpy(&a._array[a._size], items, sizeof(T) * count);
  156. a._size += count;
  157. return a._size;
  158. }
  159. template <typename T>
  160. inline void clear(Array<T>& a)
  161. {
  162. a._size = 0;
  163. }
  164. template <typename T>
  165. inline const T* begin(const Array<T>& a)
  166. {
  167. return a._array;
  168. }
  169. template <typename T>
  170. inline T* begin(Array<T>& a)
  171. {
  172. return a._array;
  173. }
  174. template <typename T>
  175. inline const T* end(const Array<T>& a)
  176. {
  177. return a._array + a._size;
  178. }
  179. template <typename T>
  180. inline T* end(Array<T>& a)
  181. {
  182. return a._array + a._size;
  183. }
  184. template <typename T>
  185. inline T& front(Array<T>& a)
  186. {
  187. CE_ASSERT(a._size > 0, "The array is empty");
  188. return a._array[0];
  189. }
  190. template <typename T>
  191. inline const T& front(const Array<T>& a)
  192. {
  193. CE_ASSERT(a._size > 0, "The array is empty");
  194. return a._array[0];
  195. }
  196. template <typename T>
  197. inline T& back(Array<T>& a)
  198. {
  199. CE_ASSERT(a._size > 0, "The array is empty");
  200. return a._array[a._size - 1];
  201. }
  202. template <typename T>
  203. inline const T& back(const Array<T>& a)
  204. {
  205. CE_ASSERT(a._size > 0, "The array is empty");
  206. return a._array[a._size - 1];
  207. }
  208. } // namespace array
  209. template <typename T>
  210. inline Array<T>::Array(Allocator& allocator)
  211. : _allocator(&allocator), _capacity(0), _size(0), _array(NULL)
  212. {
  213. }
  214. template <typename T>
  215. inline Array<T>::Array(Allocator& allocator, uint32_t capacity)
  216. : _allocator(&allocator), _capacity(0), _size(0), _array(NULL)
  217. {
  218. array::resize(*this, capacity);
  219. }
  220. template <typename T>
  221. inline Array<T>::Array(const Array<T>& other)
  222. : _allocator(other._allocator), _capacity(0), _size(0), _array(NULL)
  223. {
  224. *this = other;
  225. }
  226. template <typename T>
  227. inline Array<T>::~Array()
  228. {
  229. if (_array)
  230. {
  231. _allocator->deallocate(_array);
  232. }
  233. }
  234. template <typename T>
  235. inline T& Array<T>::operator[](uint32_t index)
  236. {
  237. CE_ASSERT(index < _size, "Index out of bounds");
  238. return _array[index];
  239. }
  240. template <typename T>
  241. inline const T& Array<T>::operator[](uint32_t index) const
  242. {
  243. CE_ASSERT(index < _size, "Index out of bounds");
  244. return _array[index];
  245. }
  246. template <typename T>
  247. inline Array<T>& Array<T>::operator=(const Array<T>& other)
  248. {
  249. const uint32_t size = other._size;
  250. array::resize(*this, size);
  251. memcpy(_array, other._array, sizeof(T) * size);
  252. return *this;
  253. }
  254. } // namespace crown