From d3ef2d36ead57e6a0490cebba3cdbc434c729e24 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Fri, 25 Mar 2016 00:14:56 +0000 Subject: [PATCH] Add a SplitView container view --- src/containers.hh | 82 +++++++++++++++++++++++++++++++++++++++++++++-- src/enum.hh | 2 +- src/file.cc | 2 +- src/normal.cc | 2 +- src/selection.cc | 2 +- 5 files changed, 84 insertions(+), 6 deletions(-) diff --git a/src/containers.hh b/src/containers.hh index b0fc58e3..675a7fb5 100644 --- a/src/containers.hh +++ b/src/containers.hh @@ -49,10 +49,16 @@ struct ReverseFactory inline ContainerView reverse() { return {}; } +template +using IteratorOf = decltype(std::begin(std::declval())); + +template +using ValueOf = typename Container::value_type; + template struct FilterView { - using ContainerIt = decltype(begin(std::declval())); + using ContainerIt = IteratorOf; struct Iterator : std::iterator @@ -119,7 +125,7 @@ using TransformedResult = decltype(std::declval()(*std::declval())); template struct TransformView { - using ContainerIt = decltype(begin(std::declval())); + using ContainerIt = IteratorOf; struct Iterator : std::iterator>::type> @@ -170,6 +176,78 @@ struct TransformFactory template inline ContainerView> transform(Transform t) { return {{std::move(t)}}; } +template, + typename ValueTypeParam = void> +struct SplitView +{ + using ContainerIt = IteratorOf; + using ValueType = typename std::conditional::value, + std::pair, IteratorOf>, + ValueTypeParam>::type; + + struct Iterator : std::iterator + { + Iterator(ContainerIt pos, ContainerIt end, char separator) + : pos(pos), sep(pos), end(end), separator(separator) + { + while (sep != end and *sep != separator) + ++sep; + } + + 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; } + + ValueType operator*() { return {pos, sep}; } + + private: + void advance() + { + if (sep == end) + { + pos = end; + return; + } + + pos = sep+1; + for (sep = pos; sep != end; ++sep) + { + if (*sep == separator) + break; + } + } + + ContainerIt pos; + ContainerIt sep; + ContainerIt end; + Separator separator; + }; + + Iterator begin() const { return {m_container.begin(), m_container.end(), m_separator}; } + Iterator end() const { return {m_container.end(), m_container.end(), m_separator}; } + + Container m_container; + Separator m_separator; +}; + +template +struct SplitViewFactory +{ + template + SplitView, Separator, ValueType> + operator()(Container&& container) const { return {std::move(container), std::move(separator)}; } + + template + SplitView + operator()(Container& container) const { return {container, std::move(separator)}; } + + Separator separator; +}; + +template +ContainerView> split(Separator separator) { return {{std::move(separator)}}; } template struct ConcatView diff --git a/src/enum.hh b/src/enum.hh index 728a56d2..6f4a4bdb 100644 --- a/src/enum.hh +++ b/src/enum.hh @@ -54,7 +54,7 @@ EnableIfWithBitOps option_from_string(StringView str, Flags& flags) { constexpr auto desc = enum_desc(Flags{}); flags = Flags{}; - for (auto s : split(str, '|')) + for (auto s : str | split('|')) { auto it = find_if(desc, [s](const EnumDesc& d) { return d.name == s; }); if (it == desc.end()) diff --git a/src/file.cc b/src/file.cc index 6cf9a735..a558dc29 100644 --- a/src/file.cc +++ b/src/file.cc @@ -449,7 +449,7 @@ Vector complete_command(StringView prefix, ByteCount cursor_pos) static UnorderedMap command_cache; Vector matches; - for (auto dir : split(getenv("PATH"), ':')) + for (auto dir : StringView{getenv("PATH")} | split(':')) { auto dirname = ((not dir.empty() and dir.back() == '/') ? dir.substr(0, dir.length()-1) : dir).str(); diff --git a/src/normal.cc b/src/normal.cc index ab08da9b..13ecd9e2 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -1385,7 +1385,7 @@ void restore_selections(Context& context, NormalParams params) size_t timestamp = str_to_int({percent + 1, desc.end()}); Vector sels; - for (auto sel_desc : split({desc.begin(), arobase}, ':')) + for (auto sel_desc : StringView{desc.begin(), arobase} | split(':')) sels.push_back(selection_from_string(sel_desc)); SelectionList sel_list{buffer, std::move(sels), timestamp}; diff --git a/src/selection.cc b/src/selection.cc index 8d9c7274..a2b2d1f2 100644 --- a/src/selection.cc +++ b/src/selection.cc @@ -587,7 +587,7 @@ Selection selection_from_string(StringView desc) SelectionList selection_list_from_string(Buffer& buffer, StringView desc) { Vector sels; - for (auto sel_desc : split(desc, ':')) + for (auto sel_desc : desc | split(':')) sels.push_back(selection_from_string(sel_desc)); return {buffer, std::move(sels)}; }