181ad6265SDimitry Andric // -*- C++ -*- 281ad6265SDimitry Andric //===----------------------------------------------------------------------===// 381ad6265SDimitry Andric // 481ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 581ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 681ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 781ad6265SDimitry Andric // 881ad6265SDimitry Andric //===----------------------------------------------------------------------===// 981ad6265SDimitry Andric 1081ad6265SDimitry Andric #ifndef _LIBCPP___RANGES_LAZY_SPLIT_VIEW_H 1181ad6265SDimitry Andric #define _LIBCPP___RANGES_LAZY_SPLIT_VIEW_H 1281ad6265SDimitry Andric 1381ad6265SDimitry Andric #include <__algorithm/ranges_find.h> 1481ad6265SDimitry Andric #include <__algorithm/ranges_mismatch.h> 1506c3fb27SDimitry Andric #include <__assert> 1681ad6265SDimitry Andric #include <__concepts/constructible.h> 1781ad6265SDimitry Andric #include <__concepts/convertible_to.h> 1881ad6265SDimitry Andric #include <__concepts/derived_from.h> 1981ad6265SDimitry Andric #include <__config> 2081ad6265SDimitry Andric #include <__functional/bind_back.h> 2181ad6265SDimitry Andric #include <__functional/ranges_operations.h> 2281ad6265SDimitry Andric #include <__iterator/concepts.h> 2381ad6265SDimitry Andric #include <__iterator/default_sentinel.h> 2481ad6265SDimitry Andric #include <__iterator/incrementable_traits.h> 2581ad6265SDimitry Andric #include <__iterator/indirectly_comparable.h> 2681ad6265SDimitry Andric #include <__iterator/iter_move.h> 2781ad6265SDimitry Andric #include <__iterator/iter_swap.h> 2881ad6265SDimitry Andric #include <__iterator/iterator_traits.h> 2981ad6265SDimitry Andric #include <__memory/addressof.h> 3081ad6265SDimitry Andric #include <__ranges/access.h> 3181ad6265SDimitry Andric #include <__ranges/all.h> 3281ad6265SDimitry Andric #include <__ranges/concepts.h> 3381ad6265SDimitry Andric #include <__ranges/non_propagating_cache.h> 3481ad6265SDimitry Andric #include <__ranges/range_adaptor.h> 3581ad6265SDimitry Andric #include <__ranges/single_view.h> 3681ad6265SDimitry Andric #include <__ranges/subrange.h> 3781ad6265SDimitry Andric #include <__ranges/view_interface.h> 3806c3fb27SDimitry Andric #include <__type_traits/conditional.h> 3906c3fb27SDimitry Andric #include <__type_traits/decay.h> 4006c3fb27SDimitry Andric #include <__type_traits/is_nothrow_constructible.h> 41bdd1243dSDimitry Andric #include <__type_traits/maybe_const.h> 4206c3fb27SDimitry Andric #include <__type_traits/remove_reference.h> 4381ad6265SDimitry Andric #include <__utility/forward.h> 4481ad6265SDimitry Andric #include <__utility/move.h> 4581ad6265SDimitry Andric 4681ad6265SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 4781ad6265SDimitry Andric # pragma GCC system_header 4881ad6265SDimitry Andric #endif 4981ad6265SDimitry Andric 50b3edf446SDimitry Andric _LIBCPP_PUSH_MACROS 51b3edf446SDimitry Andric #include <__undef_macros> 52b3edf446SDimitry Andric 5381ad6265SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 5481ad6265SDimitry Andric 5506c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 5681ad6265SDimitry Andric 5781ad6265SDimitry Andric namespace ranges { 5881ad6265SDimitry Andric 59cb14a3feSDimitry Andric template <auto> 60cb14a3feSDimitry Andric struct __require_constant; 6181ad6265SDimitry Andric 6281ad6265SDimitry Andric template <class _Range> 63cb14a3feSDimitry Andric concept __tiny_range = sized_range<_Range> && requires { 64cb14a3feSDimitry Andric typename __require_constant<remove_reference_t<_Range>::size()>; 65cb14a3feSDimitry Andric } && (remove_reference_t<_Range>::size() <= 1); 6681ad6265SDimitry Andric 6781ad6265SDimitry Andric template <input_range _View, forward_range _Pattern> 6881ad6265SDimitry Andric requires view<_View> && view<_Pattern> && 6981ad6265SDimitry Andric indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> && 7081ad6265SDimitry Andric (forward_range<_View> || __tiny_range<_Pattern>) 7181ad6265SDimitry Andric class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>> { 7281ad6265SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); 7381ad6265SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Pattern __pattern_ = _Pattern(); 7481ad6265SDimitry Andric 7581ad6265SDimitry Andric using _MaybeCurrent = _If<!forward_range<_View>, __non_propagating_cache<iterator_t<_View>>, __empty_cache>; 7681ad6265SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _MaybeCurrent __current_ = _MaybeCurrent(); 7781ad6265SDimitry Andric 78cb14a3feSDimitry Andric template <bool> 79cb14a3feSDimitry Andric struct __outer_iterator; 80cb14a3feSDimitry Andric template <bool> 81cb14a3feSDimitry Andric struct __inner_iterator; 8281ad6265SDimitry Andric 8381ad6265SDimitry Andric public: 84cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI lazy_split_view() 85cb14a3feSDimitry Andric requires default_initializable<_View> && default_initializable<_Pattern> 86cb14a3feSDimitry Andric = default; 8781ad6265SDimitry Andric 88cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 lazy_split_view(_View __base, _Pattern __pattern) 8981ad6265SDimitry Andric : __base_(std::move(__base)), __pattern_(std::move(__pattern)) {} 9081ad6265SDimitry Andric 9181ad6265SDimitry Andric template <input_range _Range> 9281ad6265SDimitry Andric requires constructible_from<_View, views::all_t<_Range>> && 9381ad6265SDimitry Andric constructible_from<_Pattern, single_view<range_value_t<_Range>>> 94cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 lazy_split_view(_Range&& __r, range_value_t<_Range> __e) 95cb14a3feSDimitry Andric : __base_(views::all(std::forward<_Range>(__r))), __pattern_(views::single(std::move(__e))) {} 9681ad6265SDimitry Andric 97cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& 98cb14a3feSDimitry Andric requires copy_constructible<_View> 99cb14a3feSDimitry Andric { 100cb14a3feSDimitry Andric return __base_; 101cb14a3feSDimitry Andric } 102cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } 10381ad6265SDimitry Andric 104cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto begin() { 10581ad6265SDimitry Andric if constexpr (forward_range<_View>) { 10681ad6265SDimitry Andric return __outer_iterator < __simple_view<_View> && __simple_view < _Pattern >> {*this, ranges::begin(__base_)}; 10781ad6265SDimitry Andric } else { 10881ad6265SDimitry Andric __current_.__emplace(ranges::begin(__base_)); 10981ad6265SDimitry Andric return __outer_iterator<false>{*this}; 11081ad6265SDimitry Andric } 11181ad6265SDimitry Andric } 11281ad6265SDimitry Andric 113cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const 114cb14a3feSDimitry Andric requires forward_range<_View> && forward_range<const _View> 115cb14a3feSDimitry Andric { 11681ad6265SDimitry Andric return __outer_iterator<true>{*this, ranges::begin(__base_)}; 11781ad6265SDimitry Andric } 11881ad6265SDimitry Andric 119cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto end() 120cb14a3feSDimitry Andric requires forward_range<_View> && common_range<_View> 121cb14a3feSDimitry Andric { 12281ad6265SDimitry Andric return __outer_iterator < __simple_view<_View> && __simple_view < _Pattern >> {*this, ranges::end(__base_)}; 12381ad6265SDimitry Andric } 12481ad6265SDimitry Andric 125cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto end() const { 12681ad6265SDimitry Andric if constexpr (forward_range<_View> && forward_range<const _View> && common_range<const _View>) { 12781ad6265SDimitry Andric return __outer_iterator<true>{*this, ranges::end(__base_)}; 12881ad6265SDimitry Andric } else { 12981ad6265SDimitry Andric return default_sentinel; 13081ad6265SDimitry Andric } 13181ad6265SDimitry Andric } 13281ad6265SDimitry Andric 13381ad6265SDimitry Andric private: 13481ad6265SDimitry Andric template <class> 13581ad6265SDimitry Andric struct __outer_iterator_category {}; 13681ad6265SDimitry Andric 13781ad6265SDimitry Andric template <forward_range _Tp> 13881ad6265SDimitry Andric struct __outer_iterator_category<_Tp> { 13981ad6265SDimitry Andric using iterator_category = input_iterator_tag; 14081ad6265SDimitry Andric }; 14181ad6265SDimitry Andric 14281ad6265SDimitry Andric template <bool _Const> 14381ad6265SDimitry Andric struct __outer_iterator : __outer_iterator_category<__maybe_const<_Const, _View>> { 14481ad6265SDimitry Andric private: 14581ad6265SDimitry Andric template <bool> 14681ad6265SDimitry Andric friend struct __inner_iterator; 14781ad6265SDimitry Andric friend __outer_iterator<true>; 14881ad6265SDimitry Andric 14981ad6265SDimitry Andric using _Parent = __maybe_const<_Const, lazy_split_view>; 15081ad6265SDimitry Andric using _Base = __maybe_const<_Const, _View>; 15181ad6265SDimitry Andric 15281ad6265SDimitry Andric _Parent* __parent_ = nullptr; 15381ad6265SDimitry Andric using _MaybeCurrent = _If<forward_range<_View>, iterator_t<_Base>, __empty_cache>; 15481ad6265SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _MaybeCurrent __current_ = _MaybeCurrent(); 15581ad6265SDimitry Andric bool __trailing_empty_ = false; 15681ad6265SDimitry Andric 157cb14a3feSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto& __current() noexcept { 15881ad6265SDimitry Andric if constexpr (forward_range<_View>) { 15981ad6265SDimitry Andric return __current_; 16081ad6265SDimitry Andric } else { 16181ad6265SDimitry Andric return *__parent_->__current_; 16281ad6265SDimitry Andric } 16381ad6265SDimitry Andric } 16481ad6265SDimitry Andric 165cb14a3feSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const auto& __current() const noexcept { 16681ad6265SDimitry Andric if constexpr (forward_range<_View>) { 16781ad6265SDimitry Andric return __current_; 16881ad6265SDimitry Andric } else { 16981ad6265SDimitry Andric return *__parent_->__current_; 17081ad6265SDimitry Andric } 17181ad6265SDimitry Andric } 17281ad6265SDimitry Andric 17381ad6265SDimitry Andric // Workaround for the GCC issue that doesn't allow calling `__parent_->__base_` from friend functions (because 17481ad6265SDimitry Andric // `__base_` is private). 175cb14a3feSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto& __parent_base() const noexcept { return __parent_->__base_; } 17681ad6265SDimitry Andric 17781ad6265SDimitry Andric public: 17881ad6265SDimitry Andric // using iterator_category = inherited; 17981ad6265SDimitry Andric using iterator_concept = conditional_t<forward_range<_Base>, forward_iterator_tag, input_iterator_tag>; 18081ad6265SDimitry Andric using difference_type = range_difference_t<_Base>; 18181ad6265SDimitry Andric 18281ad6265SDimitry Andric struct value_type : view_interface<value_type> { 18381ad6265SDimitry Andric private: 18481ad6265SDimitry Andric __outer_iterator __i_ = __outer_iterator(); 18581ad6265SDimitry Andric 18681ad6265SDimitry Andric public: 187cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI value_type() = default; 188cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit value_type(__outer_iterator __i) : __i_(std::move(__i)) {} 18981ad6265SDimitry Andric 190cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __inner_iterator<_Const> begin() const { return __inner_iterator<_Const>{__i_}; } 191cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr default_sentinel_t end() const noexcept { return default_sentinel; } 19281ad6265SDimitry Andric }; 19381ad6265SDimitry Andric 194cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __outer_iterator() = default; 19581ad6265SDimitry Andric 196cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __outer_iterator(_Parent& __parent) 19781ad6265SDimitry Andric requires(!forward_range<_Base>) 19881ad6265SDimitry Andric : __parent_(std::addressof(__parent)) {} 19981ad6265SDimitry Andric 200cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __outer_iterator(_Parent& __parent, iterator_t<_Base> __current) 20181ad6265SDimitry Andric requires forward_range<_Base> 20281ad6265SDimitry Andric : __parent_(std::addressof(__parent)), __current_(std::move(__current)) {} 20381ad6265SDimitry Andric 204cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __outer_iterator(__outer_iterator<!_Const> __i) 20581ad6265SDimitry Andric requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>> 20681ad6265SDimitry Andric : __parent_(__i.__parent_), __current_(std::move(__i.__current_)) {} 20781ad6265SDimitry Andric 208cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const { return value_type{*this}; } 20981ad6265SDimitry Andric 210cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __outer_iterator& operator++() { 21181ad6265SDimitry Andric const auto __end = ranges::end(__parent_->__base_); 21281ad6265SDimitry Andric if (__current() == __end) { 21381ad6265SDimitry Andric __trailing_empty_ = false; 21481ad6265SDimitry Andric return *this; 21581ad6265SDimitry Andric } 21681ad6265SDimitry Andric 21781ad6265SDimitry Andric const auto [__pbegin, __pend] = ranges::subrange{__parent_->__pattern_}; 21881ad6265SDimitry Andric if (__pbegin == __pend) { 21981ad6265SDimitry Andric // Empty pattern: split on every element in the input range 22081ad6265SDimitry Andric ++__current(); 22181ad6265SDimitry Andric 22281ad6265SDimitry Andric } else if constexpr (__tiny_range<_Pattern>) { 22381ad6265SDimitry Andric // One-element pattern: we can use `ranges::find`. 22481ad6265SDimitry Andric __current() = ranges::find(std::move(__current()), __end, *__pbegin); 22581ad6265SDimitry Andric if (__current() != __end) { 22681ad6265SDimitry Andric // Make sure we point to after the separator we just found. 22781ad6265SDimitry Andric ++__current(); 22881ad6265SDimitry Andric if (__current() == __end) 22981ad6265SDimitry Andric __trailing_empty_ = true; 23081ad6265SDimitry Andric } 23181ad6265SDimitry Andric 23281ad6265SDimitry Andric } else { 23381ad6265SDimitry Andric // General case for n-element pattern. 23481ad6265SDimitry Andric do { 23581ad6265SDimitry Andric const auto [__b, __p] = ranges::mismatch(__current(), __end, __pbegin, __pend); 23681ad6265SDimitry Andric if (__p == __pend) { 23781ad6265SDimitry Andric __current() = __b; 23881ad6265SDimitry Andric if (__current() == __end) { 23981ad6265SDimitry Andric __trailing_empty_ = true; 24081ad6265SDimitry Andric } 24181ad6265SDimitry Andric break; // The pattern matched; skip it. 24281ad6265SDimitry Andric } 24381ad6265SDimitry Andric } while (++__current() != __end); 24481ad6265SDimitry Andric } 24581ad6265SDimitry Andric 24681ad6265SDimitry Andric return *this; 24781ad6265SDimitry Andric } 24881ad6265SDimitry Andric 249cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator++(int) { 25081ad6265SDimitry Andric if constexpr (forward_range<_Base>) { 25181ad6265SDimitry Andric auto __tmp = *this; 25281ad6265SDimitry Andric ++*this; 25381ad6265SDimitry Andric return __tmp; 25481ad6265SDimitry Andric 25581ad6265SDimitry Andric } else { 25681ad6265SDimitry Andric ++*this; 25781ad6265SDimitry Andric } 25881ad6265SDimitry Andric } 25981ad6265SDimitry Andric 260cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __outer_iterator& __x, const __outer_iterator& __y) 261cb14a3feSDimitry Andric requires forward_range<_Base> 262cb14a3feSDimitry Andric { 26381ad6265SDimitry Andric return __x.__current_ == __y.__current_ && __x.__trailing_empty_ == __y.__trailing_empty_; 26481ad6265SDimitry Andric } 26581ad6265SDimitry Andric 266cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __outer_iterator& __x, default_sentinel_t) { 2675f757f3fSDimitry Andric _LIBCPP_ASSERT_NON_NULL(__x.__parent_ != nullptr, "Cannot call comparison on a default-constructed iterator."); 26881ad6265SDimitry Andric return __x.__current() == ranges::end(__x.__parent_base()) && !__x.__trailing_empty_; 26981ad6265SDimitry Andric } 27081ad6265SDimitry Andric }; 27181ad6265SDimitry Andric 27281ad6265SDimitry Andric template <class> 27381ad6265SDimitry Andric struct __inner_iterator_category {}; 27481ad6265SDimitry Andric 27581ad6265SDimitry Andric template <forward_range _Tp> 27681ad6265SDimitry Andric struct __inner_iterator_category<_Tp> { 277cb14a3feSDimitry Andric using iterator_category = 278cb14a3feSDimitry Andric _If< derived_from<typename iterator_traits<iterator_t<_Tp>>::iterator_category, forward_iterator_tag>, 27981ad6265SDimitry Andric forward_iterator_tag, 280cb14a3feSDimitry Andric typename iterator_traits<iterator_t<_Tp>>::iterator_category >; 28181ad6265SDimitry Andric }; 28281ad6265SDimitry Andric 28381ad6265SDimitry Andric template <bool _Const> 28481ad6265SDimitry Andric struct __inner_iterator : __inner_iterator_category<__maybe_const<_Const, _View>> { 28581ad6265SDimitry Andric private: 28681ad6265SDimitry Andric using _Base = __maybe_const<_Const, _View>; 28781ad6265SDimitry Andric // Workaround for a GCC issue. 28881ad6265SDimitry Andric static constexpr bool _OuterConst = _Const; 28981ad6265SDimitry Andric __outer_iterator<_Const> __i_ = __outer_iterator<_OuterConst>(); 29081ad6265SDimitry Andric bool __incremented_ = false; 29181ad6265SDimitry Andric 29281ad6265SDimitry Andric // Note: these private functions are necessary because GCC doesn't allow calls to private members of `__i_` from 29381ad6265SDimitry Andric // free functions that are friends of `inner-iterator`. 29481ad6265SDimitry Andric 295cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool __is_done() const { 2965f757f3fSDimitry Andric _LIBCPP_ASSERT_NON_NULL(__i_.__parent_ != nullptr, "Cannot call comparison on a default-constructed iterator."); 29781ad6265SDimitry Andric 29881ad6265SDimitry Andric auto [__pcur, __pend] = ranges::subrange{__i_.__parent_->__pattern_}; 29981ad6265SDimitry Andric auto __end = ranges::end(__i_.__parent_->__base_); 30081ad6265SDimitry Andric 30181ad6265SDimitry Andric if constexpr (__tiny_range<_Pattern>) { 30281ad6265SDimitry Andric const auto& __cur = __i_.__current(); 30381ad6265SDimitry Andric if (__cur == __end) 30481ad6265SDimitry Andric return true; 30581ad6265SDimitry Andric if (__pcur == __pend) 30681ad6265SDimitry Andric return __incremented_; 30781ad6265SDimitry Andric 30881ad6265SDimitry Andric return *__cur == *__pcur; 30981ad6265SDimitry Andric 31081ad6265SDimitry Andric } else { 31181ad6265SDimitry Andric auto __cur = __i_.__current(); 31281ad6265SDimitry Andric if (__cur == __end) 31381ad6265SDimitry Andric return true; 31481ad6265SDimitry Andric if (__pcur == __pend) 31581ad6265SDimitry Andric return __incremented_; 31681ad6265SDimitry Andric 31781ad6265SDimitry Andric do { 31881ad6265SDimitry Andric if (*__cur != *__pcur) 31981ad6265SDimitry Andric return false; 32081ad6265SDimitry Andric if (++__pcur == __pend) 32181ad6265SDimitry Andric return true; 32281ad6265SDimitry Andric } while (++__cur != __end); 32381ad6265SDimitry Andric 32481ad6265SDimitry Andric return false; 32581ad6265SDimitry Andric } 32681ad6265SDimitry Andric } 32781ad6265SDimitry Andric 328cb14a3feSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto& __outer_current() noexcept { return __i_.__current(); } 32981ad6265SDimitry Andric 330cb14a3feSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const auto& __outer_current() const noexcept { 33181ad6265SDimitry Andric return __i_.__current(); 33281ad6265SDimitry Andric } 33381ad6265SDimitry Andric 33481ad6265SDimitry Andric public: 33581ad6265SDimitry Andric // using iterator_category = inherited; 33681ad6265SDimitry Andric using iterator_concept = typename __outer_iterator<_Const>::iterator_concept; 33781ad6265SDimitry Andric using value_type = range_value_t<_Base>; 33881ad6265SDimitry Andric using difference_type = range_difference_t<_Base>; 33981ad6265SDimitry Andric 340cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __inner_iterator() = default; 34181ad6265SDimitry Andric 342cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __inner_iterator(__outer_iterator<_Const> __i) : __i_(std::move(__i)) {} 34381ad6265SDimitry Andric 344cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept { return __i_.__current(); } 345cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() && 346cb14a3feSDimitry Andric requires forward_range<_View> 347cb14a3feSDimitry Andric { 348cb14a3feSDimitry Andric return std::move(__i_.__current()); 349cb14a3feSDimitry Andric } 35081ad6265SDimitry Andric 351cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return *__i_.__current(); } 35281ad6265SDimitry Andric 353cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __inner_iterator& operator++() { 35481ad6265SDimitry Andric __incremented_ = true; 35581ad6265SDimitry Andric 35681ad6265SDimitry Andric if constexpr (!forward_range<_Base>) { 35781ad6265SDimitry Andric if constexpr (_Pattern::size() == 0) { 35881ad6265SDimitry Andric return *this; 35981ad6265SDimitry Andric } 36081ad6265SDimitry Andric } 36181ad6265SDimitry Andric 36281ad6265SDimitry Andric ++__i_.__current(); 36381ad6265SDimitry Andric return *this; 36481ad6265SDimitry Andric } 36581ad6265SDimitry Andric 366cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator++(int) { 36781ad6265SDimitry Andric if constexpr (forward_range<_Base>) { 36881ad6265SDimitry Andric auto __tmp = *this; 36981ad6265SDimitry Andric ++*this; 37081ad6265SDimitry Andric return __tmp; 37181ad6265SDimitry Andric 37281ad6265SDimitry Andric } else { 37381ad6265SDimitry Andric ++*this; 37481ad6265SDimitry Andric } 37581ad6265SDimitry Andric } 37681ad6265SDimitry Andric 377cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __inner_iterator& __x, const __inner_iterator& __y) 378cb14a3feSDimitry Andric requires forward_range<_Base> 379cb14a3feSDimitry Andric { 38081ad6265SDimitry Andric return __x.__outer_current() == __y.__outer_current(); 38181ad6265SDimitry Andric } 38281ad6265SDimitry Andric 383cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __inner_iterator& __x, default_sentinel_t) { 38481ad6265SDimitry Andric return __x.__is_done(); 38581ad6265SDimitry Andric } 38681ad6265SDimitry Andric 387cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr decltype(auto) 388cb14a3feSDimitry Andric iter_move(const __inner_iterator& __i) noexcept(noexcept(ranges::iter_move(__i.__outer_current()))) { 38981ad6265SDimitry Andric return ranges::iter_move(__i.__outer_current()); 39081ad6265SDimitry Andric } 39181ad6265SDimitry Andric 392cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr void iter_swap( 393cb14a3feSDimitry Andric const __inner_iterator& __x, 394cb14a3feSDimitry Andric const __inner_iterator& __y) noexcept(noexcept(ranges::iter_swap(__x.__outer_current(), __y.__outer_current()))) 395cb14a3feSDimitry Andric requires indirectly_swappable<iterator_t<_Base>> 396cb14a3feSDimitry Andric { 39781ad6265SDimitry Andric ranges::iter_swap(__x.__outer_current(), __y.__outer_current()); 39881ad6265SDimitry Andric } 39981ad6265SDimitry Andric }; 40081ad6265SDimitry Andric }; 40181ad6265SDimitry Andric 40281ad6265SDimitry Andric template <class _Range, class _Pattern> 40381ad6265SDimitry Andric lazy_split_view(_Range&&, _Pattern&&) -> lazy_split_view<views::all_t<_Range>, views::all_t<_Pattern>>; 40481ad6265SDimitry Andric 40581ad6265SDimitry Andric template <input_range _Range> 406*0fca6ea1SDimitry Andric lazy_split_view(_Range&&, 407*0fca6ea1SDimitry Andric range_value_t<_Range>) -> lazy_split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>; 40881ad6265SDimitry Andric 40981ad6265SDimitry Andric namespace views { 41081ad6265SDimitry Andric namespace __lazy_split_view { 4115f757f3fSDimitry Andric struct __fn { 41281ad6265SDimitry Andric template <class _Range, class _Pattern> 413cb14a3feSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Pattern&& __pattern) const 41481ad6265SDimitry Andric noexcept(noexcept(lazy_split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern)))) 415cb14a3feSDimitry Andric -> decltype(lazy_split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern))) { 416cb14a3feSDimitry Andric return lazy_split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern)); 417cb14a3feSDimitry Andric } 41881ad6265SDimitry Andric 41981ad6265SDimitry Andric template <class _Pattern> 42081ad6265SDimitry Andric requires constructible_from<decay_t<_Pattern>, _Pattern> 421cb14a3feSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pattern&& __pattern) const 42281ad6265SDimitry Andric noexcept(is_nothrow_constructible_v<decay_t<_Pattern>, _Pattern>) { 42381ad6265SDimitry Andric return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Pattern>(__pattern))); 42481ad6265SDimitry Andric } 42581ad6265SDimitry Andric }; 42681ad6265SDimitry Andric } // namespace __lazy_split_view 42781ad6265SDimitry Andric 42881ad6265SDimitry Andric inline namespace __cpo { 42981ad6265SDimitry Andric inline constexpr auto lazy_split = __lazy_split_view::__fn{}; 43081ad6265SDimitry Andric } // namespace __cpo 43181ad6265SDimitry Andric } // namespace views 43281ad6265SDimitry Andric 43381ad6265SDimitry Andric } // namespace ranges 43481ad6265SDimitry Andric 43506c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20 43681ad6265SDimitry Andric 43781ad6265SDimitry Andric _LIBCPP_END_NAMESPACE_STD 43881ad6265SDimitry Andric 439b3edf446SDimitry Andric _LIBCPP_POP_MACROS 440b3edf446SDimitry Andric 44181ad6265SDimitry Andric #endif // _LIBCPP___RANGES_LAZY_SPLIT_VIEW_H 442