xref: /llvm-project/libcxx/include/__algorithm/find_end.h (revision b905bcc5090cde734e8b7bbceae13bd5a606cc14)
1134723edSLouis Dionne // -*- C++ -*-
2134723edSLouis Dionne //===----------------------------------------------------------------------===//
3134723edSLouis Dionne //
4134723edSLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5134723edSLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
6134723edSLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7134723edSLouis Dionne //
8134723edSLouis Dionne //===----------------------------------------------------------------------===//
9134723edSLouis Dionne 
10134723edSLouis Dionne #ifndef _LIBCPP___ALGORITHM_FIND_END_OF_H
11134723edSLouis Dionne #define _LIBCPP___ALGORITHM_FIND_END_OF_H
12134723edSLouis Dionne 
13134723edSLouis Dionne #include <__algorithm/comp.h>
14101d1e9bSNikolas Klauser #include <__algorithm/iterator_operations.h>
154d81a46fSArthur O'Dwyer #include <__config>
16101d1e9bSNikolas Klauser #include <__functional/identity.h>
17134723edSLouis Dionne #include <__iterator/iterator_traits.h>
18*09e3a360SLouis Dionne #include <__type_traits/invoke.h>
19101d1e9bSNikolas Klauser #include <__utility/pair.h>
20134723edSLouis Dionne 
21134723edSLouis Dionne #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22134723edSLouis Dionne #  pragma GCC system_header
23134723edSLouis Dionne #endif
24134723edSLouis Dionne 
25134723edSLouis Dionne _LIBCPP_BEGIN_NAMESPACE_STD
26134723edSLouis Dionne 
279783f28cSLouis Dionne template < class _AlgPolicy,
28101d1e9bSNikolas Klauser            class _Iter1,
29101d1e9bSNikolas Klauser            class _Sent1,
30101d1e9bSNikolas Klauser            class _Iter2,
31101d1e9bSNikolas Klauser            class _Sent2,
32101d1e9bSNikolas Klauser            class _Pred,
33101d1e9bSNikolas Klauser            class _Proj1,
34101d1e9bSNikolas Klauser            class _Proj2>
355146b57bSNikolas Klauser _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1> __find_end_impl(
36101d1e9bSNikolas Klauser     _Iter1 __first1,
37101d1e9bSNikolas Klauser     _Sent1 __last1,
38101d1e9bSNikolas Klauser     _Iter2 __first2,
39101d1e9bSNikolas Klauser     _Sent2 __last2,
40101d1e9bSNikolas Klauser     _Pred& __pred,
41101d1e9bSNikolas Klauser     _Proj1& __proj1,
42101d1e9bSNikolas Klauser     _Proj2& __proj2,
43101d1e9bSNikolas Klauser     forward_iterator_tag,
44134723edSLouis Dionne     forward_iterator_tag) {
45134723edSLouis Dionne   // modeled after search algorithm
46101d1e9bSNikolas Klauser   _Iter1 __match_first = _IterOps<_AlgPolicy>::next(__first1, __last1); // __last1 is the "default" answer
47101d1e9bSNikolas Klauser   _Iter1 __match_last  = __match_first;
48134723edSLouis Dionne   if (__first2 == __last2)
49101d1e9bSNikolas Klauser     return pair<_Iter1, _Iter1>(__match_last, __match_last);
50134723edSLouis Dionne   while (true) {
51134723edSLouis Dionne     while (true) {
52101d1e9bSNikolas Klauser       if (__first1 == __last1) // if source exhausted return last correct answer (or __last1 if never found)
53101d1e9bSNikolas Klauser         return pair<_Iter1, _Iter1>(__match_first, __match_last);
54101d1e9bSNikolas Klauser       if (std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2)))
55134723edSLouis Dionne         break;
56134723edSLouis Dionne       ++__first1;
57134723edSLouis Dionne     }
58134723edSLouis Dionne     // *__first1 matches *__first2, now match elements after here
59101d1e9bSNikolas Klauser     _Iter1 __m1 = __first1;
60101d1e9bSNikolas Klauser     _Iter2 __m2 = __first2;
61134723edSLouis Dionne     while (true) {
62134723edSLouis Dionne       if (++__m2 == __last2) { // Pattern exhaused, record answer and search for another one
63101d1e9bSNikolas Klauser         __match_first = __first1;
64101d1e9bSNikolas Klauser         __match_last  = ++__m1;
65134723edSLouis Dionne         ++__first1;
66134723edSLouis Dionne         break;
67134723edSLouis Dionne       }
68134723edSLouis Dionne       if (++__m1 == __last1) // Source exhausted, return last answer
69101d1e9bSNikolas Klauser         return pair<_Iter1, _Iter1>(__match_first, __match_last);
70101d1e9bSNikolas Klauser       // mismatch, restart with a new __first
719783f28cSLouis Dionne       if (!std::__invoke(__pred, std::__invoke(__proj1, *__m1), std::__invoke(__proj2, *__m2))) {
72134723edSLouis Dionne         ++__first1;
73134723edSLouis Dionne         break;
74134723edSLouis Dionne       } // else there is a match, check next elements
75134723edSLouis Dionne     }
76134723edSLouis Dionne   }
77134723edSLouis Dionne }
78134723edSLouis Dionne 
79134723edSLouis Dionne template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
8017e0686aSNikolas Klauser [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 __find_end_classic(
819783f28cSLouis Dionne     _ForwardIterator1 __first1,
829783f28cSLouis Dionne     _ForwardIterator1 __last1,
839783f28cSLouis Dionne     _ForwardIterator2 __first2,
849783f28cSLouis Dionne     _ForwardIterator2 __last2,
85101d1e9bSNikolas Klauser     _BinaryPredicate& __pred) {
86101d1e9bSNikolas Klauser   auto __proj = __identity();
87101d1e9bSNikolas Klauser   return std::__find_end_impl<_ClassicAlgPolicy>(
88101d1e9bSNikolas Klauser              __first1,
89101d1e9bSNikolas Klauser              __last1,
90101d1e9bSNikolas Klauser              __first2,
91101d1e9bSNikolas Klauser              __last2,
92101d1e9bSNikolas Klauser              __pred,
93101d1e9bSNikolas Klauser              __proj,
94101d1e9bSNikolas Klauser              __proj,
95101d1e9bSNikolas Klauser              typename iterator_traits<_ForwardIterator1>::iterator_category(),
96101d1e9bSNikolas Klauser              typename iterator_traits<_ForwardIterator2>::iterator_category())
97101d1e9bSNikolas Klauser       .first;
98101d1e9bSNikolas Klauser }
99101d1e9bSNikolas Klauser 
100101d1e9bSNikolas Klauser template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
10117e0686aSNikolas Klauser [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_end(
1029783f28cSLouis Dionne     _ForwardIterator1 __first1,
1039783f28cSLouis Dionne     _ForwardIterator1 __last1,
1049783f28cSLouis Dionne     _ForwardIterator2 __first2,
1059783f28cSLouis Dionne     _ForwardIterator2 __last2,
106134723edSLouis Dionne     _BinaryPredicate __pred) {
107101d1e9bSNikolas Klauser   return std::__find_end_classic(__first1, __last1, __first2, __last2, __pred);
108134723edSLouis Dionne }
109134723edSLouis Dionne 
110134723edSLouis Dionne template <class _ForwardIterator1, class _ForwardIterator2>
11117e0686aSNikolas Klauser [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1
1129783f28cSLouis Dionne find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) {
113e07ca2aeSAlvin Wong   return std::find_end(__first1, __last1, __first2, __last2, __equal_to());
114134723edSLouis Dionne }
115134723edSLouis Dionne 
116134723edSLouis Dionne _LIBCPP_END_NAMESPACE_STD
117134723edSLouis Dionne 
118134723edSLouis Dionne #endif // _LIBCPP___ALGORITHM_FIND_END_OF_H
119