CommonLibSSE NG
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  // forward list
8  template <class T>
10  {
11  public:
12  using value_type = T;
13  using size_type = std::uint32_t;
15  using const_reference = const value_type&;
16 
17  struct Node
18  {
19  public:
20  inline Node() :
21  item{},
22  next(nullptr)
23  {}
24 
25  inline Node(value_type a_value, Node* a_next) :
26  item(a_value),
27  next(a_next)
28  {}
29 
30  inline Node(const Node& a_rhs) :
31  item(a_rhs.item),
32  next(a_rhs.next)
33  {}
34 
35  inline Node(Node&& a_rhs) :
36  item(std::move(a_rhs.item)),
37  next(std::move(a_rhs.next))
38  {
39  a_rhs.next = nullptr;
40  }
41 
42  inline Node(const value_type& a_value) :
43  item(a_value),
44  next(nullptr)
45  {}
46 
47  inline Node(value_type&& a_value) :
48  item(std::move(a_value)),
49  next(nullptr)
50  {}
51 
52  ~Node() = default;
53 
54  inline Node& operator=(const Node& a_rhs)
55  {
56  if (this != std::addressof(a_rhs)) {
57  item = a_rhs.item;
58  next = a_rhs.next;
59  }
60  return *this;
61  }
62 
63  inline Node& operator=(Node&& a_rhs)
64  {
65  if (this != std::addressof(a_rhs)) {
66  item = std::move(a_rhs.item);
67 
68  next = std::move(a_rhs.next);
69  a_rhs.next = nullptr;
70  }
71  return *this;
72  }
73 
75 
76  // members
79  };
80 
81  template <class U>
83  {
84  public:
85  using difference_type = std::ptrdiff_t;
86  using value_type = U;
87  using pointer = U*;
88  using reference = U&;
89  using iterator_category = std::forward_iterator_tag;
90 
91  constexpr iterator_base() noexcept :
92  _cur(nullptr)
93  {}
94 
95  constexpr iterator_base(const iterator_base& a_rhs) noexcept :
96  _cur(a_rhs._cur)
97  {}
98 
99  constexpr iterator_base(iterator_base&& a_rhs) noexcept :
100  _cur(std::move(a_rhs._cur))
101  {
102  a_rhs._cur = nullptr;
103  }
104 
105  constexpr iterator_base(Node* a_node) noexcept :
106  _cur(a_node)
107  {}
108 
109  inline ~iterator_base() noexcept { _cur = nullptr; }
110 
111  constexpr iterator_base& operator=(const iterator_base& a_rhs) noexcept
112  {
113  if (this != std::addressof(a_rhs)) {
114  _cur = a_rhs._cur;
115  }
116  return *this;
117  }
118 
119  constexpr iterator_base& operator=(iterator_base&& a_rhs) noexcept
120  {
121  if (this != std::addressof(a_rhs)) {
122  _cur = std::move(a_rhs._cur);
123  a_rhs._cur = nullptr;
124  }
125  return *this;
126  }
127 
128  [[nodiscard]] constexpr reference operator*() const noexcept { return _cur->item; }
129  [[nodiscard]] constexpr pointer operator->() const noexcept { return std::addressof(_cur->item); }
130 
131  [[nodiscard]] constexpr bool operator==(const iterator_base& a_rhs) const noexcept { return _cur == a_rhs._cur; }
132  [[nodiscard]] constexpr bool operator!=(const iterator_base& a_rhs) const noexcept { return !(*this == a_rhs); }
133 
134  // prefix
135  constexpr iterator_base& operator++() noexcept
136  {
137  assert(_cur);
138  _cur = _cur->next;
139  return *this;
140  }
141 
142  // postfix
143  [[nodiscard]] constexpr iterator_base operator++(int) noexcept
144  {
145  iterator_base tmp(*this);
146  ++(*this);
147  return tmp;
148  }
149 
150  protected:
151  friend class BSSimpleList<T>;
152 
153  [[nodiscard]] constexpr Node* get_current() noexcept { return _cur; }
154  [[nodiscard]] constexpr const Node* get_current() const noexcept { return _cur; }
155 
156  [[nodiscard]] constexpr bool comes_before(const iterator_base& a_rhs) const noexcept
157  {
158  for (auto iter = _cur; iter; iter = iter->next) {
159  if (iter == a_rhs._cur) {
160  return true;
161  }
162  }
163  return false;
164  }
165 
166  private:
168  };
169 
172 
173  inline BSSimpleList() :
174  _listHead()
175  {}
176 
177  inline BSSimpleList(const BSSimpleList& a_rhs) :
178  _listHead()
179  {
180  copy_from(a_rhs);
181  }
182 
183  inline BSSimpleList(BSSimpleList&& a_rhs) :
184  _listHead(std::move(a_rhs._listHead))
185  {}
186 
187  inline ~BSSimpleList()
188  {
189  clear();
190  }
191 
192  inline BSSimpleList& operator=(const BSSimpleList& a_rhs)
193  {
194  if (this != std::addressof(a_rhs)) {
195  clear();
196  copy_from(a_rhs);
197  }
198  return *this;
199  }
200 
202  {
203  if (this != std::addressof(a_rhs)) {
204  clear();
205  _listHead = std::move(a_rhs._listHead);
206  }
207  return *this;
208  }
209 
211 
212  [[nodiscard]] inline reference front()
213  {
214  assert(!empty());
215  return *begin();
216  }
217 
218  [[nodiscard]] inline const_reference front() const
219  {
220  assert(!empty());
221  return *begin();
222  }
223 
224  [[nodiscard]] inline iterator begin() { return empty() ? end() : iterator(get_head()); }
225  [[nodiscard]] inline const_iterator begin() const { return empty() ? end() : const_iterator(get_head()); }
226  [[nodiscard]] inline const_iterator cbegin() const { return begin(); }
227 
228  [[nodiscard]] constexpr iterator end() noexcept { return iterator(nullptr); }
229  [[nodiscard]] constexpr const_iterator end() const noexcept { return const_iterator(nullptr); }
230  [[nodiscard]] constexpr const_iterator cend() const noexcept { return end(); }
231 
232  [[nodiscard]] inline bool empty() const { return !_listHead.next && !_listHead.item; }
233 
234  inline void clear()
235  {
236  erase_after_impl(get_head(), nullptr);
237  if (static_cast<bool>(_listHead.item)) {
238  std::destroy_at(std::addressof(_listHead.item));
239  }
240  }
241 
243  {
244  auto node = new Node(a_value);
245  return insert_after_impl(
246  a_pos.get_current(),
247  std::make_pair(node, node));
248  }
249 
250  inline iterator insert_after(iterator a_pos, value_type&& a_value)
251  {
252  auto node = new Node(std::move(a_value));
253  return insert_after_impl(
254  a_pos.get_current(),
255  std::make_pair(node, node));
256  }
257 
259  {
260  auto node = new Node(a_value);
261  return insert_after_impl(
262  a_pos.get_current(),
263  std::make_pair(node, node));
264  }
265 
267  {
268  auto node = new Node(std::move(a_value));
269  return insert_after_impl(
270  a_pos.get_current(),
271  std::make_pair(node, node));
272  }
273 
275  {
276  if (a_count <= 0) {
277  return a_pos;
278  }
279 
280  return insert_after_impl(
281  a_pos.get_current(),
282  alloc_copies(a_count, a_value));
283  }
284 
286  {
287  if (a_pos == cend()) {
288  return end();
289  }
290 
291  auto node = a_pos.get_current();
292  erase_after_impl(node, node->next);
293  return node->next;
294  }
295 
297  {
298  assert(a_first.comes_before(a_last));
299 
300  auto head = a_first.get_current();
301  auto tail = a_last.get_current();
302 
303  erase_after_impl(head, tail);
304  return tail;
305  }
306 
307  inline void push_front(const_reference a_value) { emplace_front_impl(a_value); }
308  inline void push_front(value_type&& a_value) { emplace_front_impl(std::move(a_value)); }
309 
310  template <class... Args>
311  inline reference emplace_front(Args&&... a_args)
312  {
313  emplace_front_impl(std::forward<Args>(a_args)...);
314  return front();
315  }
316 
317  inline void pop_front()
318  {
319  assert(!empty());
320 
321  std::destroy_at(std::addressof(_listHead.item));
322  auto node = _listHead.next;
323  if (node) {
324  _listHead.next = node->next;
325  std::construct_at(std::addressof(_listHead.item), std::move(node->item));
326  delete node;
327  }
328  }
329 
330  inline void resize(size_type a_count) { resize(a_count, value_type{}); }
331  inline void resize(size_type a_count, const value_type& a_value) { resize_impl(a_count, a_value); }
332 
333  protected:
334  [[nodiscard]] constexpr Node* get_head() noexcept { return std::addressof(_listHead); }
335  [[nodiscard]] constexpr const Node* get_head() const noexcept { return std::addressof(_listHead); }
336 
337  [[nodiscard]] inline std::pair<Node*, Node*> alloc_copies(size_type a_count, const_reference a_value)
338  {
339  assert(a_count > 0);
340 
341  auto head = new Node(a_value);
342  auto tail = head;
343  for (size_type i = 1; i < a_count; ++i) {
344  tail->next = new Node(a_value);
345  tail = tail->next;
346  }
347 
348  return std::make_pair(head, tail);
349  }
350 
351  inline void copy_from(const BSSimpleList& a_rhs)
352  {
353  auto lhs = get_head();
354  auto rhs = a_rhs.get_head();
355 
356  lhs->item = rhs->item;
357  while (rhs->next) {
358  rhs = rhs->next;
359  lhs->next = new Node(rhs->item);
360  lhs = lhs->next;
361  }
362  }
363 
364  [[nodiscard]] inline Node* insert_after_impl(Node* a_pos, std::pair<Node*, Node*> a_values)
365  {
366  auto [head, tail] = a_values;
367 
368  assert(a_pos);
369  assert(head && tail);
370 
371  tail->next = a_pos->next;
372  a_pos->next = head;
373  return tail;
374  }
375 
376  inline void erase_after_impl(Node* a_head, Node* a_tail)
377  {
378  if (a_head && a_head != a_tail) {
379  auto iter = a_head->next;
380  auto tmp = iter;
381  while (iter != a_tail) {
382  tmp = iter;
383  iter = iter->next;
384  delete tmp;
385  }
386  a_head->next = a_tail;
387  }
388  }
389 
390  template <class... Args>
391  inline void emplace_front_impl(Args&&... a_args)
392  {
393  if (static_cast<bool>(_listHead.item)) {
394  auto node = new Node(std::move(_listHead));
395  _listHead.next = node;
396  }
397 
398  std::destroy_at(std::addressof(_listHead.item));
399  std::construct_at(std::addressof(_listHead.item), std::forward<Args>(a_args)...);
400  }
401 
402  inline void resize_impl(size_type a_count, const_reference a_value)
403  {
404  if (a_count <= 0) {
405  clear();
406  }
407 
408  auto iter = begin();
409  auto last = end();
410  size_type elems = 1;
411  while (iter != last && elems != a_count) {
412  ++iter;
413  ++elems;
414  }
415 
416  if (elems < a_count) {
417  // need to grow
418  insert_after(iter, a_count - elems, a_value);
419  } else if (iter != last) {
420  // need to shrink
421  erase_after(iter, last);
422  } else {
423  // already required size
424  }
425  }
426 
427  // members
429 
430  // T _item; // 00
431  // BSSimpleList<T>* _next; // ??
432  };
433 }
Definition: BSTList.h:83
constexpr bool operator==(const iterator_base &a_rhs) const noexcept
Definition: BSTList.h:131
constexpr iterator_base & operator=(const iterator_base &a_rhs) noexcept
Definition: BSTList.h:111
constexpr reference operator*() const noexcept
Definition: BSTList.h:128
constexpr iterator_base(const iterator_base &a_rhs) noexcept
Definition: BSTList.h:95
constexpr Node * get_current() noexcept
Definition: BSTList.h:153
constexpr bool operator!=(const iterator_base &a_rhs) const noexcept
Definition: BSTList.h:132
constexpr iterator_base(Node *a_node) noexcept
Definition: BSTList.h:105
constexpr iterator_base() noexcept
Definition: BSTList.h:91
constexpr iterator_base & operator++() noexcept
Definition: BSTList.h:135
constexpr iterator_base & operator=(iterator_base &&a_rhs) noexcept
Definition: BSTList.h:119
constexpr const Node * get_current() const noexcept
Definition: BSTList.h:154
std::forward_iterator_tag iterator_category
Definition: BSTList.h:89
~iterator_base() noexcept
Definition: BSTList.h:109
constexpr iterator_base(iterator_base &&a_rhs) noexcept
Definition: BSTList.h:99
U value_type
Definition: BSTList.h:86
U & reference
Definition: BSTList.h:88
std::ptrdiff_t difference_type
Definition: BSTList.h:85
constexpr bool comes_before(const iterator_base &a_rhs) const noexcept
Definition: BSTList.h:156
U * pointer
Definition: BSTList.h:87
constexpr pointer operator->() const noexcept
Definition: BSTList.h:129
Definition: BSTList.h:10
constexpr const_iterator cend() const noexcept
Definition: BSTList.h:230
const value_type & const_reference
Definition: BSTList.h:15
constexpr const_iterator end() const noexcept
Definition: BSTList.h:229
iterator insert_after(iterator a_pos, const_reference a_value)
Definition: BSTList.h:242
reference front()
Definition: BSTList.h:212
void resize(size_type a_count, const value_type &a_value)
Definition: BSTList.h:331
const_iterator cbegin() const
Definition: BSTList.h:226
BSSimpleList & operator=(BSSimpleList &&a_rhs)
Definition: BSTList.h:201
T value_type
Definition: BSTList.h:12
BSSimpleList & operator=(const BSSimpleList &a_rhs)
Definition: BSTList.h:192
Node * insert_after_impl(Node *a_pos, std::pair< Node *, Node * > a_values)
Definition: BSTList.h:364
void push_front(value_type &&a_value)
Definition: BSTList.h:308
void resize(size_type a_count)
Definition: BSTList.h:330
BSSimpleList(BSSimpleList &&a_rhs)
Definition: BSTList.h:183
iterator insert_after(const_iterator a_pos, const_reference a_value)
Definition: BSTList.h:258
iterator insert_after(const_iterator a_pos, size_type a_count, const_reference a_value)
Definition: BSTList.h:274
iterator erase_after(const_iterator a_pos)
Definition: BSTList.h:285
constexpr Node * get_head() noexcept
Definition: BSTList.h:334
reference emplace_front(Args &&... a_args)
Definition: BSTList.h:311
~BSSimpleList()
Definition: BSTList.h:187
iterator begin()
Definition: BSTList.h:224
iterator_base< const value_type > const_iterator
Definition: BSTList.h:171
void emplace_front_impl(Args &&... a_args)
Definition: BSTList.h:391
iterator erase_after(const_iterator a_first, const_iterator a_last)
Definition: BSTList.h:296
const_iterator begin() const
Definition: BSTList.h:225
std::pair< Node *, Node * > alloc_copies(size_type a_count, const_reference a_value)
Definition: BSTList.h:337
iterator insert_after(iterator a_pos, value_type &&a_value)
Definition: BSTList.h:250
void copy_from(const BSSimpleList &a_rhs)
Definition: BSTList.h:351
std::uint32_t size_type
Definition: BSTList.h:13
BSSimpleList(const BSSimpleList &a_rhs)
Definition: BSTList.h:177
constexpr iterator end() noexcept
Definition: BSTList.h:228
void erase_after_impl(Node *a_head, Node *a_tail)
Definition: BSTList.h:376
const_reference front() const
Definition: BSTList.h:218
iterator_base< value_type > iterator
Definition: BSTList.h:170
constexpr const Node * get_head() const noexcept
Definition: BSTList.h:335
iterator insert_after(const_iterator a_pos, value_type &&a_value)
Definition: BSTList.h:266
value_type & reference
Definition: BSTList.h:14
void push_front(const_reference a_value)
Definition: BSTList.h:307
Node _listHead
Definition: BSTList.h:428
void clear()
Definition: BSTList.h:234
BSSimpleList()
Definition: BSTList.h:173
bool empty() const
Definition: BSTList.h:232
void pop_front()
Definition: BSTList.h:317
void resize_impl(size_type a_count, const_reference a_value)
Definition: BSTList.h:402
Definition: AbsorbEffect.h:6
auto make_pair(T1 &&a_first, T2 &&a_second)
Definition: BSTTuple.h:177
T observer
Definition: PCH.h:92
Definition: ActorValueList.h:28
Definition: BSTList.h:18
Node()
Definition: BSTList.h:20
stl::observer< Node * > next
Definition: BSTList.h:78
Node & operator=(Node &&a_rhs)
Definition: BSTList.h:63
Node(const Node &a_rhs)
Definition: BSTList.h:30
Node(value_type &&a_value)
Definition: BSTList.h:47
Node(value_type a_value, Node *a_next)
Definition: BSTList.h:25
value_type item
Definition: BSTList.h:77
Node(const value_type &a_value)
Definition: BSTList.h:42
Node & operator=(const Node &a_rhs)
Definition: BSTList.h:54
Node(Node &&a_rhs)
Definition: BSTList.h:35