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 39bdd1243dSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 40bdd1243dSDimitry Andric 41bdd1243dSDimitry Andric #if _LIBCPP_STD_VER >= 20 42bdd1243dSDimitry Andric 43bdd1243dSDimitry Andric namespace ranges { 44bdd1243dSDimitry Andric 45bdd1243dSDimitry Andric template <forward_range _View, forward_range _Pattern> 46bdd1243dSDimitry Andric requires view<_View> && view<_Pattern> && 47bdd1243dSDimitry Andric indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> 48bdd1243dSDimitry Andric class split_view : public view_interface<split_view<_View, _Pattern>> { 49bdd1243dSDimitry Andric private: 50bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); 51bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Pattern __pattern_ = _Pattern(); 52bdd1243dSDimitry Andric using _Cache = __non_propagating_cache<subrange<iterator_t<_View>>>; 53bdd1243dSDimitry Andric _Cache __cached_begin_ = _Cache(); 54bdd1243dSDimitry Andric 55bdd1243dSDimitry Andric template <class, class> 56*1ac55f4cSDimitry Andric friend struct __iterator; 57bdd1243dSDimitry Andric 58bdd1243dSDimitry Andric template <class, class> 59*1ac55f4cSDimitry Andric friend struct __sentinel; 60bdd1243dSDimitry Andric 61*1ac55f4cSDimitry Andric struct __iterator; 62*1ac55f4cSDimitry Andric struct __sentinel; 63bdd1243dSDimitry Andric 64bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr subrange<iterator_t<_View>> __find_next(iterator_t<_View> __it) { 65bdd1243dSDimitry Andric auto [__begin, __end] = ranges::search(subrange(__it, ranges::end(__base_)), __pattern_); 66bdd1243dSDimitry Andric if (__begin != ranges::end(__base_) && ranges::empty(__pattern_)) { 67bdd1243dSDimitry Andric ++__begin; 68bdd1243dSDimitry Andric ++__end; 69bdd1243dSDimitry Andric } 70bdd1243dSDimitry Andric return {__begin, __end}; 71bdd1243dSDimitry Andric } 72bdd1243dSDimitry Andric 73bdd1243dSDimitry Andric public: 74bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI split_view() 75bdd1243dSDimitry Andric requires default_initializable<_View> && default_initializable<_Pattern> 76bdd1243dSDimitry Andric = default; 77bdd1243dSDimitry Andric 78bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr split_view(_View __base, _Pattern __pattern) 79bdd1243dSDimitry Andric : __base_(std::move(__base)), __pattern_(std::move((__pattern))) {} 80bdd1243dSDimitry Andric 81bdd1243dSDimitry Andric template <forward_range _Range> 82bdd1243dSDimitry Andric requires constructible_from<_View, views::all_t<_Range>> && 83bdd1243dSDimitry Andric constructible_from<_Pattern, single_view<range_value_t<_Range>>> 84bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr split_view(_Range&& __range, range_value_t<_Range> __elem) 85bdd1243dSDimitry Andric : __base_(views::all(std::forward<_Range>(__range))), __pattern_(views::single(std::move(__elem))) {} 86bdd1243dSDimitry Andric 87bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& 88bdd1243dSDimitry Andric requires copy_constructible<_View> 89bdd1243dSDimitry Andric { 90bdd1243dSDimitry Andric return __base_; 91bdd1243dSDimitry Andric } 92bdd1243dSDimitry Andric 93bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } 94bdd1243dSDimitry Andric 95bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator begin() { 96bdd1243dSDimitry Andric if (!__cached_begin_.__has_value()) { 97bdd1243dSDimitry Andric __cached_begin_.__emplace(__find_next(ranges::begin(__base_))); 98bdd1243dSDimitry Andric } 99bdd1243dSDimitry Andric return {*this, ranges::begin(__base_), *__cached_begin_}; 100bdd1243dSDimitry Andric } 101bdd1243dSDimitry Andric 102bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto end() { 103bdd1243dSDimitry Andric if constexpr (common_range<_View>) { 104bdd1243dSDimitry Andric return __iterator{*this, ranges::end(__base_), {}}; 105bdd1243dSDimitry Andric } else { 106bdd1243dSDimitry Andric return __sentinel{*this}; 107bdd1243dSDimitry Andric } 108bdd1243dSDimitry Andric } 109bdd1243dSDimitry Andric }; 110bdd1243dSDimitry Andric 111bdd1243dSDimitry Andric template <class _Range, class _Pattern> 112bdd1243dSDimitry Andric split_view(_Range&&, _Pattern&&) -> split_view<views::all_t<_Range>, views::all_t<_Pattern>>; 113bdd1243dSDimitry Andric 114bdd1243dSDimitry Andric template <forward_range _Range> 115bdd1243dSDimitry Andric split_view(_Range&&, range_value_t<_Range>) -> split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>; 116bdd1243dSDimitry Andric 117*1ac55f4cSDimitry Andric template <forward_range _View, forward_range _Pattern> 118*1ac55f4cSDimitry Andric requires view<_View> && view<_Pattern> && 119*1ac55f4cSDimitry Andric indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> 120*1ac55f4cSDimitry Andric struct split_view<_View, _Pattern>::__iterator { 121bdd1243dSDimitry Andric private: 122*1ac55f4cSDimitry Andric split_view* __parent_ = nullptr; 123bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __cur_ = iterator_t<_View>(); 124bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS subrange<iterator_t<_View>> __next_ = subrange<iterator_t<_View>>(); 125bdd1243dSDimitry Andric bool __trailing_empty_ = false; 126bdd1243dSDimitry Andric 127*1ac55f4cSDimitry Andric friend struct __sentinel; 128bdd1243dSDimitry Andric 129bdd1243dSDimitry Andric public: 130bdd1243dSDimitry Andric using iterator_concept = forward_iterator_tag; 131bdd1243dSDimitry Andric using iterator_category = input_iterator_tag; 132bdd1243dSDimitry Andric using value_type = subrange<iterator_t<_View>>; 133bdd1243dSDimitry Andric using difference_type = range_difference_t<_View>; 134bdd1243dSDimitry Andric 135*1ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI __iterator() = default; 136bdd1243dSDimitry Andric 137*1ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator( 138bdd1243dSDimitry Andric split_view<_View, _Pattern>& __parent, iterator_t<_View> __current, subrange<iterator_t<_View>> __next) 139bdd1243dSDimitry Andric : __parent_(std::addressof(__parent)), __cur_(std::move(__current)), __next_(std::move(__next)) {} 140bdd1243dSDimitry Andric 141bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_View> base() const { return __cur_; } 142bdd1243dSDimitry Andric 143bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const { return {__cur_, __next_.begin()}; } 144bdd1243dSDimitry Andric 145*1ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { 146bdd1243dSDimitry Andric __cur_ = __next_.begin(); 147bdd1243dSDimitry Andric if (__cur_ != ranges::end(__parent_->__base_)) { 148bdd1243dSDimitry Andric __cur_ = __next_.end(); 149bdd1243dSDimitry Andric if (__cur_ == ranges::end(__parent_->__base_)) { 150bdd1243dSDimitry Andric __trailing_empty_ = true; 151bdd1243dSDimitry Andric __next_ = {__cur_, __cur_}; 152bdd1243dSDimitry Andric } else { 153bdd1243dSDimitry Andric __next_ = __parent_->__find_next(__cur_); 154bdd1243dSDimitry Andric } 155bdd1243dSDimitry Andric } else { 156bdd1243dSDimitry Andric __trailing_empty_ = false; 157bdd1243dSDimitry Andric } 158bdd1243dSDimitry Andric return *this; 159bdd1243dSDimitry Andric } 160bdd1243dSDimitry Andric 161*1ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { 162bdd1243dSDimitry Andric auto __tmp = *this; 163bdd1243dSDimitry Andric ++*this; 164bdd1243dSDimitry Andric return __tmp; 165bdd1243dSDimitry Andric } 166bdd1243dSDimitry Andric 167*1ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) { 168bdd1243dSDimitry Andric return __x.__cur_ == __y.__cur_ && __x.__trailing_empty_ == __y.__trailing_empty_; 169bdd1243dSDimitry Andric } 170bdd1243dSDimitry Andric }; 171bdd1243dSDimitry Andric 172*1ac55f4cSDimitry Andric template <forward_range _View, forward_range _Pattern> 173*1ac55f4cSDimitry Andric requires view<_View> && view<_Pattern> && 174*1ac55f4cSDimitry Andric indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> 175*1ac55f4cSDimitry Andric struct split_view<_View, _Pattern>::__sentinel { 176bdd1243dSDimitry Andric private: 177bdd1243dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_View> __end_ = sentinel_t<_View>(); 178bdd1243dSDimitry Andric 179*1ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr bool __equals(const __iterator& __x, const __sentinel& __y) { 180bdd1243dSDimitry Andric return __x.__cur_ == __y.__end_ && !__x.__trailing_empty_; 181bdd1243dSDimitry Andric } 182bdd1243dSDimitry Andric 183bdd1243dSDimitry Andric public: 184*1ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI __sentinel() = default; 185bdd1243dSDimitry Andric 186*1ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(split_view<_View, _Pattern>& __parent) 187bdd1243dSDimitry Andric : __end_(ranges::end(__parent.__base_)) {} 188bdd1243dSDimitry Andric 189*1ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) { 190bdd1243dSDimitry Andric return __equals(__x, __y); 191bdd1243dSDimitry Andric } 192bdd1243dSDimitry Andric }; 193bdd1243dSDimitry Andric 194bdd1243dSDimitry Andric namespace views { 195bdd1243dSDimitry Andric namespace __split_view { 196bdd1243dSDimitry Andric struct __fn : __range_adaptor_closure<__fn> { 197bdd1243dSDimitry Andric // clang-format off 198bdd1243dSDimitry Andric template <class _Range, class _Pattern> 199bdd1243dSDimitry Andric _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI 200bdd1243dSDimitry Andric constexpr auto operator()(_Range&& __range, _Pattern&& __pattern) const 201bdd1243dSDimitry Andric noexcept(noexcept(split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern)))) 202bdd1243dSDimitry Andric -> decltype( split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern))) 203bdd1243dSDimitry Andric { return split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern)); } 204bdd1243dSDimitry Andric // clang-format on 205bdd1243dSDimitry Andric 206bdd1243dSDimitry Andric template <class _Pattern> 207bdd1243dSDimitry Andric requires constructible_from<decay_t<_Pattern>, _Pattern> 208bdd1243dSDimitry Andric _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pattern&& __pattern) const 209bdd1243dSDimitry Andric noexcept(is_nothrow_constructible_v<decay_t<_Pattern>, _Pattern>) { 210bdd1243dSDimitry Andric return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Pattern>(__pattern))); 211bdd1243dSDimitry Andric } 212bdd1243dSDimitry Andric }; 213bdd1243dSDimitry Andric } // namespace __split_view 214bdd1243dSDimitry Andric 215bdd1243dSDimitry Andric inline namespace __cpo { 216bdd1243dSDimitry Andric inline constexpr auto split = __split_view::__fn{}; 217bdd1243dSDimitry Andric } // namespace __cpo 218bdd1243dSDimitry Andric } // namespace views 219bdd1243dSDimitry Andric 220bdd1243dSDimitry Andric } // namespace ranges 221bdd1243dSDimitry Andric 222bdd1243dSDimitry Andric #endif // _LIBCPP_STD_VER >= 20 223bdd1243dSDimitry Andric 224bdd1243dSDimitry Andric _LIBCPP_END_NAMESPACE_STD 225bdd1243dSDimitry Andric 226bdd1243dSDimitry Andric #endif // _LIBCPP___RANGES_SPLIT_VIEW_H 227