CommonLibSSE (Parapets fork)
BSTList.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "RE/M/MemoryManager.h"
4 
5 namespace RE
6 {
7  template <class T>
8  class BSTListNode
9  {
10  public:
11  using value_type = T;
12 
13  template <class... Args>
14  inline BSTListNode(Args&&... a_args) :
15  item(std::forward<Args>(a_args)...)
16  {}
17 
18  // members
22  };
23 
24  template <class T>
26  {
27  public:
28  [[nodiscard]] inline BSTListNode<T>* allocate()
29  {
30  return malloc<BSTListNode<T>>();
31  }
32 
33  inline void deallocate(BSTListNode<T>* a_node)
34  {
35  free(a_node);
36  }
37  };
38 
39  template <class T, class Allocator = BSTListHeapAllocator<T>>
40  class BSTList
41  {
42  public:
43  using value_type = T;
44  using allocator_type = Allocator;
45  using reference = T&;
46  using const_reference = const T&;
47 
49  {
50  public:
51  using value_type = T;
52  using const_pointer = const T*;
53  using iterator_category = std::bidirectional_iterator_tag;
54 
56 
57  const_iterator(BSTListNode<T>* a_node) noexcept :
58  _cur(a_node)
59  {}
60 
61  constexpr const_iterator(const const_iterator& a_rhs) noexcept :
62  _cur(a_rhs._cur)
63  {}
64 
65  constexpr const_iterator(const const_iterator&& a_rhs) noexcept :
66  _cur(a_rhs._cur)
67  {
68  a_rhs._cur = nullptr;
69  }
70 
71  constexpr const_iterator& operator=(const const_iterator& a_rhs) noexcept
72  {
73  if (this != std::addressof(a_rhs)) {
74  _cur = a_rhs._cur;
75  }
76  return *this;
77  }
78 
79  constexpr const_iterator& operator=(const_iterator&& a_rhs) noexcept
80  {
81  if (this != std::addressof(a_rhs)) {
82  _cur = std::move(a_rhs._cur);
83  a_rhs._cur = nullptr;
84  }
85  return *this;
86  }
87 
88  [[nodiscard]] constexpr const_reference operator*() const noexcept { return _cur->item; }
89  [[nodiscard]] constexpr const_pointer operator->() const noexcept { return std::addressof(_cur->item); }
90 
91  [[nodiscard]] constexpr bool operator==(const const_iterator& a_rhs) const noexcept { return _cur == a_rhs._cur; }
92  [[nodiscard]] constexpr bool operator!=(const const_iterator& a_rhs) const noexcept { return !(*this == a_rhs); }
93 
94  // prefix
95  constexpr const_iterator& operator++() noexcept
96  {
97  assert(_cur);
98  _cur = _cur->next;
99  return *this;
100  }
101 
102  // postfix
103  [[nodiscard]] constexpr const_iterator operator++(int) noexcept
104  {
105  const_iterator tmp(*this);
106  ++(*this);
107  return tmp;
108  }
109 
110  // prefix
111  constexpr const_iterator& operator--() noexcept
112  {
113  assert(_cur);
114  _cur = _cur->prev;
115  return *this;
116  }
117 
118  // postfix
119  [[nodiscard]] constexpr const_iterator operator--(int) noexcept
120  {
121  const_iterator tmp(*this);
122  --(*this);
123  return tmp;
124  }
125 
126  protected:
128  };
129 
130  struct iterator : public const_iterator
131  {
132  public:
133  using pointer = T*;
134 
136 
137  [[nodiscard]] constexpr reference operator*() const noexcept { return const_iterator::_cur->item; }
138  [[nodiscard]] constexpr pointer operator->() const noexcept { return std::addressof(const_iterator::_cur->item); }
139 
140  // prefix
141  constexpr iterator& operator++() noexcept
142  {
144  return *this;
145  }
146 
147  // postfix
148  [[nodiscard]] constexpr iterator operator++(int) noexcept
149  {
150  iterator tmp(*this);
152  return tmp;
153  }
154 
155  // prefix
156  constexpr iterator& operator--() noexcept
157  {
159  return *this;
160  }
161 
162  // postfix
163  [[nodiscard]] constexpr iterator operator--(int) noexcept
164  {
165  iterator tmp(*this);
167  return tmp;
168  }
169  };
170 
171  constexpr BSTList() :
172  _sentinel(nullptr)
173  {}
174 
175  BSTList(const BSTList&) = delete;
176  BSTList(BSTList&&) = delete;
177 
178  inline ~BSTList()
179  {
180  clear();
181  if (_sentinel) {
182  destroy_list();
183  }
184  }
185 
186  BSTList& operator=(const BSTList&) = delete;
187  BSTList& operator=(BSTList&&) = delete;
188 
189  inline reference front()
190  {
191  return _sentinel->next->item;
192  }
193 
194  inline const_reference front() const
195  {
196  return _sentinel->next->item;
197  }
198 
199  inline reference back()
200  {
201  return _sentinel->prev->item;
202  }
203 
204  inline const_reference back() const
205  {
206  return _sentinel->prev->item;
207  }
208 
209  inline iterator begin()
210  {
211  return iterator(_sentinel ? _sentinel->next : nullptr);
212  }
213 
214  inline const_iterator begin() const
215  {
216  return const_iterator(_sentinel ? _sentinel->next : nullptr);
217  }
218 
219  inline const_iterator cbegin() const
220  {
221  return const_iterator(_sentinel ? _sentinel->next : nullptr);
222  }
223 
224  inline iterator end()
225  {
226  return iterator(_sentinel);
227  }
228 
229  inline const_iterator end() const
230  {
231  return const_iterator(_sentinel);
232  }
233 
234  inline const_iterator cend() const
235  {
236  return const_iterator(_sentinel);
237  }
238 
239  constexpr bool empty() const
240  {
241  return !_sentinel || _sentinel->next == _sentinel;
242  }
243 
244  inline void clear()
245  {
246  if (!_sentinel) {
247  return;
248  }
249 
250  for (auto node = _sentinel->next; node != _sentinel; node = node->next) {
251  std::destroy_at(node);
252  allocator_type{}.deallocate(node);
253  }
254 
255  destroy_list();
256  }
257 
258  template <class... Args>
259  inline iterator emplace(const_iterator a_pos, Args&&... a_args)
260  {
261  emplace_impl(a_pos, std::forward<Args>(a_args)...);
262  return a_pos._cur->prev;
263  }
264 
266  {
267  const auto node = a_pos._cur;
268  const auto next = node->next;
269  node->prev->next = next;
270  next->prev = node->prev;
271 
272  node->prev = nullptr;
273  node->next = nullptr;
274  allocator_type{}.deallocate(node);
275 
276  return iterator(next);
277  }
278 
279  inline void push_back(const T& a_value)
280  {
281  emplace_back(a_value);
282  }
283 
284  inline void push_back(T&& a_value)
285  {
286  emplace_back(std::move(a_value));
287  }
288 
289  template <class... Args>
290  inline reference emplace_back(Args&&... a_args)
291  {
292  emplace_back_impl(std::forward<Args>(a_args)...);
293  return back();
294  }
295 
296  inline void push_front(const T& a_value)
297  {
298  emplace_front(a_value);
299  }
300 
301  inline void push_front(T&& a_value)
302  {
303  emplace_front(std::move(a_value));
304  }
305 
306  template <class... Args>
307  inline reference emplace_front(Args&&... a_args)
308  {
309  emplace_front_impl(std::forward<Args>(a_args)...);
310  return front();
311  }
312 
313  private:
314  template <class... Args>
315  inline void emplace_impl(const_iterator a_pos, Args&&... a_args)
316  {
317  const auto node = allocator_type{}.allocate();
318  if (!node) {
319  return;
320  }
321 
322  std::construct_at(node, std::forward<Args>(a_args)...);
323  node->next = a_pos._cur;
324  node->prev = a_pos._cur->prev;
325  a_pos._cur->prev->next = node;
326  a_pos._cur->prev = node;
327  }
328 
329  template <class... Args>
330  inline void emplace_back_impl(Args&&... a_args)
331  {
332  if (!_sentinel) {
333  create_list();
334  }
335 
336  const auto node = allocator_type{}.allocate();
337  if (!node) {
338  return;
339  }
340 
341  std::construct_at(node, std::forward<Args>(a_args)...);
342  node->next = _sentinel;
343  node->prev = _sentinel->prev;
344  _sentinel->prev->next = node;
345  _sentinel->prev = node;
346  }
347 
348  template <class... Args>
349  inline void emplace_front_impl(Args&&... a_args)
350  {
351  if (!_sentinel) {
352  create_list();
353  }
354 
355  const auto node = allocator_type{}.allocate();
356  if (!node) {
357  return;
358  }
359 
360  std::construct_at(node, std::forward<Args>(a_args)...);
361  node->prev = _sentinel;
362  node->next = _sentinel->next;
363  _sentinel->next->prev = node;
364  _sentinel->next = node;
365  }
366 
367  inline bool create_list()
368  {
369  _sentinel = allocator_type{}.allocate();
370  if (_sentinel) {
371  _sentinel->next = _sentinel;
372  _sentinel->prev = _sentinel;
373  }
374  return _sentinel;
375  }
376 
377  inline void destroy_list()
378  {
379  allocator_type{}.deallocate(_sentinel);
380  _sentinel = nullptr;
381  }
382 
383  // members
384  BSTListNode<T>* _sentinel; // 0
385  };
386 }
Definition: BSTList.h:26
void deallocate(BSTListNode< T > *a_node)
Definition: BSTList.h:33
BSTListNode< T > * allocate()
Definition: BSTList.h:28
Definition: BSTList.h:9
value_type item
Definition: BSTList.h:21
T value_type
Definition: BSTList.h:11
BSTListNode(Args &&... a_args)
Definition: BSTList.h:14
BSTListNode< T > * next
Definition: BSTList.h:19
BSTListNode< T > * prev
Definition: BSTList.h:20
Definition: BSTList.h:41
reference emplace_front(Args &&... a_args)
Definition: BSTList.h:307
const_iterator cend() const
Definition: BSTList.h:234
reference emplace_back(Args &&... a_args)
Definition: BSTList.h:290
void clear()
Definition: BSTList.h:244
BSTList & operator=(const BSTList &)=delete
reference back()
Definition: BSTList.h:199
void push_back(T &&a_value)
Definition: BSTList.h:284
constexpr bool empty() const
Definition: BSTList.h:239
void push_front(const T &a_value)
Definition: BSTList.h:296
constexpr BSTList()
Definition: BSTList.h:171
const T & const_reference
Definition: BSTList.h:46
T & reference
Definition: BSTList.h:45
Allocator allocator_type
Definition: BSTList.h:44
const_reference back() const
Definition: BSTList.h:204
const_iterator cbegin() const
Definition: BSTList.h:219
reference front()
Definition: BSTList.h:189
const_iterator end() const
Definition: BSTList.h:229
const_iterator begin() const
Definition: BSTList.h:214
iterator erase(const_iterator a_pos)
Definition: BSTList.h:265
const_reference front() const
Definition: BSTList.h:194
BSTList(const BSTList &)=delete
iterator end()
Definition: BSTList.h:224
iterator emplace(const_iterator a_pos, Args &&... a_args)
Definition: BSTList.h:259
iterator begin()
Definition: BSTList.h:209
void push_back(const T &a_value)
Definition: BSTList.h:279
void push_front(T &&a_value)
Definition: BSTList.h:301
~BSTList()
Definition: BSTList.h:178
T value_type
Definition: BSTList.h:43
BSTList & operator=(BSTList &&)=delete
BSTList(BSTList &&)=delete
Definition: AbsorbEffect.h:6
void free(void *a_ptr)
T observer
Definition: PCH.h:92
Definition: NiBinaryStream.h:94
Definition: BSTList.h:49
constexpr const_reference operator*() const noexcept
Definition: BSTList.h:88
constexpr const_iterator & operator=(const const_iterator &a_rhs) noexcept
Definition: BSTList.h:71
constexpr const_iterator & operator--() noexcept
Definition: BSTList.h:111
std::bidirectional_iterator_tag iterator_category
Definition: BSTList.h:53
constexpr bool operator!=(const const_iterator &a_rhs) const noexcept
Definition: BSTList.h:92
T value_type
Definition: BSTList.h:51
constexpr const_iterator operator++(int) noexcept
Definition: BSTList.h:103
constexpr const_iterator & operator++() noexcept
Definition: BSTList.h:95
constexpr const_iterator(const const_iterator &&a_rhs) noexcept
Definition: BSTList.h:65
constexpr const_iterator operator--(int) noexcept
Definition: BSTList.h:119
stl::observer< BSTListNode< T > * > _cur
Definition: BSTList.h:127
const_iterator(BSTListNode< T > *a_node) noexcept
Definition: BSTList.h:57
constexpr const_iterator(const const_iterator &a_rhs) noexcept
Definition: BSTList.h:61
constexpr bool operator==(const const_iterator &a_rhs) const noexcept
Definition: BSTList.h:91
constexpr const_iterator & operator=(const_iterator &&a_rhs) noexcept
Definition: BSTList.h:79
constexpr const_pointer operator->() const noexcept
Definition: BSTList.h:89
const T * const_pointer
Definition: BSTList.h:52
Definition: BSTList.h:131
constexpr pointer operator->() const noexcept
Definition: BSTList.h:138
T * pointer
Definition: BSTList.h:133
constexpr iterator & operator++() noexcept
Definition: BSTList.h:141
constexpr iterator operator++(int) noexcept
Definition: BSTList.h:148
constexpr iterator & operator--() noexcept
Definition: BSTList.h:156
constexpr iterator operator--(int) noexcept
Definition: BSTList.h:163
constexpr reference operator*() const noexcept
Definition: BSTList.h:137