1111#define _LIBCPP___ALGORITHM_SEARCH_N_H
1212
1313#include < __algorithm/comp.h>
14+ #include < __algorithm/find.h>
1415#include < __algorithm/iterator_operations.h>
16+ #include < __algorithm/unwrap_iter.h>
1517#include < __config>
1618#include < __functional/identity.h>
1719#include < __iterator/advance.h>
@@ -68,43 +70,35 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter, _Iter> __search_
6870 }
6971}
7072
71- template <class _AlgPolicy , class _Pred , class _Iter , class _Sent , class _SizeT , class _Type , class _Proj , class _DiffT >
73+ template <class _AlgPolicy , class _Pred , class _Iter , class _SizeT , class _Type , class _Proj , class _DiffT >
7274_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 std::pair<_Iter, _Iter> __search_n_random_access_impl (
73- _Iter __first, _Sent __last, _SizeT __count, const _Type& __value, _Pred& __pred, _Proj& __proj, _DiffT __size1) {
74- using difference_type = typename iterator_traits<_Iter>::difference_type;
75+ _Iter __first, _SizeT __count_in, const _Type& __value, _Pred& __pred, _Proj& __proj, _DiffT __size) {
76+ auto __last = __first + __size;
77+ auto __count = static_cast <_DiffT>(__count_in);
78+
7579 if (__count == 0 )
7680 return std::make_pair (__first, __first);
77- if (__size1 < static_cast <_DiffT>(__count)) {
78- _IterOps<_AlgPolicy>::__advance_to (__first, __last);
79- return std::make_pair (__first, __first);
80- }
81+ if (__size < __count)
82+ return std::make_pair (__last, __last);
8183
82- const auto __s = __first + __size1 - difference_type (__count - 1 ); // Start of pattern match can't go beyond here
84+ _Iter __try_match_until = __last - __count;
85+ _Iter __match_start = __first;
86+ _Iter __matched_until = __first;
8387 while (true ) {
84- // Find first element in sequence that matchs __value, with a mininum of loop checks
85- while (true ) {
86- if (__first >= __s) { // return __last if no element matches __value
87- _IterOps<_AlgPolicy>::__advance_to (__first, __last);
88- return std::make_pair (__first, __first);
89- }
90- if (std::__invoke (__pred, std::__invoke (__proj, *__first), __value))
91- break ;
92- ++__first;
93- }
94- // *__first matches __value_, now match elements after here
95- auto __m = __first;
96- _SizeT __c (0 );
88+ if (__match_start > __try_match_until)
89+ return std::make_pair (__last, __last);
90+
91+ _Iter __check = __match_start + __count;
92+
9793 while (true ) {
98- if (++__c == __count) // If pattern exhausted, __first is the answer (works for 1 element pattern)
99- return std::make_pair (__first, __first + _DiffT (__count));
100- ++__m; // no need to check range on __m because __s guarantees we have enough source
94+ if (__check == __matched_until)
95+ return std::make_pair (__match_start, __match_start + __count);
10196
102- // if there is a mismatch, restart with a new __first
103- if (!std::__invoke (__pred, std::__invoke (__proj, *__m), __value)) {
104- __first = __m;
105- ++__first;
97+ if (!std::__invoke (__pred, std::__invoke (__proj, *--__check), __value)) {
98+ __matched_until = __match_start + __count;
99+ __match_start = ++__check;
106100 break ;
107- } // else there is a match, check next elements
101+ }
108102 }
109103 }
110104}
@@ -119,7 +113,7 @@ template <class _Iter,
119113_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter, _Iter>
120114__search_n_impl (_Iter __first, _Sent __last, _DiffT __count, const _Type& __value, _Pred& __pred, _Proj& __proj) {
121115 return std::__search_n_random_access_impl<_ClassicAlgPolicy>(
122- __first, __last, __count, __value, __pred, __proj, __last - __first);
116+ __first, __count, __value, __pred, __proj, __last - __first);
123117}
124118
125119template <class _Iter1 ,
@@ -142,7 +136,16 @@ template <class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate
142136 static_assert (
143137 __is_callable<_BinaryPredicate&, decltype (*__first), const _Tp&>::value, " The comparator has to be callable" );
144138 auto __proj = __identity ();
145- return std::__search_n_impl (__first, __last, std::__convert_to_integral (__count), __value, __pred, __proj).first ;
139+ return std::__rewrap_iter (
140+ __first,
141+ std::__search_n_impl (
142+ std::__unwrap_iter (__first),
143+ std::__unwrap_iter (__last),
144+ std::__convert_to_integral (__count),
145+ __value,
146+ __pred,
147+ __proj)
148+ .first );
146149}
147150
148151template <class _ForwardIterator , class _Size , class _Tp >
0 commit comments