This commit is contained in:
2024-10-07 18:09:28 +03:00
parent 8bcc8edbb0
commit 7e3aed284c
4 changed files with 117 additions and 40 deletions

View File

@@ -5,6 +5,7 @@
#include <limits>
#include <ranges>
#include <regex>
#include <utility>
#include "../common/adc_traits.h"
@@ -12,6 +13,12 @@
namespace adc::utils
{
// compile-time size of zero-terminated char array
static consteval size_t AdcCharArrSize(const char* arr)
{
return *arr ? 1 + AdcCharArrSize(arr + 1) : 0;
}
static bool AdcIsSpace(char in) noexcept
{
static constexpr auto ws = {' ', '\t', '\n', '\v', '\r', '\f'};
@@ -542,4 +549,78 @@ static size_t AdcReturnRangeElementsView(const R& r, const RD& delim, RO& ro)
return N;
}
template <std::ranges::range ResT, traits::adc_char_range R, traits::adc_input_char_range DR>
requires(std::ranges::contiguous_range<R> && traits::adc_char_view<std::ranges::range_value_t<ResT>>) ||
traits::adc_output_char_range<std::ranges::range_value_t<ResT>>
static auto AdcSplitCharRange(R&& r, DR&& delim, size_t start = 0, size_t num = std::numeric_limits<size_t>::max())
{
ResT res;
using el_t = std::ranges::range_value_t<ResT>;
if (num == 0) {
return res;
}
size_t last_el = num;
if (start) { // to prevent overflowing
if (num < (std::numeric_limits<size_t>::max() - start + 1)) {
last_el = start + num - 1;
}
} else {
if (num < (std::numeric_limits<size_t>::max())) {
last_el = num - 1;
}
}
auto begin = std::forward<R>(r).begin();
auto end = std::forward<R>(r).end();
auto it_el = begin;
auto it_next = begin;
size_t i_el = 0;
auto prev = std::ranges::search(std::forward<R>(r), std::forward<DR>(delim));
do {
if (prev.begin() != begin) {
if (i_el >= start) {
std::back_inserter(res) = el_t(it_el, prev.begin());
}
++i_el;
if (i_el > last_el) {
break;
}
it_el = prev.end();
}
if (prev.end() == end) {
break;
}
it_next = prev.end();
auto next = std::ranges::search(it_next, end, std::forward<DR>(delim).begin(), std::forward<DR>(delim).end());
while (it_next == next.begin()) {
it_next = next.end();
next = std::ranges::search(it_next, end, std::forward<DR>(delim).begin(), std::forward<DR>(delim).end());
if (next.empty()) {
break;
}
}
prev = next;
} while (true);
return res;
}
} // namespace adc::utils