10218ea4aSZijun Zhao //===----------------------------------------------------------------------===// 20218ea4aSZijun Zhao // 30218ea4aSZijun Zhao // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40218ea4aSZijun Zhao // See https://llvm.org/LICENSE.txt for license information. 50218ea4aSZijun Zhao // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60218ea4aSZijun Zhao // 70218ea4aSZijun Zhao //===----------------------------------------------------------------------===// 80218ea4aSZijun Zhao 90218ea4aSZijun Zhao #ifndef _LIBCPP___ALGORITHM_RANGES_ENDS_WITH_H 100218ea4aSZijun Zhao #define _LIBCPP___ALGORITHM_RANGES_ENDS_WITH_H 110218ea4aSZijun Zhao 120218ea4aSZijun Zhao #include <__algorithm/ranges_equal.h> 130218ea4aSZijun Zhao #include <__algorithm/ranges_starts_with.h> 140218ea4aSZijun Zhao #include <__config> 150218ea4aSZijun Zhao #include <__functional/identity.h> 160218ea4aSZijun Zhao #include <__functional/ranges_operations.h> 170218ea4aSZijun Zhao #include <__functional/reference_wrapper.h> 180218ea4aSZijun Zhao #include <__iterator/advance.h> 190218ea4aSZijun Zhao #include <__iterator/concepts.h> 200218ea4aSZijun Zhao #include <__iterator/distance.h> 210218ea4aSZijun Zhao #include <__iterator/indirectly_comparable.h> 220218ea4aSZijun Zhao #include <__iterator/reverse_iterator.h> 230218ea4aSZijun Zhao #include <__ranges/access.h> 240218ea4aSZijun Zhao #include <__ranges/concepts.h> 25*09e3a360SLouis Dionne #include <__ranges/size.h> 260218ea4aSZijun Zhao #include <__utility/move.h> 270218ea4aSZijun Zhao 280218ea4aSZijun Zhao #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 290218ea4aSZijun Zhao # pragma GCC system_header 300218ea4aSZijun Zhao #endif 310218ea4aSZijun Zhao 327b462251SLouis Dionne _LIBCPP_PUSH_MACROS 337b462251SLouis Dionne #include <__undef_macros> 347b462251SLouis Dionne 350218ea4aSZijun Zhao #if _LIBCPP_STD_VER >= 23 360218ea4aSZijun Zhao 370218ea4aSZijun Zhao _LIBCPP_BEGIN_NAMESPACE_STD 380218ea4aSZijun Zhao 390218ea4aSZijun Zhao namespace ranges { 40d10dc5a0SChristopher Di Bella struct __ends_with { 410218ea4aSZijun Zhao template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2> 42c3747883SXiaoyang Liu _LIBCPP_HIDE_FROM_ABI static constexpr bool __ends_with_fn_impl_bidirectional( 430218ea4aSZijun Zhao _Iter1 __first1, 440218ea4aSZijun Zhao _Sent1 __last1, 450218ea4aSZijun Zhao _Iter2 __first2, 460218ea4aSZijun Zhao _Sent2 __last2, 470218ea4aSZijun Zhao _Pred& __pred, 480218ea4aSZijun Zhao _Proj1& __proj1, 490218ea4aSZijun Zhao _Proj2& __proj2) { 500218ea4aSZijun Zhao auto __rbegin1 = std::make_reverse_iterator(__last1); 510218ea4aSZijun Zhao auto __rend1 = std::make_reverse_iterator(__first1); 520218ea4aSZijun Zhao auto __rbegin2 = std::make_reverse_iterator(__last2); 530218ea4aSZijun Zhao auto __rend2 = std::make_reverse_iterator(__first2); 540218ea4aSZijun Zhao return ranges::starts_with( 550218ea4aSZijun Zhao __rbegin1, __rend1, __rbegin2, __rend2, std::ref(__pred), std::ref(__proj1), std::ref(__proj2)); 560218ea4aSZijun Zhao } 570218ea4aSZijun Zhao 580218ea4aSZijun Zhao template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2> 59c3747883SXiaoyang Liu _LIBCPP_HIDE_FROM_ABI static constexpr bool __ends_with_fn_impl( 600218ea4aSZijun Zhao _Iter1 __first1, 610218ea4aSZijun Zhao _Sent1 __last1, 620218ea4aSZijun Zhao _Iter2 __first2, 630218ea4aSZijun Zhao _Sent2 __last2, 640218ea4aSZijun Zhao _Pred& __pred, 650218ea4aSZijun Zhao _Proj1& __proj1, 660218ea4aSZijun Zhao _Proj2& __proj2) { 670218ea4aSZijun Zhao if constexpr (std::bidirectional_iterator<_Sent1> && std::bidirectional_iterator<_Sent2> && 680218ea4aSZijun Zhao (!std::random_access_iterator<_Sent1>) && (!std::random_access_iterator<_Sent2>)) { 690218ea4aSZijun Zhao return __ends_with_fn_impl_bidirectional(__first1, __last1, __first2, __last2, __pred, __proj1, __proj2); 700218ea4aSZijun Zhao 710218ea4aSZijun Zhao } else { 720218ea4aSZijun Zhao auto __n1 = ranges::distance(__first1, __last1); 730218ea4aSZijun Zhao auto __n2 = ranges::distance(__first2, __last2); 740218ea4aSZijun Zhao if (__n2 == 0) 750218ea4aSZijun Zhao return true; 760218ea4aSZijun Zhao if (__n2 > __n1) 770218ea4aSZijun Zhao return false; 780218ea4aSZijun Zhao 790218ea4aSZijun Zhao return __ends_with_fn_impl_with_offset( 800218ea4aSZijun Zhao std::move(__first1), 810218ea4aSZijun Zhao std::move(__last1), 820218ea4aSZijun Zhao std::move(__first2), 830218ea4aSZijun Zhao std::move(__last2), 840218ea4aSZijun Zhao __pred, 850218ea4aSZijun Zhao __proj1, 860218ea4aSZijun Zhao __proj2, 870218ea4aSZijun Zhao __n1 - __n2); 880218ea4aSZijun Zhao } 890218ea4aSZijun Zhao } 900218ea4aSZijun Zhao 910218ea4aSZijun Zhao template <class _Iter1, 920218ea4aSZijun Zhao class _Sent1, 930218ea4aSZijun Zhao class _Iter2, 940218ea4aSZijun Zhao class _Sent2, 950218ea4aSZijun Zhao class _Pred, 960218ea4aSZijun Zhao class _Proj1, 970218ea4aSZijun Zhao class _Proj2, 980218ea4aSZijun Zhao class _Offset> 990218ea4aSZijun Zhao static _LIBCPP_HIDE_FROM_ABI constexpr bool __ends_with_fn_impl_with_offset( 1000218ea4aSZijun Zhao _Iter1 __first1, 1010218ea4aSZijun Zhao _Sent1 __last1, 1020218ea4aSZijun Zhao _Iter2 __first2, 1030218ea4aSZijun Zhao _Sent2 __last2, 1040218ea4aSZijun Zhao _Pred& __pred, 1050218ea4aSZijun Zhao _Proj1& __proj1, 1060218ea4aSZijun Zhao _Proj2& __proj2, 1070218ea4aSZijun Zhao _Offset __offset) { 1080218ea4aSZijun Zhao if constexpr (std::bidirectional_iterator<_Sent1> && std::bidirectional_iterator<_Sent2> && 1090218ea4aSZijun Zhao !std::random_access_iterator<_Sent1> && !std::random_access_iterator<_Sent2>) { 1100218ea4aSZijun Zhao return __ends_with_fn_impl_bidirectional( 1110218ea4aSZijun Zhao std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2); 1120218ea4aSZijun Zhao 1130218ea4aSZijun Zhao } else { 1140218ea4aSZijun Zhao ranges::advance(__first1, __offset); 1150218ea4aSZijun Zhao return ranges::equal( 1160218ea4aSZijun Zhao std::move(__first1), 1170218ea4aSZijun Zhao std::move(__last1), 1180218ea4aSZijun Zhao std::move(__first2), 1190218ea4aSZijun Zhao std::move(__last2), 1200218ea4aSZijun Zhao std::ref(__pred), 1210218ea4aSZijun Zhao std::ref(__proj1), 1220218ea4aSZijun Zhao std::ref(__proj2)); 1230218ea4aSZijun Zhao } 1240218ea4aSZijun Zhao } 1250218ea4aSZijun Zhao 1260218ea4aSZijun Zhao template <input_iterator _Iter1, 1270218ea4aSZijun Zhao sentinel_for<_Iter1> _Sent1, 1280218ea4aSZijun Zhao input_iterator _Iter2, 1290218ea4aSZijun Zhao sentinel_for<_Iter2> _Sent2, 1300218ea4aSZijun Zhao class _Pred = ranges::equal_to, 1310218ea4aSZijun Zhao class _Proj1 = identity, 1320218ea4aSZijun Zhao class _Proj2 = identity> 1330218ea4aSZijun Zhao requires(forward_iterator<_Iter1> || sized_sentinel_for<_Sent1, _Iter1>) && 1340218ea4aSZijun Zhao (forward_iterator<_Iter2> || sized_sentinel_for<_Sent2, _Iter2>) && 1350218ea4aSZijun Zhao indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> 13683bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( 1370218ea4aSZijun Zhao _Iter1 __first1, 1380218ea4aSZijun Zhao _Sent1 __last1, 1390218ea4aSZijun Zhao _Iter2 __first2, 1400218ea4aSZijun Zhao _Sent2 __last2, 1410218ea4aSZijun Zhao _Pred __pred = {}, 1420218ea4aSZijun Zhao _Proj1 __proj1 = {}, 1430218ea4aSZijun Zhao _Proj2 __proj2 = {}) const { 1440218ea4aSZijun Zhao return __ends_with_fn_impl( 1450218ea4aSZijun Zhao std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2); 1460218ea4aSZijun Zhao } 1470218ea4aSZijun Zhao 1480218ea4aSZijun Zhao template <input_range _Range1, 1490218ea4aSZijun Zhao input_range _Range2, 1500218ea4aSZijun Zhao class _Pred = ranges::equal_to, 1510218ea4aSZijun Zhao class _Proj1 = identity, 1520218ea4aSZijun Zhao class _Proj2 = identity> 1530218ea4aSZijun Zhao requires(forward_range<_Range1> || sized_range<_Range1>) && (forward_range<_Range2> || sized_range<_Range2>) && 1540218ea4aSZijun Zhao indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> 15583bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( 1560218ea4aSZijun Zhao _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { 1570218ea4aSZijun Zhao if constexpr (sized_range<_Range1> && sized_range<_Range2>) { 1580218ea4aSZijun Zhao auto __n1 = ranges::size(__range1); 1590218ea4aSZijun Zhao auto __n2 = ranges::size(__range2); 1600218ea4aSZijun Zhao if (__n2 == 0) 1610218ea4aSZijun Zhao return true; 1620218ea4aSZijun Zhao if (__n2 > __n1) 1630218ea4aSZijun Zhao return false; 1640218ea4aSZijun Zhao auto __offset = __n1 - __n2; 1650218ea4aSZijun Zhao 1660218ea4aSZijun Zhao return __ends_with_fn_impl_with_offset( 1670218ea4aSZijun Zhao ranges::begin(__range1), 1680218ea4aSZijun Zhao ranges::end(__range1), 1690218ea4aSZijun Zhao ranges::begin(__range2), 1700218ea4aSZijun Zhao ranges::end(__range2), 1710218ea4aSZijun Zhao __pred, 1720218ea4aSZijun Zhao __proj1, 1730218ea4aSZijun Zhao __proj2, 1740218ea4aSZijun Zhao __offset); 1750218ea4aSZijun Zhao 1760218ea4aSZijun Zhao } else { 1770218ea4aSZijun Zhao return __ends_with_fn_impl( 1780218ea4aSZijun Zhao ranges::begin(__range1), 1790218ea4aSZijun Zhao ranges::end(__range1), 1800218ea4aSZijun Zhao ranges::begin(__range2), 1810218ea4aSZijun Zhao ranges::end(__range2), 1820218ea4aSZijun Zhao __pred, 1830218ea4aSZijun Zhao __proj1, 1840218ea4aSZijun Zhao __proj2); 1850218ea4aSZijun Zhao } 1860218ea4aSZijun Zhao } 1870218ea4aSZijun Zhao }; 1880218ea4aSZijun Zhao 1890218ea4aSZijun Zhao inline namespace __cpo { 190d10dc5a0SChristopher Di Bella inline constexpr auto ends_with = __ends_with{}; 1910218ea4aSZijun Zhao } // namespace __cpo 1920218ea4aSZijun Zhao } // namespace ranges 1930218ea4aSZijun Zhao 1940218ea4aSZijun Zhao _LIBCPP_END_NAMESPACE_STD 1950218ea4aSZijun Zhao 1960218ea4aSZijun Zhao #endif // _LIBCPP_STD_VER >= 23 1970218ea4aSZijun Zhao 1987b462251SLouis Dionne _LIBCPP_POP_MACROS 1997b462251SLouis Dionne 2000218ea4aSZijun Zhao #endif // _LIBCPP___ALGORITHM_RANGES_ENDS_WITH_H 201