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