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 //===----------------------------------------------------------------------===// 8 9 #ifndef _LIBCPP___ALGORITHM_RANGES_ENDS_WITH_H 10 #define _LIBCPP___ALGORITHM_RANGES_ENDS_WITH_H 11 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> 26 27 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 28 # pragma GCC system_header 29 #endif 30 31 _LIBCPP_PUSH_MACROS 32 #include <__undef_macros> 33 34 #if _LIBCPP_STD_VER >= 23 35 36 _LIBCPP_BEGIN_NAMESPACE_STD 37 38 namespace ranges { 39 namespace __ends_with { 40 struct __fn { 41 template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2> __ends_with_fn_impl_bidirectional__fn42 _LIBCPP_HIDE_FROM_ABI static constexpr bool __ends_with_fn_impl_bidirectional( 43 _Iter1 __first1, 44 _Sent1 __last1, 45 _Iter2 __first2, 46 _Sent2 __last2, 47 _Pred& __pred, 48 _Proj1& __proj1, 49 _Proj2& __proj2) { 50 auto __rbegin1 = std::make_reverse_iterator(__last1); 51 auto __rend1 = std::make_reverse_iterator(__first1); 52 auto __rbegin2 = std::make_reverse_iterator(__last2); 53 auto __rend2 = std::make_reverse_iterator(__first2); 54 return ranges::starts_with( 55 __rbegin1, __rend1, __rbegin2, __rend2, std::ref(__pred), std::ref(__proj1), std::ref(__proj2)); 56 } 57 58 template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2> __ends_with_fn_impl__fn59 _LIBCPP_HIDE_FROM_ABI static constexpr bool __ends_with_fn_impl( 60 _Iter1 __first1, 61 _Sent1 __last1, 62 _Iter2 __first2, 63 _Sent2 __last2, 64 _Pred& __pred, 65 _Proj1& __proj1, 66 _Proj2& __proj2) { 67 if constexpr (std::bidirectional_iterator<_Sent1> && std::bidirectional_iterator<_Sent2> && 68 (!std::random_access_iterator<_Sent1>) && (!std::random_access_iterator<_Sent2>)) { 69 return __ends_with_fn_impl_bidirectional(__first1, __last1, __first2, __last2, __pred, __proj1, __proj2); 70 71 } else { 72 auto __n1 = ranges::distance(__first1, __last1); 73 auto __n2 = ranges::distance(__first2, __last2); 74 if (__n2 == 0) 75 return true; 76 if (__n2 > __n1) 77 return false; 78 79 return __ends_with_fn_impl_with_offset( 80 std::move(__first1), 81 std::move(__last1), 82 std::move(__first2), 83 std::move(__last2), 84 __pred, 85 __proj1, 86 __proj2, 87 __n1 - __n2); 88 } 89 } 90 91 template <class _Iter1, 92 class _Sent1, 93 class _Iter2, 94 class _Sent2, 95 class _Pred, 96 class _Proj1, 97 class _Proj2, 98 class _Offset> __ends_with_fn_impl_with_offset__fn99 static _LIBCPP_HIDE_FROM_ABI constexpr bool __ends_with_fn_impl_with_offset( 100 _Iter1 __first1, 101 _Sent1 __last1, 102 _Iter2 __first2, 103 _Sent2 __last2, 104 _Pred& __pred, 105 _Proj1& __proj1, 106 _Proj2& __proj2, 107 _Offset __offset) { 108 if constexpr (std::bidirectional_iterator<_Sent1> && std::bidirectional_iterator<_Sent2> && 109 !std::random_access_iterator<_Sent1> && !std::random_access_iterator<_Sent2>) { 110 return __ends_with_fn_impl_bidirectional( 111 std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2); 112 113 } else { 114 ranges::advance(__first1, __offset); 115 return ranges::equal( 116 std::move(__first1), 117 std::move(__last1), 118 std::move(__first2), 119 std::move(__last2), 120 std::ref(__pred), 121 std::ref(__proj1), 122 std::ref(__proj2)); 123 } 124 } 125 126 template <input_iterator _Iter1, 127 sentinel_for<_Iter1> _Sent1, 128 input_iterator _Iter2, 129 sentinel_for<_Iter2> _Sent2, 130 class _Pred = ranges::equal_to, 131 class _Proj1 = identity, 132 class _Proj2 = identity> 133 requires(forward_iterator<_Iter1> || sized_sentinel_for<_Sent1, _Iter1>) && 134 (forward_iterator<_Iter2> || sized_sentinel_for<_Sent2, _Iter2>) && 135 indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> operator__fn136 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( 137 _Iter1 __first1, 138 _Sent1 __last1, 139 _Iter2 __first2, 140 _Sent2 __last2, 141 _Pred __pred = {}, 142 _Proj1 __proj1 = {}, 143 _Proj2 __proj2 = {}) const { 144 return __ends_with_fn_impl( 145 std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2); 146 } 147 148 template <input_range _Range1, 149 input_range _Range2, 150 class _Pred = ranges::equal_to, 151 class _Proj1 = identity, 152 class _Proj2 = identity> 153 requires(forward_range<_Range1> || sized_range<_Range1>) && (forward_range<_Range2> || sized_range<_Range2>) && 154 indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> operator__fn155 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( 156 _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { 157 if constexpr (sized_range<_Range1> && sized_range<_Range2>) { 158 auto __n1 = ranges::size(__range1); 159 auto __n2 = ranges::size(__range2); 160 if (__n2 == 0) 161 return true; 162 if (__n2 > __n1) 163 return false; 164 auto __offset = __n1 - __n2; 165 166 return __ends_with_fn_impl_with_offset( 167 ranges::begin(__range1), 168 ranges::end(__range1), 169 ranges::begin(__range2), 170 ranges::end(__range2), 171 __pred, 172 __proj1, 173 __proj2, 174 __offset); 175 176 } else { 177 return __ends_with_fn_impl( 178 ranges::begin(__range1), 179 ranges::end(__range1), 180 ranges::begin(__range2), 181 ranges::end(__range2), 182 __pred, 183 __proj1, 184 __proj2); 185 } 186 } 187 }; 188 } // namespace __ends_with 189 190 inline namespace __cpo { 191 inline constexpr auto ends_with = __ends_with::__fn{}; 192 } // namespace __cpo 193 } // namespace ranges 194 195 _LIBCPP_END_NAMESPACE_STD 196 197 #endif // _LIBCPP_STD_VER >= 23 198 199 _LIBCPP_POP_MACROS 200 201 #endif // _LIBCPP___ALGORITHM_RANGES_ENDS_WITH_H 202