Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/libcxx/include/__algorithm/find_end.h
35233 views
1
// -*- C++ -*-
2
//===----------------------------------------------------------------------===//
3
//
4
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5
// See https://llvm.org/LICENSE.txt for license information.
6
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7
//
8
//===----------------------------------------------------------------------===//
9
10
#ifndef _LIBCPP___ALGORITHM_FIND_END_OF_H
11
#define _LIBCPP___ALGORITHM_FIND_END_OF_H
12
13
#include <__algorithm/comp.h>
14
#include <__algorithm/iterator_operations.h>
15
#include <__algorithm/search.h>
16
#include <__config>
17
#include <__functional/identity.h>
18
#include <__functional/invoke.h>
19
#include <__iterator/advance.h>
20
#include <__iterator/iterator_traits.h>
21
#include <__iterator/next.h>
22
#include <__iterator/reverse_iterator.h>
23
#include <__utility/pair.h>
24
25
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
26
# pragma GCC system_header
27
#endif
28
29
_LIBCPP_BEGIN_NAMESPACE_STD
30
31
template < class _AlgPolicy,
32
class _Iter1,
33
class _Sent1,
34
class _Iter2,
35
class _Sent2,
36
class _Pred,
37
class _Proj1,
38
class _Proj2>
39
_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1> __find_end_impl(
40
_Iter1 __first1,
41
_Sent1 __last1,
42
_Iter2 __first2,
43
_Sent2 __last2,
44
_Pred& __pred,
45
_Proj1& __proj1,
46
_Proj2& __proj2,
47
forward_iterator_tag,
48
forward_iterator_tag) {
49
// modeled after search algorithm
50
_Iter1 __match_first = _IterOps<_AlgPolicy>::next(__first1, __last1); // __last1 is the "default" answer
51
_Iter1 __match_last = __match_first;
52
if (__first2 == __last2)
53
return pair<_Iter1, _Iter1>(__match_last, __match_last);
54
while (true) {
55
while (true) {
56
if (__first1 == __last1) // if source exhausted return last correct answer (or __last1 if never found)
57
return pair<_Iter1, _Iter1>(__match_first, __match_last);
58
if (std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2)))
59
break;
60
++__first1;
61
}
62
// *__first1 matches *__first2, now match elements after here
63
_Iter1 __m1 = __first1;
64
_Iter2 __m2 = __first2;
65
while (true) {
66
if (++__m2 == __last2) { // Pattern exhaused, record answer and search for another one
67
__match_first = __first1;
68
__match_last = ++__m1;
69
++__first1;
70
break;
71
}
72
if (++__m1 == __last1) // Source exhausted, return last answer
73
return pair<_Iter1, _Iter1>(__match_first, __match_last);
74
// mismatch, restart with a new __first
75
if (!std::__invoke(__pred, std::__invoke(__proj1, *__m1), std::__invoke(__proj2, *__m2))) {
76
++__first1;
77
break;
78
} // else there is a match, check next elements
79
}
80
}
81
}
82
83
template < class _IterOps,
84
class _Pred,
85
class _Iter1,
86
class _Sent1,
87
class _Iter2,
88
class _Sent2,
89
class _Proj1,
90
class _Proj2>
91
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter1 __find_end(
92
_Iter1 __first1,
93
_Sent1 __sent1,
94
_Iter2 __first2,
95
_Sent2 __sent2,
96
_Pred& __pred,
97
_Proj1& __proj1,
98
_Proj2& __proj2,
99
bidirectional_iterator_tag,
100
bidirectional_iterator_tag) {
101
auto __last1 = _IterOps::next(__first1, __sent1);
102
auto __last2 = _IterOps::next(__first2, __sent2);
103
// modeled after search algorithm (in reverse)
104
if (__first2 == __last2)
105
return __last1; // Everything matches an empty sequence
106
_Iter1 __l1 = __last1;
107
_Iter2 __l2 = __last2;
108
--__l2;
109
while (true) {
110
// Find last element in sequence 1 that matchs *(__last2-1), with a mininum of loop checks
111
while (true) {
112
if (__first1 == __l1) // return __last1 if no element matches *__first2
113
return __last1;
114
if (std::__invoke(__pred, std::__invoke(__proj1, *--__l1), std::__invoke(__proj2, *__l2)))
115
break;
116
}
117
// *__l1 matches *__l2, now match elements before here
118
_Iter1 __m1 = __l1;
119
_Iter2 __m2 = __l2;
120
while (true) {
121
if (__m2 == __first2) // If pattern exhausted, __m1 is the answer (works for 1 element pattern)
122
return __m1;
123
if (__m1 == __first1) // Otherwise if source exhaused, pattern not found
124
return __last1;
125
126
// if there is a mismatch, restart with a new __l1
127
if (!std::__invoke(__pred, std::__invoke(__proj1, *--__m1), std::__invoke(__proj2, *--__m2))) {
128
break;
129
} // else there is a match, check next elements
130
}
131
}
132
}
133
134
template < class _AlgPolicy,
135
class _Pred,
136
class _Iter1,
137
class _Sent1,
138
class _Iter2,
139
class _Sent2,
140
class _Proj1,
141
class _Proj2>
142
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter1 __find_end(
143
_Iter1 __first1,
144
_Sent1 __sent1,
145
_Iter2 __first2,
146
_Sent2 __sent2,
147
_Pred& __pred,
148
_Proj1& __proj1,
149
_Proj2& __proj2,
150
random_access_iterator_tag,
151
random_access_iterator_tag) {
152
typedef typename iterator_traits<_Iter1>::difference_type _D1;
153
auto __last1 = _IterOps<_AlgPolicy>::next(__first1, __sent1);
154
auto __last2 = _IterOps<_AlgPolicy>::next(__first2, __sent2);
155
// Take advantage of knowing source and pattern lengths. Stop short when source is smaller than pattern
156
auto __len2 = __last2 - __first2;
157
if (__len2 == 0)
158
return __last1;
159
auto __len1 = __last1 - __first1;
160
if (__len1 < __len2)
161
return __last1;
162
const _Iter1 __s = __first1 + _D1(__len2 - 1); // End of pattern match can't go before here
163
_Iter1 __l1 = __last1;
164
_Iter2 __l2 = __last2;
165
--__l2;
166
while (true) {
167
while (true) {
168
if (__s == __l1)
169
return __last1;
170
if (std::__invoke(__pred, std::__invoke(__proj1, *--__l1), std::__invoke(__proj2, *__l2)))
171
break;
172
}
173
_Iter1 __m1 = __l1;
174
_Iter2 __m2 = __l2;
175
while (true) {
176
if (__m2 == __first2)
177
return __m1;
178
// no need to check range on __m1 because __s guarantees we have enough source
179
if (!std::__invoke(__pred, std::__invoke(__proj1, *--__m1), std::__invoke(*--__m2))) {
180
break;
181
}
182
}
183
}
184
}
185
186
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
187
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 __find_end_classic(
188
_ForwardIterator1 __first1,
189
_ForwardIterator1 __last1,
190
_ForwardIterator2 __first2,
191
_ForwardIterator2 __last2,
192
_BinaryPredicate& __pred) {
193
auto __proj = __identity();
194
return std::__find_end_impl<_ClassicAlgPolicy>(
195
__first1,
196
__last1,
197
__first2,
198
__last2,
199
__pred,
200
__proj,
201
__proj,
202
typename iterator_traits<_ForwardIterator1>::iterator_category(),
203
typename iterator_traits<_ForwardIterator2>::iterator_category())
204
.first;
205
}
206
207
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
208
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_end(
209
_ForwardIterator1 __first1,
210
_ForwardIterator1 __last1,
211
_ForwardIterator2 __first2,
212
_ForwardIterator2 __last2,
213
_BinaryPredicate __pred) {
214
return std::__find_end_classic(__first1, __last1, __first2, __last2, __pred);
215
}
216
217
template <class _ForwardIterator1, class _ForwardIterator2>
218
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1
219
find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) {
220
return std::find_end(__first1, __last1, __first2, __last2, __equal_to());
221
}
222
223
_LIBCPP_END_NAMESPACE_STD
224
225
#endif // _LIBCPP___ALGORITHM_FIND_END_OF_H
226
227