diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-05-01 11:34:54 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-05-01 11:34:54 +0200 |
| commit | a958c515e4cfcd5572ac7e2c3a567e832630a12d (patch) | |
| tree | a5636689d2338c71e9b67d7ed1e2446b4d765a49 /libs/kstd/include | |
| parent | bc7389dd19eee57fa2f34cf2e7ba7d1ebfad0878 (diff) | |
| download | kernel-a958c515e4cfcd5572ac7e2c3a567e832630a12d.tar.xz kernel-a958c515e4cfcd5572ac7e2c3a567e832630a12d.zip | |
kstd/vector: implement append_range
Diffstat (limited to 'libs/kstd/include')
| -rw-r--r-- | libs/kstd/include/kstd/bits/concepts.hpp | 15 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/vector | 69 |
2 files changed, 82 insertions, 2 deletions
diff --git a/libs/kstd/include/kstd/bits/concepts.hpp b/libs/kstd/include/kstd/bits/concepts.hpp new file mode 100644 index 0000000..74c25cb --- /dev/null +++ b/libs/kstd/include/kstd/bits/concepts.hpp @@ -0,0 +1,15 @@ +#ifndef KSTD_BITS_CONCEPTS_HPP +#define KSTD_BITS_CONCEPTS_HPP + +#include <concepts> +#include <ranges> +namespace kstd::bits +{ + + template<typename RangeType, typename ValueType> + concept container_compatible_range = + std::ranges::input_range<RangeType> && std::convertible_to<std::ranges::range_reference_t<RangeType>, ValueType>; + +} + +#endif diff --git a/libs/kstd/include/kstd/vector b/libs/kstd/include/kstd/vector index 97fdffe..2ecb6a8 100644 --- a/libs/kstd/include/kstd/vector +++ b/libs/kstd/include/kstd/vector @@ -2,6 +2,7 @@ #define KSTD_VECTOR_HPP #include <kstd/allocator> +#include <kstd/bits/concepts.hpp> #include <kstd/os/error.hpp> #include <kstd/ranges> @@ -882,6 +883,68 @@ namespace kstd return this->back(); } + //! Append the elements of a given range to this vector. + //! + //! @param range The range of elements to be appended. + //! @tparam SourceRange A container compatible range type. + template<kstd::bits::container_compatible_range<ValueType> SourceRange> + requires requires(Allocator allocator, pointer destination, SourceRange range) { + std::allocator_traits<Allocator>::construct(allocator, destination, *std::ranges::begin(range)); + } + // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward, misc-no-recursion) + constexpr auto append_range(SourceRange && range) -> void + { + if constexpr (std::ranges::forward_range<SourceRange> || std::ranges::sized_range<SourceRange>) + { + auto number_of_elements = static_cast<size_type>(std::ranges::distance(range)); + + if (!capacity()) + { + reserve(number_of_elements); + } + + if (capacity() - size() >= number_of_elements) + { + uninitialized_copy_with_allocator(std::ranges::begin(range), end(), number_of_elements); + m_size += number_of_elements; + return; + } + + auto new_capacity = m_capacity + std::max(size(), number_of_elements); + auto new_data = allocate_n(new_capacity); + auto old_size = size(); + + uninitialized_move_with_allocator(begin(), new_data, size()); + uninitialized_copy_with_allocator(std::ranges::begin(range), new_data + size(), number_of_elements); + clear_and_deallocate(); + m_data = new_data; + m_capacity = new_capacity; + m_size = old_size + number_of_elements; + return; + } + + auto range_begin = std::ranges::begin(range); + auto range_end = std::ranges::end(range); + + for (auto i = capacity() - size(); i > 0; --i, ++range_begin) + { + emplace_back(*range_begin); + } + + if (range_begin == range_end) + { + return; + } + + auto remainder = vector{get_allocator()}; + for (; range_begin != range_end; ++range_begin) + { + remainder.emplace_back(*static_cast<std::ranges::iterator_t<SourceRange>>(range_begin)); + } + reserve(size() + std::max(size(), remainder.size())); + append_range(remainder); + } + //! Remove the last element of this vector. //! //! If this vector is empty, the behavior is undefined. @@ -950,7 +1013,8 @@ namespace kstd //! @param from The start of the source range. //! @param to The start of the target range inside this vector. //! @param count The number of elements to copy - constexpr auto uninitialized_copy_with_allocator(const_iterator from, iterator to, size_type count) + template<typename SourceIterator> + constexpr auto uninitialized_copy_with_allocator(SourceIterator from, iterator to, size_type count) { for (auto i = 0uz; i < count; ++i) { @@ -963,7 +1027,8 @@ namespace kstd //! @param from The start of the source range. //! @param to The start of the target range inside this vector. //! @param count The number of elements to copy - constexpr auto uninitialized_move_with_allocator(iterator from, iterator to, size_type count) + template<typename SourceIterator> + constexpr auto uninitialized_move_with_allocator(SourceIterator from, iterator to, size_type count) { for (auto i = 0uz; i < count; ++i) { |
