Path: blob/main/contrib/llvm-project/libcxx/include/__algorithm/find_end.h
35233 views
// -*- C++ -*-1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//89#ifndef _LIBCPP___ALGORITHM_FIND_END_OF_H10#define _LIBCPP___ALGORITHM_FIND_END_OF_H1112#include <__algorithm/comp.h>13#include <__algorithm/iterator_operations.h>14#include <__algorithm/search.h>15#include <__config>16#include <__functional/identity.h>17#include <__functional/invoke.h>18#include <__iterator/advance.h>19#include <__iterator/iterator_traits.h>20#include <__iterator/next.h>21#include <__iterator/reverse_iterator.h>22#include <__utility/pair.h>2324#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)25# pragma GCC system_header26#endif2728_LIBCPP_BEGIN_NAMESPACE_STD2930template < class _AlgPolicy,31class _Iter1,32class _Sent1,33class _Iter2,34class _Sent2,35class _Pred,36class _Proj1,37class _Proj2>38_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1> __find_end_impl(39_Iter1 __first1,40_Sent1 __last1,41_Iter2 __first2,42_Sent2 __last2,43_Pred& __pred,44_Proj1& __proj1,45_Proj2& __proj2,46forward_iterator_tag,47forward_iterator_tag) {48// modeled after search algorithm49_Iter1 __match_first = _IterOps<_AlgPolicy>::next(__first1, __last1); // __last1 is the "default" answer50_Iter1 __match_last = __match_first;51if (__first2 == __last2)52return pair<_Iter1, _Iter1>(__match_last, __match_last);53while (true) {54while (true) {55if (__first1 == __last1) // if source exhausted return last correct answer (or __last1 if never found)56return pair<_Iter1, _Iter1>(__match_first, __match_last);57if (std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2)))58break;59++__first1;60}61// *__first1 matches *__first2, now match elements after here62_Iter1 __m1 = __first1;63_Iter2 __m2 = __first2;64while (true) {65if (++__m2 == __last2) { // Pattern exhaused, record answer and search for another one66__match_first = __first1;67__match_last = ++__m1;68++__first1;69break;70}71if (++__m1 == __last1) // Source exhausted, return last answer72return pair<_Iter1, _Iter1>(__match_first, __match_last);73// mismatch, restart with a new __first74if (!std::__invoke(__pred, std::__invoke(__proj1, *__m1), std::__invoke(__proj2, *__m2))) {75++__first1;76break;77} // else there is a match, check next elements78}79}80}8182template < class _IterOps,83class _Pred,84class _Iter1,85class _Sent1,86class _Iter2,87class _Sent2,88class _Proj1,89class _Proj2>90_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter1 __find_end(91_Iter1 __first1,92_Sent1 __sent1,93_Iter2 __first2,94_Sent2 __sent2,95_Pred& __pred,96_Proj1& __proj1,97_Proj2& __proj2,98bidirectional_iterator_tag,99bidirectional_iterator_tag) {100auto __last1 = _IterOps::next(__first1, __sent1);101auto __last2 = _IterOps::next(__first2, __sent2);102// modeled after search algorithm (in reverse)103if (__first2 == __last2)104return __last1; // Everything matches an empty sequence105_Iter1 __l1 = __last1;106_Iter2 __l2 = __last2;107--__l2;108while (true) {109// Find last element in sequence 1 that matchs *(__last2-1), with a mininum of loop checks110while (true) {111if (__first1 == __l1) // return __last1 if no element matches *__first2112return __last1;113if (std::__invoke(__pred, std::__invoke(__proj1, *--__l1), std::__invoke(__proj2, *__l2)))114break;115}116// *__l1 matches *__l2, now match elements before here117_Iter1 __m1 = __l1;118_Iter2 __m2 = __l2;119while (true) {120if (__m2 == __first2) // If pattern exhausted, __m1 is the answer (works for 1 element pattern)121return __m1;122if (__m1 == __first1) // Otherwise if source exhaused, pattern not found123return __last1;124125// if there is a mismatch, restart with a new __l1126if (!std::__invoke(__pred, std::__invoke(__proj1, *--__m1), std::__invoke(__proj2, *--__m2))) {127break;128} // else there is a match, check next elements129}130}131}132133template < class _AlgPolicy,134class _Pred,135class _Iter1,136class _Sent1,137class _Iter2,138class _Sent2,139class _Proj1,140class _Proj2>141_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter1 __find_end(142_Iter1 __first1,143_Sent1 __sent1,144_Iter2 __first2,145_Sent2 __sent2,146_Pred& __pred,147_Proj1& __proj1,148_Proj2& __proj2,149random_access_iterator_tag,150random_access_iterator_tag) {151typedef typename iterator_traits<_Iter1>::difference_type _D1;152auto __last1 = _IterOps<_AlgPolicy>::next(__first1, __sent1);153auto __last2 = _IterOps<_AlgPolicy>::next(__first2, __sent2);154// Take advantage of knowing source and pattern lengths. Stop short when source is smaller than pattern155auto __len2 = __last2 - __first2;156if (__len2 == 0)157return __last1;158auto __len1 = __last1 - __first1;159if (__len1 < __len2)160return __last1;161const _Iter1 __s = __first1 + _D1(__len2 - 1); // End of pattern match can't go before here162_Iter1 __l1 = __last1;163_Iter2 __l2 = __last2;164--__l2;165while (true) {166while (true) {167if (__s == __l1)168return __last1;169if (std::__invoke(__pred, std::__invoke(__proj1, *--__l1), std::__invoke(__proj2, *__l2)))170break;171}172_Iter1 __m1 = __l1;173_Iter2 __m2 = __l2;174while (true) {175if (__m2 == __first2)176return __m1;177// no need to check range on __m1 because __s guarantees we have enough source178if (!std::__invoke(__pred, std::__invoke(__proj1, *--__m1), std::__invoke(*--__m2))) {179break;180}181}182}183}184185template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>186_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 __find_end_classic(187_ForwardIterator1 __first1,188_ForwardIterator1 __last1,189_ForwardIterator2 __first2,190_ForwardIterator2 __last2,191_BinaryPredicate& __pred) {192auto __proj = __identity();193return std::__find_end_impl<_ClassicAlgPolicy>(194__first1,195__last1,196__first2,197__last2,198__pred,199__proj,200__proj,201typename iterator_traits<_ForwardIterator1>::iterator_category(),202typename iterator_traits<_ForwardIterator2>::iterator_category())203.first;204}205206template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>207_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_end(208_ForwardIterator1 __first1,209_ForwardIterator1 __last1,210_ForwardIterator2 __first2,211_ForwardIterator2 __last2,212_BinaryPredicate __pred) {213return std::__find_end_classic(__first1, __last1, __first2, __last2, __pred);214}215216template <class _ForwardIterator1, class _ForwardIterator2>217_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1218find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) {219return std::find_end(__first1, __last1, __first2, __last2, __equal_to());220}221222_LIBCPP_END_NAMESPACE_STD223224#endif // _LIBCPP___ALGORITHM_FIND_END_OF_H225226227