Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / include / __algorithm / ranges_ends_with.h
blob2afb74bff0f152639d2c4e2e7905f31bb825cb26
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___ALGORITHM_RANGES_ENDS_WITH_H
10 #define _LIBCPP___ALGORITHM_RANGES_ENDS_WITH_H
12 #include <__algorithm/ranges_equal.h>
13 #include <__algorithm/ranges_starts_with.h>
14 #include <__config>
15 #include <__functional/identity.h>
16 #include <__functional/ranges_operations.h>
17 #include <__functional/reference_wrapper.h>
18 #include <__iterator/advance.h>
19 #include <__iterator/concepts.h>
20 #include <__iterator/distance.h>
21 #include <__iterator/indirectly_comparable.h>
22 #include <__iterator/reverse_iterator.h>
23 #include <__ranges/access.h>
24 #include <__ranges/concepts.h>
25 #include <__utility/move.h>
27 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
28 # pragma GCC system_header
29 #endif
31 #if _LIBCPP_STD_VER >= 23
33 _LIBCPP_BEGIN_NAMESPACE_STD
35 namespace ranges {
36 namespace __ends_with {
37 struct __fn {
38 template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2>
39 static _LIBCPP_HIDE_FROM_ABI constexpr bool __ends_with_fn_impl_bidirectional(
40 _Iter1 __first1,
41 _Sent1 __last1,
42 _Iter2 __first2,
43 _Sent2 __last2,
44 _Pred& __pred,
45 _Proj1& __proj1,
46 _Proj2& __proj2) {
47 auto __rbegin1 = std::make_reverse_iterator(__last1);
48 auto __rend1 = std::make_reverse_iterator(__first1);
49 auto __rbegin2 = std::make_reverse_iterator(__last2);
50 auto __rend2 = std::make_reverse_iterator(__first2);
51 return ranges::starts_with(
52 __rbegin1, __rend1, __rbegin2, __rend2, std::ref(__pred), std::ref(__proj1), std::ref(__proj2));
55 template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2>
56 static _LIBCPP_HIDE_FROM_ABI constexpr bool __ends_with_fn_impl(
57 _Iter1 __first1,
58 _Sent1 __last1,
59 _Iter2 __first2,
60 _Sent2 __last2,
61 _Pred& __pred,
62 _Proj1& __proj1,
63 _Proj2& __proj2) {
64 if constexpr (std::bidirectional_iterator<_Sent1> && std::bidirectional_iterator<_Sent2> &&
65 (!std::random_access_iterator<_Sent1>)&&(!std::random_access_iterator<_Sent2>)) {
66 return __ends_with_fn_impl_bidirectional(__first1, __last1, __first2, __last2, __pred, __proj1, __proj2);
68 } else {
69 auto __n1 = ranges::distance(__first1, __last1);
70 auto __n2 = ranges::distance(__first2, __last2);
71 if (__n2 == 0)
72 return true;
73 if (__n2 > __n1)
74 return false;
76 return __ends_with_fn_impl_with_offset(
77 std::move(__first1),
78 std::move(__last1),
79 std::move(__first2),
80 std::move(__last2),
81 __pred,
82 __proj1,
83 __proj2,
84 __n1 - __n2);
88 template <class _Iter1,
89 class _Sent1,
90 class _Iter2,
91 class _Sent2,
92 class _Pred,
93 class _Proj1,
94 class _Proj2,
95 class _Offset>
96 static _LIBCPP_HIDE_FROM_ABI constexpr bool __ends_with_fn_impl_with_offset(
97 _Iter1 __first1,
98 _Sent1 __last1,
99 _Iter2 __first2,
100 _Sent2 __last2,
101 _Pred& __pred,
102 _Proj1& __proj1,
103 _Proj2& __proj2,
104 _Offset __offset) {
105 if constexpr (std::bidirectional_iterator<_Sent1> && std::bidirectional_iterator<_Sent2> &&
106 !std::random_access_iterator<_Sent1> && !std::random_access_iterator<_Sent2>) {
107 return __ends_with_fn_impl_bidirectional(
108 std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2);
110 } else {
111 ranges::advance(__first1, __offset);
112 return ranges::equal(
113 std::move(__first1),
114 std::move(__last1),
115 std::move(__first2),
116 std::move(__last2),
117 std::ref(__pred),
118 std::ref(__proj1),
119 std::ref(__proj2));
123 template <input_iterator _Iter1,
124 sentinel_for<_Iter1> _Sent1,
125 input_iterator _Iter2,
126 sentinel_for<_Iter2> _Sent2,
127 class _Pred = ranges::equal_to,
128 class _Proj1 = identity,
129 class _Proj2 = identity>
130 requires(forward_iterator<_Iter1> || sized_sentinel_for<_Sent1, _Iter1>) &&
131 (forward_iterator<_Iter2> || sized_sentinel_for<_Sent2, _Iter2>) &&
132 indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
133 _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(
134 _Iter1 __first1,
135 _Sent1 __last1,
136 _Iter2 __first2,
137 _Sent2 __last2,
138 _Pred __pred = {},
139 _Proj1 __proj1 = {},
140 _Proj2 __proj2 = {}) const {
141 return __ends_with_fn_impl(
142 std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2);
145 template <input_range _Range1,
146 input_range _Range2,
147 class _Pred = ranges::equal_to,
148 class _Proj1 = identity,
149 class _Proj2 = identity>
150 requires(forward_range<_Range1> || sized_range<_Range1>) && (forward_range<_Range2> || sized_range<_Range2>) &&
151 indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2>
152 _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(
153 _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const {
154 if constexpr (sized_range<_Range1> && sized_range<_Range2>) {
155 auto __n1 = ranges::size(__range1);
156 auto __n2 = ranges::size(__range2);
157 if (__n2 == 0)
158 return true;
159 if (__n2 > __n1)
160 return false;
161 auto __offset = __n1 - __n2;
163 return __ends_with_fn_impl_with_offset(
164 ranges::begin(__range1),
165 ranges::end(__range1),
166 ranges::begin(__range2),
167 ranges::end(__range2),
168 __pred,
169 __proj1,
170 __proj2,
171 __offset);
173 } else {
174 return __ends_with_fn_impl(
175 ranges::begin(__range1),
176 ranges::end(__range1),
177 ranges::begin(__range2),
178 ranges::end(__range2),
179 __pred,
180 __proj1,
181 __proj2);
185 } // namespace __ends_with
187 inline namespace __cpo {
188 inline constexpr auto ends_with = __ends_with::__fn{};
189 } // namespace __cpo
190 } // namespace ranges
192 _LIBCPP_END_NAMESPACE_STD
194 #endif // _LIBCPP_STD_VER >= 23
196 #endif // _LIBCPP___ALGORITHM_RANGES_ENDS_WITH_H