DArray.h 5.8 KB

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