CommonLibSSE (Parapets fork)
BSSimpleList.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 
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  if (a_count <= 0) {
261  return a_pos;
262  }
263 
264  return insert_after_impl(
265  a_pos.get_current(),
266  alloc_copies(a_count, a_value));
267  }
268 
270  {
271  if (a_pos == cend()) {
272  return end();
273  }
274 
275  auto node = a_pos.get_current();
276  erase_after_impl(node, node->next);
277  return node->next;
278  }
279 
281  {
282  assert(a_first.comes_before(a_last));
283 
284  auto head = a_first.get_current();
285  auto tail = a_last.get_current();
286 
287  erase_after_impl(head, tail);
288  return tail;
289  }
290 
291  inline void push_front(const_reference a_value) { emplace_front_impl(a_value); }
292  inline void push_front(value_type&& a_value) { emplace_front_impl(std::move(a_value)); }
293 
294  template <class... Args>
295  inline reference emplace_front(Args&&... a_args)
296  {
297  emplace_front_impl(std::forward<Args>(a_args)...);
298  return front();
299  }
300 
301  inline void pop_front()
302  {
303  assert(!empty());
304 
305  std::destroy_at(std::addressof(_listHead.item));
306  auto node = _listHead.next;
307  if (node) {
308  _listHead.next = node->next;
309  std::construct_at(std::addressof(_listHead.item), std::move(node->item));
310  delete node;
311  }
312  }
313 
314  inline void resize(size_type a_count) { resize(a_count, value_type{}); }
315  inline void resize(size_type a_count, const value_type& a_value) { resize_impl(a_count, a_value); }
316 
317  protected:
318  [[nodiscard]] constexpr Node* get_head() noexcept { return std::addressof(_listHead); }
319  [[nodiscard]] constexpr const Node* get_head() const noexcept { return std::addressof(_listHead); }
320 
321  [[nodiscard]] inline std::pair<Node*, Node*> alloc_copies(size_type a_count, const_reference a_value)
322  {
323  assert(a_count > 0);
324 
325  auto head = new Node(a_value);
326  auto tail = head;
327  for (size_type i = 1; i < a_count; ++i) {
328  tail->next = new Node(a_value);
329  tail = tail->next;
330  }
331 
332  return std::make_pair(head, tail);
333  }
334 
335  inline void copy_from(const BSSimpleList& a_rhs)
336  {
337  auto lhs = get_head();
338  auto rhs = a_rhs.get_head();
339 
340  lhs->item = rhs->item;
341  while (rhs->next) {
342  rhs = rhs->next;
343  lhs->next = new Node(rhs->item);
344  lhs = lhs->next;
345  }
346  }
347 
348  [[nodiscard]] inline Node* insert_after_impl(Node* a_pos, std::pair<Node*, Node*> a_values)
349  {
350  auto [head, tail] = a_values;
351 
352  assert(a_pos);
353  assert(head && tail);
354 
355  tail->next = a_pos->next;
356  a_pos->next = head;
357  return tail;
358  }
359 
360  inline void erase_after_impl(Node* a_head, Node* a_tail)
361  {
362  if (a_head && a_head != a_tail) {
363  auto iter = a_head->next;
364  auto tmp = iter;
365  while (iter != a_tail) {
366  tmp = iter;
367  iter = iter->next;
368  delete tmp;
369  }
370  a_head->next = a_tail;
371  }
372  }
373 
374  template <class... Args>
375  inline void emplace_front_impl(Args&&... a_args)
376  {
377  if (static_cast<bool>(_listHead.item)) {
378  auto node = new Node(std::move(_listHead));
379  _listHead.next = node;
380  }
381 
382  std::destroy_at(std::addressof(_listHead.item));
383  std::construct_at(std::addressof(_listHead.item), std::forward<Args>(a_args)...);
384  }
385 
386  inline void resize_impl(size_type a_count, const_reference a_value)
387  {
388  if (a_count <= 0) {
389  clear();
390  }
391 
392  auto iter = begin();
393  auto last = end();
394  size_type elems = 1;
395  while (iter != last && elems != a_count) {
396  ++iter;
397  ++elems;
398  }
399 
400  if (elems < a_count) {
401  // need to grow
402  insert_after(iter, a_count - elems, a_value);
403  } else if (iter != last) {
404  // need to shrink
405  erase_after(iter, last);
406  } else {
407  // already required size
408  }
409  }
410 
411  // members
413 
414  // T _item; // 00
415  // BSSimpleList<T>* _next; // ??
416  };
417 }
Definition: BSSimpleList.h:83
constexpr bool operator==(const iterator_base &a_rhs) const noexcept
Definition: BSSimpleList.h:131
constexpr iterator_base & operator=(const iterator_base &a_rhs) noexcept
Definition: BSSimpleList.h:111
constexpr reference operator*() const noexcept
Definition: BSSimpleList.h:128
constexpr iterator_base(const iterator_base &a_rhs) noexcept
Definition: BSSimpleList.h:95
constexpr Node * get_current() noexcept
Definition: BSSimpleList.h:153
constexpr bool operator!=(const iterator_base &a_rhs) const noexcept
Definition: BSSimpleList.h:132
constexpr iterator_base(Node *a_node) noexcept
Definition: BSSimpleList.h:105
constexpr iterator_base() noexcept
Definition: BSSimpleList.h:91
constexpr iterator_base & operator++() noexcept
Definition: BSSimpleList.h:135
constexpr iterator_base & operator=(iterator_base &&a_rhs) noexcept
Definition: BSSimpleList.h:119
constexpr const Node * get_current() const noexcept
Definition: BSSimpleList.h:154
std::forward_iterator_tag iterator_category
Definition: BSSimpleList.h:89
~iterator_base() noexcept
Definition: BSSimpleList.h:109
constexpr iterator_base(iterator_base &&a_rhs) noexcept
Definition: BSSimpleList.h:99
U value_type
Definition: BSSimpleList.h:86
U & reference
Definition: BSSimpleList.h:88
std::ptrdiff_t difference_type
Definition: BSSimpleList.h:85
constexpr bool comes_before(const iterator_base &a_rhs) const noexcept
Definition: BSSimpleList.h:156
U * pointer
Definition: BSSimpleList.h:87
constexpr pointer operator->() const noexcept
Definition: BSSimpleList.h:129
Definition: BSSimpleList.h:10
constexpr const_iterator cend() const noexcept
Definition: BSSimpleList.h:230
const value_type & const_reference
Definition: BSSimpleList.h:15
constexpr const_iterator end() const noexcept
Definition: BSSimpleList.h:229
reference front()
Definition: BSSimpleList.h:212
void resize(size_type a_count, const value_type &a_value)
Definition: BSSimpleList.h:315
const_iterator cbegin() const
Definition: BSSimpleList.h:226
BSSimpleList & operator=(BSSimpleList &&a_rhs)
Definition: BSSimpleList.h:201
T value_type
Definition: BSSimpleList.h:12
BSSimpleList & operator=(const BSSimpleList &a_rhs)
Definition: BSSimpleList.h:192
Node * insert_after_impl(Node *a_pos, std::pair< Node *, Node * > a_values)
Definition: BSSimpleList.h:348
void push_front(value_type &&a_value)
Definition: BSSimpleList.h:292
void resize(size_type a_count)
Definition: BSSimpleList.h:314
BSSimpleList(BSSimpleList &&a_rhs)
Definition: BSSimpleList.h:183
iterator insert_after(const_iterator a_pos, const_reference a_value)
Definition: BSSimpleList.h:242
iterator insert_after(const_iterator a_pos, size_type a_count, const_reference a_value)
Definition: BSSimpleList.h:258
iterator erase_after(const_iterator a_pos)
Definition: BSSimpleList.h:269
constexpr Node * get_head() noexcept
Definition: BSSimpleList.h:318
reference emplace_front(Args &&... a_args)
Definition: BSSimpleList.h:295
~BSSimpleList()
Definition: BSSimpleList.h:187
iterator begin()
Definition: BSSimpleList.h:224
iterator_base< const value_type > const_iterator
Definition: BSSimpleList.h:171
void emplace_front_impl(Args &&... a_args)
Definition: BSSimpleList.h:375
iterator erase_after(const_iterator a_first, const_iterator a_last)
Definition: BSSimpleList.h:280
const_iterator begin() const
Definition: BSSimpleList.h:225
std::pair< Node *, Node * > alloc_copies(size_type a_count, const_reference a_value)
Definition: BSSimpleList.h:321
void copy_from(const BSSimpleList &a_rhs)
Definition: BSSimpleList.h:335
std::uint32_t size_type
Definition: BSSimpleList.h:13
BSSimpleList(const BSSimpleList &a_rhs)
Definition: BSSimpleList.h:177
constexpr iterator end() noexcept
Definition: BSSimpleList.h:228
void erase_after_impl(Node *a_head, Node *a_tail)
Definition: BSSimpleList.h:360
const_reference front() const
Definition: BSSimpleList.h:218
iterator_base< value_type > iterator
Definition: BSSimpleList.h:170
constexpr const Node * get_head() const noexcept
Definition: BSSimpleList.h:319
iterator insert_after(const_iterator a_pos, value_type &&a_value)
Definition: BSSimpleList.h:250
value_type & reference
Definition: BSSimpleList.h:14
void push_front(const_reference a_value)
Definition: BSSimpleList.h:291
Node _listHead
Definition: BSSimpleList.h:412
void clear()
Definition: BSSimpleList.h:234
BSSimpleList()
Definition: BSSimpleList.h:173
bool empty() const
Definition: BSSimpleList.h:232
void pop_front()
Definition: BSSimpleList.h:301
void resize_impl(size_type a_count, const_reference a_value)
Definition: BSSimpleList.h:386
Definition: AbsorbEffect.h:6
auto make_pair(T1 &&a_first, T2 &&a_second)
Definition: BSTTuple.h:177
T observer
Definition: PCH.h:92
Definition: NiBinaryStream.h:94
Definition: BSSimpleList.h:18
Node()
Definition: BSSimpleList.h:20
stl::observer< Node * > next
Definition: BSSimpleList.h:78
Node & operator=(Node &&a_rhs)
Definition: BSSimpleList.h:63
Node(const Node &a_rhs)
Definition: BSSimpleList.h:30
Node(value_type &&a_value)
Definition: BSSimpleList.h:47
Node(value_type a_value, Node *a_next)
Definition: BSSimpleList.h:25
value_type item
Definition: BSSimpleList.h:77
Node(const value_type &a_value)
Definition: BSSimpleList.h:42
Node & operator=(const Node &a_rhs)
Definition: BSSimpleList.h:54
Node(Node &&a_rhs)
Definition: BSSimpleList.h:35