List.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #pragma once
  4. #include "../Container/ListBase.h"
  5. #include <initializer_list>
  6. namespace Urho3D
  7. {
  8. /// Doubly-linked list template class.
  9. template <class T> class List : public ListBase
  10. {
  11. public:
  12. /// %List node.
  13. struct Node : public ListNodeBase
  14. {
  15. /// Construct undefined.
  16. Node() = default;
  17. /// Construct with value.
  18. explicit Node(const T& value) :
  19. value_(value)
  20. {
  21. }
  22. /// Node value.
  23. T value_;
  24. /// Return next node.
  25. Node* Next() const { return static_cast<Node*>(next_); }
  26. /// Return previous node.
  27. Node* Prev() { return static_cast<Node*>(prev_); }
  28. };
  29. /// %List iterator.
  30. struct Iterator : public ListIteratorBase
  31. {
  32. /// Construct.
  33. Iterator() = default;
  34. /// Construct with a node pointer.
  35. explicit Iterator(Node* ptr) :
  36. ListIteratorBase(ptr)
  37. {
  38. }
  39. /// Preincrement the pointer.
  40. Iterator& operator ++()
  41. {
  42. GotoNext();
  43. return *this;
  44. }
  45. /// Postincrement the pointer.
  46. Iterator operator ++(int)
  47. {
  48. Iterator it = *this;
  49. GotoNext();
  50. return it;
  51. }
  52. /// Predecrement the pointer.
  53. Iterator& operator --()
  54. {
  55. GotoPrev();
  56. return *this;
  57. }
  58. /// Postdecrement the pointer.
  59. Iterator operator --(int)
  60. {
  61. Iterator it = *this;
  62. GotoPrev();
  63. return it;
  64. }
  65. /// Point to the node value.
  66. T* operator ->() const { return &(static_cast<Node*>(ptr_))->value_; }
  67. /// Dereference the node value.
  68. T& operator *() const { return (static_cast<Node*>(ptr_))->value_; }
  69. };
  70. /// %List const iterator.
  71. struct ConstIterator : public ListIteratorBase
  72. {
  73. /// Construct.
  74. ConstIterator() = default;
  75. /// Construct with a node pointer.
  76. explicit ConstIterator(Node* ptr) :
  77. ListIteratorBase(ptr)
  78. {
  79. }
  80. /// Construct from a non-const iterator.
  81. ConstIterator(const Iterator& rhs) : // NOLINT(google-explicit-constructor)
  82. ListIteratorBase(rhs.ptr_)
  83. {
  84. }
  85. /// Assign from a non-const iterator.
  86. ConstIterator& operator =(const Iterator& rhs)
  87. {
  88. ptr_ = rhs.ptr_;
  89. return *this;
  90. }
  91. /// Preincrement the pointer.
  92. ConstIterator& operator ++()
  93. {
  94. GotoNext();
  95. return *this;
  96. }
  97. /// Postincrement the pointer.
  98. ConstIterator operator ++(int)
  99. {
  100. ConstIterator it = *this;
  101. GotoNext();
  102. return it;
  103. }
  104. /// Predecrement the pointer.
  105. ConstIterator& operator --()
  106. {
  107. GotoPrev();
  108. return *this;
  109. }
  110. /// Postdecrement the pointer.
  111. ConstIterator operator --(int)
  112. {
  113. ConstIterator it = *this;
  114. GotoPrev();
  115. return it;
  116. }
  117. /// Point to the node value.
  118. const T* operator ->() const { return &(static_cast<Node*>(ptr_))->value_; }
  119. /// Dereference the node value.
  120. const T& operator *() const { return (static_cast<Node*>(ptr_))->value_; }
  121. };
  122. /// Construct empty.
  123. List()
  124. {
  125. allocator_ = AllocatorInitialize((i32)sizeof(Node));
  126. head_ = tail_ = ReserveNode();
  127. }
  128. /// Construct from another list.
  129. List(const List<T>& list)
  130. {
  131. // Reserve the tail node + initial capacity according to the list's size
  132. allocator_ = AllocatorInitialize((i32)sizeof(Node), list.Size() + 1);
  133. head_ = tail_ = ReserveNode();
  134. *this = list;
  135. }
  136. /// Move-construct from another list.
  137. List(List<T>&& list) noexcept
  138. {
  139. Swap(list);
  140. }
  141. /// Aggregate initialization constructor.
  142. List(const std::initializer_list<T>& list) : List()
  143. {
  144. for (auto it = list.begin(); it != list.end(); it++)
  145. {
  146. Push(*it);
  147. }
  148. }
  149. /// Destruct.
  150. ~List()
  151. {
  152. Clear();
  153. FreeNode(Tail());
  154. AllocatorUninitialize(allocator_);
  155. }
  156. /// Assign from another list.
  157. List& operator =(const List<T>& rhs)
  158. {
  159. // Clear, then insert the nodes of the other list. In case of self-assignment do nothing
  160. if (&rhs != this)
  161. {
  162. Clear();
  163. Insert(End(), rhs);
  164. }
  165. return *this;
  166. }
  167. /// Move-assign from another list.
  168. List& operator =(List<T>&& rhs) noexcept
  169. {
  170. Swap(rhs);
  171. return *this;
  172. }
  173. /// Add-assign an element.
  174. List& operator +=(const T& rhs)
  175. {
  176. Push(rhs);
  177. return *this;
  178. }
  179. /// Add-assign a list.
  180. List& operator +=(const List<T>& rhs)
  181. {
  182. Insert(End(), rhs);
  183. return *this;
  184. }
  185. /// Test for equality with another list.
  186. bool operator ==(const List<T>& rhs) const
  187. {
  188. if (rhs.size_ != size_)
  189. return false;
  190. ConstIterator i = Begin();
  191. ConstIterator j = rhs.Begin();
  192. while (i != End())
  193. {
  194. if (*i != *j)
  195. return false;
  196. ++i;
  197. ++j;
  198. }
  199. return true;
  200. }
  201. /// Test for inequality with another list.
  202. bool operator !=(const List<T>& rhs) const
  203. {
  204. if (rhs.size_ != size_)
  205. return true;
  206. ConstIterator i = Begin();
  207. ConstIterator j = rhs.Begin();
  208. while (i != End())
  209. {
  210. if (*i != *j)
  211. return true;
  212. ++i;
  213. ++j;
  214. }
  215. return false;
  216. }
  217. /// Insert an element to the end.
  218. void Push(const T& value) { InsertNode(Tail(), value); }
  219. /// Insert an element to the beginning.
  220. void PushFront(const T& value) { InsertNode(Head(), value); }
  221. /// Insert an element at position.
  222. void Insert(const Iterator& dest, const T& value) { InsertNode(static_cast<Node*>(dest.ptr_), value); }
  223. /// Insert a list at position.
  224. void Insert(const Iterator& dest, const List<T>& list)
  225. {
  226. auto* destNode = static_cast<Node*>(dest.ptr_);
  227. ConstIterator it = list.Begin();
  228. ConstIterator end = list.End();
  229. while (it != end)
  230. InsertNode(destNode, *it++);
  231. }
  232. /// Insert elements by iterators.
  233. void Insert(const Iterator& dest, const ConstIterator& start, const ConstIterator& end)
  234. {
  235. auto* destNode = static_cast<Node*>(dest.ptr_);
  236. ConstIterator it = start;
  237. while (it != end)
  238. InsertNode(destNode, *it++);
  239. }
  240. /// Insert elements.
  241. void Insert(const Iterator& dest, const T* start, const T* end)
  242. {
  243. auto* destNode = static_cast<Node*>(dest.ptr_);
  244. const T* ptr = start;
  245. while (ptr != end)
  246. InsertNode(destNode, *ptr++);
  247. }
  248. /// Erase the last element.
  249. void Pop()
  250. {
  251. if (size_)
  252. Erase(--End());
  253. }
  254. /// Erase the first element.
  255. void PopFront()
  256. {
  257. if (size_)
  258. Erase(Begin());
  259. }
  260. /// Erase an element by iterator. Return iterator to the next element.
  261. Iterator Erase(Iterator it)
  262. {
  263. return Iterator(EraseNode(static_cast<Node*>(it.ptr_)));
  264. }
  265. /// Erase a range by iterators. Return an iterator to the next element.
  266. Iterator Erase(const Iterator& start, const Iterator& end)
  267. {
  268. Iterator it = start;
  269. while (it != end)
  270. it = Erase(it);
  271. return it;
  272. }
  273. /// Clear the list.
  274. void Clear()
  275. {
  276. if (Size())
  277. {
  278. for (Iterator i = Begin(); i != End();)
  279. {
  280. FreeNode(static_cast<Node*>(i++.ptr_));
  281. i.ptr_->prev_ = 0;
  282. }
  283. head_ = tail_;
  284. size_ = 0;
  285. }
  286. }
  287. /// Resize the list by removing or adding items at the end.
  288. void Resize(i32 newSize)
  289. {
  290. while (size_ > newSize)
  291. Pop();
  292. while (size_ < newSize)
  293. InsertNode(Tail(), T());
  294. }
  295. /// Return iterator to value, or to the end if not found.
  296. Iterator Find(const T& value)
  297. {
  298. Iterator it = Begin();
  299. while (it != End() && *it != value)
  300. ++it;
  301. return it;
  302. }
  303. /// Return const iterator to value, or to the end if not found.
  304. ConstIterator Find(const T& value) const
  305. {
  306. ConstIterator it = Begin();
  307. while (it != End() && *it != value)
  308. ++it;
  309. return it;
  310. }
  311. /// Return whether contains a specific value.
  312. bool Contains(const T& value) const { return Find(value) != End(); }
  313. /// Return iterator to the first element.
  314. Iterator Begin() { return Iterator(Head()); }
  315. /// Return iterator to the first element.
  316. ConstIterator Begin() const { return ConstIterator(Head()); }
  317. /// Return iterator to the end.
  318. Iterator End() { return Iterator(Tail()); }
  319. /// Return iterator to the end.
  320. ConstIterator End() const { return ConstIterator(Tail()); }
  321. /// Return first element.
  322. T& Front() { return *Begin(); }
  323. /// Return const first element.
  324. const T& Front() const { return *Begin(); }
  325. /// Return last element.
  326. T& Back() { return *(--End()); }
  327. /// Return const last element.
  328. const T& Back() const { return *(--End()); }
  329. /// Return number of elements.
  330. i32 Size() const { return size_; }
  331. /// Return whether list is empty.
  332. bool Empty() const { return size_ == 0; }
  333. private:
  334. /// Return the head node.
  335. Node* Head() const { return static_cast<Node*>(head_); }
  336. /// Return the tail node.
  337. Node* Tail() const { return static_cast<Node*>(tail_); }
  338. /// Allocate and insert a node into the list.
  339. void InsertNode(Node* dest, const T& value)
  340. {
  341. if (!dest)
  342. return;
  343. Node* newNode = ReserveNode(value);
  344. Node* prev = dest->Prev();
  345. newNode->next_ = dest;
  346. newNode->prev_ = prev;
  347. if (prev)
  348. prev->next_ = newNode;
  349. dest->prev_ = newNode;
  350. // Reassign the head node if necessary
  351. if (dest == Head())
  352. head_ = newNode;
  353. ++size_;
  354. }
  355. /// Erase and free a node. Return pointer to the next node, or to the end if could not erase.
  356. Node* EraseNode(Node* node)
  357. {
  358. // The tail node can not be removed
  359. if (!node || node == tail_)
  360. return Tail();
  361. Node* prev = node->Prev();
  362. Node* next = node->Next();
  363. if (prev)
  364. prev->next_ = next;
  365. next->prev_ = prev;
  366. // Reassign the head node if necessary
  367. if (node == Head())
  368. head_ = next;
  369. FreeNode(node);
  370. --size_;
  371. return next;
  372. }
  373. /// Reserve a node.
  374. Node* ReserveNode()
  375. {
  376. auto* newNode = static_cast<Node*>(AllocatorReserve(allocator_));
  377. new(newNode) Node();
  378. return newNode;
  379. }
  380. /// Reserve a node with initial value.
  381. Node* ReserveNode(const T& value)
  382. {
  383. auto* newNode = static_cast<Node*>(AllocatorReserve(allocator_));
  384. new(newNode) Node(value);
  385. return newNode;
  386. }
  387. /// Free a node.
  388. void FreeNode(Node* node)
  389. {
  390. (node)->~Node();
  391. AllocatorFree(allocator_, node);
  392. }
  393. };
  394. template <class T> typename Urho3D::List<T>::ConstIterator begin(const Urho3D::List<T>& v) { return v.Begin(); }
  395. template <class T> typename Urho3D::List<T>::ConstIterator end(const Urho3D::List<T>& v) { return v.End(); }
  396. template <class T> typename Urho3D::List<T>::Iterator begin(Urho3D::List<T>& v) { return v.Begin(); }
  397. template <class T> typename Urho3D::List<T>::Iterator end(Urho3D::List<T>& v) { return v.End(); }
  398. }