Vector.h 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #pragma once
  4. #include "../Container/VectorBase.h"
  5. #include <algorithm>
  6. #include <cassert>
  7. #include <cstring>
  8. #include <initializer_list>
  9. #include <new>
  10. #include <type_traits>
  11. #include <utility>
  12. namespace Urho3D
  13. {
  14. /// No index.
  15. inline constexpr i32 NINDEX = -1;
  16. /// End position.
  17. inline constexpr i32 ENDPOS = -1;
  18. /// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2593r0.html
  19. /// @nobindtemp
  20. template <typename...> inline constexpr bool always_false = false;
  21. /// %Vector template class.
  22. template <class T> class Vector : public VectorBase
  23. {
  24. struct CopyTag {};
  25. struct MoveTag {};
  26. public:
  27. using ValueType = T;
  28. using Iterator = RandomAccessIterator<T>;
  29. using ConstIterator = RandomAccessConstIterator<T>;
  30. /// Construct empty.
  31. Vector() noexcept = default;
  32. /// Construct with initial size.
  33. explicit Vector(i32 size)
  34. {
  35. assert(size >= 0);
  36. Resize(size);
  37. }
  38. /// Construct with initial size and default value.
  39. Vector(i32 size, const T& value)
  40. {
  41. assert(size >= 0);
  42. Resize(size);
  43. for (i32 i = 0; i < size; ++i)
  44. At(i) = value;
  45. }
  46. /// Construct with initial data.
  47. Vector(const T* data, i32 size)
  48. {
  49. assert((size >= 0 && data) || (!size && !data));
  50. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  51. {
  52. Resize(size);
  53. CopyElements(Buffer(), data, size);
  54. }
  55. else
  56. {
  57. DoInsertElements(0, data, data + size, CopyTag{});
  58. }
  59. }
  60. /// Copy-construct from another vector.
  61. Vector(const Vector<T>& vector)
  62. {
  63. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  64. *this = vector;
  65. else
  66. DoInsertElements(0, vector.Begin(), vector.End(), CopyTag{});
  67. }
  68. /// Copy-construct from another vector (iterator version).
  69. Vector(ConstIterator start, ConstIterator end)
  70. {
  71. DoInsertElements(0, start, end, CopyTag{});
  72. }
  73. /// Move-construct from another vector.
  74. Vector(Vector<T>&& vector)
  75. {
  76. Swap(vector);
  77. }
  78. /// Aggregate initialization constructor.
  79. Vector(const std::initializer_list<T>& list) : Vector()
  80. {
  81. for (auto it = list.begin(); it != list.end(); it++)
  82. {
  83. Push(*it);
  84. }
  85. }
  86. /// Destruct.
  87. ~Vector()
  88. {
  89. if constexpr (!std::is_trivial<T>::value)
  90. DestructElements(Buffer(), size_);
  91. delete[] buffer_;
  92. }
  93. /// Assign from another vector.
  94. Vector<T>& operator =(const Vector<T>& rhs)
  95. {
  96. // In case of self-assignment do nothing
  97. if (&rhs != this)
  98. {
  99. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  100. {
  101. Resize(rhs.size_);
  102. CopyElements(Buffer(), rhs.Buffer(), rhs.size_);
  103. }
  104. else
  105. {
  106. Vector<T> copy(rhs);
  107. Swap(copy);
  108. }
  109. }
  110. return *this;
  111. }
  112. /// Move-assign from another vector.
  113. Vector<T>& operator =(Vector<T>&& rhs)
  114. {
  115. Swap(rhs);
  116. return *this;
  117. }
  118. /// Add-assign an element.
  119. Vector<T>& operator +=(const T& rhs)
  120. {
  121. Push(rhs);
  122. return *this;
  123. }
  124. /// Add-assign another vector.
  125. Vector<T>& operator +=(const Vector<T>& rhs)
  126. {
  127. Push(rhs);
  128. return *this;
  129. }
  130. /// Add an element.
  131. Vector<T> operator +(const T& rhs) const
  132. {
  133. Vector<T> ret(*this);
  134. ret.Push(rhs);
  135. return ret;
  136. }
  137. /// Add another vector.
  138. Vector<T> operator +(const Vector<T>& rhs) const
  139. {
  140. Vector<T> ret(*this);
  141. ret.Push(rhs);
  142. return ret;
  143. }
  144. /// Test for equality with another vector.
  145. bool operator ==(const Vector<T>& rhs) const
  146. {
  147. if (rhs.size_ != size_)
  148. return false;
  149. T* buffer = Buffer();
  150. T* rhsBuffer = rhs.Buffer();
  151. for (i32 i = 0; i < size_; ++i)
  152. {
  153. if (buffer[i] != rhsBuffer[i])
  154. return false;
  155. }
  156. return true;
  157. }
  158. /// Test for inequality with another vector.
  159. bool operator !=(const Vector<T>& rhs) const
  160. {
  161. if (rhs.size_ != size_)
  162. return true;
  163. T* buffer = Buffer();
  164. T* rhsBuffer = rhs.Buffer();
  165. for (i32 i = 0; i < size_; ++i)
  166. {
  167. if (buffer[i] != rhsBuffer[i])
  168. return true;
  169. }
  170. return false;
  171. }
  172. /// Return element at index.
  173. T& operator [](i32 index)
  174. {
  175. assert(index >= 0 && index < size_);
  176. return Buffer()[index];
  177. }
  178. /// Return const element at index.
  179. const T& operator [](i32 index) const
  180. {
  181. assert(index >= 0 && index < size_);
  182. return Buffer()[index];
  183. }
  184. /// Return element at index.
  185. T& At(i32 index)
  186. {
  187. assert(index >= 0 && index < size_);
  188. return Buffer()[index];
  189. }
  190. /// Return const element at index.
  191. const T& At(i32 index) const
  192. {
  193. assert(index >= 0 && index < size_);
  194. return Buffer()[index];
  195. }
  196. /// Create an element at the end.
  197. template <class... Args> T& EmplaceBack(Args&&... args)
  198. {
  199. if (size_ < capacity_)
  200. {
  201. // Optimize common case
  202. ++size_;
  203. new (&Back()) T(std::forward<Args>(args)...);
  204. }
  205. else
  206. {
  207. T value(std::forward<Args>(args)...);
  208. Push(std::move(value));
  209. }
  210. return Back();
  211. }
  212. /// Add an element at the end.
  213. #ifndef COVERITY_SCAN_MODEL
  214. void Push(const T& value)
  215. {
  216. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  217. {
  218. if (size_ < capacity_)
  219. ++size_;
  220. else
  221. Resize(size_ + 1);
  222. Back() = value;
  223. }
  224. else
  225. {
  226. if (size_ < capacity_)
  227. {
  228. // Optimize common case
  229. ++size_;
  230. new (&Back()) T(value);
  231. }
  232. else
  233. {
  234. DoInsertElements(size_, &value, &value + 1, CopyTag{});
  235. }
  236. }
  237. }
  238. /// Move-add an element at the end.
  239. void Push(T&& value)
  240. {
  241. if (size_ < capacity_)
  242. {
  243. // Optimize common case
  244. ++size_;
  245. new (&Back()) T(std::move(value));
  246. }
  247. else
  248. DoInsertElements(size_, &value, &value + 1, MoveTag{});
  249. }
  250. #else
  251. // FIXME: Attempt had been made to use this model in the Coverity-Scan model file without any success
  252. // Probably because the model had generated a different mangled name than the one used by static analyzer
  253. void Push(const T& value)
  254. {
  255. T array[] = {value};
  256. DoInsertElements(size_, array, array + 1, CopyTag{});
  257. }
  258. #endif
  259. /// Add another vector at the end.
  260. void Push(const Vector<T>& vector)
  261. {
  262. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  263. {
  264. // Obtain the size before resizing, in case the other vector is another reference to this vector
  265. i32 thisSize = size_;
  266. i32 vectorSize = vector.size_;
  267. Resize(thisSize + vectorSize);
  268. CopyElements(Buffer() + thisSize, vector.Buffer(), vectorSize);
  269. }
  270. else
  271. {
  272. DoInsertElements(size_, vector.Begin(), vector.End(), CopyTag{});
  273. }
  274. }
  275. /// Remove the last element.
  276. void Pop()
  277. {
  278. if (size_)
  279. Resize(size_ - 1);
  280. }
  281. /// Insert an element at position. If pos is ENDPOS, append the new value at the end.
  282. void Insert(i32 pos, const T& value)
  283. {
  284. assert((pos >= 0 && pos <= size_) || pos == ENDPOS);
  285. DoInsertElements(pos, &value, &value + 1, CopyTag{});
  286. }
  287. /// Insert an element at position. If pos is ENDPOS, append the new value at the end.
  288. void Insert(i32 pos, T&& value)
  289. {
  290. assert((pos >= 0 && pos <= size_) || pos == ENDPOS);
  291. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  292. {
  293. if (pos == ENDPOS)
  294. pos = size_;
  295. i32 oldSize = size_;
  296. Resize(size_ + 1);
  297. MoveRange(pos + 1, pos, oldSize - pos);
  298. Buffer()[pos] = value;
  299. }
  300. else
  301. {
  302. DoInsertElements(pos, &value, &value + 1, MoveTag{});
  303. }
  304. }
  305. /// Insert another vector at position. If pos is ENDPOS, append the new elements at the end.
  306. void Insert(i32 pos, const Vector<T>& vector)
  307. {
  308. assert((pos >= 0 && pos <= size_) || pos == ENDPOS);
  309. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  310. {
  311. if (pos == ENDPOS)
  312. pos = size_;
  313. i32 oldSize = size_;
  314. Resize(size_ + vector.size_);
  315. MoveRange(pos + vector.size_, pos, oldSize - pos);
  316. CopyElements(Buffer() + pos, vector.Buffer(), vector.size_);
  317. }
  318. else
  319. {
  320. DoInsertElements(pos, vector.Begin(), vector.End(), CopyTag{});
  321. }
  322. }
  323. /// Insert an element by iterator.
  324. Iterator Insert(const Iterator& dest, const T& value)
  325. {
  326. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  327. {
  328. i32 pos = (i32)(dest - Begin());
  329. assert(pos >= 0 && pos <= size_);
  330. Insert(pos, value);
  331. return Begin() + pos;
  332. }
  333. else
  334. {
  335. i32 pos = (i32)(dest - Begin());
  336. assert(pos >= 0 && pos <= size_);
  337. return DoInsertElements(pos, &value, &value + 1, CopyTag{});
  338. }
  339. }
  340. /// Move-insert an element by iterator.
  341. Iterator Insert(const Iterator& dest, T&& value)
  342. {
  343. i32 pos = (i32)(dest - Begin());
  344. assert(pos >= 0 && pos <= size_);
  345. return DoInsertElements(pos, &value, &value + 1, MoveTag{});
  346. }
  347. /// Insert a vector by iterator.
  348. Iterator Insert(const Iterator& dest, const Vector<T>& vector)
  349. {
  350. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  351. {
  352. i32 pos = (i32)(dest - Begin());
  353. assert(pos >= 0 && pos <= size_);
  354. Insert(pos, vector);
  355. return Begin() + pos;
  356. }
  357. else
  358. {
  359. i32 pos = (i32)(dest - Begin());
  360. assert(pos >= 0 && pos <= size_);
  361. return DoInsertElements(pos, vector.Begin(), vector.End(), CopyTag{});
  362. }
  363. }
  364. /// Insert a vector partially by iterators.
  365. Iterator Insert(const Iterator& dest, const ConstIterator& start, const ConstIterator& end)
  366. {
  367. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  368. {
  369. i32 pos = (i32)(dest - Begin());
  370. assert(pos >= 0 && pos <= size_);
  371. i32 length = (i32)(end - start);
  372. Resize(size_ + length);
  373. MoveRange(pos + length, pos, size_ - pos - length);
  374. CopyElements(Buffer() + pos, &(*start), length);
  375. return Begin() + pos;
  376. }
  377. else
  378. {
  379. i32 pos = (i32)(dest - Begin());
  380. assert(pos >= 0 && pos <= size_);
  381. return DoInsertElements(pos, start, end, CopyTag{});
  382. }
  383. }
  384. /// Insert elements.
  385. Iterator Insert(const Iterator& dest, const T* start, const T* end)
  386. {
  387. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  388. {
  389. i32 pos = (i32)(dest - Begin());
  390. assert(pos >= 0 && pos <= size_);
  391. i32 length = (i32)(end - start);
  392. Resize(size_ + length);
  393. MoveRange(pos + length, pos, size_ - pos - length);
  394. T* destPtr = Buffer() + pos;
  395. for (const T* i = start; i != end; ++i)
  396. *destPtr++ = *i;
  397. return Begin() + pos;
  398. }
  399. else
  400. {
  401. i32 pos = (i32)(dest - Begin());
  402. assert(pos >= 0 && pos <= size_);
  403. return DoInsertElements(pos, start, end, CopyTag{});
  404. }
  405. }
  406. /// Erase a range of elements.
  407. void Erase(i32 pos, i32 length = 1)
  408. {
  409. assert(pos >= 0 && length >= 0 && pos + length <= size_);
  410. if (!length)
  411. return;
  412. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  413. {
  414. MoveRange(pos, pos + length, size_ - pos - length);
  415. Resize(size_ - length);
  416. }
  417. else
  418. {
  419. DoEraseElements(pos, length);
  420. }
  421. }
  422. /// Erase a range of elements by swapping elements from the end of the array.
  423. void EraseSwap(i32 pos, i32 length = 1)
  424. {
  425. assert(pos >= 0 && length >= 1 && pos + length <= size_);
  426. i32 shiftStartIndex = pos + length;
  427. i32 newSize = size_ - length;
  428. i32 trailingCount = size_ - shiftStartIndex;
  429. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  430. {
  431. if (trailingCount <= length)
  432. {
  433. // We're removing more elements from the array than exist past the end of the range being removed, so perform a normal shift and destroy
  434. MoveRange(pos, shiftStartIndex, trailingCount);
  435. }
  436. else
  437. {
  438. // Swap elements from the end of the array into the empty space
  439. CopyElements(Buffer() + pos, Buffer() + newSize, length);
  440. }
  441. Resize(newSize);
  442. }
  443. else
  444. {
  445. if (trailingCount <= length)
  446. {
  447. // We're removing more elements from the array than exist past the end of the range being removed, so perform a normal shift and destroy
  448. DoEraseElements(pos, length);
  449. }
  450. else
  451. {
  452. // Swap elements from the end of the array into the empty space
  453. T* buffer = Buffer();
  454. std::move(buffer + newSize, buffer + size_, buffer + pos);
  455. Resize(newSize);
  456. }
  457. }
  458. }
  459. /// Erase an element by iterator. Return iterator to the next element.
  460. Iterator Erase(const Iterator& it)
  461. {
  462. i32 pos = (i32)(it - Begin());
  463. assert(pos >= 0 && pos <= size_);
  464. if (pos == size_)
  465. return End();
  466. Erase(pos);
  467. return Begin() + pos;
  468. }
  469. /// Erase a range by iterators. Return iterator to the next element.
  470. Iterator Erase(const Iterator& start, const Iterator& end)
  471. {
  472. i32 pos = (i32)(start - Begin());
  473. assert(pos >= 0 && pos <= size_);
  474. if (pos == size_)
  475. return End();
  476. i32 length = (i32)(end - start);
  477. Erase(pos, length);
  478. return Begin() + pos;
  479. }
  480. /// Erase an element by value. Return true if was found and erased.
  481. bool Remove(const T& value)
  482. {
  483. Iterator i = Find(value);
  484. if (i != End())
  485. {
  486. Erase(i);
  487. return true;
  488. }
  489. else
  490. {
  491. return false;
  492. }
  493. }
  494. /// Erase an element by value by swapping with the last element. Return true if was found and erased.
  495. bool RemoveSwap(const T& value)
  496. {
  497. Iterator i = Find(value);
  498. if (i != End())
  499. {
  500. EraseSwap(i - Begin());
  501. return true;
  502. }
  503. else
  504. {
  505. return false;
  506. }
  507. }
  508. /// Clear the vector.
  509. void Clear() { Resize(0); }
  510. /// Resize the vector.
  511. void Resize(i32 newSize)
  512. {
  513. assert(newSize >= 0);
  514. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  515. {
  516. if (newSize > capacity_)
  517. {
  518. if (!capacity_)
  519. capacity_ = newSize;
  520. else
  521. {
  522. while (capacity_ < newSize)
  523. capacity_ += (capacity_ + 1) >> 1;
  524. }
  525. u8* newBuffer = AllocateBuffer((i32)(capacity_ * sizeof(T)));
  526. // Move the data into the new buffer and delete the old
  527. if (buffer_)
  528. {
  529. CopyElements(reinterpret_cast<T*>(newBuffer), Buffer(), size_);
  530. delete[] buffer_;
  531. }
  532. buffer_ = newBuffer;
  533. }
  534. size_ = newSize;
  535. }
  536. else
  537. {
  538. DoResize(newSize);
  539. }
  540. }
  541. /// Resize the vector and fill new elements with default value.
  542. void Resize(i32 newSize, const T& value)
  543. {
  544. assert(newSize >= 0);
  545. i32 oldSize = Size();
  546. Resize(newSize);
  547. for (i32 i = oldSize; i < newSize; ++i)
  548. At(i) = value;
  549. }
  550. /// Set new capacity.
  551. void Reserve(i32 newCapacity)
  552. {
  553. assert(newCapacity >= 0);
  554. if (newCapacity < size_)
  555. newCapacity = size_;
  556. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  557. {
  558. if (newCapacity != capacity_)
  559. {
  560. u8* newBuffer = nullptr;
  561. capacity_ = newCapacity;
  562. if (capacity_)
  563. {
  564. newBuffer = AllocateBuffer((i32)(capacity_ * sizeof(T)));
  565. // Move the data into the new buffer
  566. CopyElements(reinterpret_cast<T*>(newBuffer), Buffer(), size_);
  567. }
  568. // Delete the old buffer
  569. delete[] buffer_;
  570. buffer_ = newBuffer;
  571. }
  572. }
  573. else
  574. {
  575. if (newCapacity != capacity_)
  576. {
  577. T* newBuffer = nullptr;
  578. capacity_ = newCapacity;
  579. if (capacity_)
  580. {
  581. newBuffer = reinterpret_cast<T*>(AllocateBuffer((i32)(capacity_ * sizeof(T))));
  582. // Move the data into the new buffer
  583. ConstructElements(newBuffer, Begin(), End(), MoveTag{});
  584. }
  585. // Delete the old buffer
  586. DestructElements(Buffer(), size_);
  587. delete[] buffer_;
  588. buffer_ = reinterpret_cast<u8*>(newBuffer);
  589. }
  590. }
  591. }
  592. /// Reallocate so that no extra memory is used.
  593. void Compact() { Reserve(size_); }
  594. /// Return iterator to value, or to the end if not found.
  595. Iterator Find(const T& value)
  596. {
  597. Iterator it = Begin();
  598. while (it != End() && *it != value)
  599. ++it;
  600. return it;
  601. }
  602. /// Return const iterator to value, or to the end if not found.
  603. ConstIterator Find(const T& value) const
  604. {
  605. ConstIterator it = Begin();
  606. while (it != End() && *it != value)
  607. ++it;
  608. return it;
  609. }
  610. /// Return index of value in vector, or size if not found.
  611. i32 IndexOf(const T& value) const
  612. {
  613. return Find(value) - Begin();
  614. }
  615. /// Return whether contains a specific value.
  616. bool Contains(const T& value) const { return Find(value) != End(); }
  617. /// Return iterator to the beginning.
  618. Iterator Begin() { return Iterator(Buffer()); }
  619. /// Return const iterator to the beginning.
  620. ConstIterator Begin() const { return ConstIterator(Buffer()); }
  621. /// Return iterator to the end.
  622. Iterator End() { return Iterator(Buffer() + size_); }
  623. /// Return const iterator to the end.
  624. ConstIterator End() const { return ConstIterator(Buffer() + size_); }
  625. /// Return first element.
  626. T& Front()
  627. {
  628. assert(size_);
  629. return Buffer()[0];
  630. }
  631. /// Return const first element.
  632. const T& Front() const
  633. {
  634. assert(size_);
  635. return Buffer()[0];
  636. }
  637. /// Return last element.
  638. T& Back()
  639. {
  640. assert(size_);
  641. return Buffer()[size_ - 1];
  642. }
  643. /// Return const last element.
  644. const T& Back() const
  645. {
  646. assert(size_);
  647. return Buffer()[size_ - 1];
  648. }
  649. /// Return number of elements.
  650. i32 Size() const { return size_; }
  651. /// Return capacity of vector.
  652. i32 Capacity() const { return capacity_; }
  653. /// Return whether vector is empty.
  654. bool Empty() const { return size_ == 0; }
  655. /// Return the buffer with right type.
  656. T* Buffer() const { return reinterpret_cast<T*>(buffer_); }
  657. private:
  658. /// Construct elements using default ctor.
  659. static void ConstructElements(T* dest, i32 count)
  660. {
  661. assert(count >= 0);
  662. for (i32 i = 0; i < count; ++i)
  663. new(dest + i) T();
  664. }
  665. /// Copy-construct elements.
  666. template <class RandomIteratorT>
  667. static void ConstructElements(T* dest, RandomIteratorT start, RandomIteratorT end, CopyTag)
  668. {
  669. const i32 count = (i32)(end - start);
  670. assert(count > 0);
  671. for (i32 i = 0; i < count; ++i)
  672. new(dest + i) T(*(start + i));
  673. }
  674. /// Move-construct elements.
  675. template <class RandomIteratorT>
  676. static void ConstructElements(T* dest, RandomIteratorT start, RandomIteratorT end, MoveTag)
  677. {
  678. const i32 count = (i32)(end - start);
  679. assert(count >= 0);
  680. for (i32 i = 0; i < count; ++i)
  681. new(dest + i) T(std::move(*(start + i)));
  682. }
  683. /// Calculate new vector capacity.
  684. static i32 CalculateCapacity(i32 size, i32 capacity)
  685. {
  686. assert(size > 0 && capacity >= 0);
  687. if (!capacity)
  688. {
  689. return size;
  690. }
  691. else
  692. {
  693. while (capacity < size)
  694. capacity += (capacity + 1) >> 1; // += (capacity * 0.5 and round up)
  695. return capacity;
  696. }
  697. }
  698. /// Resize the vector and create/remove new elements as necessary.
  699. void DoResize(i32 newSize)
  700. {
  701. assert(newSize >= 0);
  702. // If size shrinks, destruct the removed elements
  703. if (newSize < size_)
  704. {
  705. DestructElements(Buffer() + newSize, size_ - newSize);
  706. }
  707. else
  708. {
  709. // Allocate new buffer if necessary and copy the current elements
  710. if (newSize > capacity_)
  711. {
  712. T* src = Buffer();
  713. // Reallocate vector
  714. Vector<T> newVector;
  715. newVector.Reserve(CalculateCapacity(newSize, capacity_));
  716. newVector.size_ = size_;
  717. T* dest = newVector.Buffer();
  718. // Move old elements
  719. ConstructElements(dest, src, src + size_, MoveTag{});
  720. Swap(newVector);
  721. }
  722. // Initialize the new elements
  723. ConstructElements(Buffer() + size_, newSize - size_);
  724. }
  725. size_ = newSize;
  726. }
  727. /// Insert elements into the vector using copy or move constructor.
  728. /// If pos is ENDPOS, append the new elements at the end.
  729. template <class Tag, class RandomIteratorT>
  730. Iterator DoInsertElements(i32 pos, RandomIteratorT start, RandomIteratorT end, Tag)
  731. {
  732. assert((pos >= 0 && pos <= size_) || pos == ENDPOS);
  733. if (pos == ENDPOS)
  734. pos = size_;
  735. const i32 numElements = (i32)(end - start);
  736. if (size_ + numElements > capacity_)
  737. {
  738. T* src = Buffer();
  739. // Reallocate vector
  740. Vector<T> newVector;
  741. newVector.Reserve(CalculateCapacity(size_ + numElements, capacity_));
  742. newVector.size_ = size_ + numElements;
  743. T* dest = newVector.Buffer();
  744. // Copy or move new elements
  745. ConstructElements(dest + pos, start, end, Tag{});
  746. // Move old elements
  747. if (pos > 0)
  748. ConstructElements(dest, src, src + pos, MoveTag{});
  749. if (pos < size_)
  750. ConstructElements(dest + pos + numElements, src + pos, src + size_, MoveTag{});
  751. Swap(newVector);
  752. }
  753. else if (numElements > 0)
  754. {
  755. T* buffer = Buffer();
  756. // Copy or move new elements
  757. ConstructElements(buffer + size_, start, end, Tag{});
  758. // Rotate buffer
  759. if (pos < size_)
  760. {
  761. std::rotate(buffer + pos, buffer + size_, buffer + size_ + numElements);
  762. }
  763. // Update size
  764. size_ += numElements;
  765. }
  766. return Begin() + pos;
  767. }
  768. /// Erase elements from the vector.
  769. Iterator DoEraseElements(i32 pos, i32 count)
  770. {
  771. assert(pos >= 0 && count > 0 && pos + count <= size_);
  772. T* buffer = Buffer();
  773. std::move(buffer + pos + count, buffer + size_, buffer + pos);
  774. Resize(size_ - count);
  775. return Begin() + pos;
  776. }
  777. /// Call the elements' destructors.
  778. static void DestructElements(T* dest, i32 count)
  779. {
  780. assert(count >= 0);
  781. while (count--)
  782. {
  783. dest->~T();
  784. ++dest;
  785. }
  786. }
  787. /// Move a range of elements within the vector. Only for POD Vector.
  788. void MoveRange(i32 dest, i32 src, i32 count)
  789. {
  790. assert(dest >= 0 && src >= 0 && count >= 0);
  791. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  792. {
  793. if (count)
  794. memmove(Buffer() + dest, Buffer() + src, count * sizeof(T));
  795. }
  796. else
  797. {
  798. // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2593r0.html
  799. static_assert(always_false<T>); // static_assert(false);
  800. }
  801. }
  802. /// Copy elements from one buffer to another. Only for POD Vector.
  803. static void CopyElements(T* dest, const T* src, i32 count)
  804. {
  805. assert(count >= 0);
  806. if constexpr (std::is_trivial<T>::value && std::is_standard_layout<T>::value)
  807. {
  808. if (count)
  809. memcpy(dest, src, count * sizeof(T));
  810. }
  811. else
  812. {
  813. // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2593r0.html
  814. static_assert(always_false<T>); // static_assert(false);
  815. }
  816. }
  817. };
  818. template <class T> typename Urho3D::Vector<T>::ConstIterator begin(const Urho3D::Vector<T>& v) { return v.Begin(); }
  819. template <class T> typename Urho3D::Vector<T>::ConstIterator end(const Urho3D::Vector<T>& v) { return v.End(); }
  820. template <class T> typename Urho3D::Vector<T>::Iterator begin(Urho3D::Vector<T>& v) { return v.Begin(); }
  821. template <class T> typename Urho3D::Vector<T>::Iterator end(Urho3D::Vector<T>& v) { return v.End(); }
  822. }