blob: 9fb5bf91f753d1c0357e8b5e27caeec0cdf5e6d8 [file] [log] [blame]
Marshall Clow6e3be1c2015-07-20 16:39:28 +00001// -*- C++ -*-
Louis Dionne9bd93882021-11-17 16:25:01 -05002//===----------------------------------------------------------------------===//
Marshall Clow6e3be1c2015-07-20 16:39:28 +00003//
Chandler Carruthd2012102019-01-19 10:56:40 +00004// 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
Marshall Clow6e3be1c2015-07-20 16:39:28 +00007//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_EXPERIMENTAL_FUNCTIONAL
11#define _LIBCPP_EXPERIMENTAL_FUNCTIONAL
12
13/*
14 experimental/functional synopsis
15
16#include <algorithm>
17
18namespace std {
19namespace experimental {
20inline namespace fundamentals_v1 {
21
Marshall Clow7a0952b2015-09-08 17:59:09 +000022 // See C++14 20.9.9, Function object binders
Marshall Clow6e3be1c2015-07-20 16:39:28 +000023 template <class T> constexpr bool is_bind_expression_v
24 = is_bind_expression<T>::value;
25 template <class T> constexpr int is_placeholder_v
26 = is_placeholder<T>::value;
27
28 // 4.2, Class template function
29 template<class> class function; // undefined
30 template<class R, class... ArgTypes> class function<R(ArgTypes...)>;
31
32 template<class R, class... ArgTypes>
33 void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&);
34
35 template<class R, class... ArgTypes>
36 bool operator==(const function<R(ArgTypes...)>&, nullptr_t) noexcept;
37 template<class R, class... ArgTypes>
38 bool operator==(nullptr_t, const function<R(ArgTypes...)>&) noexcept;
39 template<class R, class... ArgTypes>
40 bool operator!=(const function<R(ArgTypes...)>&, nullptr_t) noexcept;
41 template<class R, class... ArgTypes>
42 bool operator!=(nullptr_t, const function<R(ArgTypes...)>&) noexcept;
43
44 // 4.3, Searchers
45 template<class ForwardIterator, class BinaryPredicate = equal_to<>>
46 class default_searcher;
47
48 template<class RandomAccessIterator,
49 class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
50 class BinaryPredicate = equal_to<>>
51 class boyer_moore_searcher;
52
53 template<class RandomAccessIterator,
54 class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
55 class BinaryPredicate = equal_to<>>
56 class boyer_moore_horspool_searcher;
57
58 template<class ForwardIterator, class BinaryPredicate = equal_to<>>
59 default_searcher<ForwardIterator, BinaryPredicate>
60 make_default_searcher(ForwardIterator pat_first, ForwardIterator pat_last,
61 BinaryPredicate pred = BinaryPredicate());
62
63 template<class RandomAccessIterator,
64 class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
65 class BinaryPredicate = equal_to<>>
66 boyer_moore_searcher<RandomAccessIterator, Hash, BinaryPredicate>
67 make_boyer_moore_searcher(
68 RandomAccessIterator pat_first, RandomAccessIterator pat_last,
69 Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
70
71 template<class RandomAccessIterator,
72 class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
73 class BinaryPredicate = equal_to<>>
74 boyer_moore_horspool_searcher<RandomAccessIterator, Hash, BinaryPredicate>
75 make_boyer_moore_horspool_searcher(
76 RandomAccessIterator pat_first, RandomAccessIterator pat_last,
77 Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
78
79 } // namespace fundamentals_v1
80 } // namespace experimental
81
82 template<class R, class... ArgTypes, class Alloc>
83 struct uses_allocator<experimental::function<R(ArgTypes...)>, Alloc>;
84
85} // namespace std
86
87*/
88
Arthur O'Dwyer65077c02022-01-07 09:45:05 -050089#include <__debug>
Christopher Di Bella55d7a822021-07-01 09:25:35 -040090#include <__memory/uses_allocator.h>
Arthur O'Dwyer65077c02022-01-07 09:45:05 -050091#include <algorithm>
92#include <array>
Marshall Clow6e3be1c2015-07-20 16:39:28 +000093#include <experimental/__config>
94#include <functional>
Marshall Clow7a0952b2015-09-08 17:59:09 +000095#include <type_traits>
Marshall Clow7a0952b2015-09-08 17:59:09 +000096#include <unordered_map>
Arthur O'Dwyer65077c02022-01-07 09:45:05 -050097#include <vector>
Marshall Clow6e3be1c2015-07-20 16:39:28 +000098
99#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Arthur O'Dwyer6eeaa002022-02-01 20:16:40 -0500100# pragma GCC system_header
Marshall Clow6e3be1c2015-07-20 16:39:28 +0000101#endif
102
Eric Fiselierf4433a32017-05-31 22:07:49 +0000103_LIBCPP_PUSH_MACROS
104#include <__undef_macros>
105
Marshall Clow6e3be1c2015-07-20 16:39:28 +0000106_LIBCPP_BEGIN_NAMESPACE_LFTS
107
Marshall Clow7a0952b2015-09-08 17:59:09 +0000108#if _LIBCPP_STD_VER > 11
Marshall Clow6e3be1c2015-07-20 16:39:28 +0000109// default searcher
110template<class _ForwardIterator, class _BinaryPredicate = equal_to<>>
Martin Storsjö4d6f2212021-04-06 10:55:33 +0300111class _LIBCPP_TEMPLATE_VIS default_searcher {
Marshall Clow6e3be1c2015-07-20 16:39:28 +0000112public:
Marshall Clow7a0952b2015-09-08 17:59:09 +0000113 _LIBCPP_INLINE_VISIBILITY
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700114 default_searcher(_ForwardIterator __f, _ForwardIterator __l,
Marshall Clow6e3be1c2015-07-20 16:39:28 +0000115 _BinaryPredicate __p = _BinaryPredicate())
116 : __first_(__f), __last_(__l), __pred_(__p) {}
117
118 template <typename _ForwardIterator2>
Marshall Clow7a0952b2015-09-08 17:59:09 +0000119 _LIBCPP_INLINE_VISIBILITY
Marshall Clowaf8be6c2016-03-08 15:12:52 +0000120 pair<_ForwardIterator2, _ForwardIterator2>
121 operator () (_ForwardIterator2 __f, _ForwardIterator2 __l) const
Marshall Clow7a0952b2015-09-08 17:59:09 +0000122 {
Marshall Clowaf8be6c2016-03-08 15:12:52 +0000123 return _VSTD::__search(__f, __l, __first_, __last_, __pred_,
Arthur O'Dwyerd8dddf52021-05-10 13:13:04 -0400124 typename iterator_traits<_ForwardIterator>::iterator_category(),
125 typename iterator_traits<_ForwardIterator2>::iterator_category());
Marshall Clow7a0952b2015-09-08 17:59:09 +0000126 }
Marshall Clow6e3be1c2015-07-20 16:39:28 +0000127
128private:
129 _ForwardIterator __first_;
130 _ForwardIterator __last_;
131 _BinaryPredicate __pred_;
132 };
133
134template<class _ForwardIterator, class _BinaryPredicate = equal_to<>>
Marshall Clow7a0952b2015-09-08 17:59:09 +0000135_LIBCPP_INLINE_VISIBILITY
Marshall Clow6e3be1c2015-07-20 16:39:28 +0000136default_searcher<_ForwardIterator, _BinaryPredicate>
137make_default_searcher( _ForwardIterator __f, _ForwardIterator __l, _BinaryPredicate __p = _BinaryPredicate ())
138{
139 return default_searcher<_ForwardIterator, _BinaryPredicate>(__f, __l, __p);
140}
141
Marshall Clow7a0952b2015-09-08 17:59:09 +0000142template<class _Key, class _Value, class _Hash, class _BinaryPredicate, bool /*useArray*/> class _BMSkipTable;
143
144// General case for BM data searching; use a map
145template<class _Key, typename _Value, class _Hash, class _BinaryPredicate>
146class _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, false> {
Marshall Clow7a0952b2015-09-08 17:59:09 +0000147 typedef _Value value_type;
148 typedef _Key key_type;
149
150 const _Value __default_value_;
151 std::unordered_map<_Key, _Value, _Hash, _BinaryPredicate> __table;
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700152
Marshall Clow7a0952b2015-09-08 17:59:09 +0000153public:
154 _LIBCPP_INLINE_VISIBILITY
Arthur O'Dwyer4f181dd2021-05-10 13:07:00 -0400155 _BMSkipTable(size_t __sz, _Value __default, _Hash __hf, _BinaryPredicate __pred)
Marshall Clow7a0952b2015-09-08 17:59:09 +0000156 : __default_value_(__default), __table(__sz, __hf, __pred) {}
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700157
Marshall Clow7a0952b2015-09-08 17:59:09 +0000158 _LIBCPP_INLINE_VISIBILITY
159 void insert(const key_type &__key, value_type __val)
160 {
161 __table [__key] = __val; // Would skip_.insert (val) be better here?
162 }
163
164 _LIBCPP_INLINE_VISIBILITY
165 value_type operator [](const key_type & __key) const
166 {
167 auto __it = __table.find (__key);
168 return __it == __table.end() ? __default_value_ : __it->second;
169 }
170};
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700171
Marshall Clow7a0952b2015-09-08 17:59:09 +0000172
173// Special case small numeric values; use an array
174template<class _Key, typename _Value, class _Hash, class _BinaryPredicate>
175class _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, true> {
176private:
177 typedef _Value value_type;
178 typedef _Key key_type;
179
Arthur O'Dwyer4f181dd2021-05-10 13:07:00 -0400180 typedef typename make_unsigned<key_type>::type unsigned_key_type;
181 typedef std::array<value_type, numeric_limits<unsigned_key_type>::max()> skip_map;
Marshall Clow7a0952b2015-09-08 17:59:09 +0000182 skip_map __table;
183
184public:
185 _LIBCPP_INLINE_VISIBILITY
Arthur O'Dwyer4f181dd2021-05-10 13:07:00 -0400186 _BMSkipTable(size_t /*__sz*/, _Value __default, _Hash /*__hf*/, _BinaryPredicate /*__pred*/)
Marshall Clow7a0952b2015-09-08 17:59:09 +0000187 {
188 std::fill_n(__table.begin(), __table.size(), __default);
189 }
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700190
Marshall Clow7a0952b2015-09-08 17:59:09 +0000191 _LIBCPP_INLINE_VISIBILITY
192 void insert(key_type __key, value_type __val)
193 {
194 __table[static_cast<unsigned_key_type>(__key)] = __val;
195 }
196
197 _LIBCPP_INLINE_VISIBILITY
198 value_type operator [](key_type __key) const
199 {
200 return __table[static_cast<unsigned_key_type>(__key)];
201 }
202};
203
204
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700205template <class _RandomAccessIterator1,
206 class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>,
Marshall Clow7a0952b2015-09-08 17:59:09 +0000207 class _BinaryPredicate = equal_to<>>
Martin Storsjö4d6f2212021-04-06 10:55:33 +0300208class _LIBCPP_TEMPLATE_VIS boyer_moore_searcher {
Marshall Clow7a0952b2015-09-08 17:59:09 +0000209private:
210 typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type difference_type;
211 typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type value_type;
212 typedef _BMSkipTable<value_type, difference_type, _Hash, _BinaryPredicate,
Arthur O'Dwyerd8dddf52021-05-10 13:13:04 -0400213 is_integral<value_type>::value && // what about enums?
Marshall Clow7a0952b2015-09-08 17:59:09 +0000214 sizeof(value_type) == 1 &&
215 is_same<_Hash, hash<value_type>>::value &&
216 is_same<_BinaryPredicate, equal_to<>>::value
217 > skip_table_type;
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700218
Marshall Clow7a0952b2015-09-08 17:59:09 +0000219public:
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700220 boyer_moore_searcher(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l,
Marshall Clow7a0952b2015-09-08 17:59:09 +0000221 _Hash __hf = _Hash(), _BinaryPredicate __pred = _BinaryPredicate())
222 : __first_(__f), __last_(__l), __pred_(__pred),
223 __pattern_length_(_VSTD::distance(__first_, __last_)),
224 __skip_{make_shared<skip_table_type>(__pattern_length_, -1, __hf, __pred_)},
225 __suffix_{make_shared<vector<difference_type>>(__pattern_length_ + 1)}
226 {
227 // build the skip table
228 for ( difference_type __i = 0; __f != __l; ++__f, (void) ++__i )
229 __skip_->insert(*__f, __i);
230
231 this->__build_suffix_table ( __first_, __last_, __pred_ );
232 }
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700233
Marshall Clow7a0952b2015-09-08 17:59:09 +0000234 template <typename _RandomAccessIterator2>
Marshall Clowaf8be6c2016-03-08 15:12:52 +0000235 pair<_RandomAccessIterator2, _RandomAccessIterator2>
Marshall Clow7a0952b2015-09-08 17:59:09 +0000236 operator ()(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const
237 {
238 static_assert ( std::is_same<
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700239 typename std::__uncvref<typename std::iterator_traits<_RandomAccessIterator1>::value_type>::type,
Marshall Clowe61ba952018-02-12 15:41:25 +0000240 typename std::__uncvref<typename std::iterator_traits<_RandomAccessIterator2>::value_type>::type
Marshall Clow7a0952b2015-09-08 17:59:09 +0000241 >::value,
242 "Corpus and Pattern iterators must point to the same type" );
243
Marshall Clowaf8be6c2016-03-08 15:12:52 +0000244 if (__f == __l ) return make_pair(__l, __l); // empty corpus
245 if (__first_ == __last_) return make_pair(__f, __f); // empty pattern
Marshall Clow7a0952b2015-09-08 17:59:09 +0000246
247 // If the pattern is larger than the corpus, we can't find it!
Arthur O'Dwyerd8dddf52021-05-10 13:13:04 -0400248 if ( __pattern_length_ > _VSTD::distance(__f, __l))
Marshall Clowaf8be6c2016-03-08 15:12:52 +0000249 return make_pair(__l, __l);
Marshall Clow7a0952b2015-09-08 17:59:09 +0000250
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700251 // Do the search
Marshall Clow7a0952b2015-09-08 17:59:09 +0000252 return this->__search(__f, __l);
253 }
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700254
Joe Loserb30f7d02022-02-06 19:47:45 -0500255private:
Marshall Clow7a0952b2015-09-08 17:59:09 +0000256 _RandomAccessIterator1 __first_;
257 _RandomAccessIterator1 __last_;
258 _BinaryPredicate __pred_;
259 difference_type __pattern_length_;
260 shared_ptr<skip_table_type> __skip_;
261 shared_ptr<vector<difference_type>> __suffix_;
262
263 template <typename _RandomAccessIterator2>
Marshall Clowaf8be6c2016-03-08 15:12:52 +0000264 pair<_RandomAccessIterator2, _RandomAccessIterator2>
265 __search(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const
Marshall Clow7a0952b2015-09-08 17:59:09 +0000266 {
267 _RandomAccessIterator2 __cur = __f;
268 const _RandomAccessIterator2 __last = __l - __pattern_length_;
269 const skip_table_type & __skip = *__skip_.get();
270 const vector<difference_type> & __suffix = *__suffix_.get();
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700271
Marshall Clow7a0952b2015-09-08 17:59:09 +0000272 while (__cur <= __last)
273 {
274
275 // Do we match right where we are?
276 difference_type __j = __pattern_length_;
277 while (__pred_(__first_ [__j-1], __cur [__j-1])) {
278 __j--;
279 // We matched - we're done!
280 if ( __j == 0 )
Marshall Clowaf8be6c2016-03-08 15:12:52 +0000281 return make_pair(__cur, __cur + __pattern_length_);
Marshall Clow7a0952b2015-09-08 17:59:09 +0000282 }
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700283
Marshall Clow7a0952b2015-09-08 17:59:09 +0000284 // Since we didn't match, figure out how far to skip forward
285 difference_type __k = __skip[__cur [ __j - 1 ]];
286 difference_type __m = __j - __k - 1;
287 if (__k < __j && __m > __suffix[ __j ])
288 __cur += __m;
289 else
290 __cur += __suffix[ __j ];
291 }
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700292
Marshall Clowaf8be6c2016-03-08 15:12:52 +0000293 return make_pair(__l, __l); // We didn't find anything
Marshall Clow7a0952b2015-09-08 17:59:09 +0000294 }
295
296
297 template<typename _Iterator, typename _Container>
298 void __compute_bm_prefix ( _Iterator __f, _Iterator __l, _BinaryPredicate __pred, _Container &__prefix )
299 {
Arthur O'Dwyer4f181dd2021-05-10 13:07:00 -0400300 const size_t __count = _VSTD::distance(__f, __l);
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700301
Marshall Clow7a0952b2015-09-08 17:59:09 +0000302 __prefix[0] = 0;
Arthur O'Dwyer4f181dd2021-05-10 13:07:00 -0400303 size_t __k = 0;
304 for ( size_t __i = 1; __i < __count; ++__i )
Marshall Clow7a0952b2015-09-08 17:59:09 +0000305 {
306 while ( __k > 0 && !__pred ( __f[__k], __f[__i] ))
307 __k = __prefix [ __k - 1 ];
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700308
Marshall Clow7a0952b2015-09-08 17:59:09 +0000309 if ( __pred ( __f[__k], __f[__i] ))
310 __k++;
311 __prefix [ __i ] = __k;
312 }
313 }
314
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700315 void __build_suffix_table(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l,
Marshall Clow7a0952b2015-09-08 17:59:09 +0000316 _BinaryPredicate __pred)
317 {
Arthur O'Dwyer4f181dd2021-05-10 13:07:00 -0400318 const size_t __count = _VSTD::distance(__f, __l);
Marshall Clow7a0952b2015-09-08 17:59:09 +0000319 vector<difference_type> & __suffix = *__suffix_.get();
320 if (__count > 0)
321 {
Arthur O'Dwyerd8dddf52021-05-10 13:13:04 -0400322 vector<value_type> __scratch(__count);
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700323
Marshall Clow7a0952b2015-09-08 17:59:09 +0000324 __compute_bm_prefix(__f, __l, __pred, __scratch);
Arthur O'Dwyer4f181dd2021-05-10 13:07:00 -0400325 for ( size_t __i = 0; __i <= __count; __i++ )
Marshall Clow7a0952b2015-09-08 17:59:09 +0000326 __suffix[__i] = __count - __scratch[__count-1];
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700327
Arthur O'Dwyerd8dddf52021-05-10 13:13:04 -0400328 typedef reverse_iterator<_RandomAccessIterator1> _RevIter;
Marshall Clow7a0952b2015-09-08 17:59:09 +0000329 __compute_bm_prefix(_RevIter(__l), _RevIter(__f), __pred, __scratch);
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700330
Arthur O'Dwyer4f181dd2021-05-10 13:07:00 -0400331 for ( size_t __i = 0; __i < __count; __i++ )
Marshall Clow7a0952b2015-09-08 17:59:09 +0000332 {
Arthur O'Dwyer4f181dd2021-05-10 13:07:00 -0400333 const size_t __j = __count - __scratch[__i];
Marshall Clow7a0952b2015-09-08 17:59:09 +0000334 const difference_type __k = __i - __scratch[__i] + 1;
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700335
Marshall Clow7a0952b2015-09-08 17:59:09 +0000336 if (__suffix[__j] > __k)
337 __suffix[__j] = __k;
338 }
339 }
340 }
341
342};
343
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700344template<class _RandomAccessIterator,
345 class _Hash = hash<typename iterator_traits<_RandomAccessIterator>::value_type>,
Marshall Clow7a0952b2015-09-08 17:59:09 +0000346 class _BinaryPredicate = equal_to<>>
347_LIBCPP_INLINE_VISIBILITY
348boyer_moore_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700349make_boyer_moore_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l,
Marshall Clow7a0952b2015-09-08 17:59:09 +0000350 _Hash __hf = _Hash(), _BinaryPredicate __p = _BinaryPredicate ())
351{
352 return boyer_moore_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>(__f, __l, __hf, __p);
353}
354
355// boyer-moore-horspool
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700356template <class _RandomAccessIterator1,
357 class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>,
Marshall Clow7a0952b2015-09-08 17:59:09 +0000358 class _BinaryPredicate = equal_to<>>
Martin Storsjö4d6f2212021-04-06 10:55:33 +0300359class _LIBCPP_TEMPLATE_VIS boyer_moore_horspool_searcher {
Marshall Clow7a0952b2015-09-08 17:59:09 +0000360private:
361 typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type difference_type;
362 typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type value_type;
363 typedef _BMSkipTable<value_type, difference_type, _Hash, _BinaryPredicate,
Arthur O'Dwyerd8dddf52021-05-10 13:13:04 -0400364 is_integral<value_type>::value && // what about enums?
Marshall Clow7a0952b2015-09-08 17:59:09 +0000365 sizeof(value_type) == 1 &&
366 is_same<_Hash, hash<value_type>>::value &&
367 is_same<_BinaryPredicate, equal_to<>>::value
368 > skip_table_type;
369
370public:
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700371 boyer_moore_horspool_searcher(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l,
Marshall Clow7a0952b2015-09-08 17:59:09 +0000372 _Hash __hf = _Hash(), _BinaryPredicate __pred = _BinaryPredicate())
373 : __first_(__f), __last_(__l), __pred_(__pred),
374 __pattern_length_(_VSTD::distance(__first_, __last_)),
375 __skip_{_VSTD::make_shared<skip_table_type>(__pattern_length_, __pattern_length_, __hf, __pred_)}
376 {
377 // build the skip table
378 if ( __f != __l )
379 {
380 __l = __l - 1;
381 for ( difference_type __i = 0; __f != __l; ++__f, (void) ++__i )
382 __skip_->insert(*__f, __pattern_length_ - 1 - __i);
383 }
384 }
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700385
Marshall Clowaf8be6c2016-03-08 15:12:52 +0000386 template <typename _RandomAccessIterator2>
387 pair<_RandomAccessIterator2, _RandomAccessIterator2>
Marshall Clow7a0952b2015-09-08 17:59:09 +0000388 operator ()(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const
389 {
390 static_assert ( std::is_same<
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700391 typename std::__uncvref<typename std::iterator_traits<_RandomAccessIterator1>::value_type>::type,
Marshall Clowe61ba952018-02-12 15:41:25 +0000392 typename std::__uncvref<typename std::iterator_traits<_RandomAccessIterator2>::value_type>::type
Marshall Clow7a0952b2015-09-08 17:59:09 +0000393 >::value,
394 "Corpus and Pattern iterators must point to the same type" );
395
Marshall Clowaf8be6c2016-03-08 15:12:52 +0000396 if (__f == __l ) return make_pair(__l, __l); // empty corpus
397 if (__first_ == __last_) return make_pair(__f, __f); // empty pattern
Marshall Clow7a0952b2015-09-08 17:59:09 +0000398
399 // If the pattern is larger than the corpus, we can't find it!
Arthur O'Dwyerd8dddf52021-05-10 13:13:04 -0400400 if ( __pattern_length_ > _VSTD::distance(__f, __l))
Marshall Clowaf8be6c2016-03-08 15:12:52 +0000401 return make_pair(__l, __l);
Marshall Clow7a0952b2015-09-08 17:59:09 +0000402
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700403 // Do the search
Marshall Clow7a0952b2015-09-08 17:59:09 +0000404 return this->__search(__f, __l);
405 }
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700406
Marshall Clow7a0952b2015-09-08 17:59:09 +0000407private:
408 _RandomAccessIterator1 __first_;
409 _RandomAccessIterator1 __last_;
410 _BinaryPredicate __pred_;
411 difference_type __pattern_length_;
412 shared_ptr<skip_table_type> __skip_;
413
414 template <typename _RandomAccessIterator2>
Marshall Clowaf8be6c2016-03-08 15:12:52 +0000415 pair<_RandomAccessIterator2, _RandomAccessIterator2>
416 __search ( _RandomAccessIterator2 __f, _RandomAccessIterator2 __l ) const {
Marshall Clow7a0952b2015-09-08 17:59:09 +0000417 _RandomAccessIterator2 __cur = __f;
418 const _RandomAccessIterator2 __last = __l - __pattern_length_;
419 const skip_table_type & __skip = *__skip_.get();
420
421 while (__cur <= __last)
422 {
423 // Do we match right where we are?
424 difference_type __j = __pattern_length_;
425 while (__pred_(__first_[__j-1], __cur[__j-1]))
426 {
427 __j--;
428 // We matched - we're done!
429 if ( __j == 0 )
Marshall Clowaf8be6c2016-03-08 15:12:52 +0000430 return make_pair(__cur, __cur + __pattern_length_);
Marshall Clow7a0952b2015-09-08 17:59:09 +0000431 }
432 __cur += __skip[__cur[__pattern_length_-1]];
433 }
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700434
Marshall Clowaf8be6c2016-03-08 15:12:52 +0000435 return make_pair(__l, __l);
Marshall Clow7a0952b2015-09-08 17:59:09 +0000436 }
437};
438
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700439template<class _RandomAccessIterator,
440 class _Hash = hash<typename iterator_traits<_RandomAccessIterator>::value_type>,
Marshall Clow7a0952b2015-09-08 17:59:09 +0000441 class _BinaryPredicate = equal_to<>>
442_LIBCPP_INLINE_VISIBILITY
443boyer_moore_horspool_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700444make_boyer_moore_horspool_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l,
Marshall Clow7a0952b2015-09-08 17:59:09 +0000445 _Hash __hf = _Hash(), _BinaryPredicate __p = _BinaryPredicate ())
446{
447 return boyer_moore_horspool_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>(__f, __l, __hf, __p);
448}
449
450#endif // _LIBCPP_STD_VER > 11
Marshall Clow6e3be1c2015-07-20 16:39:28 +0000451
452_LIBCPP_END_NAMESPACE_LFTS
453
Eric Fiselierf4433a32017-05-31 22:07:49 +0000454_LIBCPP_POP_MACROS
455
Marshall Clow6e3be1c2015-07-20 16:39:28 +0000456#endif /* _LIBCPP_EXPERIMENTAL_FUNCTIONAL */