blob: 419b4790a76dd1f99914f076120f22c623f208d4 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
/*
* This source code is released into the public domain.
*/
#ifndef LFJAIL_SPLIT_HH
#define LFJAIL_SPLIT_HH
#include "generator.hh"
namespace lfjail {
/*
* split: split a range of items on a given predicate and return each element
* as a subrange. This is intended to be used with strings, but in theory it
* can accept any range.
*
* The input range is never copied, so the returned ranges reference the
* input range.
*/
template<std::ranges::range Range,
std::indirect_unary_predicate<std::ranges::iterator_t<Range>> Pred>
auto split(Range &&range, Pred &&pred)
-> std::generator<decltype(std::ranges::subrange(range))>
{
auto pos = std::ranges::begin(range);
auto end = std::ranges::end(range);
for (;;) {
// Skip leading separators.
while (pos != end && pred(*pos))
++pos;
if (pos == end)
co_return;
auto const split_point = std::find_if(pos, end, pred);
// Yield this value.
co_yield std::ranges::subrange(pos, split_point);
pos = split_point;
}
}
/*
* split_string: helper function to make split() a bit more useful for strings.
* Instead of returning subranges, it returns basic_string_views.
*/
auto split_string(std::ranges::contiguous_range auto &&string, auto pred)
-> std::generator<
std::basic_string_view<
std::ranges::range_value_t<decltype(string)>>>
{
using sv_type = std::basic_string_view<
std::ranges::range_value_t<decltype(string)>>;
for (auto const &&subrange : split(string, pred))
co_yield sv_type(subrange);
}
} // namespace lfjail
#endif // !LFJAIL_SPLIT_HH
|