285 template <
typename T>
329 template <
typename T,
344 template <
typename P>
345 using has_minimum_size_mfn = decltype(std::declval<P &>().
minimum_size());
352 template <
typename P>
353 using has_get_size_mfn = decltype(std::declval<P &>().
get_size(std::declval<T const &>()));
360 template <
typename P>
361 using has_next_offset_mfn = decltype(std::declval<P &>().
get_next_offset(std::declval<T const &>()));
368 template <
typename P>
369 using can_set_next_offset_mfn = decltype(std::declval<P &>().
set_next_offset(std::declval<T &>(),
size_t{ 0 }));
376 template <
typename P>
377 using can_validate_mfn = decltype(std::declval<P &>().
validate(
size_t{0}, std::declval<T const &>()));
385 template <
typename P>
386 using has_alignment_mfn = decltype(std::declval<P &>().
alignment);
411 constexpr
static auto const has_minimum_size_v{ iffl::mpl::is_detected_v < has_minimum_size_mfn, type_traits> };
424 constexpr
static auto const has_get_size_v{ iffl::mpl::is_detected_v < has_get_size_mfn, type_traits> };
437 constexpr
static auto const has_next_offset_v{ iffl::mpl::is_detected_v < has_next_offset_mfn, type_traits> };
450 constexpr
static auto const can_set_next_offset_v{ iffl::mpl::is_detected_v < can_set_next_offset_mfn, type_traits> };
463 constexpr
static auto const can_validate_v{ iffl::mpl::is_detected_v < can_validate_mfn, type_traits> };
476 constexpr
static auto const has_alignment_v{ iffl::mpl::is_detected_v < has_alignment_mfn, type_traits> };
482 return static_cast<value_type *>(ptr);
489 return static_cast<value_type const *>(ptr);
496 return reinterpret_cast<value_type *>(ptr);
503 return reinterpret_cast<value_type const *>(ptr);
510 return reinterpret_cast<value_type *>(ptr);
517 return reinterpret_cast<value_type const *>(ptr);
523 return type_traits::minimum_size();
531 return type_traits::alignment;
584 [[nodiscard]] constexpr
static bool validate(
size_t buffer_size, T
const &buffer) noexcept {
586 return type_traits::validate(buffer_size, buffer);
599 return type_traits::get_next_offset(*
ptr_to_t(buffer));
614 "set_next_offset is not supported for type that does not have get_next_offset");
623 return type_traits::set_next_offset(*
ptr_to_t(buffer), size);
632 std::printf(
"type \"%s\" {\n", ti.name());
635 std::printf(
" minimum_size : yes -> %zu\n",
minimum_size());
637 std::printf(
" minimum_size : no \n");
641 std::printf(
" get_size : yes\n");
643 std::printf(
" get_size : no \n");
647 std::printf(
" get_next_offset : yes\n");
649 std::printf(
" get_next_offset : no \n");
653 std::printf(
" set_next_offset : yes\n");
655 std::printf(
" set_next_offset : no \n");
659 std::printf(
" validate : yes\n");
661 std::printf(
" validate : no \n");
665 std::printf(
" alignment : yes -> %zu\n",
alignment);
667 std::printf(
" alignment : no \n");
678 template <
typename T,
686 template <
typename T,
707 T
const &e)
const noexcept {
708 return TT::validate(buffer_size, e);
716 typename TT = flat_forward_list_traits<T>>
723 [[maybe_unused]] T
const &)
const noexcept {
731 typename TT = flat_forward_list_traits<T>,
732 typename F = default_validate_element_fn<T, TT>>
735 F
const &validate_element_fn = default_validate_element_fn<T, TT>{}) noexcept;
740 typename TT = flat_forward_list_traits<T>,
741 typename F = default_validate_element_fn<T, TT>>
744 F
const &validate_element_fn = default_validate_element_fn<T, TT>{}) noexcept;
749 typename TT = flat_forward_list_traits<T>,
750 typename F = default_validate_element_fn<T, TT>>
753 F
const &validate_element_fn = default_validate_element_fn<T, TT>{}) noexcept;
758 typename TT = flat_forward_list_traits<T>,
759 typename F = default_validate_element_fn<T, TT>>
762 F
const &validate_element_fn = default_validate_element_fn<T, TT>{}) noexcept;
767 typename TT = flat_forward_list_traits<T>,
768 typename F = default_validate_element_fn<T, TT>>
771 F
const &validate_element_fn = default_validate_element_fn<T, TT>{}) noexcept;
776 typename TT = flat_forward_list_traits<T>,
777 typename F = default_validate_element_fn<T, TT>>
780 F
const &validate_element_fn = default_validate_element_fn<T, TT>{}) noexcept;
785 typename TT = flat_forward_list_traits<T>,
786 typename F = default_validate_element_fn<T, TT>>
788 unsigned char const *
end,
789 F
const &validate_element_fn = default_validate_element_fn<T, TT>{}) noexcept;
794 typename TT = flat_forward_list_traits<T>,
795 typename F = default_validate_element_fn<T, TT>>
798 F
const &validate_element_fn = default_validate_element_fn<T, TT>{}) noexcept;
803 typename TT = flat_forward_list_traits<T>,
804 typename F = default_validate_element_fn<T, TT>>
807 F
const &validate_element_fn = default_validate_element_fn<T, TT>{}) noexcept;
812 typename TT = flat_forward_list_traits<T>,
813 typename F = default_validate_element_fn<T, TT>>
816 F
const &validate_element_fn = default_validate_element_fn<T, TT>{}) noexcept;
832 typename TT = flat_forward_list_traits<T>>
839 template <
typename TU,
848 template <
typename TU,
955 template <
typename Iterator>
965 template <
typename Iterator>
974 template <
typename Iterator>
976 is_const_iterator_v<Iterator> };
980 static_assert(!is_non_const_iterator_v<const_iterator>,
981 "This is a const iterator");
985 static_assert(is_non_const_iterator_v<non_const_iterator>,
986 "This is a non-const iterator");
996 template<
typename I,
997 typename = std::enable_if_t<is_const_iterator && is_non_const_iterator_v<I>>>
999 : p_{ other.get_ptr() } {
1014 template<
typename I,
1015 typename = std::enable_if_t<is_const_iterator && is_non_const_iterator_v<I>>>
1017 : p_{ other.get_ptr() } {
1031 if (
this != &other) {
1046 template <
typename I,
1047 typename = std::enable_if_t<is_const_iterator && is_non_const_iterator_v<I>>>
1049 p_ = other.get_ptr();
1066 template <
typename I,
1067 typename = std::enable_if_t<is_const_iterator && is_non_const_iterator_v<I>>>
1069 p_ = other.get_ptr();
1086 constexpr
explicit operator bool()
const {
1087 return p_ !=
nullptr;
1099 template <
typename I,
1100 typename = std::enable_if_t<is_comparable_iterator_v<I>>>
1102 return p_ == other.get_ptr();
1114 template <
typename I,
1115 typename = std::enable_if_t<is_comparable_iterator_v<I>>>
1129 template <
typename I,
1130 typename = std::enable_if_t<is_comparable_iterator_v<I>>>
1132 return p_ < other.get_ptr();
1144 template <
typename I,
1145 typename = std::enable_if_t<is_comparable_iterator_v<I>>>
1147 return p_ <= other.get_ptr();
1159 template <
typename I,
1160 typename = std::enable_if_t<is_comparable_iterator_v<I>>>
1174 template <
typename I,
1175 typename = std::enable_if_t<is_comparable_iterator_v<I>>>
1186 if (0 == next_offset) {
1188 p_ += element_size.size_padded();
1203 if (0 == next_offset) {
1205 p_ += element_size.size_padded();
1222 while (
nullptr != result.get_ptr() && 0 != advance_by) {
1233 return *reinterpret_cast<T *>(p_);
1240 return reinterpret_cast<T *>(p_);
1342 template<
typename T,
1343 typename TT = flat_forward_list_traits<T>>
1354 template<
typename T,
1366 template <
typename T,
1378 static_assert(std::is_pod_v<T>,
"T must be a Plain Old Definition");
1382 inline static bool const is_ref{ !std::is_const_v<T> };
1513 template<
typename V,
1515 typename = std::enable_if<std::is_assignable_v<T*, V*>>>
1517 : buffer_(other.buffer_) {
1529 : buffer_(other_buff) {
1548 : buffer_(
buffer_type{ buffer_begin, last_element, buffer_end }) {
1562 template <
typename V,
1564 typename = std::enable_if<std::is_assignable_v<T*, V*>>>
1569 reinterpret_cast<buffer_pointer>(
last.
get_ptr()) +
1583 size_t buffer_size) noexcept {
1584 assign(buffer, buffer_size);
1594 template <
typename V,
1597 typename UNUSED = std::enable_if<std::is_assignable_v<T*, V*>>>
1604 template <
typename V,
1606 typename = std::enable_if<std::is_assignable_v<T*, V*>>>
1608 buffer_ = other.buffer_;
1616 buffer_ = other_buffer;
1628 template <
typename V,
1631 typename UNUSED = std::enable_if<std::is_assignable_v<T*, V*>>>
1649 buffer_ = other_buff;
1664 buffer_ =
buffer_type{ buffer_begin, last_element, buffer_end };
1674 template <
typename V,
1676 typename = std::enable_if<std::is_assignable_v<T*, V*>>>
1681 reinterpret_cast<buffer_pointer>(
last.
get_ptr()) +
1690 size_t buffer_size) noexcept {
1692 auto[is_valid,
buffer_view] = flat_forward_list_validate<T, TT>(buffer,
1693 buffer + buffer_size);
1697 buffer + buffer_size };
1708 other = std::move(*
this);
1709 *
this = std::move(tmp);
1716 validate_pointer_invariants();
1718 return *(T *)buff().
begin;
1725 validate_pointer_invariants();
1727 return *(T *)buff().
begin;
1734 validate_pointer_invariants();
1736 return *(T *)buff().
last;
1743 validate_pointer_invariants();
1745 return *(T *)buff().
last;
1752 validate_pointer_invariants();
1761 validate_pointer_invariants();
1781 validate_pointer_invariants();
1790 validate_pointer_invariants();
1808 validate_pointer_invariants();
1816 return iterator{ buff().
last + last_element_size.size_padded() };
1820 return iterator{ buff().
last + last_element_size.size_padded() };
1840 validate_pointer_invariants();
1887 return buff().
begin;
1893 char const *
data() const noexcept {
1894 return buff().
begin;
1919 validate_pointer_invariants();
1920 validate_iterator_not_end(it);
1921 return size_unsafe(it).size;
1929 validate_pointer_invariants();
1930 validate_iterator_not_end(it);
1932 return used_size_unsafe(it);
1947 validate_iterator_not_end(it);
1949 return range_unsafe(it);
1966 validate_iterator_not_end(
begin);
1967 validate_iterator_not_end(
last);
1969 return closed_range_unsafe(
begin,
last);
1987 validate_iterator_not_end(
begin);
1988 validate_iterator_not_end(
end);
1990 return half_open_range_usafe(
begin,
end);
2004 validate_iterator(it);
2005 if (
cend() == it ||
npos == position) {
2008 range_t const r{ range_unsafe(it) };
2009 return r.buffer_contains(position);
2022 validate_pointer_invariants();
2023 if (empty_unsafe()) {
2026 auto[is_valid,
buffer_view] = flat_forward_list_validate<T, TT>(buff().
begin,
2027 buff().
begin + position);
2081 validate_pointer_invariants();
2083 std::for_each(
cbegin(),
cend(), [&s](T
const &) {
2096 [[nodiscard]]
bool empty() const noexcept {
2097 validate_pointer_invariants();
2098 return buff().
last ==
nullptr;
2104 explicit operator bool()
const {
2112 validate_pointer_invariants();
2120 validate_pointer_invariants();
2128 validate_pointer_invariants();
2142 bool empty_unsafe() const noexcept {
2143 return buff().
last ==
nullptr;
2148 void validate_pointer_invariants() const noexcept {
2155 void validate_iterator(
const_iterator const &it)
const noexcept {
2162 if (empty_unsafe()) {
2167 validate_compare_to_all_valid_elements(it);
2175 void validate_iterator_not_end(
const_iterator const &it)
const noexcept {
2185 validate_compare_to_all_valid_elements(it);
2192 void validate_compare_to_all_valid_elements(
const_iterator const &it)
const noexcept {
2193 #ifdef FFL_DBG_CHECK_ITERATOR_VALID 2198 bool found_match{
false };
2199 for (
auto cur =
cbegin(); cur !=
cend(); ++cur) {
2207 #else //FFL_DBG_CHECK_ITERATOR_VALID 2209 #endif //FFL_DBG_CHECK_ITERATOR_VALID 2235 if (0 == next_offset) {
2240 next_offset = s.
size;
2251 return s.size_padded();
2276 r.data_end = r.begin() + s.size;
2279 if (0 == next_offset) {
2281 r.buffer_end = r.begin() + s.size;
2283 r.buffer_end = r.begin() + next_offset;
2287 r.buffer_end = r.begin() + s.size;
2289 r.buffer_end = r.begin() + s.size_padded();
2299 if (first ==
last) {
2300 return element_range_unsafe(first);
2302 range_t first_element_range{ range_unsafe(first) };
2306 last_element_range.data_end,
2307 last_element_range.buffer_end } };
2320 if (this->
end() == end) {
2321 return closed_range_usafe(first,
last());
2324 size_t end_begin{ static_cast<size_t>(
end->
get_ptr() - buff().
begin) };
2327 return closed_range_usafe(first,
last);
2335 sizes_t get_all_sizes() const noexcept {
2338 s.total_capacity = buff().
end - buff().
begin;
2340 if (
nullptr != buff().
last) {
2373 template <
typename T,
2374 typename TT = flat_forward_list_traits<T>>
2388 template <
typename T,
2404 template <
typename T,
2420 template <
typename T,
2436 template <
typename T,
2452 template <
typename T,
2468 template <
typename T,
2484 template <
typename T,
2500 template <
typename T,
2516 template <
typename T,
2532 template <
typename T,
2600 template <
typename T,
2601 typename TT = flat_forward_list_traits<T>,
2602 typename A = std::allocator<T>>
2603 class flat_forward_list final {
2610 template <
typename TU,
2621 static_assert(std::is_pod_v<T>,
"T must be a Plain Old Definition");
2695 using allocator_type =
typename std::allocator_traits<A>::template rebind_alloc<char>;
2767 move_from(std::move(other));
2776 : buffer_(
one_then_variadic_args_t{}, allocator_type_traits::select_on_container_copy_construction(other.get_allocator()) ) {
2799 template <
typename AA = allocator_type>
2802 AA &&a = AA{}) noexcept
2817 template <
typename AA = allocator_type>
2848 template <
typename AA = allocator_type>
2853 AA &&a = AA{}) noexcept
2855 attach(buffer_begin, last_element, buffer_end);
2873 template <
typename AA = allocator_type>
2875 char const *last_element,
2876 char const *buffer_end,
2879 assign(buffer_begin, last_element, buffer_end);
2903 template <
typename AA = allocator_type>
2907 AA &&a = AA{}) noexcept
2913 (void )
attach(buffer, buffer_size);
2928 template <
typename AA = allocator_type>
2937 (void )
assign(buffer, buffer_size);
2946 template <
typename AA = allocator_type>
2959 template <
typename AA = allocator_type>
2976 if (
this != &other) {
2977 if constexpr (allocator_type_traits::propagate_on_container_move_assignment::value) {
2978 move_allocator_from(std::move(other));
2979 move_from(std::move(other));
2981 try_move_from(std::move(other));
2995 if (
this != &other) {
3000 if constexpr (allocator_type_traits::propagate_on_container_copy_assignment::value) {
3002 *static_cast<allocator_type *>(
this) = allocator_type_traits::select_on_container_copy_construction(other.get_allocator());
3056 buff() = other_buff;
3079 char *buffer_end) noexcept {
3088 buff().
begin = buffer_begin;
3089 buff().
end = buffer_end;
3090 buff().
last = last_element;
3108 size_t buffer_size) noexcept {
3110 auto [is_valid,
buffer_view] = flat_forward_list_validate<T, TT>(buffer,
3111 buffer + buffer_size);
3114 buffer + buffer_size);
3129 l.buff().begin = allocate_buffer(other_buff.
size());
3131 l.buff().end = l.buff().begin + other_buff.
size();
3132 l.buff().last = l.buff().begin + other_buff.
last_offset();
3150 char const *last_element,
3151 char const *buffer_end) {
3160 size_type buffer_size = buffer_end - buffer_begin;
3161 size_type last_element_offset = last_element - buffer_begin;
3163 l.buff().begin = allocate_buffer(buffer_size);
3164 copy_data(l.buff().begin, buffer_begin, buffer_size);
3165 l.buff().end = l.buff().begin + buffer_size;
3166 l.buff().last = l.buff().begin + last_element_offset;
3180 [[nodiscard]]
bool assign(
char const *buffer_begin,
3181 char const *buffer_end) {
3183 auto[is_valid,
buffer_view] = flat_forward_list_validate<T, TT>(buffer_begin,
3202 [[nodiscard]]
bool assign(
char const *buffer,
3205 return assign(buffer, buffer + buffer_size);
3220 new_list.push_back(
used_size(it), it.get_ptr());
3232 if (!view.
empty()) {
3240 new_list.push_back(
used_size(it), it.get_ptr());
3256 template<
typename AA>
3288 validate_pointer_invariants();
3293 validate_pointer_invariants();
3323 validate_pointer_invariants();
3325 sizes_t const prev_sizes{ get_all_sizes() };
3327 char *new_buffer{
nullptr };
3328 size_t new_buffer_size{ 0 };
3329 auto deallocate_buffer{ make_scoped_deallocator(&new_buffer, &new_buffer_size) };
3333 if (prev_sizes.total_capacity <
size) {
3334 new_buffer = allocate_buffer(
size);
3335 new_buffer_size =
size;
3336 if (
nullptr != buff().
last) {
3337 copy_data(new_buffer, buff().
begin, prev_sizes.used_capacity().size);
3338 buff().
last = new_buffer + prev_sizes.last_element.begin();
3340 commit_new_buffer(new_buffer, new_buffer_size);
3345 }
else if (0 ==
size) {
3355 }
else if (prev_sizes.total_capacity >
size) {
3357 new_buffer = allocate_buffer(
size);
3358 new_buffer_size =
size;
3360 bool is_valid{
true };
3361 char *last_valid{ buff().
last };
3367 if (prev_sizes.used_capacity().size >
size) {
3369 std::tie(is_valid,
buffer_view) = flat_forward_list_validate<T, TT>(buff().
begin,
3383 size_type const new_used_capacity{ new_last_element_offset + last_valid_element_size.
size };
3385 set_no_next_element(last_valid);
3388 buff().
last = new_buffer + new_last_element_offset;
3390 buff().
last =
nullptr;
3393 commit_new_buffer(new_buffer, new_buffer_size);
3397 validate_pointer_invariants();
3398 validate_data_invariants();
3412 char const *init_buffer =
nullptr) {
3415 [init_buffer_size, init_buffer](T &buffer,
3419 copy_data(reinterpret_cast<char *>(&buffer), init_buffer, element_size);
3421 zero_buffer(reinterpret_cast<char *>(&buffer), element_size);
3439 char const *init_buffer =
nullptr) {
3442 [init_buffer_size, init_buffer](T &buffer,
3446 copy_data(reinterpret_cast<char *>(&buffer), init_buffer, element_size);
3448 zero_buffer(reinterpret_cast<char *>(&buffer), element_size);
3465 template <
typename F>
3468 bool const result{ try_emplace_back_impl(can_reallocate::yes, element_size, fn) };
3484 template <
typename F>
3487 return try_emplace_back_impl(can_reallocate::no, element_size, fn);
3500 validate_pointer_invariants();
3504 if (has_exactly_one_entry()) {
3508 buff().
last =
nullptr;
3513 size_t const last_element_start_offset{ static_cast<size_t>(buff().
last - buff().
begin) };
3523 set_no_next_element(element_before_it.get_ptr());
3524 buff().
last = element_before_it.get_ptr();
3527 validate_pointer_invariants();
3528 validate_data_invariants();
3552 [init_buffer_size, init_buffer](T &buffer,
3557 copy_data(reinterpret_cast<char *>(&buffer), init_buffer, element_size);
3559 zero_buffer(reinterpret_cast<char *>(&buffer), element_size);
3585 char const *init_buffer =
nullptr) {
3588 [init_buffer_size, init_buffer](T &buffer,
3592 copy_data(reinterpret_cast<char *>(&buffer), init_buffer, element_size);
3594 zero_buffer(reinterpret_cast<char *>(&buffer), element_size);
3622 template <
typename F>
3626 auto [result, new_it] = try_emplace_impl(can_reallocate::yes,
3655 template <
typename F>
3659 auto[result, new_it] = try_emplace_impl(can_reallocate::no,
3678 char const *init_buffer =
nullptr) {
3681 [init_buffer_size, init_buffer](T &buffer,
3686 copy_data(reinterpret_cast<char *>(&buffer), init_buffer, element_size);
3688 zero_buffer(reinterpret_cast<char *>(&buffer), element_size);
3705 char const *init_buffer =
nullptr) {
3708 [init_buffer_size, init_buffer](T &buffer,
3712 copy_data(reinterpret_cast<char *>(&buffer), init_buffer, element_size);
3714 zero_buffer(reinterpret_cast<char *>(&buffer), element_size);
3732 template <
typename F>
3749 template <
typename F>
3759 validate_pointer_invariants();
3765 if (has_one_or_no_entry()) {
3766 buff().
last =
nullptr;
3772 sizes_t const prev_sizes{ get_all_sizes() };
3774 iterator const secont_element_it{ begin_it + 1 };
3775 range_t const second_element_range{ this->range_unsafe(secont_element_it) };
3776 size_type const bytes_to_copy{ prev_sizes.used_capacity().size - second_element_range.begin() };
3783 buff().
last -= second_element_range.begin();
3785 validate_pointer_invariants();
3786 validate_data_invariants();
3795 validate_pointer_invariants();
3799 validate_iterator_not_end(it);
3809 ++element_to_erase_it;
3810 bool const erasing_last_element = (
last() == element_to_erase_it);
3812 if (erasing_last_element) {
3817 set_no_next_element(it.get_ptr());
3818 buff().
last = it.get_ptr();
3823 sizes_t const prev_sizes{ get_all_sizes() };
3824 range_t const element_to_erase_range{ this->range_unsafe(element_to_erase_it) };
3825 size_type const tail_size{ prev_sizes.used_capacity().size - element_to_erase_range.buffer_end };
3831 buff().
begin + element_to_erase_range.buffer_end, tail_size
3833 buff().
last -= element_to_erase_range.buffer_size();
3836 validate_pointer_invariants();
3837 validate_data_invariants();
3852 validate_pointer_invariants();
3856 validate_iterator_not_end(before_start);
3857 validate_iterator(before_start);
3865 if (
end() == last) {
3878 iterator first_element_to_erase_it = before_start;
3879 ++first_element_to_erase_it;
3883 sizes_t const prev_sizes{ get_all_sizes() };
3885 range_t const first_element_to_erase_range{ this->range_unsafe(first_element_to_erase_it) };
3886 range_t const last_element_to_erase_range{ this->range_unsafe(
last) };
3892 size_type const bytes_to_copy{ prev_sizes.used_capacity().size - last_element_to_erase_range.buffer_end };
3893 size_type const bytes_erased{ last_element_to_erase_range.buffer_end - first_element_to_erase_range.begin() };
3899 buff().
begin + last_element_to_erase_range.buffer_end,
3901 buff().
last -= bytes_erased;
3903 validate_pointer_invariants();
3904 validate_data_invariants();
3913 validate_pointer_invariants();
3914 validate_iterator(it);
3920 buff().
last = it.get_ptr();
3921 set_no_next_element(buff().
last);
3923 validate_pointer_invariants();
3924 validate_data_invariants();
3935 validate_pointer_invariants();
3936 validate_iterator(it);
3943 if (it ==
begin()) {
3944 buff().
last =
nullptr;
3948 range_t const element_rtange{ range_unsafe(it) };
3954 set_no_next_element(element_before.
get_ptr());
3956 return element_before;
3965 validate_pointer_invariants();
3966 buff().
last =
nullptr;
3977 validate_pointer_invariants();
3978 validate_iterator_not_end(it);
3980 if (
begin() == it) {
3990 sizes_t const prev_sizes{ get_all_sizes() };
3991 range_t const element_range{ range_unsafe(it) };
3996 size_type const tail_size{ prev_sizes.used_capacity().size - element_range.buffer_end };
4001 buff().
begin + element_range.buffer_end,
4004 buff().
last -= element_range.buffer_size();
4006 validate_pointer_invariants();
4007 validate_data_invariants();
4020 validate_pointer_invariants();
4021 validate_iterator_not_end(start);
4022 validate_iterator(
end);
4032 if (this->
end() == end) {
4039 sizes_t const prev_sizes{ get_all_sizes() };
4041 range_t const start_range = range_unsafe(start);
4043 size_type const bytes_to_copy{ prev_sizes.used_capacity().size - end_range.buffer_end };
4044 size_type const bytes_erased{ end_range.begin() - start_range.begin() };
4047 buff().
begin + end_range.begin(),
4050 buff().
last -= bytes_erased;
4052 validate_pointer_invariants();
4053 validate_data_invariants();
4065 allocator_type_traits::propagate_on_container_move_assignment::value) {
4066 if constexpr (allocator_type_traits::propagate_on_container_swap::value) {
4073 other = std::move(*
this);
4074 *
this = std::move(tmp);
4084 template <
typename LESS_F>
4091 std::vector<const_iterator> iterator_array;
4093 iterator_array.push_back(i);
4095 std::sort(iterator_array.begin(),
4096 iterator_array.end(),
4100 return fn(*lhs, *rhs);
4110 sorted_list.push_back(
used_size(i), i.get_ptr());
4126 reversed_list.push_front(i.get_ptr(), element_used_size(i));
4131 swap(reversed_list);
4150 iterator other_start = other.begin();
4151 iterator const other_end = other.end();
4153 for ( ; this_start != this_end && other_start != other_end;) {
4154 if (fn(*this_start, *other_start)) {
4158 merged_list.push_back(other.required_size(other_start), other_start.
get_ptr());
4163 for (; this_start != this_end; ++this_start) {
4167 for (; other_start != other_end; ++other_start) {
4168 merged_list.push_back(other.required_size(other_start), other_start.
get_ptr());
4180 template<
typename F>
4183 if (first !=
end()) {
4186 for (++after; after !=
end(); ++after) {
4187 if (fn(*first, *after)) {
4217 template<
typename F>
4225 if (first ==
end()) {
4228 }
else if (first !=
end()) {
4239 validate_pointer_invariants();
4241 return *reinterpret_cast<T *>(buff().
begin);
4248 validate_pointer_invariants();
4250 return *reinterpret_cast<T *>(buff().
begin);
4257 validate_pointer_invariants();
4259 return *reinterpret_cast<T *>(buff().
last);
4266 validate_pointer_invariants();
4268 return *reinterpret_cast<T *>(buff().
last);
4275 validate_pointer_invariants();
4284 validate_pointer_invariants();
4304 validate_pointer_invariants();
4313 validate_pointer_invariants();
4323 validate_pointer_invariants();
4326 return iterator{ buff().
last + last_element_size.size_padded() };
4337 validate_pointer_invariants();
4374 return buff().
begin;
4380 char const *
data() const noexcept {
4381 return buff().
begin;
4395 if (data_size !=
npos) {
4396 new_data_size = std::min(data_size, new_data_size);
4399 buff().
begin + new_data_size);
4438 validate_pointer_invariants();
4439 validate_iterator_not_end(it);
4451 [new_element_size] ([[maybe_unused]] T &buffer,
4484 validate_pointer_invariants();
4485 validate_iterator_not_end(it);
4497 zero_buffer(reinterpret_cast<char *>(&buffer) + old_size, new_size - old_size);
4514 validate_pointer_invariants();
4515 validate_iterator_not_end(it);
4527 zero_buffer(reinterpret_cast<char *>(&buffer) + old_size, new_size - old_size);
4543 template <
typename F>
4547 auto[result, new_it] = element_resize_impl(can_reallocate::yes,
4567 template <
typename F>
4571 auto[result, new_it] = element_resize_impl(can_reallocate::no,
4584 validate_pointer_invariants();
4585 validate_iterator_not_end(it);
4586 return size_unsafe(it).size;
4594 validate_pointer_invariants();
4597 return used_size_unsafe(it);
4612 validate_iterator_not_end(it);
4614 return range_unsafe(it);
4632 validate_iterator_not_end(
begin);
4633 validate_iterator_not_end(
last);
4635 return closed_range_unsafe(
begin,
last);
4653 validate_iterator_not_end(
begin);
4654 validate_iterator_not_end(
end);
4656 return half_open_range_usafe(
begin,
end);
4670 validate_iterator(it);
4671 if (
cend() == it ||
npos == position) {
4674 range_t const r{ range_unsafe(it) };
4675 return r.buffer_contains(position);
4688 validate_pointer_invariants();
4689 if (empty_unsafe()) {
4692 auto const [is_valid,
buffer_view] = flat_forward_list_validate<T, TT>(buff().
begin,
4693 buff().
begin + position);
4712 validate_pointer_invariants();
4713 if (empty_unsafe()) {
4716 auto[is_valid,
buffer_view] = flat_forward_list_validate<T, TT>(buff().
begin,
4717 buff().
begin + position);
4811 validate_pointer_invariants();
4813 std::for_each(
cbegin(),
cend(), [&s](T
const &) noexcept {
4827 validate_pointer_invariants();
4828 return buff().
last ==
nullptr;
4835 validate_pointer_invariants();
4836 sizes_t const s{ get_all_sizes() };
4843 validate_pointer_invariants();
4851 validate_pointer_invariants();
4852 sizes_t const s{ get_all_sizes() };
4863 bool zero_unused_capacity =
true) noexcept {
4864 validate_pointer_invariants();
4872 for (
auto it =
begin();
last != it; ++it) {
4873 range_t const element_range{ range_unsafe(it) };
4874 element_range.fill_unused_capacity_data_ptr(it.get_ptr(), fill_byte);
4879 if (zero_unused_capacity) {
4880 sizes_t const prev_sizes{ get_all_sizes() };
4881 if (prev_sizes.used_capacity().size > 0) {
4882 size_type const last_element_end{ prev_sizes.
last_element.begin() + prev_sizes.last_element.data_size() };
4883 size_type const unuset_tail_size{ prev_sizes.total_capacity - last_element_end };
4890 validate_pointer_invariants();
4891 validate_data_invariants();
4901 enum class can_reallocate : bool {
4931 template <
typename F>
4932 [[nodiscard]]
bool try_emplace_back_impl(can_reallocate reallocation_policy,
4935 validate_pointer_invariants();
4939 char *new_buffer{
nullptr };
4940 size_t new_buffer_size{ 0 };
4941 auto deallocate_buffer{ make_scoped_deallocator(&new_buffer, &new_buffer_size) };
4943 sizes_t const prev_sizes{ get_all_sizes() };
4945 char *cur{
nullptr };
4951 if (prev_sizes.remaining_capacity_for_append() < element_size) {
4952 if (reallocation_policy == can_reallocate::no) {
4956 (element_size - prev_sizes.remaining_capacity_for_append());
4957 new_buffer = allocate_buffer(new_buffer_size);
4958 cur = new_buffer + prev_sizes.used_capacity().size_padded();
4960 cur = buff().
begin + prev_sizes.used_capacity().size_padded();
4965 set_no_next_element(cur);
4978 set_next_offset(buff().
last, prev_sizes.last_element.data_size_padded());
4983 if (new_buffer !=
nullptr) {
4989 copy_data(new_buffer, buff().
begin, prev_sizes.used_capacity().size);
4991 commit_new_buffer(new_buffer, new_buffer_size);
4998 validate_pointer_invariants();
4999 validate_data_invariants();
5031 template <
typename F>
5032 [[nodiscard]] std::pair<bool, iterator> try_emplace_impl(can_reallocate reallocation_policy,
5037 validate_pointer_invariants();
5038 validate_iterator(it);
5043 bool result{ try_emplace_back_impl(reallocation_policy,
5046 return std::make_pair(result,
last());
5056 char *new_buffer{
nullptr };
5057 size_t new_buffer_size{ 0 };
5058 auto deallocate_buffer{ make_scoped_deallocator(&new_buffer, &new_buffer_size) };
5060 sizes_t const prev_sizes{ get_all_sizes() };
5061 range_t const element_range{ this->range_unsafe(it) };
5066 size_type const tail_size{ prev_sizes.used_capacity().size - element_range.begin() };
5068 char *
begin{
nullptr };
5069 char *cur{
nullptr };
5076 if (prev_sizes.remaining_capacity_for_insert() < new_element_size_aligned) {
5077 if (can_reallocate::no == reallocation_policy) {
5078 return std::make_pair(
false, it);
5081 (new_element_size_aligned - prev_sizes.remaining_capacity_for_insert());
5082 new_buffer = allocate_buffer(new_buffer_size);
5083 cur = new_buffer + element_range.begin();
5089 char *new_tail_start{
nullptr };
5097 new_tail_start =
begin + element_range.begin() + new_element_size_aligned;
5098 move_data(new_tail_start, it.get_ptr(), tail_size);
5114 move_data(it.get_ptr(), new_tail_start, tail_size);
5119 set_next_offset(cur, new_element_size_aligned);
5128 new_element_size_aligned < cur_element_size.size_padded());
5131 new_element_size_aligned == cur_element_size.size_padded());
5137 if (new_buffer !=
nullptr) {
5144 copy_data(cur + new_element_size_aligned, it.get_ptr(), tail_size);
5146 commit_new_buffer(new_buffer, new_buffer_size);
5151 buff().
last = buff().
begin + prev_sizes.last_element.begin() + new_element_size_aligned;
5153 validate_pointer_invariants();
5154 validate_data_invariants();
5158 return std::make_pair(
true,
iterator{ cur });
5168 bool empty_unsafe() const noexcept {
5169 return buff().
last ==
nullptr;
5184 template <
typename F>
5185 [[nodiscard]] std::pair<bool, iterator> resize_last_element(can_reallocate reallocation_policy,
5189 validate_pointer_invariants();
5191 sizes_t const prev_sizes{ get_all_sizes() };
5192 difference_type const element_size_diff{ static_cast<difference_type>(new_size - prev_sizes.last_element.data_size()) };
5204 if (element_size_diff < 0 ||
5205 prev_sizes.remaining_capacity_for_insert() >= static_cast<size_type>(element_size_diff)) {
5208 prev_sizes.last_element.data_size(),
5213 if (can_reallocate::no == reallocation_policy) {
5214 return std::make_pair(
false,
last());
5217 char *new_buffer{
nullptr };
5219 auto deallocate_buffer{ make_scoped_deallocator(&new_buffer, &new_buffer_size) };
5221 new_buffer_size = prev_sizes.used_capacity().size + new_size - prev_sizes.last_element.data_size();
5222 new_buffer = allocate_buffer(new_buffer_size);
5224 char *new_last_ptr{ new_buffer + prev_sizes.last_element.begin() };
5229 buff().
begin + prev_sizes.last_element.begin(),
5230 prev_sizes.last_element.data_size());
5235 prev_sizes.last_element.data_size(),
5240 copy_data(new_buffer, buff().
begin, prev_sizes.last_element.begin());
5244 commit_new_buffer(new_buffer, new_buffer_size);
5245 buff().
last = new_last_ptr;
5248 validate_pointer_invariants();
5249 validate_data_invariants();
5251 return std::make_pair(
true,
last());
5265 template <
typename F>
5266 [[nodiscard]] std::pair<bool, iterator> element_resize_impl(can_reallocate reallocation_policy,
5273 if (0 == new_size) {
5274 return std::make_pair(
true,
erase(it));
5284 return resize_last_element(reallocation_policy, new_size, fn);
5290 validate_pointer_invariants();
5291 validate_iterator_not_end(it);
5295 sizes_t prev_sizes{ get_all_sizes() };
5296 range_t element_range_before{ range_unsafe(it) };
5305 size_type const tail_size{ prev_sizes.used_capacity().size - element_range_before.buffer_end };
5309 difference_type const element_size_diff{ static_cast<difference_type>(new_size_padded - element_range_before.buffer_size()) };
5314 if (element_size_diff < 0 ||
5315 prev_sizes.remaining_capacity_for_insert() >= static_cast<size_type>(element_size_diff)) {
5317 size_type tail_start_offset = element_range_before.buffer_end;
5323 if (new_size_padded > element_range_before.buffer_size()) {
5324 move_data(buff().
begin + element_range_before.begin() + new_size_padded,
5325 buff().
begin + tail_start_offset,
5328 tail_start_offset = element_range_before.begin() + new_size_padded;
5341 &element_range_before] {
5355 range_t element_range_after{ {element_range_before.
begin(),
5356 element_range_before.begin() + element_size_after.size,
5357 element_range_before.begin() + new_size_padded} };
5358 element_range_after.verify();
5366 if (element_range_after.buffer_end != element_range_before.buffer_end) {
5369 buff().
begin + tail_start_offset,
5374 difference_type tail_shift{ static_cast<difference_type>(element_range_after.buffer_size() -
5375 element_range_before.buffer_size()) };
5379 buff().
last += tail_shift;
5382 this->set_next_offset(it.get_ptr(), element_range_after.buffer_size());
5386 element_range_before.buffer_size(),
5392 if (can_reallocate::no == reallocation_policy) {
5393 return std::make_pair(
false, it);
5398 char *new_buffer{
nullptr };
5400 auto deallocate_buffer{ make_scoped_deallocator(&new_buffer, &new_buffer_size) };
5402 new_buffer_size = prev_sizes.used_capacity().size + new_size_padded - element_range_before.buffer_size();
5403 new_buffer = allocate_buffer(new_buffer_size);
5407 copy_data(new_buffer + element_range_before.begin(),
5408 buff().
begin + element_range_before.begin(),
5409 element_range_before.buffer_size());
5414 element_range_before.buffer_size(),
5420 result_it =
iterator{ new_buffer + element_range_before.begin() };
5424 copy_data(new_buffer, buff().
begin, element_range_before.begin());
5438 range_t element_range_after{ { element_range_before.
begin(),
5439 element_range_before.begin() + element_size_after.size,
5440 element_range_before.begin() + new_size_padded } };
5441 element_range_after.verify();
5445 move_data(new_buffer + element_range_after.buffer_end,
5446 buff().
begin + element_range_before.buffer_end,
5451 commit_new_buffer(new_buffer, new_buffer_size);
5455 difference_type tail_shift{ static_cast<difference_type>(element_range_after.buffer_size() -
5456 element_range_before.buffer_size()) };
5460 buff().
last = buff().
begin + prev_sizes.last_element.begin() + tail_shift;
5464 this->set_next_offset(result_it.get_ptr(), element_range_after.buffer_size());
5467 validate_pointer_invariants();
5468 validate_data_invariants();
5472 return std::make_pair(
true, result_it);
5478 [[nodiscard]] constexpr
bool has_one_or_no_entry() const noexcept {
5485 [[nodiscard]] constexpr
bool has_exactly_one_entry() const noexcept {
5486 return nullptr != buff().
last &&
5495 constexpr
static void set_no_next_element(
char *buffer) noexcept {
5496 set_next_offset(buffer, 0);
5505 constexpr
static void set_next_offset([[maybe_unused]]
char *buffer, [[maybe_unused]]
size_t size) noexcept {
5518 alloc() = std::move(other.alloc());
5528 buff().
begin = other.buff().begin;
5529 buff().
end = other.buff().end;
5530 buff().
last = other.buff().last;
5531 other.buff().begin =
nullptr;
5532 other.buff().end =
nullptr;
5533 other.buff().last =
nullptr;
5544 move_from(std::move(other));
5555 if (other.buff().last) {
5556 sizes_t const other_sizes{ other.get_all_sizes() };
5557 buff().
begin = allocate_buffer(other_sizes.used_capacity().size);
5558 copy_data(buff().
begin, other.buff().begin, other_sizes.used_capacity().size);
5559 buff().
end = buff().
begin + other_sizes.used_capacity().size;
5560 buff().
last = buff().
begin + other_sizes.last_element.begin();
5568 [[nodiscard]]
char *allocate_buffer(
size_t buffer_size) {
5569 char *ptr{ allocator_type_traits::allocate(alloc(), buffer_size) };
5579 void deallocate_buffer(
char *buffer,
size_t buffer_size) noexcept {
5582 allocator_type_traits::deallocate(alloc(), buffer, buffer_size);
5595 void commit_new_buffer(
char *&buffer,
size_t &buffer_size) noexcept {
5596 char *old_begin = buff().
begin;
5601 buff().
begin = buffer;
5602 buff().
end = buff().
begin + buffer_size;
5604 buffer_size = old_size;
5616 [[nodiscard]]
auto make_scoped_deallocator(
char **buffer,
size_t *buffer_size) noexcept {
5619 deallocate_buffer(*buffer, *buffer_size);
5629 void validate_data_invariants() const noexcept {
5630 #ifdef FFL_DBG_CHECK_DATA_VALID 5642 buffer_length = static_cast<size_type>(buff().
end - buff().
begin);
5644 buffer_length = static_cast<size_type>(buff().
last - buff().
begin) + last_element_size.size;
5647 size_type const last_element_offset{ static_cast<size_type>(buff().
last - buff().
begin) };
5650 auto const [valid,
buffer_view] = flat_forward_list_validate<T, TT>(buff().
begin, buff().
begin + buffer_length);
5654 #endif //FFL_DBG_CHECK_DATA_VALID 5659 void validate_pointer_invariants() const noexcept {
5666 void validate_iterator(
const_iterator const &it)
const noexcept {
5673 if (empty_unsafe()) {
5678 validate_compare_to_all_valid_elements(it);
5686 void validate_iterator_not_end(
const_iterator const &it)
const noexcept {
5696 validate_compare_to_all_valid_elements(it);
5703 void validate_compare_to_all_valid_elements([[maybe_unused]]
const_iterator const &it)
const noexcept {
5704 #ifdef FFL_DBG_CHECK_ITERATOR_VALID 5709 bool found_match{
false };
5710 for (
auto cur =
cbegin(); cur !=
cend(); ++cur) {
5718 #else //FFL_DBG_CHECK_ITERATOR_VALID 5720 #endif //FFL_DBG_CHECK_ITERATOR_VALID 5746 if (0 == next_offset) {
5751 next_offset = s.
size;
5762 return s.size_padded();
5787 r.data_end = r.begin() + s.size;
5790 if (0 == next_offset) {
5792 r.buffer_end = r.begin() + s.size;
5794 r.buffer_end = r.begin() + next_offset;
5798 r.buffer_end = r.begin() + s.size;
5800 r.buffer_end = r.begin() + s.size_padded();
5810 if (first ==
last) {
5811 return element_range_unsafe(first);
5813 range_t first_element_range{ range_unsafe(first) };
5817 last_element_range.data_end,
5818 last_element_range.buffer_end } };
5831 if (this->
end() == end) {
5832 return closed_range_usafe(first,
last());
5835 size_t end_begin{ static_cast<size_t>(
end->
get_ptr() - buff().
begin) };
5838 return closed_range_usafe(first,
last);
5846 sizes_t get_all_sizes() const noexcept {
5849 s.total_capacity = buff().
end - buff().
begin;
5851 if (
nullptr != buff().
last) {
5865 return buffer_.get_second();
5874 return buffer_.get_second();
5883 return buffer_.get_first();
5891 return buffer_.get_first();
5897 compressed_pair<allocator_type, buffer_type> buffer_;
5910 template <
typename T,
5914 noexcept (std::allocator_traits<A>::propagate_on_container_swap::value ||
5915 std::allocator_traits<A>::propagate_on_container_move_assignment::value) {
5929 template <
typename T,
5946 template <
typename T,
5963 template <
typename T,
5980 template <
typename T,
5997 template <
typename T,
6014 template <
typename T,
6031 template <
typename T,
6048 template <
typename T,
6065 template <
typename T,
6077 template <
typename T,
6078 typename TT = flat_forward_list_traits<T>>
6081 FFL_PMR::polymorphic_allocator<char>>;
6088 template <
typename T,
6090 template <
typename V,
6095 : buffer_(c.buff()) {
6104 template <
typename T,
6106 template <
typename V,
6130 template<
typename T,
6135 F
const &validate_element_fn) noexcept {
6137 constexpr
auto const type_has_next_offset{ traits_traits::has_next_offset_v };
6138 static_assert(type_has_next_offset,
"traits type must define get_next_offset");
6140 char const *
begin{ first };
6144 char const *last_valid =
nullptr;
6148 if (first ==
nullptr) {
6167 size_t remaining_length{ static_cast<size_t>(
end - first) };
6168 bool result =
false;
6169 for (; remaining_length > 0;) {
6173 if (remaining_length <= 0 || remaining_length < traits_traits::minimum_size()) {
6180 size_t const next_element_offset = traits_traits::get_next_offset(first);
6184 if (remaining_length < next_element_offset) {
6190 if (!validate_element_fn(remaining_length, *traits_traits::ptr_to_t(first))) {
6197 if (0 == next_element_offset) {
6209 first += next_element_offset;
6210 remaining_length -= next_element_offset;
6235 template<
typename T,
6240 F
const &validate_element_fn) noexcept {
6241 char const *
begin{ first };
6249 char const *last_valid =
nullptr;
6253 if (first ==
nullptr) {
6272 std::ptrdiff_t remaining_length =
end - first;
6273 bool result =
false;
6278 if (remaining_length <= 0 || remaining_length < static_cast<std::ptrdiff_t>(traits_traits::minimum_size())) {
6292 if (!validate_element_fn(remaining_length, *traits_traits::ptr_to_t(first))) {
6298 size_t next_element_offset = traits_traits::get_next_offset(first);
6302 if (next_element_offset < traits_traits::minimum_size()) {
6317 first += next_element_offset;
6318 remaining_length -= next_element_offset;
6382 template<
typename T,
6387 F
const &validate_element_fn) noexcept {
6389 constexpr
auto const type_has_next_offset{ traits_traits::has_next_offset_v };
6396 if constexpr (type_has_next_offset) {
6397 return flat_forward_list_validate_has_next_offset<T, TT, F>(first,
end, validate_element_fn);
6399 return flat_forward_list_validate_no_next_offset<T, TT, F>(first,
end, validate_element_fn);
6403 template<
typename T,
6408 F
const &validate_element_fn) noexcept {
6410 constexpr
auto const type_has_next_offset{ traits_traits::has_next_offset_v };
6417 if constexpr (type_has_next_offset) {
6418 return flat_forward_list_validate_has_next_offset<T, TT, F>(first,
end, validate_element_fn);
6420 return flat_forward_list_validate_no_next_offset<T, TT, F>(first,
end, validate_element_fn);
6426 template<
typename T,
6431 F
const &validate_element_fn) noexcept {
6432 return flat_forward_list_validate<T, TT>(reinterpret_cast<char *>(first),
6433 reinterpret_cast<char *>(
end),
6434 validate_element_fn);
6439 template<
typename T,
6444 F
const &validate_element_fn) noexcept {
6445 return flat_forward_list_validate<T, TT>(reinterpret_cast<char const *>(first),
6446 reinterpret_cast<char const *>(
end),
6447 validate_element_fn);
6452 template<
typename T,
6456 unsigned char const *
end,
6457 F
const &validate_element_fn) noexcept {
6458 return flat_forward_list_validate<T, TT>(reinterpret_cast<char const *>(first),
6459 reinterpret_cast<char const *>(
end),
6460 validate_element_fn);
6465 template<
typename T,
6470 F
const &validate_element_fn) noexcept {
6471 return flat_forward_list_validate<T, TT>(reinterpret_cast<char *>(first),
6472 reinterpret_cast<char *>(
end),
6473 validate_element_fn);
6478 template<
typename T,
6483 F
const &validate_element_fn) noexcept {
6484 return flat_forward_list_validate<T, TT>(reinterpret_cast<char const *>(first),
6485 reinterpret_cast<char const *>(
end),
6486 validate_element_fn);
6491 template<
typename T,
6496 F
const &validate_element_fn) noexcept {
6497 return flat_forward_list_validate<T, TT>(reinterpret_cast<char *>(first),
6498 reinterpret_cast<char *>(
end),
6499 validate_element_fn);
constexpr void clear() noexcept
Resets all pointers to nullptr.
Definition: iffl_common.h:1159
TT type_traits
Definition: iffl_list.h:398
range_with_alighment< ALIGNMENT_V > last_element
Last element range.
Definition: iffl_common.h:758
static size_type const npos
Constant that represents and invalid or non-existent position.
Definition: iffl_list.h:1498
void erase_all() noexcept
Erases all elements in the buffer without deallocating buffer.
Definition: iffl_list.h:3964
T value_type
Element value type.
Definition: iffl_list.h:1387
allocator_type & get_allocator() &noexcept
Returns reference to the allocator used by this container.
Definition: iffl_list.h:3264
void zero_buffer(char *buffer, size_t length) noexcept
sets "length" consecutive bytes of "to_buffer" to 0.
Definition: iffl_common.h:344
bool try_emplace_front(size_type element_size, F const &fn)
Inserts new element at the beginning of the container. Element is initialized with a help of the func...
Definition: iffl_list.h:3750
T & reference
Reference to the element type.
Definition: iffl_list.h:2641
buffer_t< buffer_value_type > buffer_type
Pointers that describe buffer.
Definition: iffl_list.h:1493
void pop_back() noexcept
Removes last element from the list.
Definition: iffl_list.h:3499
size_type remaining_capacity() const noexcept
Definition: iffl_list.h:4850
char const * data() const noexcept
Definition: iffl_list.h:1893
flat_forward_list_sizes< traits_traits::alignment > sizes_t
Vocabulary type that contains information about buffer size, and last element range.
Definition: iffl_list.h:2690
std::forward_iterator_tag iterator_category
Marks iterator as a forward iterator.
Definition: iffl_list.h:857
char * cast_to_char_ptr(T *p) noexcept
Helper method to cast a pointer to a char *.
Definition: iffl_common.h:362
char buffer_value_type
Since we have variable size elements, and we cannot express it in the C++ type system we treat buffer...
Definition: iffl_list.h:2708
iterator erase_all_from(iterator const &it) noexcept
Erases element in the range [it, end)
Definition: iffl_list.h:3934
This file is supposed to be generated by cmake. Cmake pushes output to the folder where it generates ...
static constexpr size_t get_alignment() noexcept
If traits defined alignment then size of alignment, and 1 otherwise.
Definition: iffl_list.h:529
bool try_emplace(iterator const &it, size_type new_element_size, F const &fn)
Constructs new element at the position described by iterator. Element is initialized with a help of t...
Definition: iffl_list.h:3656
constexpr flat_forward_list_iterator_t(I &&other) noexcept
Perfect forwarding constructor for const iterator from non-const iterator.
Definition: iffl_list.h:1016
const_iterator clast() const noexcept
Definition: iffl_list.h:1869
void assign(flat_forward_list_view< T, TT > const &view)
Copies elements from the view.
Definition: iffl_list.h:3231
constexpr size_t begin() const
Offset of the element buffer begin in a larger buffer.
Definition: iffl_common.h:544
range_t half_open_range(const_iterator const &begin, const_iterator const &end) const noexcept
Information about the buffer occupied by elements in the range [begin, end).
Definition: iffl_list.h:4652
pointer_type begin
Pointer to the beginning of buffer nullptr if no buffer.
Definition: iffl_common.h:1075
T value_type
Definition: iffl_list.h:393
flat_forward_list(flat_forward_list &&other) noexcept
Move constructor. Moves allocator and content of other container to this container.
Definition: iffl_list.h:2765
size_type required_size(const_iterator const &it) const noexcept
Returns capacity used by the element's data.
Definition: iffl_list.h:4583
Non owning container for flat forward list.
Definition: iffl_list.h:688
bool try_element_resize(iterator const &it, size_type new_size, F const &fn)
Resizes element.
Definition: iffl_list.h:4568
static constexpr auto const has_alignment_v
Instance of has_alignment_t.
Definition: iffl_list.h:476
char * data() noexcept
Definition: iffl_list.h:1886
void erase_after(iterator const &it) noexcept
Erases element after the element pointed by the iterator.
Definition: iffl_list.h:3794
size_type size() const noexcept
Number of elements in the container.
Definition: iffl_list.h:4810
range_t closed_range(const_iterator const &begin, const_iterator const &last) const noexcept
Information about the buffer occupied by elements in the range [begin, last].
Definition: iffl_list.h:4631
flat_forward_list_const_iterator< T, TT > const_iterator
Type of const iterator.
Definition: iffl_list.h:2735
iffl::mpl::is_detected< has_minimum_size_mfn, type_traits > has_minimum_size_t
Uses detect idiom with has_minimum_size_mfn to find if traits implemented minimum_size.
Definition: iffl_list.h:406
THis class implements forward iterator for intrusive flat forward list.
Definition: iffl_list.h:833
T & reference
Reference to the element type.
Definition: iffl_list.h:877
static constexpr auto const is_non_const_iterator_v
Is std::true_type{} if Iterator is same as non-const equivalent of the current iterator non-const equ...
Definition: iffl_list.h:956
void unique(F const &fn) noexcept
If there are multiple equivalent elements next to each other then first one is kept,...
Definition: iffl_list.h:4181
bool revalidate_data(size_type data_size=npos) noexcept
Validates that buffer contains a valid list.
Definition: iffl_list.h:4393
flat_forward_list(char const *buffer, size_t buffer_size, AA &&a=AA{})
Constructor that checks if buffer contains a valid list and if it does then copies that list.
Definition: iffl_list.h:2929
bool operator()(size_t buffer_size, T const &e) const noexcept
Function call iterator that validates element.
Definition: iffl_list.h:706
size_t buffer_begin
Starting offset of element in a buffer Element always starts at the beginning of the buffer.
Definition: iffl_common.h:530
typename traits_traits::offset_with_aligment_t offset_with_aligment_t
Vocabulary type used to describe size with alignment.
Definition: iffl_list.h:2685
flat_forward_list_ref(buffer_type const &other_buff) noexcept
Constructor that initializes view to point to the buffer.
Definition: iffl_list.h:1528
static constexpr size_t minimum_size() noexcept
returns minimum valid element size
Definition: iffl_list.h:522
iterator find_element_before(size_type position) noexcept
Searches for an element before the element that contains given position.
Definition: iffl_list.h:4687
static constexpr auto const is_comparable_iterator_v
Is std::true_type{} if Iterator is a const or non-const equivalent of this iterator and std::false_ty...
Definition: iffl_list.h:975
iterator last() noexcept
Definition: iffl_list.h:4303
flat_forward_list & operator=(flat_forward_list &&other) noexcept(allocator_type_traits::propagate_on_container_move_assignment::value)
Move assignment operator.
Definition: iffl_list.h:2975
Definition: iffl_list.h:717
range_t range(const_iterator const &it) const noexcept
Information about the buffer occupied by an element.
Definition: iffl_list.h:1946
static constexpr auto const is_const_iterator_v
Is std::true_type{} if Iterator is same as const equivalent of the current iterator non-const equival...
Definition: iffl_list.h:966
void sort(LESS_F const &fn)
Sorts elements of container using comparator passed as a parameter.
Definition: iffl_list.h:4085
iffl::mpl::is_detected< has_alignment_mfn, type_traits > has_alignment_t
Uses detect idiom with has_alignment_mfn to find if traits implemented validate.
Definition: iffl_list.h:471
void pop_front() noexcept
Removes first element from the container.
Definition: iffl_list.h:3758
bool try_element_add_size(iterator const &it, size_type size_to_add)
Adds unused capacity to the element.
Definition: iffl_list.h:4512
~flat_forward_list() noexcept
Destructor.
Definition: iffl_list.h:3025
void assign(buffer_type const &other_buff) noexcept
Assigns view to point to the described buffer.
Definition: iffl_list.h:1648
void fill_buffer(char *buffer, int value, size_t length) noexcept
sets "length" consecutive bytes of "to_buffer" to "value".
Definition: iffl_common.h:336
void shrink_to_fit()
Removes unused padding of each element and at the tail.
Definition: iffl_list.h:4413
typename traits_traits::offset_with_aligment_t offset_with_aligment_t
Vocabulary type used to describe size with alignment.
Definition: iffl_list.h:1446
typename traits_traits::size_with_padding_t size_with_padding_t
Vocabulary type used to describe size with padding.
Definition: iffl_list.h:2680
void push_front(size_type init_buffer_size, char const *init_buffer=nullptr)
Constructs new element at the beginning of the container. Element is initialized by copping provided ...
Definition: iffl_list.h:3677
iterator erase(iterator const &start, iterator const &end) noexcept
Erases element in the range [start, end).
Definition: iffl_list.h:4019
void emplace_front(size_type element_size, F const &fn)
Inserts new element at the beginning of the container. Element is initialized with a help of the func...
Definition: iffl_list.h:3733
constexpr auto make_scope_guard(G &&g)
Factory method for scoped_guard.
Definition: iffl_common.h:489
Helper class used as a parameter in flat_forward_list constructor to designate that it should take ow...
Definition: iffl_common.h:500
constexpr bool operator >(I const &other) const noexcept
Greater than operator used to compare to another iterator.
Definition: iffl_list.h:1161
iffl::mpl::is_detected< has_get_size_mfn, type_traits > has_get_size_t
Uses detect idiom with has_get_size_mfn to find if traits implemented get_size.
Definition: iffl_list.h:419
constexpr flat_forward_list_iterator_t() noexcept=default
Default initialize iterator.
flat_forward_list(const_iterator const &begin, const_iterator const &last, AA &&a=AA{})
Copies element pointed by the iterators.
Definition: iffl_list.h:2947
buffer_t< char const > buffer_view
Const flat forward list buffer.
Definition: iffl_common.h:1186
traits for an elements that are in the flat forward list
Definition: iffl_list.h:286
void assign(flat_forward_list_iterator< V, VV > const &begin, flat_forward_list_iterator< V, VV > const &last) noexcept
Assigns view to point to the described buffer.
Definition: iffl_list.h:1677
void swap(flat_forward_list< T, TT, A > &lhs, flat_forward_list< T, TT, A > &rhs) noexcept(std::allocator_traits< A >::propagate_on_container_swap::value||std::allocator_traits< A >::propagate_on_container_move_assignment::value)
Definition: iffl_list.h:5913
Tag type for constructing first from one argument, constructing second from remaining arguments.
Definition: iffl_common.h:798
ptrdiff_t difference_type
Element pointers difference type.
Definition: iffl_list.h:867
constexpr size_t size_padded() const noexcept
Definition: iffl_common.h:734
T const * const_pointer
Pointer to const element type.
Definition: iffl_list.h:1397
Definition: iffl_list.h:700
flat_forward_list(buffer_view const &other_buff, AA &&a=AA{})
Constructor that copies list from a buffer.
Definition: iffl_list.h:2818
std::conditional_t< std::is_const_v< T >, char const, char > buffer_value_type
Depending if T is const we will use const or non-const buffer pointer.
Definition: iffl_list.h:1461
bool try_push_front(size_type init_buffer_size, char const *init_buffer=nullptr)
Constructs new element at the beginning of the container. Element is initialized by copping provided ...
Definition: iffl_list.h:3704
bool try_insert(iterator const &it, size_type init_buffer_size, char const *init_buffer=nullptr)
Inserts new element at the position described by iterator. Element is initialized by copping provided...
Definition: iffl_list.h:3583
flat_forward_list_ref(flat_forward_list_ref< V, VV > const &other) noexcept
Assignment operator to view from a ref.
Definition: iffl_list.h:1516
flat_forward_list_ref< T, TT >::iterator begin(flat_forward_list_ref< T, TT > &c) noexcept
Definition: iffl_list.h:2406
static value_type * ptr_to_t(unsigned char *ptr)
Casts buffer pointer to a pointer to the element type.
Definition: iffl_list.h:509
TT traits
Element traits type.
Definition: iffl_list.h:882
size_type used_capacity() const noexcept
Definition: iffl_list.h:2111
size_t distance(void const *begin, void const *end) noexcept
sets "length" consecutive bytes of "to_buffer" to 0.
Definition: iffl_common.h:352
std::ptrdiff_t difference_type
Element pointers difference type.
Definition: iffl_list.h:1417
void assign(char const *buffer_begin, char const *last_element, char const *buffer_end)
Copies list from a buffer.
Definition: iffl_list.h:3149
void clear() noexcept
Deallocated buffer owned by this container.
Definition: iffl_list.h:3287
const_iterator clast() const noexcept
Definition: iffl_list.h:4356
static constexpr auto const has_minimum_size_v
Instance of has_minimum_size_t.
Definition: iffl_list.h:411
buffer_ref detach() noexcept
Container releases ownership of the buffer.
Definition: iffl_list.h:3034
#define FFL_CODDING_ERROR_IF(C)
If expression is true then fail fast with error ENOTRECOVERABLE(127 or 0x7f)
Definition: iffl_common.h:113
typename traits_traits::size_with_padding_t size_with_padding_t
Vocabulary type used to describe size with padding.
Definition: iffl_list.h:1441
intrusive flat forward list
static constexpr auto const can_validate_v
Instance of can_validate_t.
Definition: iffl_list.h:463
T & back() noexcept
Definition: iffl_list.h:4256
flat_forward_list< T, TT, FFL_PMR::polymorphic_allocator< char > > pmr_flat_forward_list
Use this typedef if you want to use container with polymorphic allocator.
Definition: iffl_list.h:6081
constexpr T * operator->() const noexcept
pointer operator.
Definition: iffl_list.h:1239
flat_forward_list_ref< T, TT >::iterator last(flat_forward_list_ref< T, TT > &c) noexcept
Definition: iffl_list.h:2502
T & back()
Definition: iffl_list.h:1733
const_iterator find_element_after(size_type position) const noexcept
Searches for an element after the element that contains given position.
Definition: iffl_list.h:4793
static value_type * ptr_to_t(char *ptr)
Casts buffer pointer to a pointer to the element type.
Definition: iffl_list.h:495
iffl::mpl::is_detected< can_validate_mfn, type_traits > can_validate_t
Uses detect idiom with can_validate_mfn to find if traits implemented validate.
Definition: iffl_list.h:458
constexpr bool operator==(I const &other) const noexcept
Equals operator used to compare to another iterator.
Definition: iffl_list.h:1101
flat_forward_list(allocator_type a) noexcept
Constructs an empty container with an instance of provided allocator.
Definition: iffl_list.h:2757
size_type size() const noexcept
Number of elements in the container.
Definition: iffl_list.h:2080
constexpr void swap(flat_forward_list_iterator_t &other) noexcept
swaps this iterator and the other iterator
Definition: iffl_list.h:1077
constexpr flat_forward_list_iterator_t operator+(unsigned int advance_by) const noexcept
Add operator. Advances iterator specified number of times.
Definition: iffl_list.h:1220
typename traits_traits::size_with_padding_t size_with_padding_t
Vocabulary type used to describe size with padding.
Definition: iffl_list.h:910
char const * const_buffer_pointer
Type used as a pointer to the const buffer.
Definition: iffl_list.h:2724
flat_forward_list(char const *buffer_begin, char const *last_element, char const *buffer_end, AA &&a=AA{})
Constructor that copies list from a buffer.
Definition: iffl_list.h:2874
bool assign(char const *buffer, size_type buffer_size)
Checks if buffer contains a valid list and if it does then copies that list.
Definition: iffl_list.h:3202
size_t size
Not padded size.
Definition: iffl_common.h:730
This module contains few meta-programming facilities that are not part of the STL.
flat_forward_list_sizes< traits_traits::alignment > sizes_t
Vocabulary type that contains information about buffer size, and last element range.
Definition: iffl_list.h:1451
T value_type
Element value type.
Definition: iffl_list.h:862
T value_type
Element value type.
Definition: iffl_list.h:2626
buffer_value_type * buffer_pointer
Type used as a buffer pointer.
Definition: iffl_list.h:1472
constexpr bool operator !=(I const &other) const noexcept
Not equals operator used to compare to another iterator.
Definition: iffl_list.h:1116
void remove_if(F const &fn) noexcept
Removes all elements that satisfy predicate.
Definition: iffl_list.h:4218
Common definitions, utility functions and vocabulary types.
T & front()
Definition: iffl_list.h:1715
constexpr size_t remaining_capacity_for_append() const
Definition: iffl_common.h:776
constexpr buffer_char_pointer get_ptr() const noexcept
Definition: iffl_list.h:1246
constexpr T & operator *() const noexcept
Dereference operator.
Definition: iffl_list.h:1232
constexpr size_type last_offset() const noexcept
Definition: iffl_common.h:1123
iterator find_element_at(size_type position) noexcept
Searches for an element that contains given position.
Definition: iffl_list.h:4732
const_iterator find_element_before(size_type position) const noexcept
Searches for an element before the element that contains given position.
Definition: iffl_list.h:4711
flat_forward_list_ref(buffer_pointer buffer_begin, buffer_pointer last_element, buffer_pointer buffer_end) noexcept
Constructor that copies list from a buffer.
Definition: iffl_list.h:1545
bool revalidate_data() noexcept
Validates that buffer contains a valid list.
Definition: iffl_list.h:1905
void assign(buffer_pointer buffer_begin, buffer_pointer last_element, buffer_pointer buffer_end) noexcept
Assigns view to point to the described buffer.
Definition: iffl_list.h:1661
void erase_all_after(iterator const &it) noexcept
Erases element in the range (before_start, end)
Definition: iffl_list.h:3912
typename traits_traits::range_t range_t
Vocabulary type used to describe buffer used by the element and how much of this buffer is used by th...
Definition: iffl_list.h:1436
std::conditional_t< std::is_const_v< T >, unsigned char const *, unsigned char * > buffer_unsigned_char_pointer
Definition: iffl_list.h:899
flat_forward_list_ref(flat_forward_list_iterator< V, VV > const &begin, flat_forward_list_iterator< V, VV > const &last) noexcept
Constructor that creates a view over a buffer described by a pair of iterators.
Definition: iffl_list.h:1565
const_iterator find_element_at(size_type position) const noexcept
Searches for an element that contains given position.
Definition: iffl_list.h:4752
static constexpr size_t get_next_offset(char const *buffer) noexcept
Returns next element offset.
Definition: iffl_list.h:597
T const & const_reference
Reference to the const element type.
Definition: iffl_list.h:1407
constexpr std::pair< bool, flat_forward_list_ref< T, TT > > flat_forward_list_validate_no_next_offset(char const *first, char const *end, F const &validate_element_fn=default_validate_element_fn< T, TT >{}) noexcept
Forward declaration.
Definition: iffl_list.h:6238
void assign(buffer_view const &other_buff)
Copies list from a buffer.
Definition: iffl_list.h:3125
std::size_t size_type
Size type.
Definition: iffl_list.h:1412
constexpr void unused_variable([[maybe_unused]] T const &)
Restore saved min and max definition.
Definition: iffl_common.h:216
constexpr bool operator >=(I const &other) const noexcept
Greater or equals than operator used to compare to another iterator.
Definition: iffl_list.h:1176
std::allocator_traits< allocator_type > allocator_type_traits
Type of allocator traits.
Definition: iffl_list.h:2700
buffer_t< buffer_value_type > buffer_type
Pointers that describe buffer.
Definition: iffl_list.h:2741
iterator element_resize(iterator const &it, size_type new_size, F const &fn)
Resizes element.
Definition: iffl_list.h:4544
bool contains(const_iterator const &it, size_type position) const noexcept
Tells if given offset in the buffer falls into a buffer used by the element.
Definition: iffl_list.h:2003
size_type used_size(const_iterator const &it) const noexcept
Definition: iffl_list.h:4593
void swap(flat_forward_list_ref< T, TT > &lhs, flat_forward_list_ref< T, TT > &rhs) noexcept
Definition: iffl_list.h:2390
bool empty() const noexcept
Tells if container contains no elements.
Definition: iffl_list.h:4826
void move_data(char *to_buffer, char const *from_buffer, size_t length) noexcept
copies length bytes from from_buffer to to_buffer. source and destination buffers can overlap
Definition: iffl_common.h:327
const_iterator find_element_before(size_type position) const noexcept
Searches for an element before the element that contains given position.
Definition: iffl_list.h:2021
T const & back() const
Definition: iffl_list.h:1742
constexpr std::pair< bool, flat_forward_list_ref< T, TT > > flat_forward_list_validate_has_next_offset(char const *first, char const *end, F const &validate_element_fn=default_validate_element_fn< T, TT >{}) noexcept
Forward declaration.
Definition: iffl_list.h:6133
const_buffer_value_type * const_buffer_pointer
Type used as a pointer not the const buffer.
Definition: iffl_list.h:1477
void erase_after_half_closed(iterator const &before_start, iterator const &last) noexcept
Erases element in the range (before_start, last].
Definition: iffl_list.h:3851
flat_forward_list_const_iterator< T, TT > const_iterator
Type of const iterator.
Definition: iffl_list.h:1487
void swap(flat_forward_list &other) noexcept(allocator_type_traits::propagate_on_container_swap::value||allocator_type_traits::propagate_on_container_move_assignment::value)
Swaps content of this container and the other container.
Definition: iffl_list.h:4064
iterator end() noexcept
Definition: iffl_list.h:4322
~flat_forward_list_ref() noexcept
Destructor.
Definition: iffl_list.h:1637
size_type remaining_capacity() const noexcept
Definition: iffl_list.h:2127
void fill_padding(int fill_byte=0, bool zero_unused_capacity=true) noexcept
Fills parts of the buffer not used by element data with fill_byte.
Definition: iffl_list.h:4862
T * pointer
Pointer to element type.
Definition: iffl_list.h:872
pointer_type end
Pointer to the end of buffer nullptr if no buffer.
Definition: iffl_common.h:1086
const_iterator cend() const noexcept
Definition: iffl_list.h:1879
static constexpr size_t const alignment
Defines static constexpr member that with value that has alignment requirements of elements.
Definition: iffl_list.h:540
flat_forward_list_ref< T, TT >::const_iterator clast(flat_forward_list_ref< T, TT > const &c) noexcept
Definition: iffl_list.h:2534
void assign(const_iterator const &begin, const_iterator const &last)
Copies element pointed by the iterators.
Definition: iffl_list.h:3212
range_t closed_range(const_iterator const &begin, const_iterator const &last) const noexcept
Information about the buffer occupied by elements in the range [begin, last].
Definition: iffl_list.h:1965
size_type required_size(const_iterator const &it) const noexcept
Returns capacity used by the element's data.
Definition: iffl_list.h:1918
T const & const_reference
Reference to the const element type.
Definition: iffl_list.h:2646
flat_forward_list_iterator< T, TT > iterator
Type of iterator.
Definition: iffl_list.h:2730
static size_type const npos
Constant that represents and invalid or non-existent position.
Definition: iffl_list.h:2746
Vocabulary type that describes a sub-buffer in a larger buffer and portion of that sub-buffer actuall...
Definition: iffl_common.h:632
const_iterator find_element_at(size_type position) const noexcept
Searches for an element that contains given position.
Definition: iffl_list.h:2042
iterator last() noexcept
Definition: iffl_list.h:1780
flat_forward_list_ref< T, TT >::const_iterator cbegin(flat_forward_list_ref< T, TT > const &c) noexcept
Definition: iffl_list.h:2438
typename std::allocator_traits< A >::template rebind_alloc< char > allocator_type
Type of allocator.
Definition: iffl_list.h:2695
flat_forward_list() noexcept
Default constructor for container.
Definition: iffl_list.h:2750
std::size_t size_type
Size type.
Definition: iffl_list.h:2651
std::ptrdiff_t difference_type
Element pointers difference type.
Definition: iffl_list.h:2656
iterator element_add_size(iterator const &it, size_type size_to_add)
Adds unused capacity to the element.
Definition: iffl_list.h:4482
iterator emplace(iterator const &it, size_type new_element_size, F const &fn)
Constructs new element at the position described by iterator. Element is initialized with a help of t...
Definition: iffl_list.h:3623
constexpr flat_forward_list_iterator_t operator++(int) noexcept
Postfix increment operator.
Definition: iffl_list.h:1200
void assign(buffer_pointer *buffer, size_t buffer_size) noexcept
Assigns view to point to the described buffer.
Definition: iffl_list.h:1689
T const & back() const noexcept
Definition: iffl_list.h:4265
char const const_buffer_value_type
When we do not intend to modify buffer we can treat it as a bag of const characters.
Definition: iffl_list.h:2714
std::conditional_t< std::is_const_v< T >, void const *, void * > buffer_void_pointer
Definition: iffl_list.h:905
bool empty() const noexcept
Tells if container contains no elements.
Definition: iffl_list.h:2096
range_with_alighment< alignment > range_t
Specialization of range_with_alighment for this type alignment.
Definition: iffl_list.h:545
iffl::mpl::is_detected< has_next_offset_mfn, type_traits > has_next_offset_t
Uses detect idiom with has_next_offset_mfn to find if traits implemented get_next_offset.
Definition: iffl_list.h:432
flat_forward_list(attach_buffer, char *buffer, size_t buffer_size, AA &&a=AA{}) noexcept
Constructor that takes ownership of a buffer and attempts to find last element of the list.
Definition: iffl_list.h:2904
char const * data() const noexcept
Definition: iffl_list.h:4380
flat_forward_list_ref & operator=(flat_forward_list_ref< V, VV > const &other)
Copy assignment operator.
Definition: iffl_list.h:1607
void swap(flat_forward_list_ref &other) noexcept
Swaps content of this container and the other container.
Definition: iffl_list.h:1706
T & front() noexcept
Definition: iffl_list.h:4238
static value_type const * ptr_to_t(unsigned char const *ptr)
Casts buffer pointer to a pointer to the element type.
Definition: iffl_list.h:516
const_iterator end() const noexcept
Definition: iffl_list.h:1839
const_iterator begin() const noexcept
Definition: iffl_list.h:1760
flat_forward_list_ref< T, TT >::iterator end(flat_forward_list_ref< T, TT > &c) noexcept
Definition: iffl_list.h:2454
bool contains(const_iterator const &it, size_type position) const noexcept
Tells if given offset in the buffer falls into a buffer used by the element.
Definition: iffl_list.h:4669
static constexpr size_t roundup_to_alignment(size_t s) noexcept
If traits defined alignment then s padded to alignment, or unchanged value of s otherwise.
Definition: iffl_list.h:562
T & reference
Reference to the element type.
Definition: iffl_list.h:1402
T const & front() const noexcept
Definition: iffl_list.h:4247
TT traits
Element traits type.
Definition: iffl_list.h:1422
bool attach(char *buffer, size_t buffer_size) noexcept
Takes ownership of a buffer and attempts to find last element of the list.
Definition: iffl_list.h:3107
offset_with_aligment< alignment > offset_with_aligment_t
Specialization of offset_with_aligment for this type alignment.
Definition: iffl_list.h:555
flat_forward_list_ref< T, TT >::const_iterator cend(flat_forward_list_ref< T, TT > const &c) noexcept
Definition: iffl_list.h:2486
void merge(flat_forward_list &other, F const &fn)
Merges two linked list ordering lists using comparison functor.
Definition: iffl_list.h:4143
T const & front() const
Definition: iffl_list.h:1724
const_iterator last() const noexcept
Definition: iffl_list.h:4312
flat_forward_list(attach_buffer, char *buffer_begin, char *last_element, char *buffer_end, AA &&a=AA{}) noexcept
Constructor that takes ownership of a buffer.
Definition: iffl_list.h:2849
iterator begin() noexcept
Definition: iffl_list.h:4274
T * pointer
Pointer to element type.
Definition: iffl_list.h:2631
size_type used_size(const_iterator const &it) const noexcept
Definition: iffl_list.h:1928
constexpr size_t roundup_size_to_alignment(size_t size, size_t alignment) noexcept
Rounds up size to specified alignment.
Definition: iffl_common.h:255
iffl::mpl::is_detected< can_set_next_offset_mfn, type_traits > can_set_next_offset_t
Uses detect idiom with can_set_next_offset_mfn to find if traits implemented set_next_offset.
Definition: iffl_list.h:445
void shrink_to_fit(iterator const &first, iterator const &end)
Removes unused padding of each element in the range [first, end).
Definition: iffl_list.h:4425
void reverse()
Reverses elements of the list.
Definition: iffl_list.h:4122
size_type max_size() const noexcept
Returns maximum size.
Definition: iffl_list.h:3280
static constexpr auto const has_get_size_v
Instance of has_get_size_t.
Definition: iffl_list.h:424
void copy_data(char *to_buffer, char const *from_buffer, size_t length) noexcept
copies length bytes from from_buffer to to_buffer. source and destination buffers cannot overlap
Definition: iffl_common.h:316
const_iterator last() const noexcept
Definition: iffl_list.h:1789
iterator insert(iterator const &it, size_type init_buffer_size, char const *init_buffer=nullptr)
Inserts new element at the position described by iterator. Element is initialized by copping provided...
Definition: iffl_list.h:3549
char * data() noexcept
Definition: iffl_list.h:4373
char * buffer_pointer
Type used as a buffer pointer.
Definition: iffl_list.h:2719
size_type total_capacity() const noexcept
Definition: iffl_list.h:4842
void attach(char *buffer_begin, char *last_element, char *buffer_end) noexcept
Takes ownership of a buffer.
Definition: iffl_list.h:3077
std::conditional_t< std::is_const_v< T >, char const *, char * > buffer_char_pointer
Definition: iffl_list.h:893
bool try_emplace_back(size_type element_size, F const &fn)
Constructs new element at the end of the list if it fits in the existing free capacity.
Definition: iffl_list.h:3485
static value_type const * ptr_to_t(void const *ptr)
Casts buffer pointer to a pointer to the element type.
Definition: iffl_list.h:488
range_t range(const_iterator const &it) const noexcept
Information about the buffer occupied by an element.
Definition: iffl_list.h:4611
const_iterator cbegin() const noexcept
Definition: iffl_list.h:1862
static constexpr bool validate(size_t buffer_size, T const &buffer) noexcept
Asks type traits to validate element.
Definition: iffl_list.h:584
void emplace_back(size_type element_size, F const &fn)
Constructs new element at the end of the list.
Definition: iffl_list.h:3466
bool is_compatible_allocator(AA const &other_allocator) const noexcept
Compares if allocator used by container is equivalent to the other allocator.
Definition: iffl_list.h:3257
pointer_type last
Pointer to the last element in the list nullptr if no buffer or if there is no elements in the list.
Definition: iffl_common.h:1081
traits for flat_forward_list_traits
Definition: iffl_list.h:331
iterator begin() noexcept
Definition: iffl_list.h:1751
static constexpr auto const has_next_offset_v
Instance of has_next_offset_t.
Definition: iffl_list.h:437
static constexpr auto const can_set_next_offset_v
Instance of can_set_next_offset_t.
Definition: iffl_list.h:450
range_t half_open_range(const_iterator const &begin, const_iterator const &end) const noexcept
Information about the buffer occupied by elements in the range [begin, end).
Definition: iffl_list.h:1986
bool try_push_back(size_type init_buffer_size, char const *init_buffer=nullptr)
Adds new element to the end of the list. Element is initialized by copping provided buffer.
Definition: iffl_list.h:3438
typename traits_traits::range_t range_t
Vocabulary type used to describe buffer used by the element and how much of this buffer is used by th...
Definition: iffl_list.h:2675
allocator_type const & get_allocator() const &noexcept
Returns const reference to the allocator used by this container.
Definition: iffl_list.h:3271
constexpr flat_forward_list_iterator_t(I const &other) noexcept
Unittest that is_non_const_iterator_v returns expected result.
Definition: iffl_list.h:998
flat_forward_list(flat_forward_list const &other)
Copy constructor. Copies allocator if supported and copies content of other container to this contain...
Definition: iffl_list.h:2775
bool operator()([[maybe_unused]] size_t, [[maybe_unused]] T const &) const noexcept
Function call iterator that validates element.
Definition: iffl_list.h:722
Intrusive flat forward list container.
Definition: iffl_list.h:681
TT traits
Element traits type.
Definition: iffl_list.h:2661
const_iterator find_element_after(size_type position) const noexcept
Searches for an element after the element that contains given position.
Definition: iffl_list.h:2063
Tag type for value - initializing first, constructing second from remaining arguments.
Definition: iffl_common.h:790
static void print_traits_info() noexcept
Prints information about what traits_traits discovered about traits class.
Definition: iffl_list.h:629
flat_forward_list_ref(buffer_pointer *buffer, size_t buffer_size) noexcept
Constructor that checks if buffer contains a valid list and if it does then copies that list.
Definition: iffl_list.h:1582
Vocabulary type that describes an offset in a larger buffer and template parameter that specifies ele...
Definition: iffl_common.h:693
size_type total_capacity() const noexcept
Definition: iffl_list.h:2119
constexpr std::pair< bool, flat_forward_list_ref< T, TT > > flat_forward_list_validate(char const *first, char const *end, F const &validate_element_fn=default_validate_element_fn< T, TT >{}) noexcept
Forward declaration.
Definition: iffl_list.h:6385
#define FFL_CRASH_APPLICATION()
Fail fast with error ENOTRECOVERABLE(127 or 0x7f)
Definition: iffl_common.h:106
static constexpr auto const is_const_iterator
Is std::true_type{} if this iterator is an iterator for a T const, and std::false_type{} otherwise.
Definition: iffl_list.h:947
void resize_buffer(size_type size)
Resizes buffer.
Definition: iffl_list.h:3322
T * pointer
Pointer to element type.
Definition: iffl_list.h:1392
constexpr bool operator<=(I const &other) const noexcept
Less than or equals operator used to compare to another iterator.
Definition: iffl_list.h:1146
constexpr void validate() const noexcept
Fail fast is invariants are broken.
Definition: iffl_common.h:1146
void shrink_to_fit(iterator const &it)
Removes unused padding of an element.
Definition: iffl_list.h:4437
size_type used_capacity() const noexcept
Definition: iffl_list.h:4834
const_iterator begin() const noexcept
Definition: iffl_list.h:4283
const_iterator end() const noexcept
Definition: iffl_list.h:4336
static constexpr void set_next_offset(char *buffer, size_t size) noexcept
Sets next element offset.
Definition: iffl_list.h:612
const_iterator cbegin() const noexcept
Definition: iffl_list.h:4349
const_iterator cend() const noexcept
Definition: iffl_list.h:4366
typename details::detector< nonesuch, void, Operation, Arguments... >::value_type is_detected
is_detected will be either true_type or false_type, depending if Operation<Arguments....
Definition: iffl_mpl.h:335
static bool const is_ref
True if this is a ref and false if this is a view.
Definition: iffl_list.h:1382
constexpr flat_forward_list_iterator_t & operator=(flat_forward_list_iterator_t const &) noexcept=default
Default generated copy constructor.
iterator erase(iterator const &it) noexcept
Erases element pointed by iterator.
Definition: iffl_list.h:3976
void attach(buffer_view const &other_buff)
Takes ownership of a buffer.
Definition: iffl_list.h:3052
void push_back(size_type init_buffer_size, char const *init_buffer=nullptr)
Adds new element to the end of the list. Element is initialized by copping provided buffer.
Definition: iffl_list.h:3411
static constexpr size_with_padding_t get_size(char const *buffer) noexcept
Asks type traits to calculate element size.
Definition: iffl_list.h:574
constexpr flat_forward_list_iterator_t & operator++() noexcept
Prefix increment operator.
Definition: iffl_list.h:1184
flat_forward_list(attach_buffer, buffer_view const &other_buff, AA &&a=AA{}) noexcept
Constructor that takes ownership of a buffer.
Definition: iffl_list.h:2800
size_with_padding< alignment > size_with_padding_t
Specialization of size_with_padding for this type alignment.
Definition: iffl_list.h:550
constexpr size_with_padding< ALIGNMENT_V > used_capacity() const
Capacity used by elements in the buffer.
Definition: iffl_common.h:762
iterator find_element_after(size_type position) noexcept
Searches for an element after the element that contains given position.
Definition: iffl_list.h:4773
T const * const_pointer
Pointer to const element type.
Definition: iffl_list.h:2636
Describes buffer used by container.
Definition: iffl_common.h:750
flat_forward_list(flat_forward_list_view< T, TT > const &view, AA &&a=AA{})
Copies element from the view.
Definition: iffl_list.h:2960
buffer_value_type const const_buffer_value_type
When we do not intend to modify buffer we can treat it as a bag of const characters.
Definition: iffl_list.h:1467
static value_type * ptr_to_t(void *ptr)
Casts buffer pointer to a pointer to the element type.
Definition: iffl_list.h:481
flat_forward_list_ref() noexcept
Default constructor.
Definition: iffl_list.h:1502
static value_type const * ptr_to_t(char const *ptr)
Casts buffer pointer to a pointer to the element type.
Definition: iffl_list.h:502
constexpr size_type size() const noexcept
Definition: iffl_common.h:1101
iterator end() noexcept
Definition: iffl_list.h:1807
Vocabulary type that describes an size and template parameter that specifies element's type alignment...
Definition: iffl_common.h:722
void tail_shrink_to_fit()
Resizes buffer to the used capacity.
Definition: iffl_list.h:3303
flat_forward_list_iterator< T, TT > iterator
Type of iterator.
Definition: iffl_list.h:1482
#define FFL_CODDING_ERROR_IF_NOT(C)
If expression is false then fail fast with error ENOTRECOVERABLE(127 or 0x7f)
Definition: iffl_common.h:120
bool assign(char const *buffer_begin, char const *buffer_end)
Checks if buffer contains a valid list and if it does then copies that list.
Definition: iffl_list.h:3180
constexpr bool operator<(I const &other) const noexcept
Less than operator used to compare to another iterator.
Definition: iffl_list.h:1131