SizedArray.h 20 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091
  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 Clear()
  236. {
  237. this->mSize = 0;
  238. }
  239. /*void Free()
  240. {
  241. if (this->mVals != NULL)
  242. {
  243. deallocate(this->mVals);
  244. }
  245. this->mVals = NULL;
  246. this->mAllocSize = 0;
  247. this->mSize = 0;
  248. }*/
  249. T GetSafe(intptr idx)
  250. {
  251. if ((idx < 0) || (idx >= this->mSize))
  252. return T();
  253. return this->mVals[idx];
  254. }
  255. T GetLastSafe()
  256. {
  257. if (this->mSize == 0)
  258. return T();
  259. return this->mVals[this->mSize - 1];
  260. }
  261. T GetFirstSafe()
  262. {
  263. if (this->mSize == 0)
  264. return T();
  265. return this->mVals[0];
  266. }
  267. bool Contains(T val) const
  268. {
  269. for (int i = 0; i < this->mSize; i++)
  270. if (this->mVals[i] == val)
  271. return true;
  272. return false;
  273. }
  274. intptr IndexOf(T val) const
  275. {
  276. for (int i = 0; i < this->mSize; i++)
  277. if (this->mVals[i] == val)
  278. return i;
  279. return -1;
  280. }
  281. };
  282. // NON-POD
  283. template <typename T, typename TAlloc, bool TIsPod>
  284. class SizedArrayBaseT : public SizedArrayBase<T, TAlloc>
  285. {
  286. public:
  287. typedef typename std::aligned_storage<sizeof(T), alignof(T)>::type TStorage;
  288. TStorage mFirstVal;
  289. protected:
  290. void MoveArray(T* to, T* from, intptr count)
  291. {
  292. if (to < from)
  293. {
  294. // Prefer in-order moves
  295. for (intptr i = 0; i < count; i++)
  296. new (&to[i]) T(std::move(from[i]));
  297. }
  298. else
  299. {
  300. for (intptr i = count - 1; i >= 0; i--)
  301. new (&to[i]) T(std::move(from[i]));
  302. }
  303. }
  304. void Grow(intptr newSize)
  305. {
  306. T* newVals = TAlloc::allocate(newSize);
  307. if (this->mVals != NULL)
  308. {
  309. if (this->mSize > 0)
  310. MoveArray(newVals, this->mVals, this->mSize);
  311. if (this->mVals != (T*)&mFirstVal)
  312. TAlloc::deallocate(this->mVals);
  313. }
  314. this->mVals = newVals;
  315. this->mAllocSize = newSize;
  316. }
  317. void EnsureFree(intptr freeCount)
  318. {
  319. if (this->mSize + freeCount > this->mAllocSize)
  320. Grow(std::max(this->mAllocSize + this->mAllocSize / 2 + 1, this->mSize + freeCount));
  321. }
  322. public:
  323. using SizedArrayBase<T, TAlloc>::SizedArrayBase;
  324. SizedArrayBaseT() : SizedArrayBase<T, TAlloc>()
  325. {
  326. }
  327. SizedArrayBaseT(const SizedArrayBaseT& val)
  328. {
  329. this->mVals = NULL;
  330. this->mSize = 0;
  331. this->mAllocSize = 0;
  332. *this = val;
  333. }
  334. SizedArrayBaseT(SizedArrayBaseT&& val) : SizedArrayBase<T, TAlloc>(val)
  335. {
  336. }
  337. ~SizedArrayBaseT()
  338. {
  339. for (int i = 0; i < this->mSize; i++)
  340. this->mVals[i].~T();
  341. if (this->mVals != (T*)&mFirstVal)
  342. {
  343. TAlloc::deallocate(this->mVals);
  344. }
  345. }
  346. void resize(intptr size)
  347. {
  348. while (size < this->mSize)
  349. pop_back();
  350. if (size > this->mSize)
  351. {
  352. reserve(size);
  353. while (size > this->mSize)
  354. new (&this->mVals[this->mSize++]) T();
  355. }
  356. }
  357. void reserve(intptr size)
  358. {
  359. if (size > this->mAllocSize)
  360. Grow(size);
  361. }
  362. void SetSize(intptr size)
  363. {
  364. if (size > this->mAllocSize)
  365. Grow(size);
  366. this->mSize = size;
  367. }
  368. SizedArrayBaseT& operator=(const SizedArrayBaseT& val)
  369. {
  370. if (&val == this)
  371. return *this;
  372. for (int i = 0; i < this->mSize; i++)
  373. this->mVals[i].~T();
  374. this->mSize = 0;
  375. if (val.mSize > this->mAllocSize)
  376. Grow(val.mSize);
  377. resize(val.mSize);
  378. for (int i = 0; i < val.mSize; i++)
  379. new (&this->mVals[i]) T(val.mVals[i]);
  380. this->mSize = val.mSize;
  381. return *this;
  382. }
  383. void RemoveAt(intptr idx)
  384. {
  385. BF_ASSERT((uintptr)idx < (uintptr)this->mSize);
  386. this->mVals[idx].~T();
  387. // If we're removing the last element then we don't have to move anything
  388. if (idx != this->mSize - 1)
  389. {
  390. intptr moveCount = this->mSize - idx - 1;
  391. MoveArray(this->mVals + idx, this->mVals + idx + 1, moveCount);
  392. }
  393. this->mSize--;
  394. }
  395. void RemoveRange(intptr idx, intptr length)
  396. {
  397. BF_ASSERT(
  398. ((uintptr)idx < (uintptr)this->mSize) &&
  399. ((uintptr)length > 0) &&
  400. ((uintptr)(idx + length) <= (uintptr)this->mSize));
  401. for (intptr i = idx; i < idx + length; i++)
  402. this->mVals[i].~T();
  403. // If we're removing the last element then we don't have to move anything
  404. if (idx != this->mSize - length)
  405. {
  406. intptr moveCount = this->mSize - idx - length;
  407. MoveArray(this->mVals + idx, this->mVals + idx + length, moveCount);
  408. }
  409. this->mSize -= length;
  410. }
  411. void Insert(intptr idx, T val)
  412. {
  413. BF_ASSERT((uintptr)idx <= (uintptr)this->mSize);
  414. if (this->mSize >= this->mAllocSize)
  415. {
  416. intptr newSize = this->mAllocSize + this->mAllocSize / 2 + 1;
  417. T* newVals = TAlloc::allocate(newSize);
  418. if (this->mVals != NULL)
  419. {
  420. if (idx > 0) // Copy left of idx
  421. MoveArray(newVals, this->mVals, idx);
  422. if (idx < this->mSize) // Copy right of idx
  423. MoveArray(newVals + idx + 1, this->mVals + idx, this->mSize - idx);
  424. if (this->mVals != (T*)&mFirstVal)
  425. TAlloc::deallocate(this->mVals);
  426. }
  427. this->mVals = newVals;
  428. this->mAllocSize = newSize;
  429. }
  430. else if (idx != this->mSize)
  431. {
  432. intptr moveCount = this->mSize - idx;
  433. MoveArray(this->mVals + idx + 1, this->mVals + idx, moveCount);
  434. }
  435. new (&this->mVals[idx]) T(val);
  436. this->mSize++;
  437. }
  438. void Insert(intptr idx, T* vals, intptr size)
  439. {
  440. BF_ASSERT((uintptr)idx <= (uintptr)this->mSize);
  441. if (this->mSize + size > this->mAllocSize)
  442. {
  443. intptr newSize = BF_MAX(this->mSize + size, this->mAllocSize + this->mAllocSize / 2 + 1);
  444. T* newVals = TAlloc::allocate(newSize);
  445. if (this->mVals != NULL)
  446. {
  447. if (idx > 0) // Copy left of idx
  448. MoveArray(newVals, this->mVals, idx);
  449. if (idx < this->mSize) // Copy right of idx
  450. MoveArray(newVals + idx + size, this->mVals + idx, this->mSize - idx);
  451. if (this->mVals != (T*)&mFirstVal)
  452. TAlloc::deallocate(this->mVals);
  453. }
  454. this->mVals = newVals;
  455. this->mAllocSize = newSize;
  456. }
  457. else if (idx != this->mSize)
  458. {
  459. intptr moveCount = this->mSize - idx;
  460. MoveArray(this->mVals + idx + size, this->mVals + idx, moveCount);
  461. }
  462. for (int i = 0; i < size; i++)
  463. new (&this->mVals[idx + i]) T(vals[i]);
  464. this->mSize += size;
  465. }
  466. bool Remove(T val)
  467. {
  468. for (intptr i = 0; i < this->mSize; i++)
  469. {
  470. if (this->mVals[i] == val)
  471. {
  472. RemoveAt(i);
  473. return true;
  474. }
  475. }
  476. return false;
  477. }
  478. typename SizedArrayBase<T, TAlloc>::iterator erase(typename SizedArrayBase<T, TAlloc>::iterator itr)
  479. {
  480. RemoveAt(itr.mPtr - this->mVals);
  481. return itr;
  482. }
  483. void push_back(T val)
  484. {
  485. if (this->mSize >= this->mAllocSize)
  486. Grow(this->mAllocSize + this->mAllocSize / 2 + 1);
  487. new (&this->mVals[this->mSize++]) T(val);
  488. }
  489. void pop_back()
  490. {
  491. BF_ASSERT(this->mSize > 0);
  492. this->mVals[this->mSize - 1].~T();
  493. --this->mSize;
  494. }
  495. void Add(T val)
  496. {
  497. if (this->mSize >= this->mAllocSize)
  498. Grow(this->mAllocSize + this->mAllocSize / 2 + 1);
  499. new (&this->mVals[this->mSize++]) T(val);
  500. }
  501. };
  502. // POD
  503. template <typename T, typename TAlloc>
  504. class SizedArrayBaseT<T, TAlloc, true> : public SizedArrayBase<T, TAlloc>
  505. {
  506. public:
  507. typedef T TStorage;
  508. T mFirstVal;
  509. protected:
  510. void Grow(intptr newSize)
  511. {
  512. T* newVals = TAlloc::allocate(newSize);
  513. if (this->mVals != NULL)
  514. {
  515. if (this->mSize > 0)
  516. memcpy(newVals, this->mVals, this->mSize * sizeof(T));
  517. if (this->mVals != &mFirstVal)
  518. TAlloc::deallocate(this->mVals);
  519. }
  520. this->mVals = newVals;
  521. this->mAllocSize = newSize;
  522. }
  523. void EnsureFree(intptr freeCount)
  524. {
  525. if (this->mSize + freeCount > this->mAllocSize)
  526. Grow(std::max(this->mAllocSize + this->mAllocSize / 2 + 1, this->mSize + freeCount));
  527. }
  528. public:
  529. using SizedArrayBase<T, TAlloc>::SizedArrayBase;
  530. SizedArrayBaseT() : SizedArrayBase<T, TAlloc>()
  531. {
  532. }
  533. SizedArrayBaseT(const SizedArrayBaseT& val)
  534. {
  535. this->mVals = NULL;
  536. this->mSize = 0;
  537. this->mAllocSize = 0;
  538. *this = val;
  539. }
  540. SizedArrayBaseT(SizedArrayBaseT&& val) : SizedArrayBase<T, TAlloc>(val)
  541. {
  542. }
  543. ~SizedArrayBaseT()
  544. {
  545. if (this->mVals != &mFirstVal)
  546. {
  547. TAlloc::deallocate(this->mVals);
  548. }
  549. }
  550. SizedArrayBaseT& operator=(const SizedArrayBaseT& val)
  551. {
  552. if (&val == this)
  553. return *this;
  554. this->mSize = 0;
  555. if (val.mSize > this->mAllocSize)
  556. Grow(val.mSize);
  557. memcpy(this->mVals, val.mVals, val.mSize * sizeof(T));
  558. this->mSize = val.mSize;
  559. return *this;
  560. }
  561. void resize(intptr size)
  562. {
  563. while (size < this->mSize)
  564. pop_back();
  565. if (size > this->mSize)
  566. {
  567. reserve(size);
  568. while (size > this->mSize)
  569. new (&this->mVals[this->mSize++]) T();
  570. }
  571. }
  572. void reserve(intptr size)
  573. {
  574. if (size > this->mAllocSize)
  575. Grow(size);
  576. }
  577. void SetSize(intptr size)
  578. {
  579. if (size > this->mAllocSize)
  580. Grow(size);
  581. this->mSize = size;
  582. }
  583. void RemoveAt(intptr idx)
  584. {
  585. BF_ASSERT((uintptr)idx < (uintptr)this->mSize);
  586. // If we're removing the last element then we don't have to move anything
  587. if (idx != this->mSize - 1)
  588. {
  589. intptr moveCount = this->mSize - idx - 1;
  590. memmove(this->mVals + idx, this->mVals + idx + 1, moveCount * sizeof(T));
  591. }
  592. this->mSize--;
  593. }
  594. void RemoveRange(intptr idx, intptr length)
  595. {
  596. BF_ASSERT(
  597. ((uintptr)idx < (uintptr)this->mSize) &&
  598. ((uintptr)length > 0) &&
  599. ((uintptr)(idx + length) <= (uintptr)this->mSize));
  600. // If we're removing the last element then we don't have to move anything
  601. if (idx != this->mSize - length)
  602. {
  603. intptr moveCount = this->mSize - idx - length;
  604. memmove(this->mVals + idx, this->mVals + idx + length, moveCount * sizeof(T));
  605. }
  606. this->mSize -= length;
  607. }
  608. void Insert(intptr idx, T val)
  609. {
  610. BF_ASSERT((uintptr)idx <= (uintptr)this->mSize);
  611. if (this->mSize >= this->mAllocSize)
  612. {
  613. intptr newSize = this->mAllocSize + this->mAllocSize / 2 + 1;
  614. T* newVals = TAlloc::allocate(newSize);
  615. if (this->mVals != NULL)
  616. {
  617. if (idx > 0) // Copy left of idx
  618. memmove(newVals, this->mVals, idx * sizeof(T));
  619. if (idx < this->mSize) // Copy right of idx
  620. memmove(newVals + idx + 1, this->mVals + idx, (this->mSize - idx) * sizeof(T));
  621. if (this->mVals != &mFirstVal)
  622. TAlloc::deallocate(this->mVals);
  623. }
  624. this->mVals = newVals;
  625. this->mAllocSize = newSize;
  626. }
  627. else if (idx != this->mSize)
  628. {
  629. intptr moveCount = this->mSize - idx;
  630. memmove(this->mVals + idx + 1, this->mVals + idx, moveCount * sizeof(T));
  631. }
  632. this->mVals[idx] = val;
  633. this->mSize++;
  634. }
  635. void Insert(intptr idx, const T* vals, intptr size)
  636. {
  637. BF_ASSERT((uintptr)idx <= (uintptr)this->mSize);
  638. if (this->mSize + size > this->mAllocSize)
  639. {
  640. intptr newSize = BF_MAX(this->mSize + size, this->mAllocSize + this->mAllocSize / 2 + 1);
  641. T* newVals = TAlloc::allocate(newSize);
  642. if (this->mVals != NULL)
  643. {
  644. if (idx > 0) // Copy left of idx
  645. memmove(newVals, this->mVals, idx * sizeof(T));
  646. if (idx < this->mSize) // Copy right of idx
  647. memmove(newVals + idx + size, this->mVals + idx, (this->mSize - idx) * sizeof(T));
  648. if (this->mVals != &mFirstVal)
  649. TAlloc::deallocate(this->mVals);
  650. }
  651. this->mVals = newVals;
  652. this->mAllocSize = newSize;
  653. }
  654. else if (idx != this->mSize)
  655. {
  656. intptr moveCount = this->mSize - idx;
  657. memmove(this->mVals + idx + size, this->mVals + idx, moveCount * sizeof(T));
  658. }
  659. for (int i = 0; i < size; i++)
  660. this->mVals[idx + i] = vals[i];
  661. this->mSize += size;
  662. }
  663. bool Remove(T val)
  664. {
  665. for (intptr i = 0; i < this->mSize; i++)
  666. {
  667. if (this->mVals[i] == val)
  668. {
  669. RemoveAt(i);
  670. return true;
  671. }
  672. }
  673. return false;
  674. }
  675. typename SizedArrayBase<T, TAlloc>::iterator erase(typename SizedArrayBase<T, TAlloc>::iterator itr)
  676. {
  677. RemoveAt(itr.mPtr - this->mVals);
  678. return itr;
  679. }
  680. void push_back(T val)
  681. {
  682. if (this->mSize >= this->mAllocSize)
  683. Grow(this->mAllocSize + this->mAllocSize / 2 + 1);
  684. this->mVals[this->mSize++] = val;
  685. }
  686. void pop_back()
  687. {
  688. BF_ASSERT(this->mSize > 0);
  689. --this->mSize;
  690. }
  691. void Add(T val)
  692. {
  693. if (this->mSize >= this->mAllocSize)
  694. Grow(this->mAllocSize + this->mAllocSize / 2 + 1);
  695. this->mVals[this->mSize++] = val;
  696. }
  697. };
  698. template <typename T, typename TAlloc = AllocatorCLib<T> >
  699. class SizedArrayImpl : public SizedArrayBaseT<T, TAlloc, std::is_pod<T>::value>
  700. {
  701. public:
  702. typedef SizedArrayBaseT<T, TAlloc, std::is_pod<T>::value> _Base;
  703. };
  704. template <typename T, int TInternalSize, typename TAlloc = AllocatorCLib<T> >
  705. class SizedArray : public SizedArrayImpl<T, TAlloc>
  706. {
  707. public:
  708. typedef SizedArrayImpl<T, TAlloc> _Base;
  709. typedef typename _Base::_Base _BaseBase;
  710. typename _Base::TStorage mInternalBuffer[TInternalSize - 1];
  711. public:
  712. using SizedArrayImpl<T, TAlloc>::SizedArrayImpl;
  713. using _Base::operator=;
  714. using _Base::operator==;
  715. using _Base::operator!=;
  716. SizedArray()
  717. {
  718. this->mVals = (T*)&this->mFirstVal;
  719. this->mSize = 0;
  720. this->mAllocSize = TInternalSize;
  721. }
  722. SizedArray(const Array<T>& arr)
  723. {
  724. this->mVals = (T*)&this->mFirstVal;
  725. this->mSize = 0;
  726. this->mAllocSize = TInternalSize;
  727. for (auto& val : arr)
  728. this->Add(val);
  729. }
  730. SizedArray(const SizedArray& val)
  731. {
  732. this->mVals = (T*)&this->mFirstVal;
  733. this->mSize = 0;
  734. this->mAllocSize = TInternalSize;
  735. _BaseBase::operator=(val);
  736. }
  737. SizedArray(const typename _Base::_Base& val)
  738. {
  739. this->mVals = (T*)&this->mFirstVal;
  740. this->mSize = 0;
  741. this->mAllocSize = TInternalSize;
  742. _BaseBase::operator=(val);
  743. }
  744. SizedArray(SizedArray&& val)
  745. {
  746. if (val.mVals == (T*)&val.mFirstVal)
  747. {
  748. this->mVals = (T*)&this->mFirstVal;
  749. this->mSize = 0;
  750. this->mAllocSize = TInternalSize;
  751. _BaseBase::operator=(val);
  752. }
  753. else
  754. {
  755. this->mVals = val.mVals;
  756. this->mSize = val.mSize;
  757. this->mAllocSize = val.mAllocSize;
  758. val.mVals = (T*)&val.mFirstVal;
  759. }
  760. }
  761. SizedArray(std::initializer_list<T> il)
  762. {
  763. this->mVals = (T*)&this->mFirstVal;
  764. this->mSize = 0;
  765. this->mAllocSize = TInternalSize;
  766. for (auto& val : il)
  767. this->push_back(val);
  768. }
  769. _BaseBase& operator=(const SizedArray& val)
  770. {
  771. if (&val == this)
  772. return *this;
  773. return _BaseBase::operator=(val);
  774. }
  775. _BaseBase& operator=(std::initializer_list<T> il)
  776. {
  777. this->mSize = 0;
  778. for (auto& val : il)
  779. this->push_back(val);
  780. return *this;
  781. }
  782. };
  783. template <typename T, typename TAlloc>
  784. class SizedArray<T, 1, TAlloc> : public SizedArrayImpl<T, TAlloc>
  785. {
  786. public:
  787. typedef SizedArrayImpl<T, TAlloc> _Base;
  788. typedef typename _Base::_Base _BaseBase;
  789. using _Base::SizedArrayImpl;
  790. using _Base::operator=;
  791. using _Base::operator==;
  792. using _Base::operator!=;
  793. SizedArray()
  794. {
  795. this->mVals = (T*)&this->mFirstVal;
  796. this->mSize = 0;
  797. this->mAllocSize = 1;
  798. }
  799. SizedArray(const SizedArray& val)
  800. {
  801. this->mVals = NULL;
  802. this->mSize = 0;
  803. this->mAllocSize = 0;
  804. _BaseBase::operator=(val);
  805. }
  806. SizedArray(const _BaseBase& val)
  807. {
  808. this->mVals = NULL;
  809. this->mSize = 0;
  810. this->mAllocSize = 0;
  811. _BaseBase::operator=(val);
  812. }
  813. SizedArray(SizedArray&& val)
  814. {
  815. if (val.mVals == val.mInternalBuffer)
  816. {
  817. this->mVals = (T*)&this->mFirstVal;
  818. this->mSize = 0;
  819. this->mAllocSize = 1;
  820. _BaseBase::operator=(val);
  821. }
  822. else
  823. {
  824. this->mVals = val.mVals;
  825. this->mSize = val.mSize;
  826. this->mAllocSize = val.mAllocSize;
  827. val.mVals = NULL;
  828. }
  829. }
  830. SizedArray(std::initializer_list<T> il)
  831. {
  832. this->mVals = (T*)&this->mFirstVal;
  833. this->mSize = 0;
  834. this->mAllocSize = 1;
  835. for (auto& val : il)
  836. this->push_back(val);
  837. }
  838. _BaseBase& operator=(const SizedArray& val)
  839. {
  840. if (&val == this)
  841. return *this;
  842. return _BaseBase::operator=(val);
  843. }
  844. };
  845. template <typename T, typename TAlloc>
  846. class SizedArray<T, 0, TAlloc> : public SizedArrayImpl<T, TAlloc>
  847. {
  848. public:
  849. typedef SizedArrayImpl<T, TAlloc> _Base;
  850. typedef typename _Base::_Base _BaseBase;
  851. using _Base::SizedArrayImpl;
  852. using _Base::operator=;
  853. using _Base::operator==;
  854. using _Base::operator!=;
  855. SizedArray()
  856. {
  857. this->mVals = (T*)&this->mFirstVal;
  858. this->mSize = 0;
  859. this->mAllocSize = 1;
  860. }
  861. SizedArray(const SizedArray& val)
  862. {
  863. this->mVals = NULL;
  864. this->mSize = 0;
  865. this->mAllocSize = 0;
  866. _BaseBase::operator=(val);
  867. }
  868. SizedArray(const _BaseBase& val)
  869. {
  870. this->mVals = NULL;
  871. this->mSize = 0;
  872. this->mAllocSize = 0;
  873. _BaseBase::operator=(val);
  874. }
  875. SizedArray(SizedArray&& val)
  876. {
  877. if (val.mVals == val.mInternalBuffer)
  878. {
  879. this->mVals = (T*)&this->mFirstVal;
  880. this->mSize = 0;
  881. this->mAllocSize = 1;
  882. _BaseBase::operator=(val);
  883. }
  884. else
  885. {
  886. this->mVals = val.mVals;
  887. this->mSize = val.mSize;
  888. this->mAllocSize = val.mAllocSize;
  889. val.mVals = &val.mInternalBuffer;
  890. }
  891. }
  892. SizedArray(std::initializer_list<T> il)
  893. {
  894. this->mVals = (T*)&this->mFirstVal;
  895. this->mSize = 0;
  896. this->mAllocSize = 1;
  897. for (auto& val : il)
  898. this->push_back(val);
  899. }
  900. _BaseBase& operator=(const SizedArray& val)
  901. {
  902. return _BaseBase::operator=(val);
  903. }
  904. };
  905. template <typename T>
  906. static bool operator==(const ArrayBase<T>& arrA, const SizedArrayBase<T>& arrB)
  907. {
  908. if (arrA.mSize != arrB.mSize)
  909. return false;
  910. for (intptr i = 0; i < arrA.mSize; i++)
  911. if (arrA.mVals[i] != arrB.mVals[i])
  912. return false;
  913. return true;
  914. }
  915. NS_BF_END;
  916. namespace std
  917. {
  918. template<typename T>
  919. struct hash<Beefy::SizedArrayImpl<T> >
  920. {
  921. size_t operator()(const Beefy::SizedArrayImpl<T>& val) const
  922. {
  923. return HashBytes((const uint8*)val.mVals, sizeof(T) * val.mSize);
  924. }
  925. };
  926. }