10#include "../utility/utility.hpp"
11#include "../macros.hpp"
24hi_warning_ignore_msvc(26459);
26namespace hi {
inline namespace v1 {
36 using pointer = value_type *;
37 using const_pointer = value_type
const *;
38 using reference = value_type&;
39 using const_reference = value_type
const&;
40 using iterator = value_type *;
41 using const_iterator = value_type
const *;
48 constexpr static size_t value_alignment =
alignof(value_type);
55 return allocator_type{};
79 hilet other_size =
other.size();
80 hilet update = _reserve<false>(other_size);
82 _reserve_update(update, other_size);
94 if (
other._is_short()) {
95 hilet other_size =
other._short_size();
96 std::uninitialized_move_n(
other.begin(), other_size,
begin());
97 other._set_short_size(0);
98 _set_short_size(other_size);
101 _ptr = std::exchange(
other._ptr,
nullptr);
102 _end = std::exchange(
other._end,
nullptr);
103 _cap = std::exchange(
other._cap,
nullptr);
116 hi_return_on_self_assignment(
other);
118 hilet other_size =
other.size();
121 hilet update = _reserve<false>(other_size);
123 _reserve_update(update, other_size);
138 hi_return_on_self_assignment(
other);
140 if (not _is_short() and not
other._is_short()) {
149 if (
other._is_short()) {
150 hilet other_size =
other._short_size();
151 std::uninitialized_move_n(
other.begin(), other_size, _short_data());
152 _set_short_size(other_size);
155 _ptr = std::exchange(
other._ptr,
nullptr);
156 _end = std::exchange(
other._end,
nullptr);
157 _cap = std::exchange(
other._cap,
nullptr);
166 hilet this_is_short = this->_is_short();
167 hilet other_is_short =
other._is_short();
174 }
else if (other_is_short) {
190 std::uninitialized_value_construct_n(_short_data(), count);
191 _set_short_size(count);
194 hilet update = _reserve<false>(count);
195 std::uninitialized_value_construct_n(update.ptr, count);
196 _reserve_update(update, count);
200 lean_vector(size_type count, value_type
const& value)
204 _set_short_size(count);
207 hilet update = _reserve<false>(count);
209 _reserve_update(update, count);
218 lean_vector(std::input_iterator
auto first, std::input_iterator
auto last)
220 insert(_short_data(), first, last);
237 void assign(size_type count, value_type
const& value)
248 void assign(std::input_iterator
auto first, std::input_iterator
auto last)
271 if (_short_size() == 0) {
274 return _short_data();
289 [[nodiscard]] const_pointer
data() const noexcept
299 [[nodiscard]]
constexpr bool empty() const noexcept
302 return _short_size() == 0;
312 [[nodiscard]]
constexpr size_type
size() const noexcept
315 return _short_size();
317 hi_axiom(_ptr <= _end);
322 [[nodiscard]]
constexpr size_type max_size() const noexcept
332 if constexpr (std::endian::native == std::endian::little) {
334 return (
sizeof(
pointer) * 3 -
alignof(value_type)) /
sizeof(value_type);
337 return (
sizeof(
pointer) * 3 - 1) /
sizeof(value_type);
350 return _long_capacity();
362 hilet is_short = _is_short();
363 hilet size_ = is_short ? _short_size() : _long_size();
365 return _begin_data(is_short)[index];
377 [[nodiscard]] const_reference
at(size_type index)
const
390 hi_axiom(index <
size());
391 return _begin_data(_is_short())[index];
400 [[nodiscard]] const_reference
operator[](size_type index)
const noexcept
402 return const_cast<lean_vector *
>(
this)->
operator[](index);
412 hi_axiom(not
empty());
413 return *_begin_data(_is_short());
421 [[nodiscard]] const_reference
front() const noexcept
433 hi_axiom(not
empty());
434 return *(_end_data(_is_short()) - 1);
442 [[nodiscard]] const_reference
back() const noexcept
451 [[nodiscard]] iterator
begin() noexcept
453 return _begin_data(_is_short());
460 [[nodiscard]] const_iterator
begin() const noexcept
462 return _begin_data(_is_short());
469 [[nodiscard]] const_iterator
cbegin() const noexcept
478 [[nodiscard]] iterator
end() noexcept
480 return _end_data(_is_short());
487 [[nodiscard]] const_iterator
end() const noexcept
496 [[nodiscard]] const_iterator
cend() const noexcept
507 hilet is_short = _is_short();
508 std::destroy(_begin_data(is_short), _end_data(is_short));
509 _set_size(0, is_short);
522 hilet update = _reserve<false>(new_capacity);
523 _reserve_update(update);
540 hilet old_ptr = _ptr;
541 hilet old_size =
size();
545 _set_short_size(old_size);
549 _end = _ptr + old_size;
550 _cap = _ptr + old_size;
553 std::uninitialized_move_n(old_ptr, old_size,
begin());
554 std::destroy_n(old_ptr, old_size);
568 template<
typename... Args>
569 iterator
emplace(const_iterator pos, Args&&...args)
571 hilet index = pos -
begin();
572 hilet new_size =
size() + 1;
574 hilet update = _reserve<true>(new_size);
576 _reserve_update(update, new_size);
578 hilet new_pos =
begin() + index;
592 iterator
insert(const_iterator pos, value_type
const& value)
594 hilet index = pos -
begin();
595 hilet new_size =
size() + 1;
597 hilet update = _reserve<true>(new_size);
599 _reserve_update(update, new_size);
601 hilet new_pos =
begin() + index;
615 iterator
insert(const_iterator pos, value_type&& value)
617 hilet index = pos -
begin();
618 hilet new_size =
size() + 1;
620 hilet update = _reserve<true>(new_size);
622 _reserve_update(update, new_size);
624 hilet new_pos =
begin() + index;
639 iterator
insert(const_iterator pos, size_type count, value_type
const& value)
641 hilet index = pos -
begin();
642 hilet new_size =
size() + count;
644 hilet update = _reserve<true>(new_size);
646 _reserve_update(update, new_size);
648 hilet new_pos =
begin() + index;
663 iterator
insert(const_iterator pos, std::input_iterator
auto first, std::input_iterator
auto last)
668 hilet index = pos -
begin();
669 hilet new_size =
size() + n;
671 hilet update = _reserve<true>(new_size);
672 std::uninitialized_move_n(first, n, update.end);
673 _reserve_update(update, new_size);
675 hilet new_pos =
begin() + index;
680 for (
auto it = first; it != last; ++it) {
681 pos =
insert(pos, *it) + 1;
714 hi_axiom(pos >=
begin() and pos <=
end());
718 hilet is_short = _is_short();
719 _set_size(
size() - 1, is_short);
720 std::destroy_at(_end_data(is_short));
736 iterator
erase(const_iterator first, const_iterator last)
742 std::destroy(
end() - n,
end());
743 _set_size(
size() - n, _is_short());
754 template<
typename... Args>
757 hilet new_size =
size() + 1;
759 hilet update = _reserve<true>(new_size);
761 _reserve_update(update, new_size);
772 hilet new_size =
size() + 1;
774 hilet update = _reserve<true>(new_size);
776 _reserve_update(update, new_size);
785 hilet new_size =
size() + 1;
787 hilet update = _reserve<true>(new_size);
789 _reserve_update(update, new_size);
800 hi_axiom(not
empty());
802 hilet is_short = _is_short();
803 _set_size(
size() - 1, is_short);
804 std::destroy_at(_end_data(is_short));
819 if (hilet old_size =
size(); new_size > old_size) {
820 hilet n = new_size - old_size;
822 hilet update = _reserve<true>(new_size);
823 std::uninitialized_value_construct_n(update.end, n);
824 _reserve_update(update, new_size);
827 hilet is_short = _is_short();
828 hilet n = old_size - new_size;
829 std::destroy(_end_data(is_short) - n, _end_data(is_short));
830 _set_size(new_size, is_short);
845 void resize(size_type new_size, value_type
const& value)
847 if (hilet old_size =
size(); new_size > old_size) {
848 hilet n = new_size - old_size;
850 hilet update = _reserve<true>(new_size);
852 _reserve_update(update, new_size);
855 hilet is_short = _is_short();
856 hilet n = old_size - new_size;
857 std::destroy(
end() - n,
end());
858 _set_size(new_size, is_short);
870 return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
881 return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
894 c.erase(it, c.end());
904 template<
typename Pred>
909 c.erase(it, c.end());
919 pointer _ptr =
nullptr;
920 pointer _end =
nullptr;
921 pointer _cap =
nullptr;
923 [[nodiscard]]
constexpr bool _is_short() const noexcept
925 if constexpr (std::endian::native == std::endian::little) {
926 if (_ptr ==
nullptr) {
929 return to_bool(to_int(_ptr) & 1);
932 if (_cap ==
nullptr) {
935 return to_bool(to_int(_cap) & 1);
940 [[nodiscard]] pointer _short_data() const noexcept
942 static_assert(
alignof(value_type) <=
alignof(pointer));
945 if constexpr (std::endian::native == std::endian::little) {
948 return std::launder(
static_cast<pointer
>(p));
951 [[nodiscard]] pointer _long_data() const noexcept
956 [[nodiscard]]
constexpr size_type _short_size() const noexcept
958 if constexpr (std::endian::native == std::endian::little) {
959 if (_ptr ==
nullptr) {
962 return (to_int(_ptr) >> 1) & 0x1f;
965 if (_cap ==
nullptr) {
968 return (to_int(_cap) >> 1) & 0x1f;
973 [[nodiscard]]
constexpr size_type _long_size() const noexcept
975 hi_axiom(_ptr <= _end);
979 [[nodiscard]]
constexpr size_type _long_capacity() const noexcept
981 hi_axiom(_ptr <= _cap);
985 void _set_short_size(
size_t new_size)
noexcept
987 constexpr auto mask = ~intptr_t{0xff};
991 if constexpr (std::endian::native == std::endian::little) {
992 _ptr = to_ptr<pointer>((to_int(_ptr) & mask) | new_size);
994 _cap = to_ptr<pointer>((to_int(_cap) & mask) | new_size);
998 void _set_size(
size_t new_size,
bool is_short)
noexcept
1002 _set_short_size(new_size);
1004 _end = _ptr + new_size;
1008 [[nodiscard]] pointer _begin_data(
bool is_short)
const noexcept
1011 return _short_data();
1013 return _long_data();
1017 [[nodiscard]] pointer _end_data(
bool is_short)
const noexcept
1020 return _short_data() + _short_size();
1026 struct _reserve_type {
1038 template<
bool ForInsert>
1039 [[nodiscard]] _reserve_type _reserve(size_type new_capacity)
const
1041 hilet is_short = _is_short();
1044 [[likely]]
return {_begin_data(is_short), _end_data(is_short),
nullptr,
false, is_short};
1047 if constexpr (ForInsert) {
1049 if (new_capacity > next_capacity) {
1050 next_capacity = new_capacity + new_capacity / 2;
1052 new_capacity = next_capacity;
1058 hilet size_ = is_short ? _short_size() : _long_size();
1059 return {new_ptr, new_ptr + size_, new_ptr + new_capacity,
true,
false};
1062 void _reserve_update(_reserve_type update)
1064 if (not update.resized) {
1068 hilet is_short = _is_short();
1069 hilet old_size = is_short ? _short_size() : _long_size();
1070 hilet old_ptr = is_short ? _short_data() : _long_data();
1072 std::uninitialized_move_n(old_ptr, old_size, update.ptr);
1073 std::destroy_n(old_ptr, old_size);
1085 void _reserve_update(_reserve_type update, size_type new_size)
1087 _reserve_update(update);
1088 _set_size(new_size, update.is_short);
1092template<std::input_iterator It, std::input_iterator ItEnd>
@ other
The gui_event does not have associated data.
Definition gui_event_variant.hpp:22
void * advance_bytes(void *ptr, std::ptrdiff_t distance) noexcept
Advance a pointer by a number of bytes.
Definition memory.hpp:195
geometry/margins.hpp
Definition lookahead_iterator.hpp:5
The HikoGUI API version 1.
Definition lookahead_iterator.hpp:6
constexpr Out truncate(In rhs) noexcept
Cast between integral types truncating or zero-extending the result.
Definition cast.hpp:534
Lean-vector with (SVO) short-vector-optimization.
Definition lean_vector.hpp:33
lean_vector(lean_vector const &other)
Copy-construct a vector.
Definition lean_vector.hpp:77
iterator insert(const_iterator pos, std::input_iterator auto first, std::input_iterator auto last)
Insert new items.
Definition lean_vector.hpp:663
const_reference front() const noexcept
Get a const-reference to the first item in the vector.
Definition lean_vector.hpp:421
size_t capacity() const noexcept
Get the current capacity of the vector.
Definition lean_vector.hpp:345
reference back() noexcept
Get a reference to the last item in the vector.
Definition lean_vector.hpp:431
void push_back(value_type &&value)
Move an item to the end of the vector.
Definition lean_vector.hpp:783
const_iterator end() const noexcept
Get an const-iterator beyond the last item in the vector.
Definition lean_vector.hpp:487
lean_vector & operator=(lean_vector &&other) noexcept
Move-assign a vector.
Definition lean_vector.hpp:136
void clear() noexcept
Remove all items from the vector.
Definition lean_vector.hpp:505
void push_back(value_type const &value)
Copy an item to the end of the vector.
Definition lean_vector.hpp:770
constexpr size_t short_capacity() const noexcept
The maximum number of items that can fit without allocation.
Definition lean_vector.hpp:330
lean_vector(std::initializer_list< value_type > list)
Construct a vector with the given initializer list.
Definition lean_vector.hpp:227
iterator end() noexcept
Get an iterator beyond the last item in the vector.
Definition lean_vector.hpp:478
const_iterator cend() const noexcept
Get an const-iterator beyond the last item in the vector.
Definition lean_vector.hpp:496
iterator begin() noexcept
Get an iterator to the first item in the vector.
Definition lean_vector.hpp:451
iterator insert(const_iterator pos, std::initializer_list< value_type > list)
Insert new items.
Definition lean_vector.hpp:695
iterator erase(const_iterator pos)
Erase an item at position.
Definition lean_vector.hpp:712
void resize(size_type new_size, value_type const &value)
Resize a vector.
Definition lean_vector.hpp:845
friend size_type erase(lean_vector &c, value_type const &value)
Erase items of a value from a vector.
Definition lean_vector.hpp:890
reference emplace_back(Args &&...args)
In-place construct an item at the end of the vector.
Definition lean_vector.hpp:755
const_pointer data() const noexcept
Get a const-pointer to the first item.
Definition lean_vector.hpp:289
void resize(size_type new_size)
Resize a vector.
Definition lean_vector.hpp:817
pointer data() noexcept
Get a pointer to the first item.
Definition lean_vector.hpp:268
lean_vector(lean_vector &&other) noexcept(std::is_nothrow_move_constructible_v< value_type >)
Move-construct a vector.
Definition lean_vector.hpp:92
constexpr bool empty() const noexcept
Check if the vector is empty.
Definition lean_vector.hpp:299
friend bool operator==(lean_vector const &lhs, lean_vector const &rhs) noexcept
Compare two vectors.
Definition lean_vector.hpp:868
iterator insert(const_iterator pos, value_type &&value)
Insert a new item.
Definition lean_vector.hpp:615
friend auto operator<=>(lean_vector const &lhs, lean_vector const &rhs) noexcept
Compare two vectors lexicographically.
Definition lean_vector.hpp:879
void assign(std::initializer_list< value_type > list)
Replace the data in the vector.
Definition lean_vector.hpp:258
const_iterator begin() const noexcept
Get an const-iterator to the first item in the vector.
Definition lean_vector.hpp:460
friend size_type erase(lean_vector &c, Pred pred)
Erase items of a value from a vector.
Definition lean_vector.hpp:905
const_iterator cbegin() const noexcept
Get an const-iterator to the first item in the vector.
Definition lean_vector.hpp:469
void assign(std::input_iterator auto first, std::input_iterator auto last)
Replace the data in the vector.
Definition lean_vector.hpp:248
iterator insert(const_iterator pos, size_type count, value_type const &value)
Insert a new item.
Definition lean_vector.hpp:639
const_reference operator[](size_type index) const noexcept
Get a const-reference to an item in the vector.
Definition lean_vector.hpp:400
constexpr lean_vector() noexcept=default
Construct an empty vector.
reference at(size_type index)
Get a reference to an item in the vector.
Definition lean_vector.hpp:360
constexpr size_type size() const noexcept
Get the number of items in the vector.
Definition lean_vector.hpp:312
void shrink_to_fit()
Shrink the allocation to fit the current number of items.
Definition lean_vector.hpp:534
void pop_back()
Remove the last item from the vector.
Definition lean_vector.hpp:798
lean_vector & operator=(lean_vector const &other) noexcept
Copy-assign a vector.
Definition lean_vector.hpp:114
const_reference at(size_type index) const
Get a const-reference to an item in the vector.
Definition lean_vector.hpp:377
reference front() noexcept
Get a reference to the first item in the vector.
Definition lean_vector.hpp:410
iterator emplace(const_iterator pos, Args &&...args)
Construct in-place a new item.
Definition lean_vector.hpp:569
const_reference back() const noexcept
Get a const-reference to the last item in the vector.
Definition lean_vector.hpp:442
constexpr allocator_type get_allocator() const noexcept
The allocator_type used to allocate items.
Definition lean_vector.hpp:52
lean_vector(std::input_iterator auto first, std::input_iterator auto last)
Construct a vector with the data pointed by iterators.
Definition lean_vector.hpp:218
void assign(size_type count, value_type const &value)
Replace the data in the vector.
Definition lean_vector.hpp:237
reference operator[](size_type index) noexcept
Get a reference to an item in the vector.
Definition lean_vector.hpp:388
iterator erase(const_iterator first, const_iterator last)
Erase an items.
Definition lean_vector.hpp:736
void reserve(size_type new_capacity)
Reserve capacity for items.
Definition lean_vector.hpp:520
iterator insert(const_iterator pos, value_type const &value)
Insert a new item.
Definition lean_vector.hpp:592
Definition concepts.hpp:39
Definition concepts.hpp:42
T uninitialized_copy_n(T... args)
T uninitialized_fill_n(T... args)