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