xref: /openbsd-src/gnu/llvm/libcxx/include/__ranges/lazy_split_view.h (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
1*4bdff4beSrobert // -*- C++ -*-
2*4bdff4beSrobert //===----------------------------------------------------------------------===//
3*4bdff4beSrobert //
4*4bdff4beSrobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*4bdff4beSrobert // See https://llvm.org/LICENSE.txt for license information.
6*4bdff4beSrobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*4bdff4beSrobert //
8*4bdff4beSrobert //===----------------------------------------------------------------------===//
9*4bdff4beSrobert 
10*4bdff4beSrobert #ifndef _LIBCPP___RANGES_LAZY_SPLIT_VIEW_H
11*4bdff4beSrobert #define _LIBCPP___RANGES_LAZY_SPLIT_VIEW_H
12*4bdff4beSrobert 
13*4bdff4beSrobert #include <__algorithm/ranges_find.h>
14*4bdff4beSrobert #include <__algorithm/ranges_mismatch.h>
15*4bdff4beSrobert #include <__concepts/constructible.h>
16*4bdff4beSrobert #include <__concepts/convertible_to.h>
17*4bdff4beSrobert #include <__concepts/derived_from.h>
18*4bdff4beSrobert #include <__config>
19*4bdff4beSrobert #include <__functional/bind_back.h>
20*4bdff4beSrobert #include <__functional/ranges_operations.h>
21*4bdff4beSrobert #include <__iterator/concepts.h>
22*4bdff4beSrobert #include <__iterator/default_sentinel.h>
23*4bdff4beSrobert #include <__iterator/incrementable_traits.h>
24*4bdff4beSrobert #include <__iterator/indirectly_comparable.h>
25*4bdff4beSrobert #include <__iterator/iter_move.h>
26*4bdff4beSrobert #include <__iterator/iter_swap.h>
27*4bdff4beSrobert #include <__iterator/iterator_traits.h>
28*4bdff4beSrobert #include <__memory/addressof.h>
29*4bdff4beSrobert #include <__ranges/access.h>
30*4bdff4beSrobert #include <__ranges/all.h>
31*4bdff4beSrobert #include <__ranges/concepts.h>
32*4bdff4beSrobert #include <__ranges/non_propagating_cache.h>
33*4bdff4beSrobert #include <__ranges/range_adaptor.h>
34*4bdff4beSrobert #include <__ranges/single_view.h>
35*4bdff4beSrobert #include <__ranges/subrange.h>
36*4bdff4beSrobert #include <__ranges/view_interface.h>
37*4bdff4beSrobert #include <__type_traits/maybe_const.h>
38*4bdff4beSrobert #include <__utility/forward.h>
39*4bdff4beSrobert #include <__utility/move.h>
40*4bdff4beSrobert #include <type_traits>
41*4bdff4beSrobert 
42*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
43*4bdff4beSrobert #  pragma GCC system_header
44*4bdff4beSrobert #endif
45*4bdff4beSrobert 
46*4bdff4beSrobert _LIBCPP_BEGIN_NAMESPACE_STD
47*4bdff4beSrobert 
48*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
49*4bdff4beSrobert 
50*4bdff4beSrobert namespace ranges {
51*4bdff4beSrobert 
52*4bdff4beSrobert template <auto> struct __require_constant;
53*4bdff4beSrobert 
54*4bdff4beSrobert template <class _Range>
55*4bdff4beSrobert concept __tiny_range =
56*4bdff4beSrobert   sized_range<_Range> &&
57*4bdff4beSrobert   requires { typename __require_constant<remove_reference_t<_Range>::size()>; } &&
58*4bdff4beSrobert   (remove_reference_t<_Range>::size() <= 1);
59*4bdff4beSrobert 
60*4bdff4beSrobert template <input_range _View, forward_range _Pattern>
61*4bdff4beSrobert   requires view<_View> && view<_Pattern> &&
62*4bdff4beSrobert            indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> &&
63*4bdff4beSrobert            (forward_range<_View> || __tiny_range<_Pattern>)
64*4bdff4beSrobert class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>> {
65*4bdff4beSrobert 
66*4bdff4beSrobert   _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();
67*4bdff4beSrobert   _LIBCPP_NO_UNIQUE_ADDRESS _Pattern __pattern_ = _Pattern();
68*4bdff4beSrobert 
69*4bdff4beSrobert   using _MaybeCurrent = _If<!forward_range<_View>, __non_propagating_cache<iterator_t<_View>>, __empty_cache>;
70*4bdff4beSrobert   _LIBCPP_NO_UNIQUE_ADDRESS _MaybeCurrent __current_ = _MaybeCurrent();
71*4bdff4beSrobert 
72*4bdff4beSrobert   template <bool> struct __outer_iterator;
73*4bdff4beSrobert   template <bool> struct __inner_iterator;
74*4bdff4beSrobert 
75*4bdff4beSrobert public:
76*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
77*4bdff4beSrobert   lazy_split_view()
78*4bdff4beSrobert     requires default_initializable<_View> && default_initializable<_Pattern> = default;
79*4bdff4beSrobert 
80*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
lazy_split_view(_View __base,_Pattern __pattern)81*4bdff4beSrobert   constexpr lazy_split_view(_View __base, _Pattern __pattern)
82*4bdff4beSrobert     : __base_(std::move(__base)), __pattern_(std::move(__pattern)) {}
83*4bdff4beSrobert 
84*4bdff4beSrobert   template <input_range _Range>
85*4bdff4beSrobert     requires constructible_from<_View, views::all_t<_Range>> &&
86*4bdff4beSrobert              constructible_from<_Pattern, single_view<range_value_t<_Range>>>
87*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
lazy_split_view(_Range && __r,range_value_t<_Range> __e)88*4bdff4beSrobert   constexpr lazy_split_view(_Range&& __r, range_value_t<_Range> __e)
89*4bdff4beSrobert     : __base_(views::all(std::forward<_Range>(__r)))
90*4bdff4beSrobert     , __pattern_(views::single(std::move(__e))) {}
91*4bdff4beSrobert 
92*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
base()93*4bdff4beSrobert   constexpr _View base() const& requires copy_constructible<_View> { return __base_; }
94*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
base()95*4bdff4beSrobert   constexpr _View base() && { return std::move(__base_); }
96*4bdff4beSrobert 
97*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
begin()98*4bdff4beSrobert   constexpr auto begin() {
99*4bdff4beSrobert     if constexpr (forward_range<_View>) {
100*4bdff4beSrobert       return __outer_iterator<__simple_view<_View> && __simple_view<_Pattern>>{*this, ranges::begin(__base_)};
101*4bdff4beSrobert     } else {
102*4bdff4beSrobert       __current_.__emplace(ranges::begin(__base_));
103*4bdff4beSrobert       return __outer_iterator<false>{*this};
104*4bdff4beSrobert     }
105*4bdff4beSrobert   }
106*4bdff4beSrobert 
107*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
begin()108*4bdff4beSrobert   constexpr auto begin() const requires forward_range<_View> && forward_range<const _View> {
109*4bdff4beSrobert     return __outer_iterator<true>{*this, ranges::begin(__base_)};
110*4bdff4beSrobert   }
111*4bdff4beSrobert 
112*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
end()113*4bdff4beSrobert   constexpr auto end() requires forward_range<_View> && common_range<_View> {
114*4bdff4beSrobert     return __outer_iterator<__simple_view<_View> && __simple_view<_Pattern>>{*this, ranges::end(__base_)};
115*4bdff4beSrobert   }
116*4bdff4beSrobert 
117*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
end()118*4bdff4beSrobert   constexpr auto end() const {
119*4bdff4beSrobert     if constexpr (forward_range<_View> && forward_range<const _View> && common_range<const _View>) {
120*4bdff4beSrobert       return __outer_iterator<true>{*this, ranges::end(__base_)};
121*4bdff4beSrobert     } else {
122*4bdff4beSrobert       return default_sentinel;
123*4bdff4beSrobert     }
124*4bdff4beSrobert   }
125*4bdff4beSrobert 
126*4bdff4beSrobert private:
127*4bdff4beSrobert 
128*4bdff4beSrobert   template <class>
129*4bdff4beSrobert   struct __outer_iterator_category {};
130*4bdff4beSrobert 
131*4bdff4beSrobert   template <forward_range _Tp>
132*4bdff4beSrobert   struct __outer_iterator_category<_Tp> {
133*4bdff4beSrobert     using iterator_category = input_iterator_tag;
134*4bdff4beSrobert   };
135*4bdff4beSrobert 
136*4bdff4beSrobert   template <bool _Const>
137*4bdff4beSrobert   struct __outer_iterator : __outer_iterator_category<__maybe_const<_Const, _View>> {
138*4bdff4beSrobert   private:
139*4bdff4beSrobert     template <bool>
140*4bdff4beSrobert     friend struct __inner_iterator;
141*4bdff4beSrobert     friend __outer_iterator<true>;
142*4bdff4beSrobert 
143*4bdff4beSrobert     using _Parent = __maybe_const<_Const, lazy_split_view>;
144*4bdff4beSrobert     using _Base = __maybe_const<_Const, _View>;
145*4bdff4beSrobert 
146*4bdff4beSrobert     _Parent* __parent_ = nullptr;
147*4bdff4beSrobert     using _MaybeCurrent = _If<forward_range<_View>, iterator_t<_Base>, __empty_cache>;
148*4bdff4beSrobert     _LIBCPP_NO_UNIQUE_ADDRESS _MaybeCurrent __current_ = _MaybeCurrent();
149*4bdff4beSrobert     bool __trailing_empty_ = false;
150*4bdff4beSrobert 
151*4bdff4beSrobert     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
152*4bdff4beSrobert     constexpr auto& __current() noexcept {
153*4bdff4beSrobert       if constexpr (forward_range<_View>) {
154*4bdff4beSrobert         return __current_;
155*4bdff4beSrobert       } else {
156*4bdff4beSrobert         return *__parent_->__current_;
157*4bdff4beSrobert       }
158*4bdff4beSrobert     }
159*4bdff4beSrobert 
160*4bdff4beSrobert     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
161*4bdff4beSrobert     constexpr const auto& __current() const noexcept {
162*4bdff4beSrobert       if constexpr (forward_range<_View>) {
163*4bdff4beSrobert         return __current_;
164*4bdff4beSrobert       } else {
165*4bdff4beSrobert         return *__parent_->__current_;
166*4bdff4beSrobert       }
167*4bdff4beSrobert     }
168*4bdff4beSrobert 
169*4bdff4beSrobert     // Workaround for the GCC issue that doesn't allow calling `__parent_->__base_` from friend functions (because
170*4bdff4beSrobert     // `__base_` is private).
171*4bdff4beSrobert     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
172*4bdff4beSrobert     constexpr auto& __parent_base() const noexcept {
173*4bdff4beSrobert       return __parent_->__base_;
174*4bdff4beSrobert     }
175*4bdff4beSrobert 
176*4bdff4beSrobert   public:
177*4bdff4beSrobert     // using iterator_category = inherited;
178*4bdff4beSrobert     using iterator_concept = conditional_t<forward_range<_Base>, forward_iterator_tag, input_iterator_tag>;
179*4bdff4beSrobert     using difference_type = range_difference_t<_Base>;
180*4bdff4beSrobert 
181*4bdff4beSrobert     struct value_type : view_interface<value_type> {
182*4bdff4beSrobert     private:
183*4bdff4beSrobert       __outer_iterator __i_ = __outer_iterator();
184*4bdff4beSrobert 
185*4bdff4beSrobert     public:
186*4bdff4beSrobert       _LIBCPP_HIDE_FROM_ABI
187*4bdff4beSrobert       value_type() = default;
188*4bdff4beSrobert       _LIBCPP_HIDE_FROM_ABI
189*4bdff4beSrobert       constexpr explicit value_type(__outer_iterator __i)
190*4bdff4beSrobert         : __i_(std::move(__i)) {}
191*4bdff4beSrobert 
192*4bdff4beSrobert       _LIBCPP_HIDE_FROM_ABI
193*4bdff4beSrobert       constexpr __inner_iterator<_Const> begin() const { return __inner_iterator<_Const>{__i_}; }
194*4bdff4beSrobert       _LIBCPP_HIDE_FROM_ABI
195*4bdff4beSrobert       constexpr default_sentinel_t end() const noexcept { return default_sentinel; }
196*4bdff4beSrobert     };
197*4bdff4beSrobert 
198*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
199*4bdff4beSrobert     __outer_iterator() = default;
200*4bdff4beSrobert 
201*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
202*4bdff4beSrobert     constexpr explicit __outer_iterator(_Parent& __parent)
203*4bdff4beSrobert       requires (!forward_range<_Base>)
204*4bdff4beSrobert       : __parent_(std::addressof(__parent)) {}
205*4bdff4beSrobert 
206*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
207*4bdff4beSrobert     constexpr __outer_iterator(_Parent& __parent, iterator_t<_Base> __current)
208*4bdff4beSrobert       requires forward_range<_Base>
209*4bdff4beSrobert       : __parent_(std::addressof(__parent)), __current_(std::move(__current)) {}
210*4bdff4beSrobert 
211*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
212*4bdff4beSrobert     constexpr __outer_iterator(__outer_iterator<!_Const> __i)
213*4bdff4beSrobert       requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>>
214*4bdff4beSrobert       : __parent_(__i.__parent_), __current_(std::move(__i.__current_)) {}
215*4bdff4beSrobert 
216*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
217*4bdff4beSrobert     constexpr value_type operator*() const { return value_type{*this}; }
218*4bdff4beSrobert 
219*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
220*4bdff4beSrobert     constexpr __outer_iterator& operator++() {
221*4bdff4beSrobert       const auto __end = ranges::end(__parent_->__base_);
222*4bdff4beSrobert       if (__current() == __end) {
223*4bdff4beSrobert         __trailing_empty_ = false;
224*4bdff4beSrobert         return *this;
225*4bdff4beSrobert       }
226*4bdff4beSrobert 
227*4bdff4beSrobert       const auto [__pbegin, __pend] = ranges::subrange{__parent_->__pattern_};
228*4bdff4beSrobert       if (__pbegin == __pend) {
229*4bdff4beSrobert         // Empty pattern: split on every element in the input range
230*4bdff4beSrobert         ++__current();
231*4bdff4beSrobert 
232*4bdff4beSrobert       } else if constexpr (__tiny_range<_Pattern>) {
233*4bdff4beSrobert         // One-element pattern: we can use `ranges::find`.
234*4bdff4beSrobert         __current() = ranges::find(std::move(__current()), __end, *__pbegin);
235*4bdff4beSrobert         if (__current() != __end) {
236*4bdff4beSrobert           // Make sure we point to after the separator we just found.
237*4bdff4beSrobert           ++__current();
238*4bdff4beSrobert           if (__current() == __end)
239*4bdff4beSrobert             __trailing_empty_ = true;
240*4bdff4beSrobert         }
241*4bdff4beSrobert 
242*4bdff4beSrobert       } else {
243*4bdff4beSrobert         // General case for n-element pattern.
244*4bdff4beSrobert         do {
245*4bdff4beSrobert           const auto [__b, __p] = ranges::mismatch(__current(), __end, __pbegin, __pend);
246*4bdff4beSrobert           if (__p == __pend) {
247*4bdff4beSrobert             __current() = __b;
248*4bdff4beSrobert             if (__current() == __end) {
249*4bdff4beSrobert               __trailing_empty_ = true;
250*4bdff4beSrobert             }
251*4bdff4beSrobert             break; // The pattern matched; skip it.
252*4bdff4beSrobert           }
253*4bdff4beSrobert         } while (++__current() != __end);
254*4bdff4beSrobert       }
255*4bdff4beSrobert 
256*4bdff4beSrobert       return *this;
257*4bdff4beSrobert     }
258*4bdff4beSrobert 
259*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
260*4bdff4beSrobert     constexpr decltype(auto) operator++(int) {
261*4bdff4beSrobert       if constexpr (forward_range<_Base>) {
262*4bdff4beSrobert         auto __tmp = *this;
263*4bdff4beSrobert         ++*this;
264*4bdff4beSrobert         return __tmp;
265*4bdff4beSrobert 
266*4bdff4beSrobert       } else {
267*4bdff4beSrobert         ++*this;
268*4bdff4beSrobert       }
269*4bdff4beSrobert     }
270*4bdff4beSrobert 
271*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
272*4bdff4beSrobert     friend constexpr bool operator==(const __outer_iterator& __x, const __outer_iterator& __y)
273*4bdff4beSrobert       requires forward_range<_Base> {
274*4bdff4beSrobert       return __x.__current_ == __y.__current_ && __x.__trailing_empty_ == __y.__trailing_empty_;
275*4bdff4beSrobert     }
276*4bdff4beSrobert 
277*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
278*4bdff4beSrobert     friend constexpr bool operator==(const __outer_iterator& __x, default_sentinel_t) {
279*4bdff4beSrobert       _LIBCPP_ASSERT(__x.__parent_, "Cannot call comparison on a default-constructed iterator.");
280*4bdff4beSrobert       return __x.__current() == ranges::end(__x.__parent_base()) && !__x.__trailing_empty_;
281*4bdff4beSrobert     }
282*4bdff4beSrobert   };
283*4bdff4beSrobert 
284*4bdff4beSrobert   template <class>
285*4bdff4beSrobert   struct __inner_iterator_category {};
286*4bdff4beSrobert 
287*4bdff4beSrobert   template <forward_range _Tp>
288*4bdff4beSrobert   struct __inner_iterator_category<_Tp> {
289*4bdff4beSrobert     using iterator_category = _If<
290*4bdff4beSrobert       derived_from<typename iterator_traits<iterator_t<_Tp>>::iterator_category, forward_iterator_tag>,
291*4bdff4beSrobert       forward_iterator_tag,
292*4bdff4beSrobert       typename iterator_traits<iterator_t<_Tp>>::iterator_category
293*4bdff4beSrobert     >;
294*4bdff4beSrobert   };
295*4bdff4beSrobert 
296*4bdff4beSrobert   template <bool _Const>
297*4bdff4beSrobert   struct __inner_iterator : __inner_iterator_category<__maybe_const<_Const, _View>> {
298*4bdff4beSrobert   private:
299*4bdff4beSrobert     using _Base = __maybe_const<_Const, _View>;
300*4bdff4beSrobert     // Workaround for a GCC issue.
301*4bdff4beSrobert     static constexpr bool _OuterConst = _Const;
302*4bdff4beSrobert     __outer_iterator<_Const> __i_ = __outer_iterator<_OuterConst>();
303*4bdff4beSrobert     bool __incremented_ = false;
304*4bdff4beSrobert 
305*4bdff4beSrobert     // Note: these private functions are necessary because GCC doesn't allow calls to private members of `__i_` from
306*4bdff4beSrobert     // free functions that are friends of `inner-iterator`.
307*4bdff4beSrobert 
308*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
309*4bdff4beSrobert     constexpr bool __is_done() const {
310*4bdff4beSrobert       _LIBCPP_ASSERT(__i_.__parent_, "Cannot call comparison on a default-constructed iterator.");
311*4bdff4beSrobert 
312*4bdff4beSrobert       auto [__pcur, __pend] = ranges::subrange{__i_.__parent_->__pattern_};
313*4bdff4beSrobert       auto __end = ranges::end(__i_.__parent_->__base_);
314*4bdff4beSrobert 
315*4bdff4beSrobert       if constexpr (__tiny_range<_Pattern>) {
316*4bdff4beSrobert         const auto& __cur = __i_.__current();
317*4bdff4beSrobert         if (__cur == __end)
318*4bdff4beSrobert           return true;
319*4bdff4beSrobert         if (__pcur == __pend)
320*4bdff4beSrobert           return __incremented_;
321*4bdff4beSrobert 
322*4bdff4beSrobert         return *__cur == *__pcur;
323*4bdff4beSrobert 
324*4bdff4beSrobert       } else {
325*4bdff4beSrobert         auto __cur = __i_.__current();
326*4bdff4beSrobert         if (__cur == __end)
327*4bdff4beSrobert           return true;
328*4bdff4beSrobert         if (__pcur == __pend)
329*4bdff4beSrobert           return __incremented_;
330*4bdff4beSrobert 
331*4bdff4beSrobert         do {
332*4bdff4beSrobert           if (*__cur != *__pcur)
333*4bdff4beSrobert             return false;
334*4bdff4beSrobert           if (++__pcur == __pend)
335*4bdff4beSrobert             return true;
336*4bdff4beSrobert         } while (++__cur != __end);
337*4bdff4beSrobert 
338*4bdff4beSrobert         return false;
339*4bdff4beSrobert       }
340*4bdff4beSrobert     }
341*4bdff4beSrobert 
342*4bdff4beSrobert     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
343*4bdff4beSrobert     constexpr auto& __outer_current() noexcept {
344*4bdff4beSrobert       return __i_.__current();
345*4bdff4beSrobert     }
346*4bdff4beSrobert 
347*4bdff4beSrobert     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
348*4bdff4beSrobert     constexpr const auto& __outer_current() const noexcept {
349*4bdff4beSrobert       return __i_.__current();
350*4bdff4beSrobert     }
351*4bdff4beSrobert 
352*4bdff4beSrobert   public:
353*4bdff4beSrobert     // using iterator_category = inherited;
354*4bdff4beSrobert     using iterator_concept = typename __outer_iterator<_Const>::iterator_concept;
355*4bdff4beSrobert     using value_type = range_value_t<_Base>;
356*4bdff4beSrobert     using difference_type = range_difference_t<_Base>;
357*4bdff4beSrobert 
358*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
359*4bdff4beSrobert     __inner_iterator() = default;
360*4bdff4beSrobert 
361*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
362*4bdff4beSrobert     constexpr explicit __inner_iterator(__outer_iterator<_Const> __i)
363*4bdff4beSrobert       : __i_(std::move(__i)) {}
364*4bdff4beSrobert 
365*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
366*4bdff4beSrobert     constexpr const iterator_t<_Base>& base() const& noexcept { return __i_.__current(); }
367*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
368*4bdff4beSrobert     constexpr iterator_t<_Base> base() &&
369*4bdff4beSrobert       requires forward_range<_View> { return std::move(__i_.__current()); }
370*4bdff4beSrobert 
371*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
372*4bdff4beSrobert     constexpr decltype(auto) operator*() const { return *__i_.__current(); }
373*4bdff4beSrobert 
374*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
375*4bdff4beSrobert     constexpr __inner_iterator& operator++() {
376*4bdff4beSrobert       __incremented_ = true;
377*4bdff4beSrobert 
378*4bdff4beSrobert       if constexpr (!forward_range<_Base>) {
379*4bdff4beSrobert         if constexpr (_Pattern::size() == 0) {
380*4bdff4beSrobert           return *this;
381*4bdff4beSrobert         }
382*4bdff4beSrobert       }
383*4bdff4beSrobert 
384*4bdff4beSrobert       ++__i_.__current();
385*4bdff4beSrobert       return *this;
386*4bdff4beSrobert     }
387*4bdff4beSrobert 
388*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
389*4bdff4beSrobert     constexpr decltype(auto) operator++(int) {
390*4bdff4beSrobert       if constexpr (forward_range<_Base>) {
391*4bdff4beSrobert         auto __tmp = *this;
392*4bdff4beSrobert         ++*this;
393*4bdff4beSrobert         return __tmp;
394*4bdff4beSrobert 
395*4bdff4beSrobert       } else {
396*4bdff4beSrobert         ++*this;
397*4bdff4beSrobert       }
398*4bdff4beSrobert     }
399*4bdff4beSrobert 
400*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
401*4bdff4beSrobert     friend constexpr bool operator==(const __inner_iterator& __x, const __inner_iterator& __y)
402*4bdff4beSrobert       requires forward_range<_Base> {
403*4bdff4beSrobert       return __x.__outer_current() == __y.__outer_current();
404*4bdff4beSrobert     }
405*4bdff4beSrobert 
406*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
407*4bdff4beSrobert     friend constexpr bool operator==(const __inner_iterator& __x, default_sentinel_t) {
408*4bdff4beSrobert       return __x.__is_done();
409*4bdff4beSrobert     }
410*4bdff4beSrobert 
411*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
412*4bdff4beSrobert     friend constexpr decltype(auto) iter_move(const __inner_iterator& __i)
413*4bdff4beSrobert         noexcept(noexcept(ranges::iter_move(__i.__outer_current()))) {
414*4bdff4beSrobert       return ranges::iter_move(__i.__outer_current());
415*4bdff4beSrobert     }
416*4bdff4beSrobert 
417*4bdff4beSrobert     _LIBCPP_HIDE_FROM_ABI
418*4bdff4beSrobert     friend constexpr void iter_swap(const __inner_iterator& __x, const __inner_iterator& __y)
419*4bdff4beSrobert         noexcept(noexcept(ranges::iter_swap(__x.__outer_current(), __y.__outer_current())))
420*4bdff4beSrobert         requires indirectly_swappable<iterator_t<_Base>> {
421*4bdff4beSrobert       ranges::iter_swap(__x.__outer_current(), __y.__outer_current());
422*4bdff4beSrobert     }
423*4bdff4beSrobert   };
424*4bdff4beSrobert 
425*4bdff4beSrobert };
426*4bdff4beSrobert 
427*4bdff4beSrobert template <class _Range, class _Pattern>
428*4bdff4beSrobert lazy_split_view(_Range&&, _Pattern&&) -> lazy_split_view<views::all_t<_Range>, views::all_t<_Pattern>>;
429*4bdff4beSrobert 
430*4bdff4beSrobert template <input_range _Range>
431*4bdff4beSrobert lazy_split_view(_Range&&, range_value_t<_Range>)
432*4bdff4beSrobert   -> lazy_split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>;
433*4bdff4beSrobert 
434*4bdff4beSrobert namespace views {
435*4bdff4beSrobert namespace __lazy_split_view {
436*4bdff4beSrobert struct __fn : __range_adaptor_closure<__fn> {
437*4bdff4beSrobert   template <class _Range, class _Pattern>
438*4bdff4beSrobert   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
439*4bdff4beSrobert   constexpr auto operator()(_Range&& __range, _Pattern&& __pattern) const
440*4bdff4beSrobert     noexcept(noexcept(lazy_split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern))))
441*4bdff4beSrobert     -> decltype(      lazy_split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern)))
442*4bdff4beSrobert     { return          lazy_split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern)); }
443*4bdff4beSrobert 
444*4bdff4beSrobert   template <class _Pattern>
445*4bdff4beSrobert     requires constructible_from<decay_t<_Pattern>, _Pattern>
446*4bdff4beSrobert   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
447*4bdff4beSrobert   constexpr auto operator()(_Pattern&& __pattern) const
448*4bdff4beSrobert       noexcept(is_nothrow_constructible_v<decay_t<_Pattern>, _Pattern>) {
449*4bdff4beSrobert     return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Pattern>(__pattern)));
450*4bdff4beSrobert   }
451*4bdff4beSrobert };
452*4bdff4beSrobert } // namespace __lazy_split_view
453*4bdff4beSrobert 
454*4bdff4beSrobert inline namespace __cpo {
455*4bdff4beSrobert   inline constexpr auto lazy_split = __lazy_split_view::__fn{};
456*4bdff4beSrobert } // namespace __cpo
457*4bdff4beSrobert } // namespace views
458*4bdff4beSrobert 
459*4bdff4beSrobert } // namespace ranges
460*4bdff4beSrobert 
461*4bdff4beSrobert #endif // _LIBCPP_STD_VER > 17
462*4bdff4beSrobert 
463*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD
464*4bdff4beSrobert 
465*4bdff4beSrobert #endif // _LIBCPP___RANGES_LAZY_SPLIT_VIEW_H
466