#ifndef ranges_hh_INCLUDED #define ranges_hh_INCLUDED #include #include #include #include #include #include "constexpr_utils.hh" namespace Kakoune { template struct ViewFactory { Func func; }; template ViewFactory(Func&&) -> ViewFactory>; template decltype(auto) operator| (Range&& range, ViewFactory factory) { return factory.func(std::forward(range)); } template struct DecayRangeImpl { using type = std::remove_cvref_t; }; template struct DecayRangeImpl { using type = Range&; }; template using DecayRange = typename DecayRangeImpl::type; template struct RangeHolderImpl { using type = std::remove_cvref_t; }; template struct RangeHolderImpl { struct type { Range* range{}; decltype(auto) begin() { return std::begin(*range); } decltype(auto) end() { return std::end(*range); } type& operator=(Range& r) { range = &r; return *this; } operator Range&() { return *range; } }; }; template using RangeHolder = typename RangeHolderImpl::type; template struct ReverseView { decltype(auto) begin() { return m_range.rbegin(); } decltype(auto) end() { return m_range.rend(); } decltype(auto) rbegin() { return m_range.begin(); } decltype(auto) rend() { return m_range.end(); } decltype(auto) begin() const { return m_range.rbegin(); } decltype(auto) end() const { return m_range.rend(); } decltype(auto) rbegin() const { return m_range.begin(); } decltype(auto) rend() const { return m_range.end(); } Range m_range; }; constexpr auto reverse() { return ViewFactory{[](auto&& range) { using Range = decltype(range); return ReverseView>{std::forward(range)}; }}; } template using IteratorOf = decltype(std::begin(std::declval())); template using ValueOf = decltype(*std::declval>()); template struct SkipView { auto begin() const { return std::next(std::begin(m_range), m_skip_count); } auto end() const { return std::end(m_range); } Range m_range; size_t m_skip_count; }; constexpr auto skip(size_t count) { return ViewFactory{[count](auto&& range) { using Range = decltype(range); return SkipView>{std::forward(range), count}; }}; } template struct DropView { auto begin() const { return std::begin(m_range); } auto end() const { return std::end(m_range) - m_drop_count; } Range m_range; size_t m_drop_count; }; constexpr auto drop(size_t count) { return ViewFactory{[count](auto&& range) { using Range = decltype(range); return DropView>{std::forward(range), count}; }}; } template struct FilterView { using RangeIt = IteratorOf; struct Iterator { using difference_type = ptrdiff_t; using value_type = typename std::iterator_traits::value_type; using pointer = value_type*; using reference = value_type&; using iterator_category = std::forward_iterator_tag; Iterator(Filter& filter, RangeIt it, RangeIt end) : m_it{std::move(it)}, m_end{std::move(end)}, m_filter{&filter} { do_filter(); } decltype(auto) operator*() { return *m_it; } Iterator& operator++() { ++m_it; do_filter(); return *this; } Iterator operator++(int) { auto copy = *this; ++(*this); return copy; } friend bool operator==(const Iterator& lhs, const Iterator& rhs) { return lhs.m_it == rhs.m_it; } const RangeIt& base() const { return m_it; } private: void do_filter() { while (m_it != m_end and not (*m_filter)(*m_it)) ++m_it; } RangeIt m_it; RangeIt m_end; Filter* m_filter; }; Iterator begin() const { return {m_filter, std::begin(m_range), std::end(m_range)}; } Iterator end() const { return {m_filter, std::end(m_range), std::end(m_range)}; } Range m_range; mutable Filter m_filter; }; template constexpr auto filter(Filter f) { return ViewFactory{[f = std::move(f)](auto&& range) { using Range = decltype(range); return FilterView, Filter>{std::forward(range), std::move(f)}; }}; } template struct EnumerateView { using RangeIt = IteratorOf; struct Iterator { using difference_type = ptrdiff_t; using value_type = typename std::iterator_traits::value_type; using pointer = value_type*; using reference = value_type&; using iterator_category = std::forward_iterator_tag; Iterator(size_t index, RangeIt it) : m_index{index}, m_it{std::move(it)} {} decltype(auto) operator*() { return std::tuple(m_index, *m_it); } Iterator& operator++() { ++m_index; ++m_it; return *this; } Iterator operator++(int) { auto copy = *this; ++(*this); return copy; } friend bool operator==(const Iterator& lhs, const Iterator& rhs) { return lhs.m_it == rhs.m_it; } const RangeIt& base() const { return m_it; } private: size_t m_index; RangeIt m_it; }; Iterator begin() const { return {0, std::begin(m_range)}; } Iterator end() const { return {(size_t)-1, std::end(m_range)}; } Range m_range; }; constexpr auto enumerate() { return ViewFactory{[](auto&& range) { using Range = decltype(range); return EnumerateView>{std::forward(range)}; }}; } template struct TransformView { using RangeIt = IteratorOf; using ResType = decltype(std::declval()(*std::declval())); struct Iterator { using iterator_category = typename std::iterator_traits::iterator_category; using value_type = std::remove_reference_t; using difference_type = typename std::iterator_traits::difference_type; using pointer = value_type*; using reference = value_type&; Iterator(Transform& transform, RangeIt it) : m_it{std::move(it)}, m_transform{&transform} {} decltype(auto) operator*() { return (*m_transform)(*m_it); } decltype(auto) operator[](difference_type i) const { return (*m_transform)(m_it[i]); } Iterator& operator++() { ++m_it; return *this; } Iterator operator++(int) { auto copy = *this; ++m_it; return copy; } Iterator& operator--() { --m_it; return *this; } Iterator operator--(int) { auto copy = *this; --m_it; return copy; } Iterator& operator+=(difference_type diff) { m_it += diff; return *this; } Iterator& operator-=(difference_type diff) { m_it -= diff; return *this; } Iterator operator+(difference_type diff) const { return {*m_transform, m_it + diff}; } Iterator operator-(difference_type diff) const { return {*m_transform, m_it - diff}; } friend bool operator==(const Iterator& lhs, const Iterator& rhs) { return lhs.m_it == rhs.m_it; } friend difference_type operator-(const Iterator& lhs, const Iterator& rhs) { return lhs.m_it - rhs.m_it; } RangeIt base() const { return m_it; } private: RangeIt m_it; Transform* m_transform; }; Iterator begin() const { return {m_transform, std::begin(m_range)}; } Iterator end() const { return {m_transform, std::end(m_range)}; } Range m_range; mutable Transform m_transform; }; template constexpr auto transform(Transform t) { return ViewFactory{[t = std::move(t)](auto&& range) { using Range = decltype(range); return TransformView, Transform>{std::forward(range), std::move(t)}; }}; } template struct is_pointer_like : std::false_type {}; template requires std::is_same_v())>, std::remove_cvref_t> struct is_pointer_like : std::true_type {}; template constexpr auto transform(M T::*member) { return transform([member](auto&& arg) -> decltype(auto) { using Arg = decltype(arg); using Member = decltype(member); auto get_object = [&] () mutable -> decltype(auto) { if constexpr (is_pointer_like::value) return *std::forward(arg); else return std::forward(arg); }; if constexpr (std::is_member_function_pointer_v) return (get_object().*member)(); else return get_object().*member; }); } template, typename ValueTypeParam = void> struct SplitView { using RangeIt = IteratorOf; using ValueType = std::conditional_t::value, std::pair, IteratorOf>, ValueTypeParam>; struct Iterator { using difference_type = ptrdiff_t; using value_type = ValueType; using pointer = ValueType*; using reference = ValueType&; using iterator_category = std::forward_iterator_tag; 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 not escaped and *sep == escaper; ++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 and done == other.done; } ValueType operator*() { return {pos, (not include_separator or sep == end) ? sep : sep + 1}; } private: void advance() { if (sep == end) { pos = end; done = true; return; } pos = sep+1; if (include_separator and pos == end) { done = true; return; } bool escaped = escape and *sep == escaper; for (sep = pos; sep != end; ++sep) { if (not escaped and *sep == separator) break; escaped = escape and not escaped and *sep == escaper; } } bool done; RangeIt pos; RangeIt sep; RangeIt end; Element separator; Element escaper; }; Iterator begin() const { return {std::begin(m_range), std::end(m_range), m_separator, m_escaper}; } Iterator end() const { return {std::end(m_range), std::end(m_range), m_separator, m_escaper}; } Range m_range; Element m_separator; Element m_escaper; }; template auto split(Element separator) { return ViewFactory{[s = std::move(separator)](auto&& range) { using Range = decltype(range); return SplitView, false, false, Element, ValueType>{std::forward(range), std::move(s), {}}; }}; } template auto split_after(Element separator) { return ViewFactory{[s = std::move(separator)](auto&& range) { using Range = decltype(range); return SplitView, false, true, Element, ValueType>{std::forward(range), std::move(s), {}}; }}; } template auto split(Element separator, Element escaper) { return ViewFactory{[s = std::move(separator), e = std::move(escaper)](auto&& range) { using Range = decltype(range); return SplitView, true, false, Element, ValueType>{std::forward(range), std::move(s), std::move(e)}; }}; } template struct FlattenedView { using OuterIt = IteratorOf; using InnerRange = ValueOf; using InnerIt = IteratorOf; struct Iterator { using value_type = typename std::iterator_traits::value_type; using iterator_category = std::forward_iterator_tag; using difference_type = std::size_t; using reference = value_type&; using pointer = value_type*; Iterator() = default; Iterator(OuterIt begin, OuterIt end) : m_outer_it{begin}, m_outer_end{end} { find_next_inner(); } decltype(auto) operator*() { return *m_inner_it; } Iterator& operator++() { if (++m_inner_it == std::end(m_inner_range)) { ++m_outer_it; find_next_inner(); } return *this; } Iterator operator++(int) { auto copy = *this; ++*this; return copy; } friend bool operator==(const Iterator& lhs, const Iterator& rhs) { return lhs.m_outer_it == rhs.m_outer_it and lhs.m_inner_it == rhs.m_inner_it; } void find_next_inner() { m_inner_it = InnerIt{}; for (; m_outer_it != m_outer_end; ++m_outer_it) { m_inner_range = *m_outer_it; if (std::begin(m_inner_range) != std::end(m_inner_range)) { m_inner_it = std::begin(m_inner_range); return; } } } OuterIt m_outer_it{}; OuterIt m_outer_end{}; InnerIt m_inner_it{}; RangeHolder m_inner_range; }; Iterator begin() const { return {std::begin(m_range), std::end(m_range)}; } Iterator end() const { return {std::end(m_range), std::end(m_range)}; } Range m_range; }; constexpr auto flatten() { return ViewFactory{[](auto&& range){ using Range = decltype(range); return FlattenedView>{std::forward(range)}; }}; } template struct ConcatView { using RangeIt1 = decltype(std::declval().begin()); using RangeIt2 = decltype(std::declval().begin()); using ValueType = typename std::common_type_t::value_type, typename std::iterator_traits::value_type>; struct Iterator { using difference_type = ptrdiff_t; using value_type = ValueType; using pointer = ValueType*; using reference = ValueType&; using iterator_category = std::forward_iterator_tag; static_assert(std::is_convertible::value_type, ValueType>::value, ""); static_assert(std::is_convertible::value_type, ValueType>::value, ""); Iterator(RangeIt1 it1, RangeIt1 end1, RangeIt2 it2) : m_it1(std::move(it1)), m_end1(std::move(end1)), m_it2(std::move(it2)) {} decltype(auto) operator*() { return is2() ? *m_it2 : *m_it1; } Iterator& operator++() { if (is2()) ++m_it2; else ++m_it1; return *this; } Iterator operator++(int) { auto copy = *this; ++*this; return copy; } friend bool operator==(const Iterator& lhs, const Iterator& rhs) { return lhs.m_it1 == rhs.m_it1 and lhs.m_end1 == rhs.m_end1 and lhs.m_it2 == rhs.m_it2; } private: bool is2() const { return m_it1 == m_end1; } RangeIt1 m_it1; RangeIt1 m_end1; RangeIt2 m_it2; }; Iterator begin() const { return {m_range1.begin(), m_range1.end(), m_range2.begin()}; } Iterator end() const { return {m_range1.end(), m_range1.end(), m_range2.end()}; } Range1 m_range1; Range2 m_range2; }; template ConcatView, DecayRange> concatenated(Range1&& range1, Range2&& range2) { return {range1, range2}; } template auto find(Range&& range, const T& value) { using std::begin; using std::end; return std::find(begin(range), end(range), value); } template auto find_if(Range&& range, T op) { using std::begin; using std::end; return std::find_if(begin(range), end(range), op); } template bool contains(Range&& range, const T& value) { using std::end; return find(range, value) != end(range); } template bool all_of(Range&& range, T op) { using std::begin; using std::end; return std::all_of(begin(range), end(range), op); } template bool any_of(Range&& range, T op) { using std::begin; using std::end; return std::any_of(begin(range), end(range), op); } template auto remove_if(Range&& range, T op) { using std::begin; using std::end; return std::remove_if(begin(range), end(range), op); } template void unordered_erase(Range&& vec, U&& value) { auto it = find(vec, std::forward(value)); if (it != vec.end()) { using std::swap; swap(vec.back(), *it); vec.pop_back(); } } template Init accumulate(Range&& c, Init&& init, BinOp&& op) { using std::begin; using std::end; return std::accumulate(begin(c), end(c), init, op); } template void for_n_best(Range&& c, size_t count, Compare&& compare, Func&& func) { using std::begin; using std::end; auto b = begin(c), e = end(c); std::make_heap(b, e, compare); while (count > 0 and b != e) { if (func(*b)) --count; std::pop_heap(b, e--, compare); } } template auto gather() { return ViewFactory{[](auto&& range) { using std::begin; using std::end; return Container(begin(range), end(range)); }}; } template