#ifndef containers_hh_INCLUDED #define containers_hh_INCLUDED #include #include #include namespace Kakoune { template struct ContainerView { Factory factory; }; template auto operator| (Container&& container, ContainerView view) -> decltype(view.factory(std::forward(container))) { return view.factory(std::forward(container)); } template struct ReverseView { using iterator = decltype(std::declval().rbegin()); iterator begin() { return m_container.rbegin(); } iterator end() { return m_container.rend(); } Container m_container; }; template using RemoveReference = typename std::remove_reference::type; struct ReverseFactory { template ReverseView> operator()(Container&& container) const { return {std::move(container)}; } template ReverseView operator()(Container& container) const { return {container}; } }; inline ContainerView reverse() { return {}; } template using IteratorOf = decltype(std::begin(std::declval())); template using ValueOf = typename Container::value_type; template struct FilterView { using ContainerIt = IteratorOf; struct Iterator : std::iterator::value_type> { Iterator(const FilterView& view, ContainerIt it, ContainerIt end) : m_it{std::move(it)}, m_end{std::move(end)}, m_view{view} { do_filter(); } auto operator*() -> decltype(*std::declval()) { 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; } friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { return not (lhs == rhs); } const ContainerIt& base() const { return m_it; } private: void do_filter() { while (m_it != m_end and not m_view.m_filter(*m_it)) ++m_it; } ContainerIt m_it; ContainerIt m_end; const FilterView& m_view; }; Iterator begin() const { return {*this, std::begin(m_container), std::end(m_container)}; } Iterator end() const { return {*this, std::end(m_container), std::end(m_container)}; } Container m_container; mutable Filter m_filter; }; template struct FilterFactory { template FilterView operator()(Container& container) const { return {container, std::move(m_filter)}; } template FilterView, Filter> operator()(Container&& container) const { return {std::move(container), std::move(m_filter)}; } Filter m_filter; }; template inline ContainerView> filter(Filter f) { return {{std::move(f)}}; } template using TransformedResult = decltype(std::declval()(*std::declval())); template struct TransformView { using ContainerIt = IteratorOf; struct Iterator : std::iterator>::type> { Iterator(const TransformView& view, ContainerIt it) : m_it{std::move(it)}, m_view{view} {} auto operator*() -> TransformedResult { return m_view.m_transform(*m_it); } Iterator& operator++() { ++m_it; return *this; } Iterator operator++(int) { auto copy = *this; ++m_it; return copy; } friend bool operator==(const Iterator& lhs, const Iterator& rhs) { return lhs.m_it == rhs.m_it; } friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { return not (lhs == rhs); } ContainerIt base() const { return m_it; } private: ContainerIt m_it; const TransformView& m_view; }; Iterator begin() const { return {*this, std::begin(m_container)}; } Iterator end() const { return {*this, std::end(m_container)}; } Container m_container; mutable Transform m_transform; }; template struct TransformFactory { template TransformView operator()(Container& container) const { return {container, std::move(m_transform)}; } template TransformView, Transform> operator()(Container&& container) const { return {std::move(container), std::move(m_transform)}; } Transform m_transform; }; 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 {std::begin(m_container), std::end(m_container), m_separator}; } Iterator end() const { return {std::end(m_container), std::end(m_container), 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 { using ContainerIt1 = decltype(begin(std::declval())); using ContainerIt2 = decltype(begin(std::declval())); using ValueType = typename std::common_type::value_type, typename std::iterator_traits::value_type>::type; struct Iterator : std::iterator { static_assert(std::is_convertible::value_type, ValueType>::value, ""); static_assert(std::is_convertible::value_type, ValueType>::value, ""); Iterator(ContainerIt1 it1, ContainerIt1 end1, ContainerIt2 it2) : m_it1(std::move(it1)), m_end1(std::move(end1)), m_it2(std::move(it2)) {} ValueType 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; } friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { return not (lhs == rhs); } private: bool is2() const { return m_it1 == m_end1; } ContainerIt1 m_it1; ContainerIt1 m_end1; ContainerIt2 m_it2; }; ConcatView(Container1& container1, Container2& container2) : m_container1(container1), m_container2(container2) {} Iterator begin() const { return {m_container1.begin(), m_container1.end(), m_container2.begin()}; } Iterator end() const { return {m_container1.end(), m_container1.end(), m_container2.end()}; } private: Container1& m_container1; Container2& m_container2; }; template ConcatView concatenated(Container1&& container1, Container2&& container2) { return {container1, container2}; } // Todo: move that into the following functions once we can remove the decltype // return type. using std::begin; using std::end; template auto find(Container&& container, const T& value) -> decltype(begin(container)) { return std::find(begin(container), end(container), value); } template auto find_if(Container&& container, T op) -> decltype(begin(container)) { return std::find_if(begin(container), end(container), op); } template bool contains(Container&& container, const T& value) { return find(container, value) != end(container); } template bool contains_that(Container&& container, T op) { return find_if(container, op) != end(container); } template void unordered_erase(Container&& vec, U&& value) { auto it = find(vec, std::forward(value)); if (it != vec.end()) { using std::swap; swap(vec.back(), *it); vec.pop_back(); } } } #endif // containers_hh_INCLUDED