diff --git a/src/ranges.cc b/src/ranges.cc new file mode 100644 index 00000000..d1603c18 --- /dev/null +++ b/src/ranges.cc @@ -0,0 +1,27 @@ +#include "ranges.hh" +#include "unit_tests.hh" +#include "string.hh" +#include "string_utils.hh" + +namespace Kakoune +{ + +UnitTest test_ranges{[] { + auto check_equal = [](auto&& container, ConstArrayView expected) { + kak_assert(std::equal(container.begin(), container.end(), expected.begin(), expected.end())); + }; + check_equal("a,b,c"_sv | split(','), {"a", "b", "c"}); + check_equal(",b,c"_sv | split(','), {"", "b", "c"}); + check_equal(",b,"_sv | split(','), {"", "b", ""}); + check_equal(","_sv | split(','), {"", ""}); + check_equal(""_sv | split(','), {}); + + check_equal(R"(a\,,\,b,\,)"_sv | split(',', '\\') + | transform(unescape<',', '\\'>), {"a,", ",b", ","}); + check_equal(R"(\,\,)"_sv | split(',', '\\') + | transform(unescape<',', '\\'>), {",,"}); + check_equal(R"(\\,\\,)"_sv | split(',', '\\') + | transform(unescape<',', '\\'>), {R"(\)", R"(\)", ""}); +}}; + +} diff --git a/src/ranges.hh b/src/ranges.hh index 9a4b1c8e..aebe6f50 100644 --- a/src/ranges.hh +++ b/src/ranges.hh @@ -173,13 +173,13 @@ struct SplitView struct Iterator : std::iterator { - Iterator(RangeIt pos, RangeIt end, Element separator, Element escaper) - : pos(pos), sep(pos), end(end), separator(separator), escaper(escaper) + Iterator(RangeIt pos, const RangeIt& end, Element separator, Element escaper) + : done{pos == end}, pos{pos}, sep{pos}, end(end), separator{std::move(separator)}, escaper{std::move(escaper)} { bool escaped = false; while (sep != end and (escaped or *sep != separator)) { - escaped = escape and *sep == escaper; + escaped = escape and not escaped and *sep == escaper; ++sep; } } @@ -187,8 +187,8 @@ struct SplitView Iterator& operator++() { advance(); return *this; } Iterator operator++(int) { auto copy = *this; advance(); return copy; } - bool operator==(const Iterator& other) const { return pos == other.pos; } - bool operator!=(const Iterator& other) const { return pos != other.pos; } + bool operator==(const Iterator& other) const { return pos == other.pos and done == other.done; } + bool operator!=(const Iterator& other) const { return pos != other.pos or done != other.done; } ValueType operator*() { return {pos, sep}; } @@ -198,6 +198,7 @@ struct SplitView if (sep == end) { pos = end; + done = true; return; } @@ -211,6 +212,7 @@ struct SplitView } } + bool done; RangeIt pos; RangeIt sep; RangeIt end;