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_TAKE_WHILE_VIEW_H
11bdd1243dSDimitry Andric #define _LIBCPP___RANGES_TAKE_WHILE_VIEW_H
12bdd1243dSDimitry Andric 
13bdd1243dSDimitry Andric #include <__concepts/constructible.h>
14bdd1243dSDimitry Andric #include <__concepts/convertible_to.h>
15bdd1243dSDimitry Andric #include <__config>
16bdd1243dSDimitry Andric #include <__functional/bind_back.h>
17bdd1243dSDimitry Andric #include <__functional/invoke.h>
18bdd1243dSDimitry Andric #include <__iterator/concepts.h>
19bdd1243dSDimitry Andric #include <__memory/addressof.h>
20bdd1243dSDimitry Andric #include <__ranges/access.h>
21bdd1243dSDimitry Andric #include <__ranges/all.h>
22bdd1243dSDimitry Andric #include <__ranges/concepts.h>
2306c3fb27SDimitry Andric #include <__ranges/movable_box.h>
24bdd1243dSDimitry Andric #include <__ranges/range_adaptor.h>
25bdd1243dSDimitry Andric #include <__ranges/view_interface.h>
26bdd1243dSDimitry Andric #include <__type_traits/decay.h>
27bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_constructible.h>
28bdd1243dSDimitry Andric #include <__type_traits/is_object.h>
29bdd1243dSDimitry Andric #include <__type_traits/maybe_const.h>
30bdd1243dSDimitry Andric #include <__utility/forward.h>
31bdd1243dSDimitry Andric #include <__utility/in_place.h>
32bdd1243dSDimitry Andric #include <__utility/move.h>
33bdd1243dSDimitry Andric 
34bdd1243dSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
35bdd1243dSDimitry Andric #  pragma GCC system_header
36bdd1243dSDimitry Andric #endif
37bdd1243dSDimitry Andric 
38*b3edf446SDimitry Andric _LIBCPP_PUSH_MACROS
39*b3edf446SDimitry Andric #include <__undef_macros>
40*b3edf446SDimitry Andric 
41bdd1243dSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
42bdd1243dSDimitry Andric 
43bdd1243dSDimitry Andric #if _LIBCPP_STD_VER >= 20
44bdd1243dSDimitry Andric 
45bdd1243dSDimitry Andric namespace ranges {
46bdd1243dSDimitry Andric 
47bdd1243dSDimitry Andric template <view _View, class _Pred>
48bdd1243dSDimitry Andric   requires input_range<_View> && is_object_v<_Pred> && indirect_unary_predicate<const _Pred, iterator_t<_View>>
497a6dacacSDimitry Andric class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS take_while_view : public view_interface<take_while_view<_View, _Pred>> {
501ac55f4cSDimitry Andric   template <bool>
511ac55f4cSDimitry Andric   class __sentinel;
52bdd1243dSDimitry Andric 
53bdd1243dSDimitry Andric   _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();
5406c3fb27SDimitry Andric   _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Pred> __pred_;
55bdd1243dSDimitry Andric 
56bdd1243dSDimitry Andric public:
57bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI take_while_view()
58bdd1243dSDimitry Andric     requires default_initializable<_View> && default_initializable<_Pred>
59bdd1243dSDimitry Andric   = default;
60bdd1243dSDimitry Andric 
take_while_view(_View __base,_Pred __pred)6106c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 take_while_view(_View __base, _Pred __pred)
62bdd1243dSDimitry Andric       : __base_(std::move(__base)), __pred_(std::in_place, std::move(__pred)) {}
63bdd1243dSDimitry Andric 
base()64bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
65bdd1243dSDimitry Andric     requires copy_constructible<_View>
66bdd1243dSDimitry Andric   {
67bdd1243dSDimitry Andric     return __base_;
68bdd1243dSDimitry Andric   }
69bdd1243dSDimitry Andric 
base()70bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
71bdd1243dSDimitry Andric 
pred()72bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Pred& pred() const { return *__pred_; }
73bdd1243dSDimitry Andric 
begin()74bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto begin()
75bdd1243dSDimitry Andric     requires(!__simple_view<_View>)
76bdd1243dSDimitry Andric   {
77bdd1243dSDimitry Andric     return ranges::begin(__base_);
78bdd1243dSDimitry Andric   }
79bdd1243dSDimitry Andric 
begin()80bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
815f757f3fSDimitry Andric     requires range<const _View> && indirect_unary_predicate<const _Pred, iterator_t<const _View>>
82bdd1243dSDimitry Andric   {
83bdd1243dSDimitry Andric     return ranges::begin(__base_);
84bdd1243dSDimitry Andric   }
85bdd1243dSDimitry Andric 
end()86bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto end()
87bdd1243dSDimitry Andric     requires(!__simple_view<_View>)
88bdd1243dSDimitry Andric   {
89bdd1243dSDimitry Andric     return __sentinel</*_Const=*/false>(ranges::end(__base_), std::addressof(*__pred_));
90bdd1243dSDimitry Andric   }
91bdd1243dSDimitry Andric 
end()92bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
935f757f3fSDimitry Andric     requires range<const _View> && indirect_unary_predicate<const _Pred, iterator_t<const _View>>
94bdd1243dSDimitry Andric   {
95bdd1243dSDimitry Andric     return __sentinel</*_Const=*/true>(ranges::end(__base_), std::addressof(*__pred_));
96bdd1243dSDimitry Andric   }
97bdd1243dSDimitry Andric };
98bdd1243dSDimitry Andric 
99bdd1243dSDimitry Andric template <class _Range, class _Pred>
100bdd1243dSDimitry Andric take_while_view(_Range&&, _Pred) -> take_while_view<views::all_t<_Range>, _Pred>;
101bdd1243dSDimitry Andric 
1021ac55f4cSDimitry Andric template <view _View, class _Pred>
1031ac55f4cSDimitry Andric   requires input_range<_View> && is_object_v<_Pred> && indirect_unary_predicate<const _Pred, iterator_t<_View>>
1041ac55f4cSDimitry Andric template <bool _Const>
1051ac55f4cSDimitry Andric class take_while_view<_View, _Pred>::__sentinel {
106bdd1243dSDimitry Andric   using _Base = __maybe_const<_Const, _View>;
107bdd1243dSDimitry Andric 
108bdd1243dSDimitry Andric   sentinel_t<_Base> __end_ = sentinel_t<_Base>();
109bdd1243dSDimitry Andric   const _Pred* __pred_     = nullptr;
110bdd1243dSDimitry Andric 
1111ac55f4cSDimitry Andric   friend class __sentinel<!_Const>;
112bdd1243dSDimitry Andric 
113bdd1243dSDimitry Andric public:
1141ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI __sentinel() = default;
115bdd1243dSDimitry Andric 
__sentinel(sentinel_t<_Base> __end,const _Pred * __pred)1161ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end, const _Pred* __pred)
117bdd1243dSDimitry Andric       : __end_(std::move(__end)), __pred_(__pred) {}
118bdd1243dSDimitry Andric 
__sentinel(__sentinel<!_Const> __s)1191ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __s)
120bdd1243dSDimitry Andric     requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
121bdd1243dSDimitry Andric       : __end_(std::move(__s.__end_)), __pred_(__s.__pred_) {}
122bdd1243dSDimitry Andric 
base()123bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Base> base() const { return __end_; }
124bdd1243dSDimitry Andric 
1251ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const iterator_t<_Base>& __x, const __sentinel& __y) {
126bdd1243dSDimitry Andric     return __x == __y.__end_ || !std::invoke(*__y.__pred_, *__x);
127bdd1243dSDimitry Andric   }
128bdd1243dSDimitry Andric 
129bdd1243dSDimitry Andric   template <bool _OtherConst = !_Const>
130bdd1243dSDimitry Andric     requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
131bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool
1321ac55f4cSDimitry Andric   operator==(const iterator_t<__maybe_const<_OtherConst, _View>>& __x, const __sentinel& __y) {
133bdd1243dSDimitry Andric     return __x == __y.__end_ || !std::invoke(*__y.__pred_, *__x);
134bdd1243dSDimitry Andric   }
135bdd1243dSDimitry Andric };
136bdd1243dSDimitry Andric 
137bdd1243dSDimitry Andric namespace views {
138bdd1243dSDimitry Andric namespace __take_while {
139bdd1243dSDimitry Andric 
140bdd1243dSDimitry Andric struct __fn {
141bdd1243dSDimitry Andric   template <class _Range, class _Pred>
142bdd1243dSDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Pred&& __pred) const
143bdd1243dSDimitry Andric       noexcept(noexcept(/**/ take_while_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred))))
144bdd1243dSDimitry Andric           -> decltype(/*--*/ take_while_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred))) {
145bdd1243dSDimitry Andric     return /*-------------*/ take_while_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred));
146bdd1243dSDimitry Andric   }
147bdd1243dSDimitry Andric 
148bdd1243dSDimitry Andric   template <class _Pred>
149bdd1243dSDimitry Andric     requires constructible_from<decay_t<_Pred>, _Pred>
operator__fn150bdd1243dSDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pred&& __pred) const
151bdd1243dSDimitry Andric       noexcept(is_nothrow_constructible_v<decay_t<_Pred>, _Pred>) {
152bdd1243dSDimitry Andric     return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Pred>(__pred)));
153bdd1243dSDimitry Andric   }
154bdd1243dSDimitry Andric };
155bdd1243dSDimitry Andric 
156bdd1243dSDimitry Andric } // namespace __take_while
157bdd1243dSDimitry Andric 
158bdd1243dSDimitry Andric inline namespace __cpo {
159bdd1243dSDimitry Andric inline constexpr auto take_while = __take_while::__fn{};
160bdd1243dSDimitry Andric } // namespace __cpo
161bdd1243dSDimitry Andric } // namespace views
162bdd1243dSDimitry Andric } // namespace ranges
163bdd1243dSDimitry Andric 
164bdd1243dSDimitry Andric #endif // _LIBCPP_STD_VER >= 20
165bdd1243dSDimitry Andric 
166bdd1243dSDimitry Andric _LIBCPP_END_NAMESPACE_STD
167bdd1243dSDimitry Andric 
168*b3edf446SDimitry Andric _LIBCPP_POP_MACROS
169*b3edf446SDimitry Andric 
170bdd1243dSDimitry Andric #endif // _LIBCPP___RANGES_TAKE_WHILE_VIEW_H
171