1 | // -*- C++ -*- |
2 | //===----------------------------------------------------------------------===// |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef _LIBCPP___RANGES_ISTREAM_VIEW_H |
11 | #define _LIBCPP___RANGES_ISTREAM_VIEW_H |
12 | |
13 | #include <__concepts/constructible.h> |
14 | #include <__concepts/derived_from.h> |
15 | #include <__concepts/movable.h> |
16 | #include <__config> |
17 | #include <__fwd/istream.h> |
18 | #include <__fwd/string.h> |
19 | #include <__iterator/default_sentinel.h> |
20 | #include <__iterator/iterator_traits.h> |
21 | #include <__memory/addressof.h> |
22 | #include <__ranges/view_interface.h> |
23 | #include <__type_traits/remove_cvref.h> |
24 | #include <__utility/forward.h> |
25 | #include <cstddef> |
26 | |
27 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
28 | # pragma GCC system_header |
29 | #endif |
30 | |
31 | #if _LIBCPP_STD_VER >= 20 |
32 | |
33 | _LIBCPP_BEGIN_NAMESPACE_STD |
34 | |
35 | namespace ranges { |
36 | |
37 | template <class _Val, class _CharT, class _Traits> |
38 | concept __stream_extractable = requires(basic_istream<_CharT, _Traits>& __is, _Val& __t) { __is >> __t; }; |
39 | |
40 | template <movable _Val, class _CharT, class _Traits = char_traits<_CharT>> |
41 | requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits> |
42 | class basic_istream_view : public view_interface<basic_istream_view<_Val, _CharT, _Traits>> { |
43 | class __iterator; |
44 | |
45 | public: |
46 | _LIBCPP_HIDE_FROM_ABI constexpr explicit basic_istream_view(basic_istream<_CharT, _Traits>& __stream) |
47 | : __stream_(std::addressof(__stream)) {} |
48 | |
49 | _LIBCPP_HIDE_FROM_ABI constexpr auto begin() { |
50 | *__stream_ >> __value_; |
51 | return __iterator{*this}; |
52 | } |
53 | |
54 | _LIBCPP_HIDE_FROM_ABI constexpr default_sentinel_t end() const noexcept { return default_sentinel; } |
55 | |
56 | private: |
57 | basic_istream<_CharT, _Traits>* __stream_; |
58 | _LIBCPP_NO_UNIQUE_ADDRESS _Val __value_ = _Val(); |
59 | }; |
60 | |
61 | template <movable _Val, class _CharT, class _Traits> |
62 | requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits> |
63 | class basic_istream_view<_Val, _CharT, _Traits>::__iterator { |
64 | public: |
65 | using iterator_concept = input_iterator_tag; |
66 | using difference_type = ptrdiff_t; |
67 | using value_type = _Val; |
68 | |
69 | _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(basic_istream_view<_Val, _CharT, _Traits>& __parent) noexcept |
70 | : __parent_(std::addressof(__parent)) {} |
71 | |
72 | __iterator(const __iterator&) = delete; |
73 | _LIBCPP_HIDE_FROM_ABI __iterator(__iterator&&) = default; |
74 | |
75 | __iterator& operator=(const __iterator&) = delete; |
76 | _LIBCPP_HIDE_FROM_ABI __iterator& operator=(__iterator&&) = default; |
77 | |
78 | _LIBCPP_HIDE_FROM_ABI __iterator& operator++() { |
79 | *__parent_->__stream_ >> __parent_->__value_; |
80 | return *this; |
81 | } |
82 | |
83 | _LIBCPP_HIDE_FROM_ABI void operator++(int) { ++*this; } |
84 | |
85 | _LIBCPP_HIDE_FROM_ABI _Val& operator*() const { return __parent_->__value_; } |
86 | |
87 | _LIBCPP_HIDE_FROM_ABI friend bool operator==(const __iterator& __x, default_sentinel_t) { |
88 | return !*__x.__get_parent_stream(); |
89 | } |
90 | |
91 | private: |
92 | basic_istream_view<_Val, _CharT, _Traits>* __parent_; |
93 | |
94 | _LIBCPP_HIDE_FROM_ABI constexpr basic_istream<_CharT, _Traits>* __get_parent_stream() const { |
95 | return __parent_->__stream_; |
96 | } |
97 | }; |
98 | |
99 | template <class _Val> |
100 | using istream_view = basic_istream_view<_Val, char>; |
101 | |
102 | # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS |
103 | template <class _Val> |
104 | using wistream_view = basic_istream_view<_Val, wchar_t>; |
105 | # endif |
106 | |
107 | namespace views { |
108 | namespace __istream { |
109 | |
110 | // clang-format off |
111 | template <class _Tp> |
112 | struct __fn { |
113 | template <class _Up, class _UnCVRef = remove_cvref_t<_Up>> |
114 | requires derived_from<_UnCVRef, basic_istream<typename _UnCVRef::char_type, |
115 | typename _UnCVRef::traits_type>> |
116 | _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Up&& __u) const |
117 | noexcept(noexcept(basic_istream_view<_Tp, typename _UnCVRef::char_type, |
118 | typename _UnCVRef::traits_type>(std::forward<_Up>(__u)))) |
119 | -> decltype( basic_istream_view<_Tp, typename _UnCVRef::char_type, |
120 | typename _UnCVRef::traits_type>(std::forward<_Up>(__u))) |
121 | { return basic_istream_view<_Tp, typename _UnCVRef::char_type, |
122 | typename _UnCVRef::traits_type>(std::forward<_Up>(__u)); |
123 | } |
124 | }; |
125 | // clang-format on |
126 | |
127 | } // namespace __istream |
128 | |
129 | inline namespace __cpo { |
130 | template <class _Tp> |
131 | inline constexpr auto istream = __istream::__fn<_Tp>{}; |
132 | } // namespace __cpo |
133 | } // namespace views |
134 | |
135 | } // namespace ranges |
136 | |
137 | _LIBCPP_END_NAMESPACE_STD |
138 | |
139 | #endif // _LIBCPP_STD_VER >= 20 |
140 | |
141 | #endif // _LIBCPP___RANGES_ISTREAM_VIEW_H |
142 | |