1bdd1243dSDimitry Andric // -*- C++ -*- 2bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 3bdd1243dSDimitry Andric // 4bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7bdd1243dSDimitry Andric // 8bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 9bdd1243dSDimitry Andric 10bdd1243dSDimitry Andric #ifndef _LIBCPP___RANGES_SPLIT_VIEW_H 11bdd1243dSDimitry Andric #define _LIBCPP___RANGES_SPLIT_VIEW_H 12bdd1243dSDimitry Andric 13bdd1243dSDimitry Andric #include <__algorithm/ranges_search.h> 14bdd1243dSDimitry Andric #include <__concepts/constructible.h> 15bdd1243dSDimitry Andric #include <__config> 16bdd1243dSDimitry Andric #include <__functional/bind_back.h> 17bdd1243dSDimitry Andric #include <__functional/ranges_operations.h> 18bdd1243dSDimitry Andric #include <__iterator/indirectly_comparable.h> 19bdd1243dSDimitry Andric #include <__iterator/iterator_traits.h> 20bdd1243dSDimitry Andric #include <__memory/addressof.h> 21bdd1243dSDimitry Andric #include <__ranges/access.h> 22bdd1243dSDimitry Andric #include <__ranges/all.h> 23bdd1243dSDimitry Andric #include <__ranges/concepts.h> 24bdd1243dSDimitry Andric #include <__ranges/empty.h> 25bdd1243dSDimitry Andric #include <__ranges/non_propagating_cache.h> 26bdd1243dSDimitry Andric #include <__ranges/range_adaptor.h> 27bdd1243dSDimitry Andric #include <__ranges/single_view.h> 28bdd1243dSDimitry Andric #include <__ranges/subrange.h> 29bdd1243dSDimitry Andric #include <__ranges/view_interface.h> 30bdd1243dSDimitry Andric #include <__type_traits/decay.h> 31bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_constructible.h> 32bdd1243dSDimitry Andric #include <__utility/forward.h> 33bdd1243dSDimitry Andric #include <__utility/move.h> 34bdd1243dSDimitry Andric 35bdd1243dSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 36bdd1243dSDimitry Andric # pragma GCC system_header 37bdd1243dSDimitry Andric #endif 38bdd1243dSDimitry Andric 39b3edf446SDimitry Andric _LIBCPP_PUSH_MACROS 40b3edf446SDimitry Andric #include <__undef_macros> 41b3edf446SDimitry Andric 42bdd1243dSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 43bdd1243dSDimitry Andric 44bdd1243dSDimitry Andric #if _LIBCPP_STD_VER >= 20 45bdd1243dSDimitry Andric 46bdd1243dSDimitry Andric namespace ranges { 47bdd1243dSDimitry Andric 48bdd1243dSDimitry Andric template <forward_range _View, forward_range _Pattern> 49bdd1243dSDimitry Andric requires view<_View> && view<_Pattern> && 50bdd1243dSDimitry Andric indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> 51bdd1243dSDimitry Andric class split_view : public view_interface<split_view<_View, _Pattern>> { 52bdd1243dSDimitry Andric private: 53bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); 54bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Pattern __pattern_ = _Pattern(); 55bdd1243dSDimitry Andric using _Cache = __non_propagating_cache<subrange<iterator_t<_View>>>; 56bdd1243dSDimitry Andric _Cache __cached_begin_ = _Cache(); 57bdd1243dSDimitry Andric 58bdd1243dSDimitry Andric template <class, class> 591ac55f4cSDimitry Andric friend struct __iterator; 60bdd1243dSDimitry Andric 61bdd1243dSDimitry Andric template <class, class> 621ac55f4cSDimitry Andric friend struct __sentinel; 63bdd1243dSDimitry Andric 641ac55f4cSDimitry Andric struct __iterator; 651ac55f4cSDimitry Andric struct __sentinel; 66bdd1243dSDimitry Andric 67bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr subrange<iterator_t<_View>> __find_next(iterator_t<_View> __it) { 68bdd1243dSDimitry Andric auto [__begin, __end] = ranges::search(subrange(__it, ranges::end(__base_)), __pattern_); 69bdd1243dSDimitry Andric if (__begin != ranges::end(__base_) && ranges::empty(__pattern_)) { 70bdd1243dSDimitry Andric ++__begin; 71bdd1243dSDimitry Andric ++__end; 72bdd1243dSDimitry Andric } 73bdd1243dSDimitry Andric return {__begin, __end}; 74bdd1243dSDimitry Andric } 75bdd1243dSDimitry Andric 76bdd1243dSDimitry Andric public: 77bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI split_view() 78bdd1243dSDimitry Andric requires default_initializable<_View> && default_initializable<_Pattern> 79bdd1243dSDimitry Andric = default; 80bdd1243dSDimitry Andric 8106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 split_view(_View __base, _Pattern __pattern) 82bdd1243dSDimitry Andric : __base_(std::move(__base)), __pattern_(std::move((__pattern))) {} 83bdd1243dSDimitry Andric 84bdd1243dSDimitry Andric template <forward_range _Range> 85bdd1243dSDimitry Andric requires constructible_from<_View, views::all_t<_Range>> && 86bdd1243dSDimitry Andric constructible_from<_Pattern, single_view<range_value_t<_Range>>> 8706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 8806c3fb27SDimitry Andric split_view(_Range&& __range, range_value_t<_Range> __elem) 89bdd1243dSDimitry Andric : __base_(views::all(std::forward<_Range>(__range))), __pattern_(views::single(std::move(__elem))) {} 90bdd1243dSDimitry Andric 91bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& 92bdd1243dSDimitry Andric requires copy_constructible<_View> 93bdd1243dSDimitry Andric { 94bdd1243dSDimitry Andric return __base_; 95bdd1243dSDimitry Andric } 96bdd1243dSDimitry Andric 97bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } 98bdd1243dSDimitry Andric 99bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator begin() { 100bdd1243dSDimitry Andric if (!__cached_begin_.__has_value()) { 101bdd1243dSDimitry Andric __cached_begin_.__emplace(__find_next(ranges::begin(__base_))); 102bdd1243dSDimitry Andric } 103bdd1243dSDimitry Andric return {*this, ranges::begin(__base_), *__cached_begin_}; 104bdd1243dSDimitry Andric } 105bdd1243dSDimitry Andric 106bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto end() { 107bdd1243dSDimitry Andric if constexpr (common_range<_View>) { 108bdd1243dSDimitry Andric return __iterator{*this, ranges::end(__base_), {}}; 109bdd1243dSDimitry Andric } else { 110bdd1243dSDimitry Andric return __sentinel{*this}; 111bdd1243dSDimitry Andric } 112bdd1243dSDimitry Andric } 113bdd1243dSDimitry Andric }; 114bdd1243dSDimitry Andric 115bdd1243dSDimitry Andric template <class _Range, class _Pattern> 116bdd1243dSDimitry Andric split_view(_Range&&, _Pattern&&) -> split_view<views::all_t<_Range>, views::all_t<_Pattern>>; 117bdd1243dSDimitry Andric 118bdd1243dSDimitry Andric template <forward_range _Range> 119bdd1243dSDimitry Andric split_view(_Range&&, range_value_t<_Range>) -> split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>; 120bdd1243dSDimitry Andric 1211ac55f4cSDimitry Andric template <forward_range _View, forward_range _Pattern> 1221ac55f4cSDimitry Andric requires view<_View> && view<_Pattern> && 1231ac55f4cSDimitry Andric indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> 1241ac55f4cSDimitry Andric struct split_view<_View, _Pattern>::__iterator { 125bdd1243dSDimitry Andric private: 1261ac55f4cSDimitry Andric split_view* __parent_ = nullptr; 127bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __cur_ = iterator_t<_View>(); 128bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS subrange<iterator_t<_View>> __next_ = subrange<iterator_t<_View>>(); 129bdd1243dSDimitry Andric bool __trailing_empty_ = false; 130bdd1243dSDimitry Andric 1311ac55f4cSDimitry Andric friend struct __sentinel; 132bdd1243dSDimitry Andric 133bdd1243dSDimitry Andric public: 134bdd1243dSDimitry Andric using iterator_concept = forward_iterator_tag; 135bdd1243dSDimitry Andric using iterator_category = input_iterator_tag; 136bdd1243dSDimitry Andric using value_type = subrange<iterator_t<_View>>; 137bdd1243dSDimitry Andric using difference_type = range_difference_t<_View>; 138bdd1243dSDimitry Andric 1391ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI __iterator() = default; 140bdd1243dSDimitry Andric 1411ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator( 142bdd1243dSDimitry Andric split_view<_View, _Pattern>& __parent, iterator_t<_View> __current, subrange<iterator_t<_View>> __next) 143bdd1243dSDimitry Andric : __parent_(std::addressof(__parent)), __cur_(std::move(__current)), __next_(std::move(__next)) {} 144bdd1243dSDimitry Andric 145bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_View> base() const { return __cur_; } 146bdd1243dSDimitry Andric 147bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const { return {__cur_, __next_.begin()}; } 148bdd1243dSDimitry Andric 1491ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { 150bdd1243dSDimitry Andric __cur_ = __next_.begin(); 151bdd1243dSDimitry Andric if (__cur_ != ranges::end(__parent_->__base_)) { 152bdd1243dSDimitry Andric __cur_ = __next_.end(); 153bdd1243dSDimitry Andric if (__cur_ == ranges::end(__parent_->__base_)) { 154bdd1243dSDimitry Andric __trailing_empty_ = true; 155bdd1243dSDimitry Andric __next_ = {__cur_, __cur_}; 156bdd1243dSDimitry Andric } else { 157bdd1243dSDimitry Andric __next_ = __parent_->__find_next(__cur_); 158bdd1243dSDimitry Andric } 159bdd1243dSDimitry Andric } else { 160bdd1243dSDimitry Andric __trailing_empty_ = false; 161bdd1243dSDimitry Andric } 162bdd1243dSDimitry Andric return *this; 163bdd1243dSDimitry Andric } 164bdd1243dSDimitry Andric 1651ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { 166bdd1243dSDimitry Andric auto __tmp = *this; 167bdd1243dSDimitry Andric ++*this; 168bdd1243dSDimitry Andric return __tmp; 169bdd1243dSDimitry Andric } 170bdd1243dSDimitry Andric 1711ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) { 172bdd1243dSDimitry Andric return __x.__cur_ == __y.__cur_ && __x.__trailing_empty_ == __y.__trailing_empty_; 173bdd1243dSDimitry Andric } 174bdd1243dSDimitry Andric }; 175bdd1243dSDimitry Andric 1761ac55f4cSDimitry Andric template <forward_range _View, forward_range _Pattern> 1771ac55f4cSDimitry Andric requires view<_View> && view<_Pattern> && 1781ac55f4cSDimitry Andric indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> 1791ac55f4cSDimitry Andric struct split_view<_View, _Pattern>::__sentinel { 180bdd1243dSDimitry Andric private: 181bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_View> __end_ = sentinel_t<_View>(); 182bdd1243dSDimitry Andric 1831ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __equals(const __iterator& __x, const __sentinel& __y) { 184bdd1243dSDimitry Andric return __x.__cur_ == __y.__end_ && !__x.__trailing_empty_; 185bdd1243dSDimitry Andric } 186bdd1243dSDimitry Andric 187bdd1243dSDimitry Andric public: 1881ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI __sentinel() = default; 189bdd1243dSDimitry Andric 1901ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(split_view<_View, _Pattern>& __parent) 191bdd1243dSDimitry Andric : __end_(ranges::end(__parent.__base_)) {} 192bdd1243dSDimitry Andric 1931ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) { 194bdd1243dSDimitry Andric return __equals(__x, __y); 195bdd1243dSDimitry Andric } 196bdd1243dSDimitry Andric }; 197bdd1243dSDimitry Andric 198bdd1243dSDimitry Andric namespace views { 199bdd1243dSDimitry Andric namespace __split_view { 2005f757f3fSDimitry Andric struct __fn { 201bdd1243dSDimitry Andric // clang-format off 202bdd1243dSDimitry Andric template <class _Range, class _Pattern> 203*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 204bdd1243dSDimitry Andric constexpr auto operator()(_Range&& __range, _Pattern&& __pattern) const 205bdd1243dSDimitry Andric noexcept(noexcept(split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern)))) 206bdd1243dSDimitry Andric -> decltype( split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern))) 207bdd1243dSDimitry Andric { return split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern)); } 208bdd1243dSDimitry Andric // clang-format on 209bdd1243dSDimitry Andric 210bdd1243dSDimitry Andric template <class _Pattern> 211bdd1243dSDimitry Andric requires constructible_from<decay_t<_Pattern>, _Pattern> 212*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pattern&& __pattern) const 213bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<decay_t<_Pattern>, _Pattern>) { 214bdd1243dSDimitry Andric return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Pattern>(__pattern))); 215bdd1243dSDimitry Andric } 216bdd1243dSDimitry Andric }; 217bdd1243dSDimitry Andric } // namespace __split_view 218bdd1243dSDimitry Andric 219bdd1243dSDimitry Andric inline namespace __cpo { 220bdd1243dSDimitry Andric inline constexpr auto split = __split_view::__fn{}; 221bdd1243dSDimitry Andric } // namespace __cpo 222bdd1243dSDimitry Andric } // namespace views 223bdd1243dSDimitry Andric 224bdd1243dSDimitry Andric } // namespace ranges 225bdd1243dSDimitry Andric 226bdd1243dSDimitry Andric #endif // _LIBCPP_STD_VER >= 20 227bdd1243dSDimitry Andric 228bdd1243dSDimitry Andric _LIBCPP_END_NAMESPACE_STD 229bdd1243dSDimitry Andric 230b3edf446SDimitry Andric _LIBCPP_POP_MACROS 231b3edf446SDimitry Andric 232bdd1243dSDimitry Andric #endif // _LIBCPP___RANGES_SPLIT_VIEW_H 233