Atoms Crowd  7.0.0
Set.impl.h
1 #pragma once
2 
3 namespace ToolchefsSTL
4 {
5 
6  template<typename T>
7  Set<T>::Set(Allocator* allocator) noexcept :
8  m_data(nullptr),
9  m_allocator(allocator),
10  m_length(0),
11  m_capacity(0)
12  {
13 
14  }
15 
16  template<typename T>
17  Set<T>::~Set() noexcept
18  {
19  clear();
20  }
21 
22  template<typename T>
23  Set<T>::Set(const Set<T>& rhs) noexcept :
24  m_data(nullptr),
25  m_allocator(rhs.m_allocator),
26  m_length(rhs.m_length),
27  m_capacity(rhs.m_length)
28  {
29  if (m_length == 0) return;
30  m_data = static_cast<Set::ptr_type>(m_allocator->malloc(sizeof(T) * m_capacity));
31 #if __cplusplus >= 201703L
32  if (std::is_trivially_copyable_v<T>)
33  {
34  std::memcpy(m_data, rhs.m_data, sizeof(T) * m_length);
35  }
36  else
37 #endif
38  {
39  for (size_t i = 0; i < m_length; ++i)
40  {
41  new (m_data + i) T(rhs.m_data[i]);
42  }
43  }
44  }
45 
46  template<typename T>
47  Set<T>& Set<T>::operator=(const Set<T>& rhs) noexcept
48  {
49  if (this == &rhs) return *this;
50  if (rhs.m_length == 0)
51  {
52  clear();
53  return *this;
54  }
55 
56  resize(rhs.m_length);
57 #if __cplusplus >= 201703L
58  if (std::is_trivially_copyable_v<T>)
59  {
60  std::memcpy(m_data, rhs.m_data, sizeof(T) * m_length);
61  }
62  else
63 #endif
64  {
65  for (size_t i = 0; i < m_length; ++i)
66  {
67  ;
68  m_data[i] = rhs.m_data[i];
69  }
70  }
71  return *this;
72  }
73 
74  template<typename T>
75  Set<T>::Set(Set<T>&& rhs) noexcept :
76  m_data(rhs.m_data),
77  m_allocator(rhs.m_allocator),
78  m_length(rhs.m_length),
79  m_capacity(rhs.m_capacity)
80  {
81  rhs.m_length = 0;
82  rhs.m_capacity = 0;
83  rhs.m_data = nullptr;
84  }
85 
86  template<typename T>
87  Set<T>& Set<T>::operator=(Set<T>&& rhs) noexcept
88  {
89  if (m_data) clear();
90  m_data = rhs.m_data;
91  m_allocator = rhs.m_allocator;
92  m_length = rhs.m_length;
93  m_capacity = rhs.m_capacity;
94 
95  rhs.m_data = nullptr;
96  rhs.m_length = 0;
97  rhs.m_capacity = 0;
98  return *this;
99  }
100 
101  template<typename T>
102  bool Set<T>::operator==(const Set& rhs) const noexcept
103  {
104  if (rhs.m_length != m_length) return false;
105  for (size_t i = 0; i < m_length; ++i)
106  {
107  if (m_data[i] != m_data[i]) return false;
108  }
109  return true;
110  }
111 
112  template<typename T>
113  void Set<T>::insert(const T& element) noexcept
114  {
115  if (find(element) != end()) return;
116  if (m_capacity == m_length) grow();
117  new (m_data + m_length++) T(element);
118  }
119 
120 
121  template<typename T>
122  typename Set<T>::iterator Set<T>::begin() noexcept
123  {
124  return m_data;
125  }
126 
127  template<typename T>
128  typename Set<T>::iterator Set<T>::end() noexcept
129  {
130  return &m_data[m_length];
131  }
132 
133  template<typename T>
134  typename Set<T>::const_iterator Set<T>::cbegin() const noexcept
135  {
136  return m_data;
137  }
138 
139  template<typename T>
140  typename Set<T>::const_iterator Set<T>::cend() const noexcept
141  {
142  return &m_data[m_length];
143  }
144 
145  template<typename T>
146  typename Set<T>::reverse_iterator Set<T>::rbegin() noexcept
147  {
148  return reverse_iterator(&back());
149  }
150 
151  template<typename T>
152  typename Set<T>::reverse_iterator Set<T>::rend() noexcept
153  {
154  T* front_ptr = &front();
155  return reverse_iterator(--front_ptr);
156  }
157 
158  template<typename T>
159  typename Set<T>::const_reverse_iterator Set<T>::crbegin() const noexcept
160  {
161  return const_reverse_iterator(&back());
162  }
163 
164  template<typename T>
165  typename Set<T>::const_reverse_iterator Set<T>::crend() const noexcept
166  {
167  T* front_ptr = const_cast<T*>(&front());
168  return const_reverse_iterator(--front_ptr);
169  }
170 
171  template<typename T>
172  T& Set<T>::back() noexcept
173  {
174  return m_data[m_length - 1];
175  }
176 
177  template<typename T>
178  const T& Set<T>::back() const noexcept
179  {
180  return m_data[m_length - 1];
181  }
182 
183  template<typename T>
184  T& Set<T>::front() noexcept
185  {
186  return m_data[0];
187  }
188 
189  template<typename T>
190  const T& Set<T>::front() const noexcept
191  {
192  return m_data[0];
193  }
194 
195  template<typename T>
196  const T* Set<T>::data() const noexcept
197  {
198  return m_data;
199  }
200 
201  template<typename T>
202  void Set<T>::resize(size_t new_length) noexcept
203  {
204  if (new_length == m_length) return;
205  if (new_length == 0)
206  {
207  clear();
208  return;
209  }
210  if (new_length > m_length)
211  {
212  reserve(new_length);
213  for (size_t i = m_length; i < new_length; ++i)
214  {
215  new (m_data + i) T();
216  }
217  m_length = new_length;
218  }
219  else
220  {
221  m_capacity = new_length;
222  ptr_type new_buffer = static_cast<ptr_type>(m_allocator->malloc(sizeof(T) * new_length));
223 #if __cplusplus >= 201703L
224  if (std::is_trivially_copyable_v<T>)
225  {
226  std::memcpy(new_buffer, m_data, sizeof(T) * new_length);
227  }
228  else
229 #endif
230  {
231  for (size_t i = 0; i < m_length; ++i)
232  {
233  T& item = m_data[i];
234  if (i < new_length)
235  new (new_buffer + i) T(std::move(item));
236  item.~T();
237  }
238  }
239  m_allocator->free(m_data);
240  m_data = new_buffer;
241  m_length = new_length;
242  }
243  }
244 
245  template<typename T>
246  void Set<T>::clear() noexcept
247  {
248  if (!std::is_trivially_destructible<T>::value)
249  {
250  for (size_t i = 0; i < m_length; ++i)
251  {
252  m_data[i].~T();
253  }
254  }
255 
256  if (m_data)
257  {
258  m_allocator->free(m_data);
259  m_data = nullptr;
260  }
261 
262  m_length = 0;
263  m_capacity = 0;
264  }
265 
266  template<typename T>
267  void Set<T>::reserve(size_t new_capacity) noexcept
268  {
269  if (new_capacity <= m_capacity) return;
270  m_capacity = new_capacity;
271  ptr_type new_buffer = static_cast<ptr_type>(m_allocator->malloc(sizeof(T) * m_capacity));
272 #if __cplusplus >= 201703L
273  if (std::is_trivially_copyable_v<T>)
274  {
275  std::memcpy(new_buffer, m_data, sizeof(T) * m_length);
276  }
277  else
278 #endif
279  {
280  for (size_t i = 0; i < m_length; ++i)
281  {
282  T& item = m_data[i];
283  new (new_buffer + i) T(std::move(item));
284  item.~T();
285  }
286  }
287 
288  m_allocator->free(m_data);
289  m_data = new_buffer;
290  }
291 
292  template<typename T>
293  size_t Set<T>::size() const noexcept
294  {
295  return m_length;
296  }
297 
298  template<typename T>
299  size_t Set<T>::length() const noexcept
300  {
301  return m_length;
302  }
303 
304  template<typename T>
305  size_t Set<T>::capacity() const noexcept
306  {
307  return m_capacity;
308  }
309 
310  template<typename T>
311  void Set<T>::grow() noexcept
312  {
313  m_capacity = m_capacity == 0 ? 1 : m_capacity << 1;
314  ptr_type new_buffer = static_cast<ptr_type>(m_allocator->malloc(sizeof(T) * m_capacity));
315 #if __cplusplus >= 201703L
316  if (std::is_trivially_copyable_v<T>)
317  {
318  std::memcpy(new_buffer, m_data, sizeof(T) * m_length);
319  }
320  else
321 #endif
322  {
323  for (size_t i = 0; i < m_length; ++i)
324  {
325  T& item = m_data[i];
326  new (new_buffer + i) T(std::move(item));
327  item.~T();
328  }
329  }
330 
331  m_allocator->free(m_data);
332  m_data = new_buffer;
333 
334  }
335 
336  template<typename T>
337  void Set<T>::erase(const T& element) noexcept
338  {
339  auto it = find(element);
340  if (it == end()) return;
341  size_t index(it - m_data);
342  if (index >= m_length) return;
343  for (size_t i = (index + 1); i < m_length; ++i)
344  m_data[i - 1] = std::move(m_data[i]);
345  m_length--;
346  m_data[m_length].~T();
347  }
348 
349 
350 
351  template<typename T>
352  void Set<T>::erase(iterator it) noexcept
353  {
354  size_t index(it - m_data);
355  if (index >= m_length) return;
356  for (size_t i = (index + 1); i < m_length; ++i)
357  m_data[i - 1] = std::move(m_data[i]);
358  m_length--;
359  m_data[m_length].~T();
360  }
361 
362  template<typename T>
363  void Set<T>::shrink_to_fit() noexcept
364  {
365  m_capacity = m_length;
366  ptr_type new_buffer = static_cast<ptr_type>(m_allocator->malloc(sizeof(T) * m_capacity));
367 #if __cplusplus >= 201703L
368  if (std::is_trivially_copyable_v<T>)
369  {
370  std::memcpy(new_buffer, m_data, sizeof(T) * m_length);
371  }
372  else
373 #endif
374  {
375  for (size_t i = 0; i < m_capacity; ++i)
376  {
377  T& item = m_data[i];
378  new (new_buffer + i) T(std::move(item));
379  item.~T();
380  }
381  }
382 
383  m_allocator->free(m_data);
384  m_data = new_buffer;
385  }
386 
387  template<typename T>
388  typename Set<T>::iterator Set<T>::find(const T& element) noexcept
389  {
390  auto end_it = end();
391  for (auto it = begin(); it != end_it; ++it)
392  {
393  if (*it == element) return it;
394  }
395  return end();
396  }
397 
398  template<typename T>
399  typename Set<T>::const_iterator Set<T>::find(const T& element) const noexcept
400  {
401  auto end_it = cend();
402  for (auto it = cbegin(); it != end_it; ++it)
403  {
404  if (*it == element) return it;
405  }
406  return cend();
407  }
408 
409  template<typename T>
410  bool Set<T>::empty() const noexcept
411  {
412  return m_length == 0;
413  }
414 
415 }
Definition: Set.h:8
iterator begin() noexcept
Iterators.
Definition: Set.impl.h:122