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