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_TAKE_VIEW_H
11*4bdff4beSrobert #define _LIBCPP___RANGES_TAKE_VIEW_H
12*4bdff4beSrobert 
13*4bdff4beSrobert #include <__algorithm/min.h>
14*4bdff4beSrobert #include <__algorithm/ranges_min.h>
15*4bdff4beSrobert #include <__assert>
16*4bdff4beSrobert #include <__concepts/constructible.h>
17*4bdff4beSrobert #include <__concepts/convertible_to.h>
18*4bdff4beSrobert #include <__config>
19*4bdff4beSrobert #include <__functional/bind_back.h>
20*4bdff4beSrobert #include <__fwd/span.h>
21*4bdff4beSrobert #include <__fwd/string_view.h>
22*4bdff4beSrobert #include <__iterator/concepts.h>
23*4bdff4beSrobert #include <__iterator/counted_iterator.h>
24*4bdff4beSrobert #include <__iterator/default_sentinel.h>
25*4bdff4beSrobert #include <__iterator/distance.h>
26*4bdff4beSrobert #include <__iterator/iterator_traits.h>
27*4bdff4beSrobert #include <__ranges/access.h>
28*4bdff4beSrobert #include <__ranges/all.h>
29*4bdff4beSrobert #include <__ranges/concepts.h>
30*4bdff4beSrobert #include <__ranges/empty_view.h>
31*4bdff4beSrobert #include <__ranges/enable_borrowed_range.h>
32*4bdff4beSrobert #include <__ranges/iota_view.h>
33*4bdff4beSrobert #include <__ranges/range_adaptor.h>
34*4bdff4beSrobert #include <__ranges/size.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/auto_cast.h>
39*4bdff4beSrobert #include <__utility/forward.h>
40*4bdff4beSrobert #include <__utility/move.h>
41*4bdff4beSrobert #include <type_traits>
42*4bdff4beSrobert 
43*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
44*4bdff4beSrobert #  pragma GCC system_header
45*4bdff4beSrobert #endif
46*4bdff4beSrobert 
47*4bdff4beSrobert _LIBCPP_PUSH_MACROS
48*4bdff4beSrobert #include <__undef_macros>
49*4bdff4beSrobert 
50*4bdff4beSrobert _LIBCPP_BEGIN_NAMESPACE_STD
51*4bdff4beSrobert 
52*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
53*4bdff4beSrobert 
54*4bdff4beSrobert namespace ranges {
55*4bdff4beSrobert 
56*4bdff4beSrobert template<view _View>
57*4bdff4beSrobert class take_view : public view_interface<take_view<_View>> {
58*4bdff4beSrobert   _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();
59*4bdff4beSrobert   range_difference_t<_View> __count_ = 0;
60*4bdff4beSrobert 
61*4bdff4beSrobert   template<bool> class __sentinel;
62*4bdff4beSrobert 
63*4bdff4beSrobert public:
64*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
65*4bdff4beSrobert   take_view() requires default_initializable<_View> = default;
66*4bdff4beSrobert 
take_view(_View __base,range_difference_t<_View> __count)67*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI constexpr take_view(_View __base, range_difference_t<_View> __count)
68*4bdff4beSrobert       : __base_(std::move(__base)), __count_(__count) {
69*4bdff4beSrobert     _LIBCPP_ASSERT(__count >= 0, "count has to be greater than or equal to zero");
70*4bdff4beSrobert   }
71*4bdff4beSrobert 
72*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
base()73*4bdff4beSrobert   constexpr _View base() const& requires copy_constructible<_View> { return __base_; }
74*4bdff4beSrobert 
75*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
base()76*4bdff4beSrobert   constexpr _View base() && { return std::move(__base_); }
77*4bdff4beSrobert 
78*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
begin()79*4bdff4beSrobert   constexpr auto begin() requires (!__simple_view<_View>) {
80*4bdff4beSrobert     if constexpr (sized_range<_View>) {
81*4bdff4beSrobert       if constexpr (random_access_range<_View>) {
82*4bdff4beSrobert         return ranges::begin(__base_);
83*4bdff4beSrobert       } else {
84*4bdff4beSrobert         using _DifferenceT = range_difference_t<_View>;
85*4bdff4beSrobert         auto __size = size();
86*4bdff4beSrobert         return counted_iterator(ranges::begin(__base_), static_cast<_DifferenceT>(__size));
87*4bdff4beSrobert       }
88*4bdff4beSrobert     } else {
89*4bdff4beSrobert       return counted_iterator(ranges::begin(__base_), __count_);
90*4bdff4beSrobert     }
91*4bdff4beSrobert   }
92*4bdff4beSrobert 
93*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
begin()94*4bdff4beSrobert   constexpr auto begin() const requires range<const _View> {
95*4bdff4beSrobert     if constexpr (sized_range<const _View>) {
96*4bdff4beSrobert       if constexpr (random_access_range<const _View>) {
97*4bdff4beSrobert         return ranges::begin(__base_);
98*4bdff4beSrobert       } else {
99*4bdff4beSrobert         using _DifferenceT = range_difference_t<const _View>;
100*4bdff4beSrobert         auto __size = size();
101*4bdff4beSrobert         return counted_iterator(ranges::begin(__base_), static_cast<_DifferenceT>(__size));
102*4bdff4beSrobert       }
103*4bdff4beSrobert     } else {
104*4bdff4beSrobert       return counted_iterator(ranges::begin(__base_), __count_);
105*4bdff4beSrobert     }
106*4bdff4beSrobert   }
107*4bdff4beSrobert 
108*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
end()109*4bdff4beSrobert   constexpr auto end() requires (!__simple_view<_View>) {
110*4bdff4beSrobert     if constexpr (sized_range<_View>) {
111*4bdff4beSrobert       if constexpr (random_access_range<_View>) {
112*4bdff4beSrobert         return ranges::begin(__base_) + size();
113*4bdff4beSrobert       } else {
114*4bdff4beSrobert         return default_sentinel;
115*4bdff4beSrobert       }
116*4bdff4beSrobert     } else {
117*4bdff4beSrobert       return __sentinel<false>{ranges::end(__base_)};
118*4bdff4beSrobert     }
119*4bdff4beSrobert   }
120*4bdff4beSrobert 
121*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
end()122*4bdff4beSrobert   constexpr auto end() const requires range<const _View> {
123*4bdff4beSrobert     if constexpr (sized_range<const _View>) {
124*4bdff4beSrobert       if constexpr (random_access_range<const _View>) {
125*4bdff4beSrobert         return ranges::begin(__base_) + size();
126*4bdff4beSrobert       } else {
127*4bdff4beSrobert         return default_sentinel;
128*4bdff4beSrobert       }
129*4bdff4beSrobert     } else {
130*4bdff4beSrobert       return __sentinel<true>{ranges::end(__base_)};
131*4bdff4beSrobert     }
132*4bdff4beSrobert   }
133*4bdff4beSrobert 
134*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
size()135*4bdff4beSrobert   constexpr auto size() requires sized_range<_View> {
136*4bdff4beSrobert     auto __n = ranges::size(__base_);
137*4bdff4beSrobert     return ranges::min(__n, static_cast<decltype(__n)>(__count_));
138*4bdff4beSrobert   }
139*4bdff4beSrobert 
140*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
size()141*4bdff4beSrobert   constexpr auto size() const requires sized_range<const _View> {
142*4bdff4beSrobert     auto __n = ranges::size(__base_);
143*4bdff4beSrobert     return ranges::min(__n, static_cast<decltype(__n)>(__count_));
144*4bdff4beSrobert   }
145*4bdff4beSrobert };
146*4bdff4beSrobert 
147*4bdff4beSrobert template<view _View>
148*4bdff4beSrobert template<bool _Const>
149*4bdff4beSrobert class take_view<_View>::__sentinel {
150*4bdff4beSrobert   using _Base = __maybe_const<_Const, _View>;
151*4bdff4beSrobert   template<bool _OtherConst>
152*4bdff4beSrobert   using _Iter = counted_iterator<iterator_t<__maybe_const<_OtherConst, _View>>>;
153*4bdff4beSrobert   _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>();
154*4bdff4beSrobert 
155*4bdff4beSrobert   template<bool>
156*4bdff4beSrobert   friend class take_view<_View>::__sentinel;
157*4bdff4beSrobert 
158*4bdff4beSrobert public:
159*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
160*4bdff4beSrobert   __sentinel() = default;
161*4bdff4beSrobert 
162*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
__sentinel(sentinel_t<_Base> __end)163*4bdff4beSrobert   constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {}
164*4bdff4beSrobert 
165*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
__sentinel(__sentinel<!_Const> __s)166*4bdff4beSrobert   constexpr __sentinel(__sentinel<!_Const> __s)
167*4bdff4beSrobert     requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
168*4bdff4beSrobert     : __end_(std::move(__s.__end_)) {}
169*4bdff4beSrobert 
170*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
base()171*4bdff4beSrobert   constexpr sentinel_t<_Base> base() const { return __end_; }
172*4bdff4beSrobert 
173*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
174*4bdff4beSrobert   friend constexpr bool operator==(const _Iter<_Const>& __lhs, const __sentinel& __rhs) {
175*4bdff4beSrobert     return __lhs.count() == 0 || __lhs.base() == __rhs.__end_;
176*4bdff4beSrobert   }
177*4bdff4beSrobert 
178*4bdff4beSrobert   template<bool _OtherConst = !_Const>
179*4bdff4beSrobert     requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
180*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI
181*4bdff4beSrobert   friend constexpr bool operator==(const _Iter<_Const>& __lhs, const __sentinel& __rhs) {
182*4bdff4beSrobert     return __lhs.count() == 0 || __lhs.base() == __rhs.__end_;
183*4bdff4beSrobert   }
184*4bdff4beSrobert };
185*4bdff4beSrobert 
186*4bdff4beSrobert template<class _Range>
187*4bdff4beSrobert take_view(_Range&&, range_difference_t<_Range>) -> take_view<views::all_t<_Range>>;
188*4bdff4beSrobert 
189*4bdff4beSrobert template<class _Tp>
190*4bdff4beSrobert inline constexpr bool enable_borrowed_range<take_view<_Tp>> = enable_borrowed_range<_Tp>;
191*4bdff4beSrobert 
192*4bdff4beSrobert namespace views {
193*4bdff4beSrobert namespace __take {
194*4bdff4beSrobert 
195*4bdff4beSrobert template <class _Tp>
196*4bdff4beSrobert inline constexpr bool __is_empty_view = false;
197*4bdff4beSrobert 
198*4bdff4beSrobert template <class _Tp>
199*4bdff4beSrobert inline constexpr bool __is_empty_view<empty_view<_Tp>> = true;
200*4bdff4beSrobert 
201*4bdff4beSrobert template <class _Tp>
202*4bdff4beSrobert inline constexpr bool __is_passthrough_specialization = false;
203*4bdff4beSrobert 
204*4bdff4beSrobert template <class _Tp, size_t _Extent>
205*4bdff4beSrobert inline constexpr bool __is_passthrough_specialization<span<_Tp, _Extent>> = true;
206*4bdff4beSrobert 
207*4bdff4beSrobert template <class _CharT, class _Traits>
208*4bdff4beSrobert inline constexpr bool __is_passthrough_specialization<basic_string_view<_CharT, _Traits>> = true;
209*4bdff4beSrobert 
210*4bdff4beSrobert template <class _Iter, class _Sent, subrange_kind _Kind>
211*4bdff4beSrobert inline constexpr bool __is_passthrough_specialization<subrange<_Iter, _Sent, _Kind>> = true;
212*4bdff4beSrobert 
213*4bdff4beSrobert template <class _Tp>
214*4bdff4beSrobert inline constexpr bool __is_iota_specialization = false;
215*4bdff4beSrobert 
216*4bdff4beSrobert template <class _Np, class _Bound>
217*4bdff4beSrobert inline constexpr bool __is_iota_specialization<iota_view<_Np, _Bound>> = true;
218*4bdff4beSrobert 
219*4bdff4beSrobert template <class _Tp>
220*4bdff4beSrobert struct __passthrough_type;
221*4bdff4beSrobert 
222*4bdff4beSrobert template <class _Tp, size_t _Extent>
223*4bdff4beSrobert struct __passthrough_type<span<_Tp, _Extent>> {
224*4bdff4beSrobert   using type = span<_Tp>;
225*4bdff4beSrobert };
226*4bdff4beSrobert 
227*4bdff4beSrobert template <class _CharT, class _Traits>
228*4bdff4beSrobert struct __passthrough_type<basic_string_view<_CharT, _Traits>> {
229*4bdff4beSrobert   using type = basic_string_view<_CharT, _Traits>;
230*4bdff4beSrobert };
231*4bdff4beSrobert 
232*4bdff4beSrobert template <class _Iter, class _Sent, subrange_kind _Kind>
233*4bdff4beSrobert   requires requires{typename subrange<_Iter>;}
234*4bdff4beSrobert struct __passthrough_type<subrange<_Iter, _Sent, _Kind>> {
235*4bdff4beSrobert   using type = subrange<_Iter>;
236*4bdff4beSrobert };
237*4bdff4beSrobert 
238*4bdff4beSrobert template <class _Tp>
239*4bdff4beSrobert using __passthrough_type_t = typename __passthrough_type<_Tp>::type;
240*4bdff4beSrobert 
241*4bdff4beSrobert struct __fn {
242*4bdff4beSrobert   // [range.take.overview]: the `empty_view` case.
243*4bdff4beSrobert   template <class _Range, convertible_to<range_difference_t<_Range>> _Np>
244*4bdff4beSrobert     requires __is_empty_view<remove_cvref_t<_Range>>
245*4bdff4beSrobert   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
246*4bdff4beSrobert   constexpr auto operator()(_Range&& __range, _Np&&) const
247*4bdff4beSrobert     noexcept(noexcept(_LIBCPP_AUTO_CAST(std::forward<_Range>(__range))))
248*4bdff4beSrobert     -> decltype(      _LIBCPP_AUTO_CAST(std::forward<_Range>(__range)))
249*4bdff4beSrobert     { return          _LIBCPP_AUTO_CAST(std::forward<_Range>(__range)); }
250*4bdff4beSrobert 
251*4bdff4beSrobert   // [range.take.overview]: the `span | basic_string_view | subrange` case.
252*4bdff4beSrobert   template <class _Range,
253*4bdff4beSrobert             convertible_to<range_difference_t<_Range>> _Np,
254*4bdff4beSrobert             class _RawRange = remove_cvref_t<_Range>,
255*4bdff4beSrobert             class _Dist = range_difference_t<_Range>>
256*4bdff4beSrobert     requires (!__is_empty_view<_RawRange> &&
257*4bdff4beSrobert               random_access_range<_RawRange> &&
258*4bdff4beSrobert               sized_range<_RawRange> &&
259*4bdff4beSrobert               __is_passthrough_specialization<_RawRange>)
260*4bdff4beSrobert   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
261*4bdff4beSrobert   constexpr auto operator()(_Range&& __rng, _Np&& __n) const
262*4bdff4beSrobert     noexcept(noexcept(__passthrough_type_t<_RawRange>(
263*4bdff4beSrobert                               ranges::begin(__rng),
264*4bdff4beSrobert                               ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n))
265*4bdff4beSrobert                               )))
266*4bdff4beSrobert     -> decltype(      __passthrough_type_t<_RawRange>(
267*4bdff4beSrobert                               // Note: deliberately not forwarding `__rng` to guard against double moves.
268*4bdff4beSrobert                               ranges::begin(__rng),
269*4bdff4beSrobert                               ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n))
270*4bdff4beSrobert                               ))
271*4bdff4beSrobert     { return          __passthrough_type_t<_RawRange>(
272*4bdff4beSrobert                               ranges::begin(__rng),
273*4bdff4beSrobert                               ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n))
274*4bdff4beSrobert                               ); }
275*4bdff4beSrobert 
276*4bdff4beSrobert   // [range.take.overview]: the `iota_view` case.
277*4bdff4beSrobert   template <class _Range,
278*4bdff4beSrobert             convertible_to<range_difference_t<_Range>> _Np,
279*4bdff4beSrobert             class _RawRange = remove_cvref_t<_Range>,
280*4bdff4beSrobert             class _Dist = range_difference_t<_Range>>
281*4bdff4beSrobert     requires (!__is_empty_view<_RawRange> &&
282*4bdff4beSrobert               random_access_range<_RawRange> &&
283*4bdff4beSrobert               sized_range<_RawRange> &&
284*4bdff4beSrobert               __is_iota_specialization<_RawRange>)
285*4bdff4beSrobert   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
286*4bdff4beSrobert   constexpr auto operator()(_Range&& __rng, _Np&& __n) const
287*4bdff4beSrobert     noexcept(noexcept(ranges::iota_view(
288*4bdff4beSrobert                               *ranges::begin(__rng),
289*4bdff4beSrobert                               *ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n))
290*4bdff4beSrobert                               )))
291*4bdff4beSrobert     -> decltype(      ranges::iota_view(
292*4bdff4beSrobert                               // Note: deliberately not forwarding `__rng` to guard against double moves.
293*4bdff4beSrobert                               *ranges::begin(__rng),
294*4bdff4beSrobert                               *ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n))
295*4bdff4beSrobert                               ))
296*4bdff4beSrobert     { return          ranges::iota_view(
297*4bdff4beSrobert                               *ranges::begin(__rng),
298*4bdff4beSrobert                               *ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n))
299*4bdff4beSrobert                               ); }
300*4bdff4beSrobert 
301*4bdff4beSrobert   // [range.take.overview]: the "otherwise" case.
302*4bdff4beSrobert   template <class _Range, convertible_to<range_difference_t<_Range>> _Np,
303*4bdff4beSrobert             class _RawRange = remove_cvref_t<_Range>>
304*4bdff4beSrobert     // Note: without specifically excluding the other cases, GCC sees this overload as ambiguous with the other
305*4bdff4beSrobert     // overloads.
306*4bdff4beSrobert     requires (!(__is_empty_view<_RawRange> ||
307*4bdff4beSrobert                (__is_iota_specialization<_RawRange> &&
308*4bdff4beSrobert                 sized_range<_RawRange> &&
309*4bdff4beSrobert                 random_access_range<_RawRange>) ||
310*4bdff4beSrobert                (__is_passthrough_specialization<_RawRange> &&
311*4bdff4beSrobert                 sized_range<_RawRange> &&
312*4bdff4beSrobert                 random_access_range<_RawRange>)
313*4bdff4beSrobert              ))
314*4bdff4beSrobert   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
315*4bdff4beSrobert   constexpr auto operator()(_Range&& __range, _Np&& __n) const
316*4bdff4beSrobert     noexcept(noexcept(take_view(std::forward<_Range>(__range), std::forward<_Np>(__n))))
317*4bdff4beSrobert     -> decltype(      take_view(std::forward<_Range>(__range), std::forward<_Np>(__n)))
318*4bdff4beSrobert     { return          take_view(std::forward<_Range>(__range), std::forward<_Np>(__n)); }
319*4bdff4beSrobert 
320*4bdff4beSrobert   template <class _Np>
321*4bdff4beSrobert     requires constructible_from<decay_t<_Np>, _Np>
322*4bdff4beSrobert   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
323*4bdff4beSrobert   constexpr auto operator()(_Np&& __n) const
324*4bdff4beSrobert     noexcept(is_nothrow_constructible_v<decay_t<_Np>, _Np>)
325*4bdff4beSrobert   { return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Np>(__n))); }
326*4bdff4beSrobert };
327*4bdff4beSrobert 
328*4bdff4beSrobert } // namespace __take
329*4bdff4beSrobert 
330*4bdff4beSrobert inline namespace __cpo {
331*4bdff4beSrobert   inline constexpr auto take = __take::__fn{};
332*4bdff4beSrobert } // namespace __cpo
333*4bdff4beSrobert } // namespace views
334*4bdff4beSrobert 
335*4bdff4beSrobert } // namespace ranges
336*4bdff4beSrobert 
337*4bdff4beSrobert #endif // _LIBCPP_STD_VER > 17
338*4bdff4beSrobert 
339*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD
340*4bdff4beSrobert 
341*4bdff4beSrobert _LIBCPP_POP_MACROS
342*4bdff4beSrobert 
343*4bdff4beSrobert #endif // _LIBCPP___RANGES_TAKE_VIEW_H
344