xref: /llvm-project/libcxx/include/__algorithm/ranges_ends_with.h (revision 09e3a360581dc36d0820d3fb6da9bd7cfed87b5d)
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