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) {
80 darr(size_type count) {
84 template <
typename InputIt>
85 darr(InputIt first, InputIt last) {
86 const auto count = (size_type)core::distance(first, last);
89 if constexpr (std::is_pointer_v<InputIt>) {
90 for (size_type i = 0; i < count; ++i)
91 operator[](i) = first[i];
92 }
else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
93 for (size_type i = 0; i < count; ++i)
94 operator[](i) = *(first[i]);
97 for (
auto it = first; it != last; ++it)
98 operator[](++i) = *it;
102 darr(std::initializer_list<T> il):
darr(il.begin(), il.end()) {}
104 darr(
const darr& other):
darr(other.begin(), other.end()) {}
106 darr(
darr&& other)
noexcept: m_pData(other.m_pData), m_cnt(other.m_cnt), m_cap(other.m_cap) {
107 other.m_pData =
nullptr;
108 other.m_cnt = size_type(0);
109 other.m_cap = size_type(0);
112 darr& operator=(std::initializer_list<T> il) {
113 *
this =
darr(il.begin(), il.end());
117 darr& operator=(
const darr& other) {
118 GAIA_ASSERT(core::addressof(other) !=
this);
120 resize(other.size());
121 mem::copy_elements<T, false>(
122 m_pData, (
const uint8_t*)other.m_pData, other.size(), 0, capacity(), other.capacity());
127 darr& operator=(
darr&& other)
noexcept {
128 GAIA_ASSERT(core::addressof(other) !=
this);
131 view_policy::template free<Allocator>(m_pData, m_cap, m_cnt);
133 m_pData = other.m_pData;
137 other.m_pData =
nullptr;
138 other.m_cnt = size_type(0);
139 other.m_cap = size_type(0);
145 view_policy::template free<Allocator>(m_pData, m_cap, m_cnt);
148 GAIA_CLANG_WARNING_PUSH()
150 GAIA_CLANG_WARNING_DISABLE(
"-Wcast-align")
152 GAIA_NODISCARD pointer data()
noexcept {
153 return reinterpret_cast<pointer
>(m_pData);
156 GAIA_NODISCARD const_pointer data()
const noexcept {
157 return reinterpret_cast<const_pointer
>(m_pData);
160 GAIA_NODISCARD
decltype(
auto)
operator[](size_type pos)
noexcept {
161 GAIA_ASSERT(pos < size());
162 return view_policy::set({(
typename view_policy::TargetCastType)m_pData, capacity()}, pos);
165 GAIA_NODISCARD
decltype(
auto)
operator[](size_type pos)
const noexcept {
166 GAIA_ASSERT(pos < size());
167 return view_policy::get({(
typename view_policy::TargetCastType)m_pData, capacity()}, pos);
170 GAIA_CLANG_WARNING_POP()
172 void reserve(size_type cap) {
176 auto* pDataOld = m_pData;
177 m_pData = view_policy::template alloc<Allocator>(cap);
178 if (pDataOld !=
nullptr) {
179 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pData, cap, m_cnt);
180 mem::move_elements<T, false>(m_pData, pDataOld, m_cnt, 0, cap, m_cap);
181 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
187 void resize(size_type count) {
192 if (m_pData ==
nullptr) {
194 m_pData = view_policy::template alloc<Allocator>(count);
195 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pData, count, count);
196 core::call_ctor_n(m_pData, count);
206 core::call_dtor_n(&data()[count], m_cnt - count);
207 GAIA_MEM_SANI_POP_N(value_size, m_pData, m_cap, m_cnt, m_cnt - count);
214 if (count <= m_cap) {
216 GAIA_MEM_SANI_PUSH_N(value_size, m_pData, m_cap, m_cnt, count - m_cnt);
217 core::call_ctor_n(&data()[m_cnt], count - m_cnt);
223 auto* pDataOld = m_pData;
224 m_pData = view_policy::template alloc<Allocator>(count);
225 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pData, count, count);
227 mem::move_elements<T, false>(m_pData, pDataOld, m_cnt, 0, count, m_cap);
229 core::call_ctor_n(&data()[m_cnt], count - m_cnt);
231 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
237 void resize(size_type count, const_reference value) {
238 const auto oldCount = m_cnt;
241 if constexpr (std::is_copy_constructible_v<value_type>) {
242 const value_type valueCopy = value;
243 for (size_type i = oldCount; i < m_cnt; ++i)
244 operator[](i) = valueCopy;
246 for (size_type i = oldCount; i < m_cnt; ++i)
247 operator[](i) = value;
251 void push_back(
const T& arg) {
254 GAIA_MEM_SANI_PUSH(value_size, m_pData, m_cap, m_cnt);
255 auto* ptr = &data()[m_cnt++];
256 core::call_ctor(ptr, arg);
259 void push_back(T&& arg) {
262 GAIA_MEM_SANI_PUSH(value_size, m_pData, m_cap, m_cnt);
263 auto* ptr = &data()[m_cnt++];
264 core::call_ctor(ptr, GAIA_MOV(arg));
267 template <
typename... Args>
268 decltype(
auto) emplace_back(Args&&... args) {
271 GAIA_MEM_SANI_PUSH(value_size, m_pData, m_cap, m_cnt);
272 auto* ptr = &data()[m_cnt++];
273 core::call_ctor(ptr, GAIA_FWD(args)...);
274 return (reference)*ptr;
277 void pop_back()
noexcept {
278 GAIA_ASSERT(!empty());
280 auto* ptr = &data()[m_cnt - 1];
281 core::call_dtor(ptr);
282 GAIA_MEM_SANI_POP(value_size, m_pData, m_cap, m_cnt);
290 iterator
insert(iterator pos,
const T& arg) {
291 GAIA_ASSERT(pos >= data());
292 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
294 const auto idxSrc = (size_type)core::distance(begin(), pos);
296 const auto idxDst = (size_type)core::distance(begin(), end()) + 1;
298 GAIA_MEM_SANI_PUSH(value_size, m_pData, m_cap, m_cnt);
299 mem::shift_elements_right<T, false>(m_pData, idxDst, idxSrc, m_cap);
300 auto* ptr = &data()[m_cnt];
301 core::call_ctor(ptr, arg);
305 return iterator(&data()[idxSrc]);
312 GAIA_ASSERT(pos >= data());
313 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
315 const auto idxSrc = (size_type)core::distance(begin(), pos);
317 const auto idxDst = (size_type)core::distance(begin(), end());
319 GAIA_MEM_SANI_PUSH(value_size, m_pData, m_cap, m_cnt);
320 mem::shift_elements_right<T, false>(m_pData, idxDst, idxSrc, m_cap);
321 auto* ptr = &data()[idxSrc];
322 core::call_ctor(ptr, GAIA_MOV(arg));
326 return iterator(&data()[idxSrc]);
331 iterator
erase(iterator pos)
noexcept {
332 GAIA_ASSERT(pos >= data());
333 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
338 const auto idxSrc = (size_type)core::distance(begin(), pos);
339 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
341 mem::shift_elements_left<T, false>(m_pData, idxDst, idxSrc, m_cap);
343 auto* ptr = &data()[m_cnt - 1];
344 core::call_dtor(ptr);
345 GAIA_MEM_SANI_POP(value_size, m_pData, m_cap, m_cnt);
349 return iterator(&data()[idxSrc]);
355 iterator
erase(iterator first, iterator last)
noexcept {
356 GAIA_ASSERT(first >= data())
357 GAIA_ASSERT(empty() || (first < iterator(data() + size())));
358 GAIA_ASSERT(last > first);
359 GAIA_ASSERT(last <= iterator(data() + size()));
364 const auto idxSrc = (size_type)core::distance(begin(), first);
365 const auto idxDst = size();
366 const auto cnt = (size_type)(last - first);
368 mem::shift_elements_left_fast<T, false>(m_pData, idxDst, idxSrc, cnt, m_cap);
370 auto* ptr = &data()[m_cnt - cnt];
371 core::call_dtor_n(ptr, cnt);
372 GAIA_MEM_SANI_POP_N(value_size, data(), m_cap, m_cnt, cnt);
376 return iterator(&data()[idxSrc]);
379 void clear() noexcept {
383 void shrink_to_fit() {
384 const auto cap = capacity();
385 const auto cnt = size();
390 auto* pDataOld = m_pData;
391 m_pData = view_policy::template alloc<Allocator>(m_cap = cnt);
392 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pData, m_cap, m_cnt);
393 mem::move_elements<T, false>(m_pData, pDataOld, cnt, 0);
394 GAIA_MEM_SANI_DEL_BLOCK(value_size, pDataOld, cap, cnt);
395 view_policy::template free<Allocator>(pDataOld);
401 template <
typename Func>
403 size_type erased = 0;
404 size_type idxDst = 0;
405 size_type idxSrc = 0;
407 while (idxSrc < m_cnt) {
408 if (func(
operator[](idxSrc))) {
409 if (idxDst < idxSrc) {
410 mem::move_element<T, false>(m_pData, m_pData, idxDst, idxSrc, m_cap, m_cap);
411 auto* ptr = &data()[idxSrc];
412 core::call_dtor(ptr);
416 auto* ptr = &data()[idxSrc];
417 core::call_dtor(ptr);
424 GAIA_MEM_SANI_POP_N(value_size, data(), m_cap, m_cnt, erased);
430 GAIA_NODISCARD size_type size() const noexcept {
434 GAIA_NODISCARD
bool empty() const noexcept {
438 GAIA_NODISCARD size_type capacity() const noexcept {
442 GAIA_NODISCARD size_type max_size() const noexcept {
443 return static_cast<size_type
>(-1);
446 GAIA_NODISCARD
decltype(
auto) front() noexcept {
447 GAIA_ASSERT(!empty());
448 return (reference)*begin();
451 GAIA_NODISCARD
decltype(
auto) front() const noexcept {
452 GAIA_ASSERT(!empty());
453 return (const_reference)*begin();
456 GAIA_NODISCARD
decltype(
auto) back() noexcept {
457 GAIA_ASSERT(!empty());
458 return (reference)(operator[](m_cnt - 1));
461 GAIA_NODISCARD
decltype(
auto) back() const noexcept {
462 GAIA_ASSERT(!empty());
463 return (const_reference) operator[](m_cnt - 1);
466 GAIA_NODISCARD
auto begin() noexcept {
467 return iterator(data());
470 GAIA_NODISCARD
auto begin() const noexcept {
474 GAIA_NODISCARD
auto cbegin() const noexcept {
475 return const_iterator(data());
478 GAIA_NODISCARD
auto rbegin() noexcept {
479 return iterator((pointer)&back());
482 GAIA_NODISCARD
auto rbegin() const noexcept {
483 return const_iterator((const_pointer)&back());
486 GAIA_NODISCARD
auto crbegin() const noexcept {
487 return const_iterator((const_pointer)&back());
490 GAIA_NODISCARD
auto end() noexcept {
491 return iterator(data() + size());
494 GAIA_NODISCARD
auto end() const noexcept {
495 return const_iterator(data() + size());
498 GAIA_NODISCARD
auto cend() const noexcept {
499 return const_iterator(data() + size());
502 GAIA_NODISCARD
auto rend() noexcept {
503 return iterator(data() - 1);
506 GAIA_NODISCARD
auto rend() const noexcept {
507 return const_iterator(data() - 1);
510 GAIA_NODISCARD
auto crend() const noexcept {
511 return const_iterator(data() - 1);
514 GAIA_NODISCARD
bool operator==(
const darr& other)
const noexcept {
515 if (m_cnt != other.m_cnt)
517 const size_type n = size();
518 for (size_type i = 0; i < n; ++i)
519 if (!(
operator[](i) == other[i]))
524 GAIA_NODISCARD
constexpr bool operator!=(
const darr& other)
const noexcept {
525 return !operator==(other);