...
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user