201 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef _LIBCPP___ALGORITHM_RANGES_ENDS_WITH_H10#define _LIBCPP___ALGORITHM_RANGES_ENDS_WITH_H11 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 <__ranges/size.h>26#include <__utility/move.h>27 28#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)29# pragma GCC system_header30#endif31 32_LIBCPP_PUSH_MACROS33#include <__undef_macros>34 35#if _LIBCPP_STD_VER >= 2336 37_LIBCPP_BEGIN_NAMESPACE_STD38 39namespace ranges {40struct __ends_with {41 template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2>42 _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>59 _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>99 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>136 [[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>155 [[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 189inline namespace __cpo {190inline constexpr auto ends_with = __ends_with{};191} // namespace __cpo192} // namespace ranges193 194_LIBCPP_END_NAMESPACE_STD195 196#endif // _LIBCPP_STD_VER >= 23197 198_LIBCPP_POP_MACROS199 200#endif // _LIBCPP___ALGORITHM_RANGES_ENDS_WITH_H201