15f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 25f757f3fSDimitry Andric // 35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f757f3fSDimitry Andric // 75f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 85f757f3fSDimitry Andric 95f757f3fSDimitry Andric #ifndef _LIBCPP___ALGORITHM_RANGES_ENDS_WITH_H 105f757f3fSDimitry Andric #define _LIBCPP___ALGORITHM_RANGES_ENDS_WITH_H 115f757f3fSDimitry Andric 125f757f3fSDimitry Andric #include <__algorithm/ranges_equal.h> 135f757f3fSDimitry Andric #include <__algorithm/ranges_starts_with.h> 145f757f3fSDimitry Andric #include <__config> 155f757f3fSDimitry Andric #include <__functional/identity.h> 165f757f3fSDimitry Andric #include <__functional/ranges_operations.h> 175f757f3fSDimitry Andric #include <__functional/reference_wrapper.h> 185f757f3fSDimitry Andric #include <__iterator/advance.h> 195f757f3fSDimitry Andric #include <__iterator/concepts.h> 205f757f3fSDimitry Andric #include <__iterator/distance.h> 215f757f3fSDimitry Andric #include <__iterator/indirectly_comparable.h> 225f757f3fSDimitry Andric #include <__iterator/reverse_iterator.h> 235f757f3fSDimitry Andric #include <__ranges/access.h> 245f757f3fSDimitry Andric #include <__ranges/concepts.h> 255f757f3fSDimitry Andric #include <__utility/move.h> 265f757f3fSDimitry Andric 275f757f3fSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 285f757f3fSDimitry Andric # pragma GCC system_header 295f757f3fSDimitry Andric #endif 305f757f3fSDimitry Andric 31*b3edf446SDimitry Andric _LIBCPP_PUSH_MACROS 32*b3edf446SDimitry Andric #include <__undef_macros> 33*b3edf446SDimitry Andric 345f757f3fSDimitry Andric #if _LIBCPP_STD_VER >= 23 355f757f3fSDimitry Andric 365f757f3fSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 375f757f3fSDimitry Andric 385f757f3fSDimitry Andric namespace ranges { 395f757f3fSDimitry Andric namespace __ends_with { 405f757f3fSDimitry Andric struct __fn { 415f757f3fSDimitry Andric template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2> __ends_with_fn_impl_bidirectional__fn425f757f3fSDimitry Andric static _LIBCPP_HIDE_FROM_ABI constexpr bool __ends_with_fn_impl_bidirectional( 435f757f3fSDimitry Andric _Iter1 __first1, 445f757f3fSDimitry Andric _Sent1 __last1, 455f757f3fSDimitry Andric _Iter2 __first2, 465f757f3fSDimitry Andric _Sent2 __last2, 475f757f3fSDimitry Andric _Pred& __pred, 485f757f3fSDimitry Andric _Proj1& __proj1, 495f757f3fSDimitry Andric _Proj2& __proj2) { 505f757f3fSDimitry Andric auto __rbegin1 = std::make_reverse_iterator(__last1); 515f757f3fSDimitry Andric auto __rend1 = std::make_reverse_iterator(__first1); 525f757f3fSDimitry Andric auto __rbegin2 = std::make_reverse_iterator(__last2); 535f757f3fSDimitry Andric auto __rend2 = std::make_reverse_iterator(__first2); 545f757f3fSDimitry Andric return ranges::starts_with( 555f757f3fSDimitry Andric __rbegin1, __rend1, __rbegin2, __rend2, std::ref(__pred), std::ref(__proj1), std::ref(__proj2)); 565f757f3fSDimitry Andric } 575f757f3fSDimitry Andric 585f757f3fSDimitry Andric template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2> __ends_with_fn_impl__fn595f757f3fSDimitry Andric static _LIBCPP_HIDE_FROM_ABI constexpr bool __ends_with_fn_impl( 605f757f3fSDimitry Andric _Iter1 __first1, 615f757f3fSDimitry Andric _Sent1 __last1, 625f757f3fSDimitry Andric _Iter2 __first2, 635f757f3fSDimitry Andric _Sent2 __last2, 645f757f3fSDimitry Andric _Pred& __pred, 655f757f3fSDimitry Andric _Proj1& __proj1, 665f757f3fSDimitry Andric _Proj2& __proj2) { 675f757f3fSDimitry Andric if constexpr (std::bidirectional_iterator<_Sent1> && std::bidirectional_iterator<_Sent2> && 685f757f3fSDimitry Andric (!std::random_access_iterator<_Sent1>)&&(!std::random_access_iterator<_Sent2>)) { 695f757f3fSDimitry Andric return __ends_with_fn_impl_bidirectional(__first1, __last1, __first2, __last2, __pred, __proj1, __proj2); 705f757f3fSDimitry Andric 715f757f3fSDimitry Andric } else { 725f757f3fSDimitry Andric auto __n1 = ranges::distance(__first1, __last1); 735f757f3fSDimitry Andric auto __n2 = ranges::distance(__first2, __last2); 745f757f3fSDimitry Andric if (__n2 == 0) 755f757f3fSDimitry Andric return true; 765f757f3fSDimitry Andric if (__n2 > __n1) 775f757f3fSDimitry Andric return false; 785f757f3fSDimitry Andric 795f757f3fSDimitry Andric return __ends_with_fn_impl_with_offset( 805f757f3fSDimitry Andric std::move(__first1), 815f757f3fSDimitry Andric std::move(__last1), 825f757f3fSDimitry Andric std::move(__first2), 835f757f3fSDimitry Andric std::move(__last2), 845f757f3fSDimitry Andric __pred, 855f757f3fSDimitry Andric __proj1, 865f757f3fSDimitry Andric __proj2, 875f757f3fSDimitry Andric __n1 - __n2); 885f757f3fSDimitry Andric } 895f757f3fSDimitry Andric } 905f757f3fSDimitry Andric 915f757f3fSDimitry Andric template <class _Iter1, 925f757f3fSDimitry Andric class _Sent1, 935f757f3fSDimitry Andric class _Iter2, 945f757f3fSDimitry Andric class _Sent2, 955f757f3fSDimitry Andric class _Pred, 965f757f3fSDimitry Andric class _Proj1, 975f757f3fSDimitry Andric class _Proj2, 985f757f3fSDimitry Andric class _Offset> __ends_with_fn_impl_with_offset__fn995f757f3fSDimitry Andric static _LIBCPP_HIDE_FROM_ABI constexpr bool __ends_with_fn_impl_with_offset( 1005f757f3fSDimitry Andric _Iter1 __first1, 1015f757f3fSDimitry Andric _Sent1 __last1, 1025f757f3fSDimitry Andric _Iter2 __first2, 1035f757f3fSDimitry Andric _Sent2 __last2, 1045f757f3fSDimitry Andric _Pred& __pred, 1055f757f3fSDimitry Andric _Proj1& __proj1, 1065f757f3fSDimitry Andric _Proj2& __proj2, 1075f757f3fSDimitry Andric _Offset __offset) { 1085f757f3fSDimitry Andric if constexpr (std::bidirectional_iterator<_Sent1> && std::bidirectional_iterator<_Sent2> && 1095f757f3fSDimitry Andric !std::random_access_iterator<_Sent1> && !std::random_access_iterator<_Sent2>) { 1105f757f3fSDimitry Andric return __ends_with_fn_impl_bidirectional( 1115f757f3fSDimitry Andric std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2); 1125f757f3fSDimitry Andric 1135f757f3fSDimitry Andric } else { 1145f757f3fSDimitry Andric ranges::advance(__first1, __offset); 1155f757f3fSDimitry Andric return ranges::equal( 1165f757f3fSDimitry Andric std::move(__first1), 1175f757f3fSDimitry Andric std::move(__last1), 1185f757f3fSDimitry Andric std::move(__first2), 1195f757f3fSDimitry Andric std::move(__last2), 1205f757f3fSDimitry Andric std::ref(__pred), 1215f757f3fSDimitry Andric std::ref(__proj1), 1225f757f3fSDimitry Andric std::ref(__proj2)); 1235f757f3fSDimitry Andric } 1245f757f3fSDimitry Andric } 1255f757f3fSDimitry Andric 1265f757f3fSDimitry Andric template <input_iterator _Iter1, 1275f757f3fSDimitry Andric sentinel_for<_Iter1> _Sent1, 1285f757f3fSDimitry Andric input_iterator _Iter2, 1295f757f3fSDimitry Andric sentinel_for<_Iter2> _Sent2, 1305f757f3fSDimitry Andric class _Pred = ranges::equal_to, 1315f757f3fSDimitry Andric class _Proj1 = identity, 1325f757f3fSDimitry Andric class _Proj2 = identity> 1335f757f3fSDimitry Andric requires(forward_iterator<_Iter1> || sized_sentinel_for<_Sent1, _Iter1>) && 1345f757f3fSDimitry Andric (forward_iterator<_Iter2> || sized_sentinel_for<_Sent2, _Iter2>) && 1355f757f3fSDimitry Andric indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> operator__fn1365f757f3fSDimitry Andric _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( 1375f757f3fSDimitry Andric _Iter1 __first1, 1385f757f3fSDimitry Andric _Sent1 __last1, 1395f757f3fSDimitry Andric _Iter2 __first2, 1405f757f3fSDimitry Andric _Sent2 __last2, 1415f757f3fSDimitry Andric _Pred __pred = {}, 1425f757f3fSDimitry Andric _Proj1 __proj1 = {}, 1435f757f3fSDimitry Andric _Proj2 __proj2 = {}) const { 1445f757f3fSDimitry Andric return __ends_with_fn_impl( 1455f757f3fSDimitry Andric std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2); 1465f757f3fSDimitry Andric } 1475f757f3fSDimitry Andric 1485f757f3fSDimitry Andric template <input_range _Range1, 1495f757f3fSDimitry Andric input_range _Range2, 1505f757f3fSDimitry Andric class _Pred = ranges::equal_to, 1515f757f3fSDimitry Andric class _Proj1 = identity, 1525f757f3fSDimitry Andric class _Proj2 = identity> 1535f757f3fSDimitry Andric requires(forward_range<_Range1> || sized_range<_Range1>) && (forward_range<_Range2> || sized_range<_Range2>) && 1545f757f3fSDimitry Andric indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> operator__fn1555f757f3fSDimitry Andric _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( 1565f757f3fSDimitry Andric _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { 1575f757f3fSDimitry Andric if constexpr (sized_range<_Range1> && sized_range<_Range2>) { 1585f757f3fSDimitry Andric auto __n1 = ranges::size(__range1); 1595f757f3fSDimitry Andric auto __n2 = ranges::size(__range2); 1605f757f3fSDimitry Andric if (__n2 == 0) 1615f757f3fSDimitry Andric return true; 1625f757f3fSDimitry Andric if (__n2 > __n1) 1635f757f3fSDimitry Andric return false; 1645f757f3fSDimitry Andric auto __offset = __n1 - __n2; 1655f757f3fSDimitry Andric 1665f757f3fSDimitry Andric return __ends_with_fn_impl_with_offset( 1675f757f3fSDimitry Andric ranges::begin(__range1), 1685f757f3fSDimitry Andric ranges::end(__range1), 1695f757f3fSDimitry Andric ranges::begin(__range2), 1705f757f3fSDimitry Andric ranges::end(__range2), 1715f757f3fSDimitry Andric __pred, 1725f757f3fSDimitry Andric __proj1, 1735f757f3fSDimitry Andric __proj2, 1745f757f3fSDimitry Andric __offset); 1755f757f3fSDimitry Andric 1765f757f3fSDimitry Andric } else { 1775f757f3fSDimitry Andric return __ends_with_fn_impl( 1785f757f3fSDimitry Andric ranges::begin(__range1), 1795f757f3fSDimitry Andric ranges::end(__range1), 1805f757f3fSDimitry Andric ranges::begin(__range2), 1815f757f3fSDimitry Andric ranges::end(__range2), 1825f757f3fSDimitry Andric __pred, 1835f757f3fSDimitry Andric __proj1, 1845f757f3fSDimitry Andric __proj2); 1855f757f3fSDimitry Andric } 1865f757f3fSDimitry Andric } 1875f757f3fSDimitry Andric }; 1885f757f3fSDimitry Andric } // namespace __ends_with 1895f757f3fSDimitry Andric 1905f757f3fSDimitry Andric inline namespace __cpo { 1915f757f3fSDimitry Andric inline constexpr auto ends_with = __ends_with::__fn{}; 1925f757f3fSDimitry Andric } // namespace __cpo 1935f757f3fSDimitry Andric } // namespace ranges 1945f757f3fSDimitry Andric 1955f757f3fSDimitry Andric _LIBCPP_END_NAMESPACE_STD 1965f757f3fSDimitry Andric 1975f757f3fSDimitry Andric #endif // _LIBCPP_STD_VER >= 23 1985f757f3fSDimitry Andric 199*b3edf446SDimitry Andric _LIBCPP_POP_MACROS 200*b3edf446SDimitry Andric 2015f757f3fSDimitry Andric #endif // _LIBCPP___ALGORITHM_RANGES_ENDS_WITH_H 202