DynamicArray.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. // Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <anki/util/Allocator.h>
  7. #include <anki/util/NonCopyable.h>
  8. #include <anki/util/Functions.h>
  9. namespace anki
  10. {
  11. /// @addtogroup util_containers
  12. /// @{
  13. /// Dynamic array with manual destruction. It doesn't hold the allocator and
  14. /// that makes it compact. At the same time that requires manual destruction.
  15. /// Used in permanent classes.
  16. template<typename T>
  17. class DynamicArray : public NonCopyable
  18. {
  19. public:
  20. using Value = T;
  21. using Iterator = Value*;
  22. using ConstIterator = const Value*;
  23. using Reference = Value&;
  24. using ConstReference = const Value&;
  25. DynamicArray()
  26. : m_data(nullptr)
  27. , m_size(0)
  28. {
  29. }
  30. /// Move.
  31. DynamicArray(DynamicArray&& b)
  32. : DynamicArray()
  33. {
  34. move(b);
  35. }
  36. ~DynamicArray()
  37. {
  38. ANKI_ASSERT(
  39. m_data == nullptr && m_size == 0 && "Requires manual destruction");
  40. }
  41. /// Move.
  42. DynamicArray& operator=(DynamicArray&& b)
  43. {
  44. move(b);
  45. return *this;
  46. }
  47. Reference operator[](const PtrSize n)
  48. {
  49. ANKI_ASSERT(n < m_size);
  50. return m_data[n];
  51. }
  52. ConstReference operator[](const PtrSize n) const
  53. {
  54. ANKI_ASSERT(n < m_size);
  55. return m_data[n];
  56. }
  57. /// Make it compatible with the C++11 range based for loop.
  58. Iterator getBegin()
  59. {
  60. return &m_data[0];
  61. }
  62. /// Make it compatible with the C++11 range based for loop.
  63. ConstIterator getBegin() const
  64. {
  65. return &m_data[0];
  66. }
  67. /// Make it compatible with the C++11 range based for loop.
  68. Iterator getEnd()
  69. {
  70. return &m_data[0] + m_size;
  71. }
  72. /// Make it compatible with the C++11 range based for loop.
  73. ConstIterator getEnd() const
  74. {
  75. return &m_data[0] + m_size;
  76. }
  77. /// Make it compatible with the C++11 range based for loop.
  78. Iterator begin()
  79. {
  80. return getBegin();
  81. }
  82. /// Make it compatible with the C++11 range based for loop.
  83. ConstIterator begin() const
  84. {
  85. return getBegin();
  86. }
  87. /// Make it compatible with the C++11 range based for loop.
  88. Iterator end()
  89. {
  90. return getEnd();
  91. }
  92. /// Make it compatible with the C++11 range based for loop.
  93. ConstIterator end() const
  94. {
  95. return getEnd();
  96. }
  97. /// Get first element.
  98. Reference getFront()
  99. {
  100. return m_data[0];
  101. }
  102. /// Get first element.
  103. ConstReference getFront() const
  104. {
  105. return m_data[0];
  106. }
  107. /// Get last element.
  108. Reference getBack()
  109. {
  110. return m_data[m_size - 1];
  111. }
  112. /// Get last element.
  113. ConstReference getBack() const
  114. {
  115. return m_data[m_size - 1];
  116. }
  117. /// Get last element.
  118. ConstReference back() const
  119. {
  120. return m_data[m_size - 1];
  121. }
  122. PtrSize getSize() const
  123. {
  124. return m_size;
  125. }
  126. PtrSize getByteSize() const
  127. {
  128. return m_size * sizeof(Value);
  129. }
  130. Bool isEmpty() const
  131. {
  132. return m_size == 0;
  133. }
  134. PtrSize getSizeInBytes() const
  135. {
  136. return m_size * sizeof(Value);
  137. }
  138. /// Create the array.
  139. template<typename TAllocator>
  140. void create(TAllocator alloc, PtrSize size)
  141. {
  142. ANKI_ASSERT(m_data == nullptr && m_size == 0);
  143. destroy(alloc);
  144. if(size > 0)
  145. {
  146. m_data = alloc.template newArray<Value>(size);
  147. m_size = size;
  148. }
  149. }
  150. /// Create the array.
  151. template<typename TAllocator>
  152. void create(TAllocator alloc, PtrSize size, const Value& v)
  153. {
  154. ANKI_ASSERT(m_data == nullptr && m_size == 0);
  155. if(size > 0)
  156. {
  157. m_data = alloc.template newArray<Value>(size, v);
  158. m_size = size;
  159. }
  160. }
  161. /// Grow the array.
  162. template<typename TAllocator>
  163. void resize(TAllocator alloc, PtrSize size)
  164. {
  165. ANKI_ASSERT(size > 0);
  166. DynamicArray newArr;
  167. newArr.create(alloc, size);
  168. PtrSize minSize = min<PtrSize>(size, m_size);
  169. for(U i = 0; i < minSize; i++)
  170. {
  171. newArr[i] = std::move((*this)[i]);
  172. }
  173. destroy(alloc);
  174. move(newArr);
  175. }
  176. /// Destroy the array.
  177. template<typename TAllocator>
  178. void destroy(TAllocator alloc)
  179. {
  180. if(m_data)
  181. {
  182. ANKI_ASSERT(m_size > 0);
  183. alloc.deleteArray(m_data, m_size);
  184. m_data = nullptr;
  185. m_size = 0;
  186. }
  187. ANKI_ASSERT(m_data == nullptr && m_size == 0);
  188. }
  189. protected:
  190. Value* m_data;
  191. U32 m_size;
  192. void move(DynamicArray& b)
  193. {
  194. ANKI_ASSERT(m_data == nullptr && m_size == 0
  195. && "Cannot move before destroying");
  196. m_data = b.m_data;
  197. b.m_data = nullptr;
  198. m_size = b.m_size;
  199. b.m_size = 0;
  200. }
  201. };
  202. /// Dynamic array with automatic destruction. It's the same as DynamicArray but
  203. /// it holds the allocator in order to perform automatic destruction. Use it for
  204. /// temp operations and on transient classes.
  205. template<typename T>
  206. class DynamicArrayAuto : public DynamicArray<T>
  207. {
  208. public:
  209. using Base = DynamicArray<T>;
  210. using Value = T;
  211. template<typename TAllocator>
  212. DynamicArrayAuto(TAllocator alloc)
  213. : Base()
  214. , m_alloc(alloc)
  215. {
  216. }
  217. /// Move.
  218. DynamicArrayAuto(DynamicArrayAuto&& b)
  219. : DynamicArrayAuto()
  220. {
  221. move(b);
  222. }
  223. ~DynamicArrayAuto()
  224. {
  225. Base::destroy(m_alloc);
  226. }
  227. /// Move.
  228. DynamicArrayAuto& operator=(DynamicArrayAuto&& b)
  229. {
  230. move(b);
  231. return *this;
  232. }
  233. /// Create the array.
  234. void create(PtrSize size)
  235. {
  236. Base::create(m_alloc, size);
  237. }
  238. /// Create the array.
  239. void create(PtrSize size, const Value& v)
  240. {
  241. Base::create(m_alloc, size, v);
  242. }
  243. /// Grow the array.
  244. void resize(PtrSize size)
  245. {
  246. Base::resize(m_alloc, size);
  247. }
  248. private:
  249. GenericMemoryPoolAllocator<T> m_alloc;
  250. void move(DynamicArrayAuto& b)
  251. {
  252. Base::move(b);
  253. m_alloc = b.m_alloc;
  254. }
  255. };
  256. /// Array with preallocated memory.
  257. template<typename T>
  258. class WeakArray : public DynamicArray<T>
  259. {
  260. public:
  261. using Base = DynamicArray<T>;
  262. using Value = T;
  263. WeakArray()
  264. : Base()
  265. {
  266. }
  267. WeakArray(T* mem, PtrSize size)
  268. : Base()
  269. {
  270. if(size)
  271. {
  272. ANKI_ASSERT(mem);
  273. }
  274. Base::m_data = mem;
  275. Base::m_size = size;
  276. }
  277. /// Copy.
  278. WeakArray(const WeakArray& b)
  279. : Base::m_data(b.m_data)
  280. , Base::m_size(b.m_size)
  281. {
  282. }
  283. /// Move.
  284. WeakArray(WeakArray&& b)
  285. {
  286. *this = std::move(b);
  287. }
  288. ~WeakArray()
  289. {
  290. #if ANKI_ASSERTIONS
  291. Base::m_data = nullptr;
  292. Base::m_size = 0;
  293. #endif
  294. }
  295. /// Copy.
  296. WeakArray& operator=(const WeakArray& b)
  297. {
  298. Base::m_data = b.m_data;
  299. Base::m_size = b.m_size;
  300. return *this;
  301. }
  302. /// Move.
  303. WeakArray& operator=(WeakArray&& b)
  304. {
  305. Base::m_data = b.m_data;
  306. b.m_data = nullptr;
  307. Base::m_size = b.m_size;
  308. b.m_size = 0;
  309. return *this;
  310. }
  311. };
  312. /// @}
  313. } // end namespace anki