29 using const_reference =
const T&;
31 using const_pointer =
const T*;
33 using difference_type = darr_detail::difference_type;
34 using size_type = darr_detail::size_type;
36 using iterator = pointer;
37 using const_iterator = const_pointer;
40 static constexpr size_t value_size =
sizeof(T);
43 uint8_t* m_pData =
nullptr;
44 size_type m_cnt = size_type(0);
45 size_type m_cap = size_type(0);
48 const auto cnt = size();
49 const auto cap = capacity();
52 if GAIA_LIKELY (cap != 0 && cnt < cap)
56 if GAIA_UNLIKELY (m_pData ==
nullptr) {
57 m_pData = view_policy::template alloc<Allocator>(m_cap = 4);
63 m_cap = (cap * 3 + 1) / 2;
65 auto* pDataOld = m_pData;
66 m_pData = view_policy::template alloc<Allocator>(m_cap);
67 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pData, m_cap, cnt);
68 mem::move_elements<T, false>(m_pData, pDataOld, cnt, 0, m_cap, cap);
69 view_policy::template free<Allocator>(pDataOld, cap, cnt);
73 darr()
noexcept =
default;
76 darr(size_type count, const_reference value) {
82 darr(size_type count) {
86 template <
typename InputIt>
87 darr(InputIt first, InputIt last) {
88 const auto count = (size_type)core::distance(first, last);
91 if constexpr (std::is_pointer_v<InputIt>) {
92 for (size_type i = 0; i < count; ++i)
93 operator[](i) = first[i];
94 }
else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
95 for (size_type i = 0; i < count; ++i)
96 operator[](i) = *(first[i]);
99 for (
auto it = first; it != last; ++it)
100 operator[](++i) = *it;
104 darr(std::initializer_list<T> il):
darr(il.begin(), il.end()) {}
106 darr(
const darr& other):
darr(other.begin(), other.end()) {}
108 darr(
darr&& other)
noexcept: m_pData(other.m_pData), m_cnt(other.m_cnt), m_cap(other.m_cap) {
109 other.m_pData =
nullptr;
110 other.m_cnt = size_type(0);
111 other.m_cap = size_type(0);
114 darr& operator=(std::initializer_list<T> il) {
115 *
this =
darr(il.begin(), il.end());
119 darr& operator=(
const darr& other) {
120 GAIA_ASSERT(core::addressof(other) !=
this);
122 resize(other.size());
123 mem::copy_elements<T, false>(
124 m_pData, (
const uint8_t*)other.m_pData, other.size(), 0, capacity(), other.capacity());
129 darr& operator=(
darr&& other)
noexcept {
130 GAIA_ASSERT(core::addressof(other) !=
this);
133 view_policy::template free<Allocator>(m_pData, m_cap, m_cnt);
135 m_pData = other.m_pData;
139 other.m_pData =
nullptr;
140 other.m_cnt = size_type(0);
141 other.m_cap = size_type(0);
147 view_policy::template free<Allocator>(m_pData, m_cap, m_cnt);
150 GAIA_CLANG_WARNING_PUSH()
152 GAIA_CLANG_WARNING_DISABLE(
"-Wcast-align")
154 GAIA_NODISCARD pointer data()
noexcept {
155 return reinterpret_cast<pointer
>(m_pData);
158 GAIA_NODISCARD const_pointer data()
const noexcept {
159 return reinterpret_cast<const_pointer
>(m_pData);
162 GAIA_NODISCARD
decltype(
auto)
operator[](size_type pos)
noexcept {
163 GAIA_ASSERT(pos < size());
164 return view_policy::set({(
typename view_policy::TargetCastType)m_pData, capacity()}, pos);
167 GAIA_NODISCARD
decltype(
auto)
operator[](size_type pos)
const noexcept {
168 GAIA_ASSERT(pos < size());
169 return view_policy::get({(
typename view_policy::TargetCastType)m_pData, capacity()}, pos);
172 GAIA_CLANG_WARNING_POP()
174 void reserve(size_type cap) {
178 auto* pDataOld = m_pData;
179 m_pData = view_policy::template alloc<Allocator>(cap);
180 if (pDataOld !=
nullptr) {
181 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pData, cap, m_cnt);
182 mem::move_elements<T, false>(m_pData, pDataOld, m_cnt, 0, cap, m_cap);
183 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
189 void resize(size_type count) {
194 if (m_pData ==
nullptr) {
196 m_pData = view_policy::template alloc<Allocator>(count);
197 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pData, count, count);
198 core::call_ctor_n(m_pData, count);
208 core::call_dtor_n(&data()[count], m_cnt - count);
209 GAIA_MEM_SANI_POP_N(value_size, m_pData, m_cap, m_cnt, m_cnt - count);
216 if (count <= m_cap) {
218 GAIA_MEM_SANI_PUSH_N(value_size, m_pData, m_cap, m_cnt, count - m_cnt);
219 core::call_ctor_n(&data()[m_cnt], count - m_cnt);
225 auto* pDataOld = m_pData;
226 m_pData = view_policy::template alloc<Allocator>(count);
227 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pData, count, count);
229 mem::move_elements<T, false>(m_pData, pDataOld, m_cnt, 0, count, m_cap);
231 core::call_ctor_n(&data()[m_cnt], count - m_cnt);
233 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
239 void push_back(
const T& arg) {
242 GAIA_MEM_SANI_PUSH(value_size, m_pData, m_cap, m_cnt);
243 auto* ptr = &data()[m_cnt++];
244 core::call_ctor(ptr, arg);
247 void push_back(T&& arg) {
250 GAIA_MEM_SANI_PUSH(value_size, m_pData, m_cap, m_cnt);
251 auto* ptr = &data()[m_cnt++];
252 core::call_ctor(ptr, GAIA_MOV(arg));
255 template <
typename... Args>
256 decltype(
auto) emplace_back(Args&&... args) {
259 GAIA_MEM_SANI_PUSH(value_size, m_pData, m_cap, m_cnt);
260 auto* ptr = &data()[m_cnt++];
261 core::call_ctor(ptr, GAIA_FWD(args)...);
262 return (reference)*ptr;
265 void pop_back()
noexcept {
266 GAIA_ASSERT(!empty());
268 auto* ptr = &data()[m_cnt];
269 core::call_dtor(ptr);
270 GAIA_MEM_SANI_POP(value_size, m_pData, m_cap, m_cnt);
278 iterator
insert(iterator pos,
const T& arg) {
279 GAIA_ASSERT(pos >= data());
280 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
282 const auto idxSrc = (size_type)core::distance(begin(), pos);
284 const auto idxDst = (size_type)core::distance(begin(), end()) + 1;
286 GAIA_MEM_SANI_PUSH(value_size, m_pData, m_cap, m_cnt);
287 mem::shift_elements_right<T, false>(m_pData, idxDst, idxSrc, m_cap);
288 auto* ptr = &data()[m_cnt];
289 core::call_ctor(ptr, arg);
293 return iterator(&data()[idxSrc]);
300 GAIA_ASSERT(pos >= data());
301 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
303 const auto idxSrc = (size_type)core::distance(begin(), pos);
305 const auto idxDst = (size_type)core::distance(begin(), end());
307 GAIA_MEM_SANI_PUSH(value_size, m_pData, m_cap, m_cnt);
308 mem::shift_elements_right<T, false>(m_pData, idxDst, idxSrc, m_cap);
309 auto* ptr = &data()[idxSrc];
310 core::call_ctor(ptr, GAIA_MOV(arg));
314 return iterator(&data()[idxSrc]);
319 iterator
erase(iterator pos)
noexcept {
320 GAIA_ASSERT(pos >= data());
321 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
326 const auto idxSrc = (size_type)core::distance(begin(), pos);
327 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
329 mem::shift_elements_left<T, false>(m_pData, idxDst, idxSrc, m_cap);
331 auto* ptr = &data()[m_cnt - 1];
332 core::call_dtor(ptr);
333 GAIA_MEM_SANI_POP(value_size, m_pData, m_cap, m_cnt);
337 return iterator(&data()[idxSrc]);
343 iterator
erase(iterator first, iterator last)
noexcept {
344 GAIA_ASSERT(first >= data())
345 GAIA_ASSERT(empty() || (first < iterator(data() + size())));
346 GAIA_ASSERT(last > first);
347 GAIA_ASSERT(last <= iterator(data() + size()));
352 const auto idxSrc = (size_type)core::distance(begin(), first);
353 const auto idxDst = size();
354 const auto cnt = (size_type)(last - first);
356 mem::shift_elements_left_fast<T, false>(m_pData, idxDst, idxSrc, cnt, m_cap);
358 auto* ptr = &data()[m_cnt - cnt];
359 core::call_dtor_n(ptr, cnt);
360 GAIA_MEM_SANI_POP_N(value_size, data(), m_cap, m_cnt, cnt);
364 return iterator(&data()[idxSrc]);
367 void clear() noexcept {
371 void shrink_to_fit() {
372 const auto cap = capacity();
373 const auto cnt = size();
378 auto* pDataOld = m_pData;
379 m_pData = view_policy::template alloc<Allocator>(m_cap = cnt);
380 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pData, m_cap, m_cnt);
381 mem::move_elements<T, false>(m_pData, pDataOld, cnt, 0);
382 GAIA_MEM_SANI_DEL_BLOCK(value_size, pDataOld, cap, cnt);
383 view_policy::template free<Allocator>(pDataOld);
389 template <
typename Func>
391 size_type erased = 0;
392 size_type idxDst = 0;
393 size_type idxSrc = 0;
395 while (idxSrc < m_cnt) {
396 if (func(
operator[](idxSrc))) {
397 if (idxDst < idxSrc) {
398 mem::move_element<T, false>(m_pData, m_pData, idxDst, idxSrc, m_cap, m_cap);
399 auto* ptr = &data()[idxSrc];
400 core::call_dtor(ptr);
404 auto* ptr = &data()[idxSrc];
405 core::call_dtor(ptr);
412 GAIA_MEM_SANI_POP_N(value_size, data(), m_cap, m_cnt, erased);
418 GAIA_NODISCARD size_type size() const noexcept {
422 GAIA_NODISCARD
bool empty() const noexcept {
426 GAIA_NODISCARD size_type capacity() const noexcept {
430 GAIA_NODISCARD size_type max_size() const noexcept {
431 return static_cast<size_type
>(-1);
434 GAIA_NODISCARD
decltype(
auto) front() noexcept {
435 GAIA_ASSERT(!empty());
436 return (reference)*begin();
439 GAIA_NODISCARD
decltype(
auto) front() const noexcept {
440 GAIA_ASSERT(!empty());
441 return (const_reference)*begin();
444 GAIA_NODISCARD
decltype(
auto) back() noexcept {
445 GAIA_ASSERT(!empty());
446 return (reference)(operator[](m_cnt - 1));
449 GAIA_NODISCARD
decltype(
auto) back() const noexcept {
450 GAIA_ASSERT(!empty());
451 return (const_reference) operator[](m_cnt - 1);
454 GAIA_NODISCARD
auto begin() noexcept {
455 return iterator(data());
458 GAIA_NODISCARD
auto begin() const noexcept {
462 GAIA_NODISCARD
auto cbegin() const noexcept {
463 return const_iterator(data());
466 GAIA_NODISCARD
auto rbegin() noexcept {
467 return iterator((pointer)&back());
470 GAIA_NODISCARD
auto rbegin() const noexcept {
471 return const_iterator((const_pointer)&back());
474 GAIA_NODISCARD
auto crbegin() const noexcept {
475 return const_iterator((const_pointer)&back());
478 GAIA_NODISCARD
auto end() noexcept {
479 return iterator(data() + size());
482 GAIA_NODISCARD
auto end() const noexcept {
483 return const_iterator(data() + size());
486 GAIA_NODISCARD
auto cend() const noexcept {
487 return const_iterator(data() + size());
490 GAIA_NODISCARD
auto rend() noexcept {
491 return iterator(data() - 1);
494 GAIA_NODISCARD
auto rend() const noexcept {
495 return const_iterator(data() - 1);
498 GAIA_NODISCARD
auto crend() const noexcept {
499 return const_iterator(data() - 1);
502 GAIA_NODISCARD
bool operator==(
const darr& other)
const noexcept {
503 if (m_cnt != other.m_cnt)
505 const size_type n = size();
506 for (size_type i = 0; i < n; ++i)
507 if (!(
operator[](i) == other[i]))
512 GAIA_NODISCARD
constexpr bool operator!=(
const darr& other)
const noexcept {
513 return !operator==(other);