DArray.h 6.2 KB

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