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