1*46035553Spatrick// -*- C++ -*- 2*46035553Spatrick//===-------------------------- functional --------------------------------===// 3*46035553Spatrick// 4*46035553Spatrick// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*46035553Spatrick// See https://llvm.org/LICENSE.txt for license information. 6*46035553Spatrick// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*46035553Spatrick// 8*46035553Spatrick//===----------------------------------------------------------------------===// 9*46035553Spatrick 10*46035553Spatrick#ifndef _LIBCPP_EXPERIMENTAL_FUNCTIONAL 11*46035553Spatrick#define _LIBCPP_EXPERIMENTAL_FUNCTIONAL 12*46035553Spatrick 13*46035553Spatrick/* 14*46035553Spatrick experimental/functional synopsis 15*46035553Spatrick 16*46035553Spatrick#include <algorithm> 17*46035553Spatrick 18*46035553Spatricknamespace std { 19*46035553Spatricknamespace experimental { 20*46035553Spatrickinline namespace fundamentals_v1 { 21*46035553Spatrick 22*46035553Spatrick // See C++14 20.9.9, Function object binders 23*46035553Spatrick template <class T> constexpr bool is_bind_expression_v 24*46035553Spatrick = is_bind_expression<T>::value; 25*46035553Spatrick template <class T> constexpr int is_placeholder_v 26*46035553Spatrick = is_placeholder<T>::value; 27*46035553Spatrick 28*46035553Spatrick // 4.2, Class template function 29*46035553Spatrick template<class> class function; // undefined 30*46035553Spatrick template<class R, class... ArgTypes> class function<R(ArgTypes...)>; 31*46035553Spatrick 32*46035553Spatrick template<class R, class... ArgTypes> 33*46035553Spatrick void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&); 34*46035553Spatrick 35*46035553Spatrick template<class R, class... ArgTypes> 36*46035553Spatrick bool operator==(const function<R(ArgTypes...)>&, nullptr_t) noexcept; 37*46035553Spatrick template<class R, class... ArgTypes> 38*46035553Spatrick bool operator==(nullptr_t, const function<R(ArgTypes...)>&) noexcept; 39*46035553Spatrick template<class R, class... ArgTypes> 40*46035553Spatrick bool operator!=(const function<R(ArgTypes...)>&, nullptr_t) noexcept; 41*46035553Spatrick template<class R, class... ArgTypes> 42*46035553Spatrick bool operator!=(nullptr_t, const function<R(ArgTypes...)>&) noexcept; 43*46035553Spatrick 44*46035553Spatrick // 4.3, Searchers 45*46035553Spatrick template<class ForwardIterator, class BinaryPredicate = equal_to<>> 46*46035553Spatrick class default_searcher; 47*46035553Spatrick 48*46035553Spatrick template<class RandomAccessIterator, 49*46035553Spatrick class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>, 50*46035553Spatrick class BinaryPredicate = equal_to<>> 51*46035553Spatrick class boyer_moore_searcher; 52*46035553Spatrick 53*46035553Spatrick template<class RandomAccessIterator, 54*46035553Spatrick class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>, 55*46035553Spatrick class BinaryPredicate = equal_to<>> 56*46035553Spatrick class boyer_moore_horspool_searcher; 57*46035553Spatrick 58*46035553Spatrick template<class ForwardIterator, class BinaryPredicate = equal_to<>> 59*46035553Spatrick default_searcher<ForwardIterator, BinaryPredicate> 60*46035553Spatrick make_default_searcher(ForwardIterator pat_first, ForwardIterator pat_last, 61*46035553Spatrick BinaryPredicate pred = BinaryPredicate()); 62*46035553Spatrick 63*46035553Spatrick template<class RandomAccessIterator, 64*46035553Spatrick class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>, 65*46035553Spatrick class BinaryPredicate = equal_to<>> 66*46035553Spatrick boyer_moore_searcher<RandomAccessIterator, Hash, BinaryPredicate> 67*46035553Spatrick make_boyer_moore_searcher( 68*46035553Spatrick RandomAccessIterator pat_first, RandomAccessIterator pat_last, 69*46035553Spatrick Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate()); 70*46035553Spatrick 71*46035553Spatrick template<class RandomAccessIterator, 72*46035553Spatrick class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>, 73*46035553Spatrick class BinaryPredicate = equal_to<>> 74*46035553Spatrick boyer_moore_horspool_searcher<RandomAccessIterator, Hash, BinaryPredicate> 75*46035553Spatrick make_boyer_moore_horspool_searcher( 76*46035553Spatrick RandomAccessIterator pat_first, RandomAccessIterator pat_last, 77*46035553Spatrick Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate()); 78*46035553Spatrick 79*46035553Spatrick } // namespace fundamentals_v1 80*46035553Spatrick } // namespace experimental 81*46035553Spatrick 82*46035553Spatrick template<class R, class... ArgTypes, class Alloc> 83*46035553Spatrick struct uses_allocator<experimental::function<R(ArgTypes...)>, Alloc>; 84*46035553Spatrick 85*46035553Spatrick} // namespace std 86*46035553Spatrick 87*46035553Spatrick*/ 88*46035553Spatrick 89*46035553Spatrick#include <experimental/__config> 90*46035553Spatrick#include <functional> 91*46035553Spatrick#include <algorithm> 92*46035553Spatrick#include <type_traits> 93*46035553Spatrick#include <vector> 94*46035553Spatrick#include <array> 95*46035553Spatrick#include <unordered_map> 96*46035553Spatrick 97*46035553Spatrick#include <__debug> 98*46035553Spatrick 99*46035553Spatrick#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 100*46035553Spatrick#pragma GCC system_header 101*46035553Spatrick#endif 102*46035553Spatrick 103*46035553Spatrick_LIBCPP_PUSH_MACROS 104*46035553Spatrick#include <__undef_macros> 105*46035553Spatrick 106*46035553Spatrick 107*46035553Spatrick_LIBCPP_BEGIN_NAMESPACE_LFTS 108*46035553Spatrick 109*46035553Spatrick#if _LIBCPP_STD_VER > 11 110*46035553Spatrick// default searcher 111*46035553Spatricktemplate<class _ForwardIterator, class _BinaryPredicate = equal_to<>> 112*46035553Spatrickclass _LIBCPP_TYPE_VIS default_searcher { 113*46035553Spatrickpublic: 114*46035553Spatrick _LIBCPP_INLINE_VISIBILITY 115*46035553Spatrick default_searcher(_ForwardIterator __f, _ForwardIterator __l, 116*46035553Spatrick _BinaryPredicate __p = _BinaryPredicate()) 117*46035553Spatrick : __first_(__f), __last_(__l), __pred_(__p) {} 118*46035553Spatrick 119*46035553Spatrick template <typename _ForwardIterator2> 120*46035553Spatrick _LIBCPP_INLINE_VISIBILITY 121*46035553Spatrick pair<_ForwardIterator2, _ForwardIterator2> 122*46035553Spatrick operator () (_ForwardIterator2 __f, _ForwardIterator2 __l) const 123*46035553Spatrick { 124*46035553Spatrick return _VSTD::__search(__f, __l, __first_, __last_, __pred_, 125*46035553Spatrick typename _VSTD::iterator_traits<_ForwardIterator>::iterator_category(), 126*46035553Spatrick typename _VSTD::iterator_traits<_ForwardIterator2>::iterator_category()); 127*46035553Spatrick } 128*46035553Spatrick 129*46035553Spatrickprivate: 130*46035553Spatrick _ForwardIterator __first_; 131*46035553Spatrick _ForwardIterator __last_; 132*46035553Spatrick _BinaryPredicate __pred_; 133*46035553Spatrick }; 134*46035553Spatrick 135*46035553Spatricktemplate<class _ForwardIterator, class _BinaryPredicate = equal_to<>> 136*46035553Spatrick_LIBCPP_INLINE_VISIBILITY 137*46035553Spatrickdefault_searcher<_ForwardIterator, _BinaryPredicate> 138*46035553Spatrickmake_default_searcher( _ForwardIterator __f, _ForwardIterator __l, _BinaryPredicate __p = _BinaryPredicate ()) 139*46035553Spatrick{ 140*46035553Spatrick return default_searcher<_ForwardIterator, _BinaryPredicate>(__f, __l, __p); 141*46035553Spatrick} 142*46035553Spatrick 143*46035553Spatricktemplate<class _Key, class _Value, class _Hash, class _BinaryPredicate, bool /*useArray*/> class _BMSkipTable; 144*46035553Spatrick 145*46035553Spatrick// General case for BM data searching; use a map 146*46035553Spatricktemplate<class _Key, typename _Value, class _Hash, class _BinaryPredicate> 147*46035553Spatrickclass _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, false> { 148*46035553Spatrickpublic: // TODO private: 149*46035553Spatrick typedef _Value value_type; 150*46035553Spatrick typedef _Key key_type; 151*46035553Spatrick 152*46035553Spatrick const _Value __default_value_; 153*46035553Spatrick std::unordered_map<_Key, _Value, _Hash, _BinaryPredicate> __table; 154*46035553Spatrick 155*46035553Spatrickpublic: 156*46035553Spatrick _LIBCPP_INLINE_VISIBILITY 157*46035553Spatrick _BMSkipTable(std::size_t __sz, _Value __default, _Hash __hf, _BinaryPredicate __pred) 158*46035553Spatrick : __default_value_(__default), __table(__sz, __hf, __pred) {} 159*46035553Spatrick 160*46035553Spatrick _LIBCPP_INLINE_VISIBILITY 161*46035553Spatrick void insert(const key_type &__key, value_type __val) 162*46035553Spatrick { 163*46035553Spatrick __table [__key] = __val; // Would skip_.insert (val) be better here? 164*46035553Spatrick } 165*46035553Spatrick 166*46035553Spatrick _LIBCPP_INLINE_VISIBILITY 167*46035553Spatrick value_type operator [](const key_type & __key) const 168*46035553Spatrick { 169*46035553Spatrick auto __it = __table.find (__key); 170*46035553Spatrick return __it == __table.end() ? __default_value_ : __it->second; 171*46035553Spatrick } 172*46035553Spatrick}; 173*46035553Spatrick 174*46035553Spatrick 175*46035553Spatrick// Special case small numeric values; use an array 176*46035553Spatricktemplate<class _Key, typename _Value, class _Hash, class _BinaryPredicate> 177*46035553Spatrickclass _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, true> { 178*46035553Spatrickprivate: 179*46035553Spatrick typedef _Value value_type; 180*46035553Spatrick typedef _Key key_type; 181*46035553Spatrick 182*46035553Spatrick typedef typename std::make_unsigned<key_type>::type unsigned_key_type; 183*46035553Spatrick typedef std::array<value_type, _VSTD::numeric_limits<unsigned_key_type>::max()> skip_map; 184*46035553Spatrick skip_map __table; 185*46035553Spatrick 186*46035553Spatrickpublic: 187*46035553Spatrick _LIBCPP_INLINE_VISIBILITY 188*46035553Spatrick _BMSkipTable(std::size_t /*__sz*/, _Value __default, _Hash /*__hf*/, _BinaryPredicate /*__pred*/) 189*46035553Spatrick { 190*46035553Spatrick std::fill_n(__table.begin(), __table.size(), __default); 191*46035553Spatrick } 192*46035553Spatrick 193*46035553Spatrick _LIBCPP_INLINE_VISIBILITY 194*46035553Spatrick void insert(key_type __key, value_type __val) 195*46035553Spatrick { 196*46035553Spatrick __table[static_cast<unsigned_key_type>(__key)] = __val; 197*46035553Spatrick } 198*46035553Spatrick 199*46035553Spatrick _LIBCPP_INLINE_VISIBILITY 200*46035553Spatrick value_type operator [](key_type __key) const 201*46035553Spatrick { 202*46035553Spatrick return __table[static_cast<unsigned_key_type>(__key)]; 203*46035553Spatrick } 204*46035553Spatrick}; 205*46035553Spatrick 206*46035553Spatrick 207*46035553Spatricktemplate <class _RandomAccessIterator1, 208*46035553Spatrick class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>, 209*46035553Spatrick class _BinaryPredicate = equal_to<>> 210*46035553Spatrickclass _LIBCPP_TYPE_VIS boyer_moore_searcher { 211*46035553Spatrickprivate: 212*46035553Spatrick typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type difference_type; 213*46035553Spatrick typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type value_type; 214*46035553Spatrick typedef _BMSkipTable<value_type, difference_type, _Hash, _BinaryPredicate, 215*46035553Spatrick _VSTD::is_integral<value_type>::value && // what about enums? 216*46035553Spatrick sizeof(value_type) == 1 && 217*46035553Spatrick is_same<_Hash, hash<value_type>>::value && 218*46035553Spatrick is_same<_BinaryPredicate, equal_to<>>::value 219*46035553Spatrick > skip_table_type; 220*46035553Spatrick 221*46035553Spatrickpublic: 222*46035553Spatrick boyer_moore_searcher(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l, 223*46035553Spatrick _Hash __hf = _Hash(), _BinaryPredicate __pred = _BinaryPredicate()) 224*46035553Spatrick : __first_(__f), __last_(__l), __pred_(__pred), 225*46035553Spatrick __pattern_length_(_VSTD::distance(__first_, __last_)), 226*46035553Spatrick __skip_{make_shared<skip_table_type>(__pattern_length_, -1, __hf, __pred_)}, 227*46035553Spatrick __suffix_{make_shared<vector<difference_type>>(__pattern_length_ + 1)} 228*46035553Spatrick { 229*46035553Spatrick // build the skip table 230*46035553Spatrick for ( difference_type __i = 0; __f != __l; ++__f, (void) ++__i ) 231*46035553Spatrick __skip_->insert(*__f, __i); 232*46035553Spatrick 233*46035553Spatrick this->__build_suffix_table ( __first_, __last_, __pred_ ); 234*46035553Spatrick } 235*46035553Spatrick 236*46035553Spatrick template <typename _RandomAccessIterator2> 237*46035553Spatrick pair<_RandomAccessIterator2, _RandomAccessIterator2> 238*46035553Spatrick operator ()(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const 239*46035553Spatrick { 240*46035553Spatrick static_assert ( std::is_same< 241*46035553Spatrick typename std::__uncvref<typename std::iterator_traits<_RandomAccessIterator1>::value_type>::type, 242*46035553Spatrick typename std::__uncvref<typename std::iterator_traits<_RandomAccessIterator2>::value_type>::type 243*46035553Spatrick >::value, 244*46035553Spatrick "Corpus and Pattern iterators must point to the same type" ); 245*46035553Spatrick 246*46035553Spatrick if (__f == __l ) return make_pair(__l, __l); // empty corpus 247*46035553Spatrick if (__first_ == __last_) return make_pair(__f, __f); // empty pattern 248*46035553Spatrick 249*46035553Spatrick // If the pattern is larger than the corpus, we can't find it! 250*46035553Spatrick if ( __pattern_length_ > _VSTD::distance (__f, __l)) 251*46035553Spatrick return make_pair(__l, __l); 252*46035553Spatrick 253*46035553Spatrick // Do the search 254*46035553Spatrick return this->__search(__f, __l); 255*46035553Spatrick } 256*46035553Spatrick 257*46035553Spatrickpublic: // TODO private: 258*46035553Spatrick _RandomAccessIterator1 __first_; 259*46035553Spatrick _RandomAccessIterator1 __last_; 260*46035553Spatrick _BinaryPredicate __pred_; 261*46035553Spatrick difference_type __pattern_length_; 262*46035553Spatrick shared_ptr<skip_table_type> __skip_; 263*46035553Spatrick shared_ptr<vector<difference_type>> __suffix_; 264*46035553Spatrick 265*46035553Spatrick template <typename _RandomAccessIterator2> 266*46035553Spatrick pair<_RandomAccessIterator2, _RandomAccessIterator2> 267*46035553Spatrick __search(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const 268*46035553Spatrick { 269*46035553Spatrick _RandomAccessIterator2 __cur = __f; 270*46035553Spatrick const _RandomAccessIterator2 __last = __l - __pattern_length_; 271*46035553Spatrick const skip_table_type & __skip = *__skip_.get(); 272*46035553Spatrick const vector<difference_type> & __suffix = *__suffix_.get(); 273*46035553Spatrick 274*46035553Spatrick while (__cur <= __last) 275*46035553Spatrick { 276*46035553Spatrick 277*46035553Spatrick // Do we match right where we are? 278*46035553Spatrick difference_type __j = __pattern_length_; 279*46035553Spatrick while (__pred_(__first_ [__j-1], __cur [__j-1])) { 280*46035553Spatrick __j--; 281*46035553Spatrick // We matched - we're done! 282*46035553Spatrick if ( __j == 0 ) 283*46035553Spatrick return make_pair(__cur, __cur + __pattern_length_); 284*46035553Spatrick } 285*46035553Spatrick 286*46035553Spatrick // Since we didn't match, figure out how far to skip forward 287*46035553Spatrick difference_type __k = __skip[__cur [ __j - 1 ]]; 288*46035553Spatrick difference_type __m = __j - __k - 1; 289*46035553Spatrick if (__k < __j && __m > __suffix[ __j ]) 290*46035553Spatrick __cur += __m; 291*46035553Spatrick else 292*46035553Spatrick __cur += __suffix[ __j ]; 293*46035553Spatrick } 294*46035553Spatrick 295*46035553Spatrick return make_pair(__l, __l); // We didn't find anything 296*46035553Spatrick } 297*46035553Spatrick 298*46035553Spatrick 299*46035553Spatrick template<typename _Iterator, typename _Container> 300*46035553Spatrick void __compute_bm_prefix ( _Iterator __f, _Iterator __l, _BinaryPredicate __pred, _Container &__prefix ) 301*46035553Spatrick { 302*46035553Spatrick const std::size_t __count = _VSTD::distance(__f, __l); 303*46035553Spatrick 304*46035553Spatrick __prefix[0] = 0; 305*46035553Spatrick std::size_t __k = 0; 306*46035553Spatrick for ( std::size_t __i = 1; __i < __count; ++__i ) 307*46035553Spatrick { 308*46035553Spatrick while ( __k > 0 && !__pred ( __f[__k], __f[__i] )) 309*46035553Spatrick __k = __prefix [ __k - 1 ]; 310*46035553Spatrick 311*46035553Spatrick if ( __pred ( __f[__k], __f[__i] )) 312*46035553Spatrick __k++; 313*46035553Spatrick __prefix [ __i ] = __k; 314*46035553Spatrick } 315*46035553Spatrick } 316*46035553Spatrick 317*46035553Spatrick void __build_suffix_table(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l, 318*46035553Spatrick _BinaryPredicate __pred) 319*46035553Spatrick { 320*46035553Spatrick const std::size_t __count = _VSTD::distance(__f, __l); 321*46035553Spatrick vector<difference_type> & __suffix = *__suffix_.get(); 322*46035553Spatrick if (__count > 0) 323*46035553Spatrick { 324*46035553Spatrick _VSTD::vector<value_type> __scratch(__count); 325*46035553Spatrick 326*46035553Spatrick __compute_bm_prefix(__f, __l, __pred, __scratch); 327*46035553Spatrick for ( std::size_t __i = 0; __i <= __count; __i++ ) 328*46035553Spatrick __suffix[__i] = __count - __scratch[__count-1]; 329*46035553Spatrick 330*46035553Spatrick typedef _VSTD::reverse_iterator<_RandomAccessIterator1> _RevIter; 331*46035553Spatrick __compute_bm_prefix(_RevIter(__l), _RevIter(__f), __pred, __scratch); 332*46035553Spatrick 333*46035553Spatrick for ( std::size_t __i = 0; __i < __count; __i++ ) 334*46035553Spatrick { 335*46035553Spatrick const std::size_t __j = __count - __scratch[__i]; 336*46035553Spatrick const difference_type __k = __i - __scratch[__i] + 1; 337*46035553Spatrick 338*46035553Spatrick if (__suffix[__j] > __k) 339*46035553Spatrick __suffix[__j] = __k; 340*46035553Spatrick } 341*46035553Spatrick } 342*46035553Spatrick } 343*46035553Spatrick 344*46035553Spatrick}; 345*46035553Spatrick 346*46035553Spatricktemplate<class _RandomAccessIterator, 347*46035553Spatrick class _Hash = hash<typename iterator_traits<_RandomAccessIterator>::value_type>, 348*46035553Spatrick class _BinaryPredicate = equal_to<>> 349*46035553Spatrick_LIBCPP_INLINE_VISIBILITY 350*46035553Spatrickboyer_moore_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate> 351*46035553Spatrickmake_boyer_moore_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l, 352*46035553Spatrick _Hash __hf = _Hash(), _BinaryPredicate __p = _BinaryPredicate ()) 353*46035553Spatrick{ 354*46035553Spatrick return boyer_moore_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>(__f, __l, __hf, __p); 355*46035553Spatrick} 356*46035553Spatrick 357*46035553Spatrick// boyer-moore-horspool 358*46035553Spatricktemplate <class _RandomAccessIterator1, 359*46035553Spatrick class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>, 360*46035553Spatrick class _BinaryPredicate = equal_to<>> 361*46035553Spatrickclass _LIBCPP_TYPE_VIS boyer_moore_horspool_searcher { 362*46035553Spatrickprivate: 363*46035553Spatrick typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type difference_type; 364*46035553Spatrick typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type value_type; 365*46035553Spatrick typedef _BMSkipTable<value_type, difference_type, _Hash, _BinaryPredicate, 366*46035553Spatrick _VSTD::is_integral<value_type>::value && // what about enums? 367*46035553Spatrick sizeof(value_type) == 1 && 368*46035553Spatrick is_same<_Hash, hash<value_type>>::value && 369*46035553Spatrick is_same<_BinaryPredicate, equal_to<>>::value 370*46035553Spatrick > skip_table_type; 371*46035553Spatrick 372*46035553Spatrickpublic: 373*46035553Spatrick boyer_moore_horspool_searcher(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l, 374*46035553Spatrick _Hash __hf = _Hash(), _BinaryPredicate __pred = _BinaryPredicate()) 375*46035553Spatrick : __first_(__f), __last_(__l), __pred_(__pred), 376*46035553Spatrick __pattern_length_(_VSTD::distance(__first_, __last_)), 377*46035553Spatrick __skip_{_VSTD::make_shared<skip_table_type>(__pattern_length_, __pattern_length_, __hf, __pred_)} 378*46035553Spatrick { 379*46035553Spatrick // build the skip table 380*46035553Spatrick if ( __f != __l ) 381*46035553Spatrick { 382*46035553Spatrick __l = __l - 1; 383*46035553Spatrick for ( difference_type __i = 0; __f != __l; ++__f, (void) ++__i ) 384*46035553Spatrick __skip_->insert(*__f, __pattern_length_ - 1 - __i); 385*46035553Spatrick } 386*46035553Spatrick } 387*46035553Spatrick 388*46035553Spatrick template <typename _RandomAccessIterator2> 389*46035553Spatrick pair<_RandomAccessIterator2, _RandomAccessIterator2> 390*46035553Spatrick operator ()(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const 391*46035553Spatrick { 392*46035553Spatrick static_assert ( std::is_same< 393*46035553Spatrick typename std::__uncvref<typename std::iterator_traits<_RandomAccessIterator1>::value_type>::type, 394*46035553Spatrick typename std::__uncvref<typename std::iterator_traits<_RandomAccessIterator2>::value_type>::type 395*46035553Spatrick >::value, 396*46035553Spatrick "Corpus and Pattern iterators must point to the same type" ); 397*46035553Spatrick 398*46035553Spatrick if (__f == __l ) return make_pair(__l, __l); // empty corpus 399*46035553Spatrick if (__first_ == __last_) return make_pair(__f, __f); // empty pattern 400*46035553Spatrick 401*46035553Spatrick // If the pattern is larger than the corpus, we can't find it! 402*46035553Spatrick if ( __pattern_length_ > _VSTD::distance (__f, __l)) 403*46035553Spatrick return make_pair(__l, __l); 404*46035553Spatrick 405*46035553Spatrick // Do the search 406*46035553Spatrick return this->__search(__f, __l); 407*46035553Spatrick } 408*46035553Spatrick 409*46035553Spatrickprivate: 410*46035553Spatrick _RandomAccessIterator1 __first_; 411*46035553Spatrick _RandomAccessIterator1 __last_; 412*46035553Spatrick _BinaryPredicate __pred_; 413*46035553Spatrick difference_type __pattern_length_; 414*46035553Spatrick shared_ptr<skip_table_type> __skip_; 415*46035553Spatrick 416*46035553Spatrick template <typename _RandomAccessIterator2> 417*46035553Spatrick pair<_RandomAccessIterator2, _RandomAccessIterator2> 418*46035553Spatrick __search ( _RandomAccessIterator2 __f, _RandomAccessIterator2 __l ) const { 419*46035553Spatrick _RandomAccessIterator2 __cur = __f; 420*46035553Spatrick const _RandomAccessIterator2 __last = __l - __pattern_length_; 421*46035553Spatrick const skip_table_type & __skip = *__skip_.get(); 422*46035553Spatrick 423*46035553Spatrick while (__cur <= __last) 424*46035553Spatrick { 425*46035553Spatrick // Do we match right where we are? 426*46035553Spatrick difference_type __j = __pattern_length_; 427*46035553Spatrick while (__pred_(__first_[__j-1], __cur[__j-1])) 428*46035553Spatrick { 429*46035553Spatrick __j--; 430*46035553Spatrick // We matched - we're done! 431*46035553Spatrick if ( __j == 0 ) 432*46035553Spatrick return make_pair(__cur, __cur + __pattern_length_); 433*46035553Spatrick } 434*46035553Spatrick __cur += __skip[__cur[__pattern_length_-1]]; 435*46035553Spatrick } 436*46035553Spatrick 437*46035553Spatrick return make_pair(__l, __l); 438*46035553Spatrick } 439*46035553Spatrick}; 440*46035553Spatrick 441*46035553Spatricktemplate<class _RandomAccessIterator, 442*46035553Spatrick class _Hash = hash<typename iterator_traits<_RandomAccessIterator>::value_type>, 443*46035553Spatrick class _BinaryPredicate = equal_to<>> 444*46035553Spatrick_LIBCPP_INLINE_VISIBILITY 445*46035553Spatrickboyer_moore_horspool_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate> 446*46035553Spatrickmake_boyer_moore_horspool_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l, 447*46035553Spatrick _Hash __hf = _Hash(), _BinaryPredicate __p = _BinaryPredicate ()) 448*46035553Spatrick{ 449*46035553Spatrick return boyer_moore_horspool_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>(__f, __l, __hf, __p); 450*46035553Spatrick} 451*46035553Spatrick 452*46035553Spatrick#endif // _LIBCPP_STD_VER > 11 453*46035553Spatrick 454*46035553Spatrick_LIBCPP_END_NAMESPACE_LFTS 455*46035553Spatrick 456*46035553Spatrick_LIBCPP_POP_MACROS 457*46035553Spatrick 458*46035553Spatrick#endif /* _LIBCPP_EXPERIMENTAL_FUNCTIONAL */ 459