Array.h 22 KB

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