cesium-native 0.43.0
Loading...
Searching...
No Matches
DoublyLinkedList.h
1#pragma once
2
3#include <cstddef>
4
5namespace CesiumUtility {
6
11template <class T> class DoublyLinkedListPointers final {
12public:
16 DoublyLinkedListPointers() noexcept : pNext(nullptr), pPrevious(nullptr) {}
17
23 // Following the example of boost::instrusive::list's list_member_hook, the
24 // copy constructor and assignment operator do nothing.
25 // https://www.boost.org/doc/libs/1_73_0/doc/html/boost/intrusive/list_member_hook.html
27 [[maybe_unused]] DoublyLinkedListPointers& rhs) noexcept
29
34 operator=(const DoublyLinkedListPointers& /*rhs*/) noexcept {
35 return *this;
36 }
37
38private:
39 template <
40 typename TElement,
41 typename TElementBase,
42 DoublyLinkedListPointers<TElement>(TElementBase::*Pointers)>
43 friend class DoublyLinkedListAdvanced;
44
45 T* pNext;
46 T* pPrevious;
47};
48
59template <
60 typename T,
61 typename TPointerBase,
62 DoublyLinkedListPointers<T>(TPointerBase::*Pointers)>
64public:
68 void remove(T& node) noexcept {
69 DoublyLinkedListPointers<T>& nodePointers = node.*Pointers;
70
71 if (nodePointers.pPrevious) {
72 DoublyLinkedListPointers<T>& previousPointers =
73 nodePointers.pPrevious->*Pointers;
74 previousPointers.pNext = nodePointers.pNext;
75 --this->_size;
76 } else if (this->_pHead == &node) {
77 this->_pHead = nodePointers.pNext;
78 --this->_size;
79 }
80
81 if (nodePointers.pNext) {
82 DoublyLinkedListPointers<T>& nextPointers = nodePointers.pNext->*Pointers;
83 nextPointers.pPrevious = nodePointers.pPrevious;
84 } else if (this->_pTail == &node) {
85 this->_pTail = nodePointers.pPrevious;
86 }
87
88 nodePointers.pPrevious = nullptr;
89 nodePointers.pNext = nullptr;
90 }
91
95 void insertAfter(T& after, T& node) noexcept {
96 this->remove(node);
97
98 DoublyLinkedListPointers<T>& afterPointers = after.*Pointers;
99 DoublyLinkedListPointers<T>& nodePointers = node.*Pointers;
100
101 nodePointers.pPrevious = &after;
102 nodePointers.pNext = afterPointers.pNext;
103 afterPointers.pNext = &node;
104
105 if (nodePointers.pNext) {
106 DoublyLinkedListPointers<T>& nextPointers = nodePointers.pNext->*Pointers;
107 nextPointers.pPrevious = &node;
108 }
109
110 if (this->_pTail == &after) {
111 this->_pTail = &node;
112 }
113
114 ++this->_size;
115 }
116
120 void insertBefore(T& before, T& node) noexcept {
121 this->remove(node);
122
123 DoublyLinkedListPointers<T>& beforePointers = before.*Pointers;
124 DoublyLinkedListPointers<T>& nodePointers = node.*Pointers;
125
126 nodePointers.pPrevious = beforePointers.pPrevious;
127 nodePointers.pNext = &before;
128 beforePointers.pPrevious = &node;
129
130 if (nodePointers.pPrevious) {
131 DoublyLinkedListPointers<T>& previousPointers =
132 nodePointers.pPrevious->*Pointers;
133 previousPointers.pNext = &node;
134 }
135
136 if (this->_pHead == &before) {
137 this->_pHead = &node;
138 }
139
140 ++this->_size;
141 }
142
146 void insertAtHead(T& node) noexcept {
147 this->remove(node);
148
149 if (this->_pHead) {
150 (this->_pHead->*Pointers).pPrevious = &node;
151 (node.*Pointers).pNext = this->_pHead;
152 } else {
153 this->_pTail = &node;
154 }
155 this->_pHead = &node;
156
157 ++this->_size;
158 }
159
163 void insertAtTail(T& node) noexcept {
164 this->remove(node);
165
166 if (this->_pTail) {
167 (this->_pTail->*Pointers).pNext = &node;
168 (node.*Pointers).pPrevious = this->_pTail;
169 } else {
170 this->_pHead = &node;
171 }
172 this->_pTail = &node;
173
174 ++this->_size;
175 }
176
180 size_t size() const noexcept { return this->_size; }
181
186 T* head() noexcept { return this->_pHead; }
187
189 const T* head() const noexcept { return this->_pHead; }
190
195 T* tail() noexcept { return this->_pTail; }
196
198 const T* tail() const noexcept { return this->_pTail; }
199
204 T* next(T& node) noexcept { return (node.*Pointers).pNext; }
205
207 const T* next(const T& node) const noexcept { return (node.*Pointers).pNext; }
208
213 T* next(T* pNode) noexcept {
214 return pNode ? this->next(*pNode) : this->_pHead;
215 }
216
218 const T* next(const T* pNode) const noexcept {
219 return pNode ? this->next(*pNode) : this->_pHead;
220 }
221
226 T* previous(T& node) noexcept { return (node.*Pointers).pPrevious; }
227
229 const T* previous(const T& node) const noexcept {
230 return (node.*Pointers).pPrevious;
231 }
232
237 T* previous(T* pNode) {
238 return pNode ? this->previous(*pNode) : this->_pTail;
239 }
240
242 const T* previous(const T* pNode) const noexcept {
243 return pNode ? this->previous(*pNode) : this->_pTail;
244 }
245
257 bool contains(const T& node) const {
258 return this->next(node) != nullptr || this->previous(node) != nullptr ||
259 this->_pHead == &node;
260 }
261
262private:
263 size_t _size = 0;
264 T* _pHead = nullptr;
265 T* _pTail = nullptr;
266};
267
271template <typename T, DoublyLinkedListPointers<T>(T::*Pointers)>
273
274} // namespace CesiumUtility
void insertAtHead(T &node) noexcept
Insert the given node as the new head of the list.
void insertAfter(T &after, T &node) noexcept
Insert the given node after the other node.
const T * head() const noexcept
Returns the head node of this list, or nullptr if the list is empty.
void insertBefore(T &before, T &node) noexcept
Insert the given node before the other node.
size_t size() const noexcept
Returns the size of this list.
void remove(T &node) noexcept
Removes the given node from this list.
T * next(T *pNode) noexcept
Returns the next node after the given one, or the head if the given node is nullptr.
const T * previous(const T &node) const noexcept
Returns the previous node before the given one, or nullptr if the given node is the head.
T * head() noexcept
Returns the head node of this list, or nullptr if the list is empty.
const T * next(const T &node) const noexcept
Returns the next node after the given one, or nullptr if the given node is the tail.
T * previous(T &node) noexcept
Returns the previous node before the given one, or nullptr if the given node is the head.
const T * next(const T *pNode) const noexcept
Returns the next node after the given one, or the head if the given node is nullptr.
const T * previous(const T *pNode) const noexcept
Returns the previous node before the given one, or the tail if the given node is nullptr.
const T * tail() const noexcept
Returns the tail node of this list, or nullptr if the list is empty.
bool contains(const T &node) const
Determines if this list contains a given node in constant time. In order to avoid a full list scan,...
T * next(T &node) noexcept
Returns the next node after the given one, or nullptr if the given node is the tail.
T * tail() noexcept
Returns the tail node of this list, or nullptr if the list is empty.
void insertAtTail(T &node) noexcept
Insert the given node as the new tail of the list.
T * previous(T *pNode)
Returns the previous node before the given one, or the tail if the given node is nullptr.
Contains the previous and next pointers for an element in a DoublyLinkedList.
DoublyLinkedListPointers(DoublyLinkedListPointers &rhs) noexcept
Copy constructor.
DoublyLinkedListPointers & operator=(const DoublyLinkedListPointers &) noexcept
Assignment operator.
DoublyLinkedListPointers() noexcept
Default constructor.
Utility classes for Cesium.