10 namespace ToolchefsSTL
14 Array<T>::Array(Allocator* allocator) noexcept:
16 m_allocator(allocator),
24 Array<T>::Array(
size_t num_elements, Allocator* allocator) noexcept:
26 m_allocator(allocator),
27 m_length(num_elements),
28 m_capacity(num_elements)
30 m_data =
static_cast<Array::ptr_type
>(m_allocator->malloc(
sizeof(T) * m_capacity));
31 for (
size_t i = 0; i < m_capacity; ++i)
38 Array<T>::Array(
size_t num_elements,
const T& init_value, Allocator* allocator) noexcept:
40 m_allocator(allocator),
41 m_length(num_elements),
42 m_capacity(num_elements)
44 m_data =
static_cast<Array::ptr_type
>(m_allocator->malloc(
sizeof(T) * m_capacity));
45 for (
size_t i = 0; i < m_capacity; ++i)
47 new (m_data + i) T(init_value);
52 Array<T>::~Array() noexcept
58 Array<T>::Array(
const Array& rhs) noexcept:
60 m_allocator(rhs.m_allocator),
61 m_length(rhs.m_length),
62 m_capacity(rhs.m_length)
64 if (m_length == 0)
return;
65 m_data =
static_cast<Array::ptr_type
>(m_allocator->malloc(
sizeof(T) * m_capacity));
66 #if __cplusplus >= 201703L
67 if(std::is_trivially_copyable_v<T>)
69 memcpy(m_data, rhs.m_data,
sizeof(T) * m_length);
74 for (
size_t i = 0; i < m_length; ++i)
76 new (m_data + i) T(rhs.m_data[i]);
82 Array<T>& Array<T>::operator=(
const Array<T>& rhs) noexcept
84 if (
this == &rhs)
return *
this;
85 if (rhs.m_length == 0)
92 #if __cplusplus >= 201703L
93 if (std::is_trivially_copyable_v<T>)
95 memcpy(m_data, rhs.m_data,
sizeof(T) * m_length);
100 for (
size_t i = 0; i < m_length; ++i)
102 m_data[i] = rhs.m_data[i];
109 Array<T>::Array(Array<T>&& rhs) noexcept:
111 m_allocator(rhs.m_allocator),
112 m_length(rhs.m_length),
113 m_capacity(rhs.m_capacity)
117 rhs.m_data =
nullptr;
121 Array<T>& Array<T>::operator=(Array<T>&& rhs) noexcept
125 m_allocator = rhs.m_allocator;
126 m_length = rhs.m_length;
127 m_capacity = rhs.m_capacity;
129 rhs.m_data =
nullptr;
136 bool Array<T>::operator==(
const Array& rhs)
const noexcept
138 if (rhs.m_length != m_length)
return false;
139 for (
size_t i=0; i < m_length; ++i)
141 if (m_data[i] != m_data[i])
return false;
147 void Array<T>::push_back(
const T& element) noexcept
149 if (m_capacity == m_length) grow();
150 new (m_data + m_length++) T(element);
155 #if __cplusplus >= 201703L
157 constexpr T& Array<T>::operator[](
const size_t index) noexcept
159 assert(index >= 0 && index < m_length);
160 return m_data[index];
164 constexpr
const T& Array<T>::operator[](
const size_t index)
const noexcept
166 assert(index >= 0 && index < m_length);
167 return m_data[index];
180 return &m_data[m_length];
184 typename Array<T>::const_iterator Array<T>::cbegin() const noexcept
190 typename Array<T>::const_iterator Array<T>::cend() const noexcept
192 return &m_data[m_length];
196 typename Array<T>::reverse_iterator Array<T>::rbegin() noexcept
198 return reverse_iterator(&back());
202 typename Array<T>::reverse_iterator Array<T>::rend() noexcept
204 T* front_ptr = &front();
205 return reverse_iterator(--front_ptr);
209 typename Array<T>::const_reverse_iterator Array<T>::crbegin() const noexcept
211 return const_reverse_iterator(&back());
215 typename Array<T>::const_reverse_iterator Array<T>::crend() const noexcept
217 T* front_ptr =
const_cast<T*
>(&front());
218 return const_reverse_iterator(--front_ptr);
224 return m_data[m_length - 1];
230 return m_data[m_length - 1];
234 T& Array<T>::front() noexcept
240 const T& Array<T>::front() const noexcept
246 const T* Array<T>::data() const noexcept
252 void Array<T>::resize(
size_t new_length) noexcept
254 if (new_length == m_length)
return;
260 if (new_length > m_length)
263 for (
size_t i = m_length; i < new_length; ++i)
265 new (m_data + i) T();
267 m_length = new_length;
271 m_capacity = new_length;
272 ptr_type new_buffer =
static_cast<ptr_type
>(m_allocator->malloc(
sizeof(T) * new_length));
273 #if __cplusplus >= 201703L
274 if (std::is_trivially_copyable_v<T>)
276 memcpy(new_buffer, m_data,
sizeof(T) * new_length);
281 for (
size_t i = 0; i < m_length; ++i)
285 new (new_buffer + i) T(std::move(item));
289 m_allocator->free(m_data);
291 m_length = new_length;
296 void Array<T>::clear() noexcept
298 if (!std::is_trivially_destructible<T>::value)
300 for (
size_t i = 0; i < m_length; ++i)
308 m_allocator->free(m_data);
317 void Array<T>::reserve(
size_t new_capacity) noexcept
319 if (new_capacity <= m_capacity)
return;
320 m_capacity = new_capacity;
321 ptr_type new_buffer =
static_cast<ptr_type
>(m_allocator->malloc(
sizeof(T) * m_capacity));
322 #if __cplusplus >= 201703L
323 if (std::is_trivially_copyable_v<T>)
325 memcpy(new_buffer, m_data,
sizeof(T) * m_length);
330 for (
size_t i = 0; i < m_length; ++i)
333 new (new_buffer + i) T(std::move(item));
338 m_allocator->free(m_data);
343 size_t Array<T>::size() const noexcept
349 size_t Array<T>::length() const noexcept
355 size_t Array<T>::capacity() const noexcept
361 void Array<T>::grow() noexcept
363 m_capacity = m_capacity == 0 ? 1 : m_capacity << 1;
364 ptr_type new_buffer =
static_cast<ptr_type
>(m_allocator->malloc(
sizeof(T) * m_capacity));
365 #if __cplusplus >= 201703L
366 if (std::is_trivially_copyable_v<T>)
368 memcpy(new_buffer, m_data,
sizeof(T) * m_length);
373 for (
size_t i=0; i < m_length; ++i)
376 new (new_buffer + i) T(std::move(item));
381 m_allocator->free(m_data);
387 void Array<T>::pop_back() noexcept
389 if (m_length == 0)
return;
390 m_data[--m_length].~T();
391 if (m_length == 0) clear();
395 void Array<T>::insert(
size_t index,
const T& value) noexcept
397 if (index >= m_length)
return;
398 resize(m_length + 1);
399 for (
size_t i = (m_length-1); i > index; --i)
400 m_data[i] = std::move(m_data[i-1]);
401 m_data[index] = value;
405 void Array<T>::insert(iterator it,
const T& value) noexcept
407 insert(it - m_data, value);
411 void Array<T>::erase(
size_t index) noexcept
413 if (index >= m_length)
return;
414 for (
size_t i = (index + 1); i < m_length; ++i)
415 m_data[i-1] = std::move(m_data[i]);
417 m_data[m_length].~T();
421 typename Array<T>::iterator Array<T>::erase(iterator it) noexcept
423 size_t index = it - m_data;
425 return begin() + index;
429 void Array<T>::shrink_to_fit() noexcept
431 m_capacity = m_length;
432 ptr_type new_buffer =
static_cast<ptr_type
>(m_allocator->malloc(
sizeof(T) * m_capacity));
433 #if __cplusplus >= 201703L
434 if (std::is_trivially_copyable_v<T>)
436 memcpy(new_buffer, m_data,
sizeof(T) * m_length);
441 for (
size_t i = 0; i < m_capacity; ++i)
444 new (new_buffer + i) T(std::move(item));
449 m_allocator->free(m_data);
454 typename Array<T>::iterator Array<T>::find(
const T& element) noexcept
457 for (
auto it=begin(); it != end_it; ++it)
459 if (*it == element)
return it;
465 typename Array<T>::const_iterator Array<T>::find(
const T& element)
const noexcept
467 auto end_it = cend();
468 for (
auto it = cbegin(); it != end_it; ++it)
470 if (*it == element)
return it;
476 bool Array<T>::empty() const noexcept
478 return m_length == 0;