SizedArray.h 20 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076
  1. #pragma once
  2. #pragma once
  3. #include "Array.h"
  4. NS_BF_BEGIN;
  5. template <typename T, typename TAlloc = AllocatorCLib<T> >
  6. class SizedArrayBase : protected TAlloc
  7. {
  8. public:
  9. typedef T value_type;
  10. T* mVals;
  11. intptr mSize;
  12. intptr mAllocSize;
  13. struct iterator
  14. {
  15. public:
  16. typedef std::random_access_iterator_tag iterator_category;
  17. typedef T value_type;
  18. typedef intptr difference_type;
  19. typedef T* pointer;
  20. typedef T& reference;
  21. public:
  22. T* mPtr;
  23. public:
  24. iterator()
  25. {
  26. mPtr = NULL;
  27. }
  28. iterator(T* ptr)
  29. {
  30. mPtr = ptr;
  31. }
  32. iterator& operator++()
  33. {
  34. mPtr++;
  35. return *this;
  36. }
  37. iterator operator++(int)
  38. {
  39. auto prevVal = *this;
  40. mPtr++;
  41. return prevVal;
  42. }
  43. iterator& operator--()
  44. {
  45. mPtr--;
  46. return *this;
  47. }
  48. iterator operator--(int)
  49. {
  50. auto prevVal = *this;
  51. mPtr--;
  52. return prevVal;
  53. }
  54. iterator& operator+=(intptr offset)
  55. {
  56. mPtr += offset;
  57. return *this;
  58. }
  59. bool operator!=(const iterator& itr) const
  60. {
  61. return itr.mPtr != mPtr;
  62. }
  63. bool operator==(const iterator& itr) const
  64. {
  65. return itr.mPtr == mPtr;
  66. }
  67. intptr operator-(const iterator& itr) const
  68. {
  69. return mPtr - itr.mPtr;
  70. }
  71. iterator operator+(intptr offset) const
  72. {
  73. iterator itr(mPtr + offset);
  74. return itr;
  75. }
  76. iterator operator-(intptr offset) const
  77. {
  78. iterator itr(mPtr - offset);
  79. return itr;
  80. }
  81. T& operator*()
  82. {
  83. return *mPtr;
  84. }
  85. T* operator->()
  86. {
  87. return mPtr;
  88. }
  89. bool operator<(const iterator& val2)
  90. {
  91. return mPtr < val2.mPtr;
  92. }
  93. };
  94. struct const_iterator
  95. {
  96. public:
  97. typedef std::random_access_iterator_tag iterator_category;
  98. typedef T value_type;
  99. typedef intptr difference_type;
  100. typedef const T* pointer;
  101. typedef const T& reference;
  102. public:
  103. const T* mPtr;
  104. public:
  105. const_iterator(const T* ptr)
  106. {
  107. mPtr = ptr;
  108. }
  109. const_iterator& operator++()
  110. {
  111. mPtr++;
  112. return *this;
  113. }
  114. const_iterator operator++(int)
  115. {
  116. auto prevVal = *this;
  117. mPtr++;
  118. return prevVal;
  119. }
  120. bool operator!=(const const_iterator& itr) const
  121. {
  122. return itr.mPtr != mPtr;
  123. }
  124. bool operator==(const const_iterator& itr) const
  125. {
  126. return itr.mPtr == mPtr;
  127. }
  128. intptr operator-(const iterator& itr) const
  129. {
  130. return mPtr - itr.mPtr;
  131. }
  132. const_iterator operator+(intptr offset) const
  133. {
  134. const_iterator itr(mPtr + offset);
  135. return itr;
  136. }
  137. const T& operator*()
  138. {
  139. return *mPtr;
  140. }
  141. const T* operator->()
  142. {
  143. return mPtr;
  144. }
  145. bool operator<(const const_iterator& val2)
  146. {
  147. return mPtr < val2.mPtr;
  148. }
  149. };
  150. private:
  151. public:
  152. SizedArrayBase()
  153. {
  154. this->mVals = NULL;
  155. this->mSize = 0;
  156. this->mAllocSize = 0;
  157. }
  158. SizedArrayBase(SizedArrayBase<T, TAlloc>&& val)
  159. {
  160. this->mVals = val.mVals;
  161. this->mSize = val.mSize;
  162. this->mAllocSize = val.mAllocSize;
  163. val.mVals = NULL;
  164. val.mSize = 0;
  165. val.mAllocSize = 0;
  166. }
  167. T& operator[](intptr idx)
  168. {
  169. BF_ASSERT((uintptr)idx < (uintptr)this->mSize);
  170. return this->mVals[idx];
  171. }
  172. const T& operator[](intptr idx) const
  173. {
  174. BF_ASSERT((uintptr)idx < (uintptr)this->mSize);
  175. return this->mVals[idx];
  176. }
  177. bool operator==(const SizedArrayBase& arrB) const
  178. {
  179. if (this->mSize != arrB.mSize)
  180. return false;
  181. for (int i = 0; i < this->mSize; i++)
  182. if (this->mVals[i] != arrB.mVals[i])
  183. return false;
  184. return true;
  185. }
  186. bool operator!=(const SizedArrayBase& arrB) const
  187. {
  188. if (this->mSize != arrB.mSize)
  189. return true;
  190. for (int i = 0; i < this->mSize; i++)
  191. if (this->mVals[i] != arrB.mVals[i])
  192. return true;
  193. return false;
  194. }
  195. const_iterator begin() const
  196. {
  197. return this->mVals;
  198. }
  199. const_iterator end() const
  200. {
  201. return this->mVals + this->mSize;
  202. }
  203. iterator begin()
  204. {
  205. return this->mVals;
  206. }
  207. iterator end()
  208. {
  209. return this->mVals + this->mSize;
  210. }
  211. T& front() const
  212. {
  213. return this->mVals[0];
  214. }
  215. T& back() const
  216. {
  217. return this->mVals[this->mSize - 1];
  218. }
  219. intptr size() const
  220. {
  221. return this->mSize;
  222. }
  223. bool empty() const
  224. {
  225. return this->mSize == 0;
  226. }
  227. bool IsEmpty() const
  228. {
  229. return this->mSize == 0;
  230. }
  231. void clear()
  232. {
  233. this->mSize = 0;
  234. }
  235. /*void Free()
  236. {
  237. if (this->mVals != NULL)
  238. {
  239. deallocate(this->mVals);
  240. }
  241. this->mVals = NULL;
  242. this->mAllocSize = 0;
  243. this->mSize = 0;
  244. }*/
  245. T GetSafe(intptr idx)
  246. {
  247. if ((idx < 0) || (idx >= this->mSize))
  248. return T();
  249. return this->mVals[idx];
  250. }
  251. T GetLastSafe()
  252. {
  253. if (this->mSize == 0)
  254. return T();
  255. return this->mVals[this->mSize - 1];
  256. }
  257. T GetFirstSafe()
  258. {
  259. if (this->mSize == 0)
  260. return T();
  261. return this->mVals[0];
  262. }
  263. bool Contains(T val) const
  264. {
  265. for (int i = 0; i < this->mSize; i++)
  266. if (this->mVals[i] == val)
  267. return true;
  268. return false;
  269. }
  270. intptr IndexOf(T val) const
  271. {
  272. for (int i = 0; i < this->mSize; i++)
  273. if (this->mVals[i] == val)
  274. return i;
  275. return -1;
  276. }
  277. };
  278. // NON-POD
  279. template <typename T, typename TAlloc, bool TIsPod>
  280. class SizedArrayBaseT : public SizedArrayBase<T, TAlloc>
  281. {
  282. public:
  283. typedef typename std::aligned_storage<sizeof(T), alignof(T)>::type TStorage;
  284. TStorage mFirstVal;
  285. protected:
  286. void MoveArray(T* to, T* from, intptr count)
  287. {
  288. if (to < from)
  289. {
  290. // Prefer in-order moves
  291. for (intptr i = 0; i < count; i++)
  292. new (&to[i]) T(std::move(from[i]));
  293. }
  294. else
  295. {
  296. for (intptr i = count - 1; i >= 0; i--)
  297. new (&to[i]) T(std::move(from[i]));
  298. }
  299. }
  300. void Grow(intptr newSize)
  301. {
  302. T* newVals = TAlloc::allocate(newSize);
  303. if (this->mVals != NULL)
  304. {
  305. if (this->mSize > 0)
  306. MoveArray(newVals, this->mVals, this->mSize);
  307. if (this->mVals != (T*)&mFirstVal)
  308. TAlloc::deallocate(this->mVals);
  309. }
  310. this->mVals = newVals;
  311. this->mAllocSize = newSize;
  312. }
  313. void EnsureFree(intptr freeCount)
  314. {
  315. if (this->mSize + freeCount > this->mAllocSize)
  316. Grow(std::max(this->mAllocSize + this->mAllocSize / 2 + 1, this->mSize + freeCount));
  317. }
  318. public:
  319. using SizedArrayBase<T, TAlloc>::SizedArrayBase;
  320. SizedArrayBaseT() : SizedArrayBase<T, TAlloc>()
  321. {
  322. }
  323. SizedArrayBaseT(const SizedArrayBaseT& val)
  324. {
  325. this->mVals = NULL;
  326. this->mSize = 0;
  327. this->mAllocSize = 0;
  328. *this = val;
  329. }
  330. SizedArrayBaseT(SizedArrayBaseT&& val) : SizedArrayBase<T, TAlloc>(val)
  331. {
  332. }
  333. ~SizedArrayBaseT()
  334. {
  335. for (int i = 0; i < this->mSize; i++)
  336. this->mVals[i].~T();
  337. if (this->mVals != (T*)&mFirstVal)
  338. {
  339. TAlloc::deallocate(this->mVals);
  340. }
  341. }
  342. void resize(intptr size)
  343. {
  344. while (size < this->mSize)
  345. pop_back();
  346. if (size > this->mSize)
  347. {
  348. reserve(size);
  349. while (size > this->mSize)
  350. new (&this->mVals[this->mSize++]) T();
  351. }
  352. }
  353. void reserve(intptr size)
  354. {
  355. if (size > this->mAllocSize)
  356. Grow(size);
  357. }
  358. void SetSize(intptr size)
  359. {
  360. if (size > this->mAllocSize)
  361. Grow(size);
  362. this->mSize = size;
  363. }
  364. SizedArrayBaseT& operator=(const SizedArrayBaseT& val)
  365. {
  366. if (&val == this)
  367. return *this;
  368. for (int i = 0; i < this->mSize; i++)
  369. this->mVals[i].~T();
  370. this->mSize = 0;
  371. if (val.mSize > this->mAllocSize)
  372. Grow(val.mSize);
  373. resize(val.mSize);
  374. for (int i = 0; i < val.mSize; i++)
  375. new (&this->mVals[i]) T(val.mVals[i]);
  376. this->mSize = val.mSize;
  377. return *this;
  378. }
  379. void RemoveAt(intptr idx)
  380. {
  381. BF_ASSERT((uintptr)idx < (uintptr)this->mSize);
  382. this->mVals[idx].~T();
  383. // If we're removing the last element then we don't have to move anything
  384. if (idx != this->mSize - 1)
  385. {
  386. intptr moveCount = this->mSize - idx - 1;
  387. MoveArray(this->mVals + idx, this->mVals + idx + 1, moveCount);
  388. }
  389. this->mSize--;
  390. }
  391. void RemoveRange(intptr idx, intptr length)
  392. {
  393. BF_ASSERT(
  394. ((uintptr)idx < (uintptr)this->mSize) &&
  395. ((uintptr)length > 0) &&
  396. ((uintptr)(idx + length) <= (uintptr)this->mSize));
  397. for (intptr i = idx; i < idx + length; i++)
  398. this->mVals[i].~T();
  399. // If we're removing the last element then we don't have to move anything
  400. if (idx != this->mSize - length)
  401. {
  402. intptr moveCount = this->mSize - idx - length;
  403. MoveArray(this->mVals + idx, this->mVals + idx + length, moveCount);
  404. }
  405. this->mSize -= length;
  406. }
  407. void Insert(intptr idx, T val)
  408. {
  409. BF_ASSERT((uintptr)idx <= (uintptr)this->mSize);
  410. if (this->mSize >= this->mAllocSize)
  411. {
  412. intptr newSize = this->mAllocSize + this->mAllocSize / 2 + 1;
  413. T* newVals = TAlloc::allocate(newSize);
  414. if (this->mVals != NULL)
  415. {
  416. if (idx > 0) // Copy left of idx
  417. MoveArray(newVals, this->mVals, idx);
  418. if (idx < this->mSize) // Copy right of idx
  419. MoveArray(newVals + idx + 1, this->mVals + idx, this->mSize - idx);
  420. if (this->mVals != (T*)&mFirstVal)
  421. TAlloc::deallocate(this->mVals);
  422. }
  423. this->mVals = newVals;
  424. this->mAllocSize = newSize;
  425. }
  426. else if (idx != this->mSize)
  427. {
  428. intptr moveCount = this->mSize - idx;
  429. MoveArray(this->mVals + idx + 1, this->mVals + idx, moveCount);
  430. }
  431. new (&this->mVals[idx]) T(val);
  432. this->mSize++;
  433. }
  434. void Insert(intptr idx, T* vals, intptr size)
  435. {
  436. BF_ASSERT((uintptr)idx <= (uintptr)this->mSize);
  437. if (this->mSize + size > this->mAllocSize)
  438. {
  439. intptr newSize = BF_MAX(this->mSize + size, this->mAllocSize + this->mAllocSize / 2 + 1);
  440. T* newVals = TAlloc::allocate(newSize);
  441. if (this->mVals != NULL)
  442. {
  443. if (idx > 0) // Copy left of idx
  444. MoveArray(newVals, this->mVals, idx);
  445. if (idx < this->mSize) // Copy right of idx
  446. MoveArray(newVals + idx + size, this->mVals + idx, this->mSize - idx);
  447. if (this->mVals != (T*)&mFirstVal)
  448. TAlloc::deallocate(this->mVals);
  449. }
  450. this->mVals = newVals;
  451. this->mAllocSize = newSize;
  452. }
  453. else if (idx != this->mSize)
  454. {
  455. intptr moveCount = this->mSize - idx;
  456. MoveArray(this->mVals + idx + size, this->mVals + idx, moveCount);
  457. }
  458. for (int i = 0; i < size; i++)
  459. new (&this->mVals[idx + i]) T(vals[i]);
  460. this->mSize += size;
  461. }
  462. bool Remove(T val)
  463. {
  464. for (intptr i = 0; i < this->mSize; i++)
  465. {
  466. if (this->mVals[i] == val)
  467. {
  468. RemoveAt(i);
  469. return true;
  470. }
  471. }
  472. return false;
  473. }
  474. typename SizedArrayBase<T, TAlloc>::iterator erase(typename SizedArrayBase<T, TAlloc>::iterator itr)
  475. {
  476. RemoveAt(itr.mPtr - this->mVals);
  477. return itr;
  478. }
  479. void push_back(T val)
  480. {
  481. if (this->mSize >= this->mAllocSize)
  482. Grow(this->mAllocSize + this->mAllocSize / 2 + 1);
  483. new (&this->mVals[this->mSize++]) T(val);
  484. }
  485. void pop_back()
  486. {
  487. BF_ASSERT(this->mSize > 0);
  488. this->mVals[this->mSize - 1].~T();
  489. --this->mSize;
  490. }
  491. void Add(T val)
  492. {
  493. if (this->mSize >= this->mAllocSize)
  494. Grow(this->mAllocSize + this->mAllocSize / 2 + 1);
  495. new (&this->mVals[this->mSize++]) T(val);
  496. }
  497. };
  498. // POD
  499. template <typename T, typename TAlloc>
  500. class SizedArrayBaseT<T, TAlloc, true> : public SizedArrayBase<T, TAlloc>
  501. {
  502. public:
  503. typedef T TStorage;
  504. T mFirstVal;
  505. protected:
  506. void Grow(intptr newSize)
  507. {
  508. T* newVals = TAlloc::allocate(newSize);
  509. if (this->mVals != NULL)
  510. {
  511. if (this->mSize > 0)
  512. memcpy(newVals, this->mVals, this->mSize * sizeof(T));
  513. if (this->mVals != &mFirstVal)
  514. TAlloc::deallocate(this->mVals);
  515. }
  516. this->mVals = newVals;
  517. this->mAllocSize = newSize;
  518. }
  519. void EnsureFree(intptr freeCount)
  520. {
  521. if (this->mSize + freeCount > this->mAllocSize)
  522. Grow(std::max(this->mAllocSize + this->mAllocSize / 2 + 1, this->mSize + freeCount));
  523. }
  524. public:
  525. using SizedArrayBase<T, TAlloc>::SizedArrayBase;
  526. SizedArrayBaseT() : SizedArrayBase<T, TAlloc>()
  527. {
  528. }
  529. SizedArrayBaseT(const SizedArrayBaseT& val)
  530. {
  531. this->mVals = NULL;
  532. this->mSize = 0;
  533. this->mAllocSize = 0;
  534. *this = val;
  535. }
  536. SizedArrayBaseT(SizedArrayBaseT&& val) : SizedArrayBase<T, TAlloc>(val)
  537. {
  538. }
  539. ~SizedArrayBaseT()
  540. {
  541. if (this->mVals != &mFirstVal)
  542. {
  543. TAlloc::deallocate(this->mVals);
  544. }
  545. }
  546. SizedArrayBaseT& operator=(const SizedArrayBaseT& val)
  547. {
  548. if (&val == this)
  549. return *this;
  550. this->mSize = 0;
  551. if (val.mSize > this->mAllocSize)
  552. Grow(val.mSize);
  553. memcpy(this->mVals, val.mVals, val.mSize * sizeof(T));
  554. this->mSize = val.mSize;
  555. return *this;
  556. }
  557. void resize(intptr size)
  558. {
  559. while (size < this->mSize)
  560. pop_back();
  561. if (size > this->mSize)
  562. {
  563. reserve(size);
  564. while (size > this->mSize)
  565. new (&this->mVals[this->mSize++]) T();
  566. }
  567. }
  568. void reserve(intptr size)
  569. {
  570. if (size > this->mAllocSize)
  571. Grow(size);
  572. }
  573. void SetSize(intptr size)
  574. {
  575. if (size > this->mAllocSize)
  576. Grow(size);
  577. this->mSize = size;
  578. }
  579. void RemoveAt(intptr idx)
  580. {
  581. BF_ASSERT((uintptr)idx < (uintptr)this->mSize);
  582. // If we're removing the last element then we don't have to move anything
  583. if (idx != this->mSize - 1)
  584. {
  585. intptr moveCount = this->mSize - idx - 1;
  586. memmove(this->mVals + idx, this->mVals + idx + 1, moveCount * sizeof(T));
  587. }
  588. this->mSize--;
  589. }
  590. void RemoveRange(intptr idx, intptr length)
  591. {
  592. BF_ASSERT(
  593. ((uintptr)idx < (uintptr)this->mSize) &&
  594. ((uintptr)length > 0) &&
  595. ((uintptr)(idx + length) <= (uintptr)this->mSize));
  596. // If we're removing the last element then we don't have to move anything
  597. if (idx != this->mSize - length)
  598. {
  599. intptr moveCount = this->mSize - idx - length;
  600. memmove(this->mVals + idx, this->mVals + idx + length, moveCount * sizeof(T));
  601. }
  602. this->mSize -= length;
  603. }
  604. void Insert(intptr idx, T val)
  605. {
  606. BF_ASSERT((uintptr)idx <= (uintptr)this->mSize);
  607. if (this->mSize >= this->mAllocSize)
  608. {
  609. intptr newSize = this->mAllocSize + this->mAllocSize / 2 + 1;
  610. T* newVals = TAlloc::allocate(newSize);
  611. if (this->mVals != NULL)
  612. {
  613. if (idx > 0) // Copy left of idx
  614. memmove(newVals, this->mVals, idx * sizeof(T));
  615. if (idx < this->mSize) // Copy right of idx
  616. memmove(newVals + idx + 1, this->mVals + idx, (this->mSize - idx) * sizeof(T));
  617. if (this->mVals != &mFirstVal)
  618. TAlloc::deallocate(this->mVals);
  619. }
  620. this->mVals = newVals;
  621. this->mAllocSize = newSize;
  622. }
  623. else if (idx != this->mSize)
  624. {
  625. intptr moveCount = this->mSize - idx;
  626. memmove(this->mVals + idx + 1, this->mVals + idx, moveCount * sizeof(T));
  627. }
  628. this->mVals[idx] = val;
  629. this->mSize++;
  630. }
  631. void Insert(intptr idx, const T* vals, intptr size)
  632. {
  633. BF_ASSERT((uintptr)idx <= (uintptr)this->mSize);
  634. if (this->mSize + size > this->mAllocSize)
  635. {
  636. intptr newSize = BF_MAX(this->mSize + size, this->mAllocSize + this->mAllocSize / 2 + 1);
  637. T* newVals = TAlloc::allocate(newSize);
  638. if (this->mVals != NULL)
  639. {
  640. if (idx > 0) // Copy left of idx
  641. memmove(newVals, this->mVals, idx * sizeof(T));
  642. if (idx < this->mSize) // Copy right of idx
  643. memmove(newVals + idx + size, this->mVals + idx, (this->mSize - idx) * sizeof(T));
  644. if (this->mVals != &mFirstVal)
  645. TAlloc::deallocate(this->mVals);
  646. }
  647. this->mVals = newVals;
  648. this->mAllocSize = newSize;
  649. }
  650. else if (idx != this->mSize)
  651. {
  652. intptr moveCount = this->mSize - idx;
  653. memmove(this->mVals + idx + size, this->mVals + idx, moveCount * sizeof(T));
  654. }
  655. for (int i = 0; i < size; i++)
  656. this->mVals[idx + i] = vals[i];
  657. this->mSize += size;
  658. }
  659. bool Remove(T val)
  660. {
  661. for (intptr i = 0; i < this->mSize; i++)
  662. {
  663. if (this->mVals[i] == val)
  664. {
  665. RemoveAt(i);
  666. return true;
  667. }
  668. }
  669. return false;
  670. }
  671. typename SizedArrayBase<T, TAlloc>::iterator erase(typename SizedArrayBase<T, TAlloc>::iterator itr)
  672. {
  673. RemoveAt(itr.mPtr - this->mVals);
  674. return itr;
  675. }
  676. void push_back(T val)
  677. {
  678. if (this->mSize >= this->mAllocSize)
  679. Grow(this->mAllocSize + this->mAllocSize / 2 + 1);
  680. this->mVals[this->mSize++] = val;
  681. }
  682. void pop_back()
  683. {
  684. BF_ASSERT(this->mSize > 0);
  685. --this->mSize;
  686. }
  687. void Add(T val)
  688. {
  689. if (this->mSize >= this->mAllocSize)
  690. Grow(this->mAllocSize + this->mAllocSize / 2 + 1);
  691. this->mVals[this->mSize++] = val;
  692. }
  693. };
  694. template <typename T, typename TAlloc = AllocatorCLib<T> >
  695. class SizedArrayImpl : public SizedArrayBaseT<T, TAlloc, std::is_pod<T>::value>
  696. {
  697. public:
  698. typedef SizedArrayBaseT<T, TAlloc, std::is_pod<T>::value> _Base;
  699. };
  700. template <typename T, int TInternalSize, typename TAlloc = AllocatorCLib<T> >
  701. class SizedArray : public SizedArrayImpl<T, TAlloc>
  702. {
  703. public:
  704. typedef SizedArrayImpl<T, TAlloc> _Base;
  705. typedef typename _Base::_Base _BaseBase;
  706. typename _Base::TStorage mInternalBuffer[TInternalSize - 1];
  707. public:
  708. using SizedArrayImpl<T, TAlloc>::SizedArrayImpl;
  709. using _Base::operator=;
  710. using _Base::operator==;
  711. using _Base::operator!=;
  712. SizedArray()
  713. {
  714. this->mVals = (T*)&this->mFirstVal;
  715. this->mSize = 0;
  716. this->mAllocSize = TInternalSize;
  717. }
  718. SizedArray(const Array<T>& arr)
  719. {
  720. this->mVals = (T*)&this->mFirstVal;
  721. this->mSize = 0;
  722. this->mAllocSize = TInternalSize;
  723. for (auto& val : arr)
  724. this->Add(val);
  725. }
  726. SizedArray(const SizedArray& val)
  727. {
  728. this->mVals = (T*)&this->mFirstVal;
  729. this->mSize = 0;
  730. this->mAllocSize = TInternalSize;
  731. _BaseBase::operator=(val);
  732. }
  733. SizedArray(const typename _Base::_Base& val)
  734. {
  735. this->mVals = (T*)&this->mFirstVal;
  736. this->mSize = 0;
  737. this->mAllocSize = TInternalSize;
  738. _BaseBase::operator=(val);
  739. }
  740. SizedArray(SizedArray&& val)
  741. {
  742. if (val.mVals == (T*)&val.mFirstVal)
  743. {
  744. this->mVals = (T*)&this->mFirstVal;
  745. this->mSize = 0;
  746. this->mAllocSize = TInternalSize;
  747. _BaseBase::operator=(val);
  748. }
  749. else
  750. {
  751. this->mVals = val.mVals;
  752. this->mSize = val.mSize;
  753. this->mAllocSize = val.mAllocSize;
  754. val.mVals = (T*)&val.mFirstVal;
  755. }
  756. }
  757. SizedArray(std::initializer_list<T> il)
  758. {
  759. this->mVals = (T*)&this->mFirstVal;
  760. this->mSize = 0;
  761. this->mAllocSize = TInternalSize;
  762. for (auto& val : il)
  763. this->push_back(val);
  764. }
  765. _BaseBase& operator=(const SizedArray& val)
  766. {
  767. if (&val == this)
  768. return *this;
  769. return _BaseBase::operator=(val);
  770. }
  771. _BaseBase& operator=(std::initializer_list<T> il)
  772. {
  773. this->mSize = 0;
  774. for (auto& val : il)
  775. this->push_back(val);
  776. return *this;
  777. }
  778. };
  779. template <typename T, typename TAlloc>
  780. class SizedArray<T, 1, TAlloc> : public SizedArrayImpl<T, TAlloc>
  781. {
  782. public:
  783. typedef SizedArrayImpl<T, TAlloc> _Base;
  784. typedef typename _Base::_Base _BaseBase;
  785. using _Base::SizedArrayImpl;
  786. using _Base::operator=;
  787. using _Base::operator==;
  788. using _Base::operator!=;
  789. SizedArray()
  790. {
  791. this->mVals = (T*)&this->mFirstVal;
  792. this->mSize = 0;
  793. this->mAllocSize = 1;
  794. }
  795. SizedArray(const SizedArray& val)
  796. {
  797. this->mVals = NULL;
  798. this->mSize = 0;
  799. this->mAllocSize = 0;
  800. _BaseBase::operator=(val);
  801. }
  802. SizedArray(const _BaseBase& val)
  803. {
  804. this->mVals = NULL;
  805. this->mSize = 0;
  806. this->mAllocSize = 0;
  807. _BaseBase::operator=(val);
  808. }
  809. SizedArray(SizedArray&& val)
  810. {
  811. if (val.mVals == val.mInternalBuffer)
  812. {
  813. this->mVals = (T*)&this->mFirstVal;
  814. this->mSize = 0;
  815. this->mAllocSize = 1;
  816. _BaseBase::operator=(val);
  817. }
  818. else
  819. {
  820. this->mVals = val.mVals;
  821. this->mSize = val.mSize;
  822. this->mAllocSize = val.mAllocSize;
  823. val.mVals = NULL;
  824. }
  825. }
  826. SizedArray(std::initializer_list<T> il)
  827. {
  828. this->mVals = (T*)&this->mFirstVal;
  829. this->mSize = 0;
  830. this->mAllocSize = 1;
  831. for (auto& val : il)
  832. this->push_back(val);
  833. }
  834. _BaseBase& operator=(const SizedArray& val)
  835. {
  836. if (&val == this)
  837. return *this;
  838. return _BaseBase::operator=(val);
  839. }
  840. };
  841. template <typename T, typename TAlloc>
  842. class SizedArray<T, 0, TAlloc> : public SizedArrayImpl<T, TAlloc>
  843. {
  844. public:
  845. typedef SizedArrayImpl<T, TAlloc> _Base;
  846. typedef typename _Base::_Base _BaseBase;
  847. using _Base::SizedArrayImpl;
  848. using _Base::operator=;
  849. using _Base::operator==;
  850. using _Base::operator!=;
  851. SizedArray()
  852. {
  853. this->mVals = (T*)&this->mFirstVal;
  854. this->mSize = 0;
  855. this->mAllocSize = 1;
  856. }
  857. SizedArray(const SizedArray& val)
  858. {
  859. this->mVals = NULL;
  860. this->mSize = 0;
  861. this->mAllocSize = 0;
  862. _BaseBase::operator=(val);
  863. }
  864. SizedArray(const _BaseBase& val)
  865. {
  866. this->mVals = NULL;
  867. this->mSize = 0;
  868. this->mAllocSize = 0;
  869. _BaseBase::operator=(val);
  870. }
  871. SizedArray(SizedArray&& val)
  872. {
  873. if (val.mVals == val.mInternalBuffer)
  874. {
  875. this->mVals = (T*)&this->mFirstVal;
  876. this->mSize = 0;
  877. this->mAllocSize = 1;
  878. _BaseBase::operator=(val);
  879. }
  880. else
  881. {
  882. this->mVals = val.mVals;
  883. this->mSize = val.mSize;
  884. this->mAllocSize = val.mAllocSize;
  885. val.mVals = &val.mInternalBuffer;
  886. }
  887. }
  888. SizedArray(std::initializer_list<T> il)
  889. {
  890. this->mVals = (T*)&this->mFirstVal;
  891. this->mSize = 0;
  892. this->mAllocSize = 1;
  893. for (auto& val : il)
  894. this->push_back(val);
  895. }
  896. _BaseBase& operator=(const SizedArray& val)
  897. {
  898. return _BaseBase::operator=(val);
  899. }
  900. };
  901. NS_BF_END;
  902. /*namespace std
  903. {
  904. template<typename T>
  905. struct hash<Beefy::Array<T> >
  906. {
  907. size_t operator()(const Beefy::Array<T>& val) const
  908. {
  909. return _Hash_seq((const uint8*)val.mVals, sizeof(T) * val.mSize);
  910. }
  911. };
  912. }*/