146035553Spatrick// -*- C++ -*-
2*4bdff4beSrobert//===----------------------------------------------------------------------===//
346035553Spatrick//
446035553Spatrick// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
546035553Spatrick// See https://llvm.org/LICENSE.txt for license information.
646035553Spatrick// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
746035553Spatrick//
846035553Spatrick//===----------------------------------------------------------------------===//
946035553Spatrick
1046035553Spatrick#ifndef _LIBCPP_EXPERIMENTAL_FUNCTIONAL
1146035553Spatrick#define _LIBCPP_EXPERIMENTAL_FUNCTIONAL
1246035553Spatrick
1346035553Spatrick/*
1446035553Spatrick   experimental/functional synopsis
1546035553Spatrick
1646035553Spatrick#include <algorithm>
1746035553Spatrick
1846035553Spatricknamespace std {
1946035553Spatricknamespace experimental {
2046035553Spatrickinline namespace fundamentals_v1 {
2146035553Spatrick    // 4.3, Searchers
2246035553Spatrick    template<class ForwardIterator, class BinaryPredicate = equal_to<>>
2346035553Spatrick      class default_searcher;
2446035553Spatrick
2546035553Spatrick    template<class RandomAccessIterator,
2646035553Spatrick             class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
2746035553Spatrick             class BinaryPredicate = equal_to<>>
2846035553Spatrick      class boyer_moore_searcher;
2946035553Spatrick
3046035553Spatrick    template<class RandomAccessIterator,
3146035553Spatrick             class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
3246035553Spatrick             class BinaryPredicate = equal_to<>>
3346035553Spatrick      class boyer_moore_horspool_searcher;
3446035553Spatrick
3546035553Spatrick    template<class ForwardIterator, class BinaryPredicate = equal_to<>>
3646035553Spatrick    default_searcher<ForwardIterator, BinaryPredicate>
3746035553Spatrick    make_default_searcher(ForwardIterator pat_first, ForwardIterator pat_last,
3846035553Spatrick                          BinaryPredicate pred = BinaryPredicate());
3946035553Spatrick
4046035553Spatrick    template<class RandomAccessIterator,
4146035553Spatrick             class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
4246035553Spatrick             class BinaryPredicate = equal_to<>>
4346035553Spatrick    boyer_moore_searcher<RandomAccessIterator, Hash, BinaryPredicate>
4446035553Spatrick    make_boyer_moore_searcher(
4546035553Spatrick        RandomAccessIterator pat_first, RandomAccessIterator pat_last,
4646035553Spatrick        Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
4746035553Spatrick
4846035553Spatrick    template<class RandomAccessIterator,
4946035553Spatrick             class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
5046035553Spatrick             class BinaryPredicate = equal_to<>>
5146035553Spatrick    boyer_moore_horspool_searcher<RandomAccessIterator, Hash, BinaryPredicate>
5246035553Spatrick    make_boyer_moore_horspool_searcher(
5346035553Spatrick        RandomAccessIterator pat_first, RandomAccessIterator pat_last,
5446035553Spatrick        Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
5546035553Spatrick
5646035553Spatrick  } // namespace fundamentals_v1
5746035553Spatrick  } // namespace experimental
5846035553Spatrick
5946035553Spatrick} // namespace std
6046035553Spatrick
6146035553Spatrick*/
6246035553Spatrick
63*4bdff4beSrobert#include <__assert> // all public C++ headers provide the assertion handler
64*4bdff4beSrobert#include <__debug>
65*4bdff4beSrobert#include <__functional/identity.h>
6676d0caaeSpatrick#include <__memory/uses_allocator.h>
67*4bdff4beSrobert#include <array>
6846035553Spatrick#include <experimental/__config>
6946035553Spatrick#include <functional>
7046035553Spatrick#include <type_traits>
7146035553Spatrick#include <unordered_map>
72*4bdff4beSrobert#include <vector>
7346035553Spatrick
7446035553Spatrick#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
7546035553Spatrick#  pragma GCC system_header
7646035553Spatrick#endif
7746035553Spatrick
7846035553Spatrick_LIBCPP_PUSH_MACROS
7946035553Spatrick#include <__undef_macros>
8046035553Spatrick
8146035553Spatrick_LIBCPP_BEGIN_NAMESPACE_LFTS
8246035553Spatrick
83*4bdff4beSrobert#ifdef _LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
84*4bdff4beSrobert#  define _LIBCPP_DEPRECATED_DEFAULT_SEARCHER
85*4bdff4beSrobert#  define _LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER
86*4bdff4beSrobert#  define _LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER
87*4bdff4beSrobert#else
88*4bdff4beSrobert#  define _LIBCPP_DEPRECATED_DEFAULT_SEARCHER _LIBCPP_DEPRECATED_("std::experimental::default_searcher will be removed in LLVM 17. Use std::default_searcher instead")
89*4bdff4beSrobert#  define _LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER _LIBCPP_DEPRECATED_("std::experimental::boyer_moore_searcher will be removed in LLVM 17. Use std::boyer_moore_searcher instead")
90*4bdff4beSrobert#  define _LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER _LIBCPP_DEPRECATED_("std::experimental::boyer_moore_horspool_searcher will be removed in LLVM 17. Use std::boyer_moore_horspool_searcher instead")
91*4bdff4beSrobert#endif
92*4bdff4beSrobert
9346035553Spatrick#if _LIBCPP_STD_VER > 11
9446035553Spatrick// default searcher
9546035553Spatricktemplate<class _ForwardIterator, class _BinaryPredicate = equal_to<>>
96*4bdff4beSrobertclass _LIBCPP_DEPRECATED_DEFAULT_SEARCHER _LIBCPP_TEMPLATE_VIS default_searcher {
9746035553Spatrickpublic:
9846035553Spatrick    _LIBCPP_INLINE_VISIBILITY
9946035553Spatrick    default_searcher(_ForwardIterator __f, _ForwardIterator __l,
10046035553Spatrick                       _BinaryPredicate __p = _BinaryPredicate())
10146035553Spatrick        : __first_(__f), __last_(__l), __pred_(__p) {}
10246035553Spatrick
10346035553Spatrick    template <typename _ForwardIterator2>
10446035553Spatrick    _LIBCPP_INLINE_VISIBILITY
10546035553Spatrick    pair<_ForwardIterator2, _ForwardIterator2>
10646035553Spatrick    operator () (_ForwardIterator2 __f, _ForwardIterator2 __l) const
10746035553Spatrick    {
108*4bdff4beSrobert        auto __proj = __identity();
109*4bdff4beSrobert        return std::__search_impl(__f, __l, __first_, __last_, __pred_, __proj, __proj);
11046035553Spatrick    }
11146035553Spatrick
11246035553Spatrickprivate:
11346035553Spatrick    _ForwardIterator __first_;
11446035553Spatrick    _ForwardIterator __last_;
11546035553Spatrick    _BinaryPredicate __pred_;
11646035553Spatrick    };
11746035553Spatrick
11846035553Spatricktemplate<class _ForwardIterator, class _BinaryPredicate = equal_to<>>
119*4bdff4beSrobert_LIBCPP_DEPRECATED_DEFAULT_SEARCHER _LIBCPP_INLINE_VISIBILITY
12046035553Spatrickdefault_searcher<_ForwardIterator, _BinaryPredicate>
12146035553Spatrickmake_default_searcher( _ForwardIterator __f, _ForwardIterator __l, _BinaryPredicate __p = _BinaryPredicate ())
12246035553Spatrick{
12346035553Spatrick    return default_searcher<_ForwardIterator, _BinaryPredicate>(__f, __l, __p);
12446035553Spatrick}
12546035553Spatrick
12646035553Spatricktemplate<class _Key, class _Value, class _Hash, class _BinaryPredicate, bool /*useArray*/> class _BMSkipTable;
12746035553Spatrick
12846035553Spatrick//  General case for BM data searching; use a map
12946035553Spatricktemplate<class _Key, typename _Value, class _Hash, class _BinaryPredicate>
13046035553Spatrickclass _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, false> {
13146035553Spatrick    typedef _Value value_type;
13246035553Spatrick    typedef _Key   key_type;
13346035553Spatrick
13446035553Spatrick    const _Value __default_value_;
135*4bdff4beSrobert    std::unordered_map<_Key, _Value, _Hash, _BinaryPredicate> __table_;
13646035553Spatrick
13746035553Spatrickpublic:
13846035553Spatrick    _LIBCPP_INLINE_VISIBILITY
13976d0caaeSpatrick    _BMSkipTable(size_t __sz, _Value __default, _Hash __hf, _BinaryPredicate __pred)
140*4bdff4beSrobert        : __default_value_(__default), __table_(__sz, __hf, __pred) {}
14146035553Spatrick
14246035553Spatrick    _LIBCPP_INLINE_VISIBILITY
14346035553Spatrick    void insert(const key_type &__key, value_type __val)
14446035553Spatrick    {
145*4bdff4beSrobert        __table_ [__key] = __val;    // Would skip_.insert (val) be better here?
14646035553Spatrick    }
14746035553Spatrick
14846035553Spatrick    _LIBCPP_INLINE_VISIBILITY
14946035553Spatrick    value_type operator [](const key_type & __key) const
15046035553Spatrick    {
151*4bdff4beSrobert        auto __it = __table_.find (__key);
152*4bdff4beSrobert        return __it == __table_.end() ? __default_value_ : __it->second;
15346035553Spatrick    }
15446035553Spatrick};
15546035553Spatrick
15646035553Spatrick
15746035553Spatrick//  Special case small numeric values; use an array
15846035553Spatricktemplate<class _Key, typename _Value, class _Hash, class _BinaryPredicate>
15946035553Spatrickclass _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, true> {
16046035553Spatrickprivate:
16146035553Spatrick    typedef _Value value_type;
16246035553Spatrick    typedef _Key   key_type;
16346035553Spatrick
164*4bdff4beSrobert    typedef __make_unsigned_t<key_type> unsigned_key_type;
165*4bdff4beSrobert    typedef std::array<value_type, 256> skip_map;
166*4bdff4beSrobert    skip_map __table_;
16746035553Spatrick
16846035553Spatrickpublic:
16946035553Spatrick    _LIBCPP_INLINE_VISIBILITY
17076d0caaeSpatrick    _BMSkipTable(size_t /*__sz*/, _Value __default, _Hash /*__hf*/, _BinaryPredicate /*__pred*/)
17146035553Spatrick    {
172*4bdff4beSrobert        std::fill_n(__table_.begin(), __table_.size(), __default);
17346035553Spatrick    }
17446035553Spatrick
17546035553Spatrick    _LIBCPP_INLINE_VISIBILITY
17646035553Spatrick    void insert(key_type __key, value_type __val)
17746035553Spatrick    {
178*4bdff4beSrobert        __table_[static_cast<unsigned_key_type>(__key)] = __val;
17946035553Spatrick    }
18046035553Spatrick
18146035553Spatrick    _LIBCPP_INLINE_VISIBILITY
18246035553Spatrick    value_type operator [](key_type __key) const
18346035553Spatrick    {
184*4bdff4beSrobert        return __table_[static_cast<unsigned_key_type>(__key)];
18546035553Spatrick    }
18646035553Spatrick};
18746035553Spatrick
18846035553Spatrick
18946035553Spatricktemplate <class _RandomAccessIterator1,
19046035553Spatrick          class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>,
19146035553Spatrick          class _BinaryPredicate = equal_to<>>
192*4bdff4beSrobertclass _LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER _LIBCPP_TEMPLATE_VIS boyer_moore_searcher {
19346035553Spatrickprivate:
19446035553Spatrick    typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type difference_type;
19546035553Spatrick    typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type      value_type;
19646035553Spatrick    typedef _BMSkipTable<value_type, difference_type, _Hash, _BinaryPredicate,
19776d0caaeSpatrick                    is_integral<value_type>::value && // what about enums?
19846035553Spatrick                    sizeof(value_type) == 1 &&
19946035553Spatrick                    is_same<_Hash, hash<value_type>>::value &&
20046035553Spatrick                    is_same<_BinaryPredicate, equal_to<>>::value
20146035553Spatrick            > skip_table_type;
20246035553Spatrick
20346035553Spatrickpublic:
20446035553Spatrick    boyer_moore_searcher(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l,
20546035553Spatrick                _Hash __hf = _Hash(), _BinaryPredicate __pred = _BinaryPredicate())
20646035553Spatrick            : __first_(__f), __last_(__l), __pred_(__pred),
20746035553Spatrick              __pattern_length_(_VSTD::distance(__first_, __last_)),
208*4bdff4beSrobert              __skip_{std::make_shared<skip_table_type>(__pattern_length_, -1, __hf, __pred_)},
209*4bdff4beSrobert              __suffix_{std::make_shared<vector<difference_type>>(__pattern_length_ + 1)}
21046035553Spatrick        {
21146035553Spatrick    //  build the skip table
21246035553Spatrick        for ( difference_type __i = 0; __f != __l; ++__f, (void) ++__i )
21346035553Spatrick            __skip_->insert(*__f, __i);
21446035553Spatrick
21546035553Spatrick        this->__build_suffix_table ( __first_, __last_, __pred_ );
21646035553Spatrick        }
21746035553Spatrick
21846035553Spatrick    template <typename _RandomAccessIterator2>
21946035553Spatrick    pair<_RandomAccessIterator2, _RandomAccessIterator2>
22046035553Spatrick    operator ()(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const
22146035553Spatrick    {
222*4bdff4beSrobert        static_assert(__is_same_uncvref<typename iterator_traits<_RandomAccessIterator1>::value_type,
223*4bdff4beSrobert                                        typename iterator_traits<_RandomAccessIterator2>::value_type>::value,
22446035553Spatrick                      "Corpus and Pattern iterators must point to the same type");
22546035553Spatrick
226*4bdff4beSrobert        if (__f      == __l )    return std::make_pair(__l, __l); // empty corpus
227*4bdff4beSrobert        if (__first_ == __last_) return std::make_pair(__f, __f); // empty pattern
22846035553Spatrick
22946035553Spatrick    //  If the pattern is larger than the corpus, we can't find it!
23046035553Spatrick        if ( __pattern_length_ > _VSTD::distance(__f, __l))
231*4bdff4beSrobert            return std::make_pair(__l, __l);
23246035553Spatrick
23346035553Spatrick    //  Do the search
23446035553Spatrick        return this->__search(__f, __l);
23546035553Spatrick    }
23646035553Spatrick
237*4bdff4beSrobertprivate:
23846035553Spatrick    _RandomAccessIterator1               __first_;
23946035553Spatrick    _RandomAccessIterator1               __last_;
24046035553Spatrick    _BinaryPredicate                     __pred_;
24146035553Spatrick    difference_type                      __pattern_length_;
24246035553Spatrick    shared_ptr<skip_table_type>          __skip_;
24346035553Spatrick    shared_ptr<vector<difference_type>>  __suffix_;
24446035553Spatrick
24546035553Spatrick    template <typename _RandomAccessIterator2>
24646035553Spatrick    pair<_RandomAccessIterator2, _RandomAccessIterator2>
24746035553Spatrick    __search(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const
24846035553Spatrick    {
24946035553Spatrick        _RandomAccessIterator2 __cur = __f;
25046035553Spatrick        const _RandomAccessIterator2 __last = __l - __pattern_length_;
25146035553Spatrick        const skip_table_type &         __skip   = *__skip_.get();
25246035553Spatrick        const vector<difference_type> & __suffix = *__suffix_.get();
25346035553Spatrick
25446035553Spatrick        while (__cur <= __last)
25546035553Spatrick        {
25646035553Spatrick
25746035553Spatrick        //  Do we match right where we are?
25846035553Spatrick            difference_type __j = __pattern_length_;
25946035553Spatrick            while (__pred_(__first_ [__j-1], __cur [__j-1])) {
26046035553Spatrick                __j--;
26146035553Spatrick            //  We matched - we're done!
26246035553Spatrick                if ( __j == 0 )
263*4bdff4beSrobert                    return std::make_pair(__cur, __cur + __pattern_length_);
26446035553Spatrick                }
26546035553Spatrick
26646035553Spatrick        //  Since we didn't match, figure out how far to skip forward
26746035553Spatrick            difference_type __k = __skip[__cur [ __j - 1 ]];
26846035553Spatrick            difference_type __m = __j - __k - 1;
26946035553Spatrick            if (__k < __j && __m > __suffix[ __j ])
27046035553Spatrick                __cur += __m;
27146035553Spatrick            else
27246035553Spatrick                __cur += __suffix[ __j ];
27346035553Spatrick        }
27446035553Spatrick
275*4bdff4beSrobert        return std::make_pair(__l, __l);     // We didn't find anything
27646035553Spatrick    }
27746035553Spatrick
27846035553Spatrick
27946035553Spatrick    template<typename _Iterator, typename _Container>
28046035553Spatrick    void __compute_bm_prefix ( _Iterator __f, _Iterator __l, _BinaryPredicate __pred, _Container &__prefix )
28146035553Spatrick    {
28276d0caaeSpatrick        const size_t __count = _VSTD::distance(__f, __l);
28346035553Spatrick
28446035553Spatrick        __prefix[0] = 0;
28576d0caaeSpatrick        size_t __k = 0;
28676d0caaeSpatrick        for ( size_t __i = 1; __i < __count; ++__i )
28746035553Spatrick        {
28846035553Spatrick            while ( __k > 0 && !__pred ( __f[__k], __f[__i] ))
28946035553Spatrick                __k = __prefix [ __k - 1 ];
29046035553Spatrick
29146035553Spatrick            if ( __pred ( __f[__k], __f[__i] ))
29246035553Spatrick                __k++;
29346035553Spatrick            __prefix [ __i ] = __k;
29446035553Spatrick        }
29546035553Spatrick    }
29646035553Spatrick
29746035553Spatrick    void __build_suffix_table(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l,
29846035553Spatrick                                                    _BinaryPredicate __pred)
29946035553Spatrick    {
30076d0caaeSpatrick        const size_t __count = _VSTD::distance(__f, __l);
30146035553Spatrick        vector<difference_type> & __suffix = *__suffix_.get();
30246035553Spatrick        if (__count > 0)
30346035553Spatrick        {
304*4bdff4beSrobert            vector<difference_type> __scratch(__count);
30546035553Spatrick
30646035553Spatrick            __compute_bm_prefix(__f, __l, __pred, __scratch);
30776d0caaeSpatrick            for ( size_t __i = 0; __i <= __count; __i++ )
30846035553Spatrick                __suffix[__i] = __count - __scratch[__count-1];
30946035553Spatrick
31076d0caaeSpatrick            typedef reverse_iterator<_RandomAccessIterator1> _RevIter;
31146035553Spatrick            __compute_bm_prefix(_RevIter(__l), _RevIter(__f), __pred, __scratch);
31246035553Spatrick
31376d0caaeSpatrick            for ( size_t __i = 0; __i < __count; __i++ )
31446035553Spatrick            {
31576d0caaeSpatrick                const size_t     __j = __count - __scratch[__i];
31646035553Spatrick                const difference_type __k = __i     - __scratch[__i] + 1;
31746035553Spatrick
31846035553Spatrick                if (__suffix[__j] > __k)
31946035553Spatrick                    __suffix[__j] = __k;
32046035553Spatrick            }
32146035553Spatrick        }
32246035553Spatrick    }
32346035553Spatrick
32446035553Spatrick};
32546035553Spatrick
32646035553Spatricktemplate<class _RandomAccessIterator,
32746035553Spatrick         class _Hash = hash<typename iterator_traits<_RandomAccessIterator>::value_type>,
32846035553Spatrick         class _BinaryPredicate = equal_to<>>
329*4bdff4beSrobert_LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER _LIBCPP_INLINE_VISIBILITY
33046035553Spatrickboyer_moore_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>
33146035553Spatrickmake_boyer_moore_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l,
33246035553Spatrick                    _Hash __hf = _Hash(), _BinaryPredicate __p = _BinaryPredicate ())
33346035553Spatrick{
33446035553Spatrick    return boyer_moore_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>(__f, __l, __hf, __p);
33546035553Spatrick}
33646035553Spatrick
33746035553Spatrick// boyer-moore-horspool
33846035553Spatricktemplate <class _RandomAccessIterator1,
33946035553Spatrick          class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>,
34046035553Spatrick          class _BinaryPredicate = equal_to<>>
341*4bdff4beSrobertclass _LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER _LIBCPP_TEMPLATE_VIS boyer_moore_horspool_searcher {
34246035553Spatrickprivate:
34346035553Spatrick    typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type difference_type;
34446035553Spatrick    typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type      value_type;
34546035553Spatrick    typedef _BMSkipTable<value_type, difference_type, _Hash, _BinaryPredicate,
34676d0caaeSpatrick                    is_integral<value_type>::value && // what about enums?
34746035553Spatrick                    sizeof(value_type) == 1 &&
34846035553Spatrick                    is_same<_Hash, hash<value_type>>::value &&
34946035553Spatrick                    is_same<_BinaryPredicate, equal_to<>>::value
35046035553Spatrick            > skip_table_type;
35146035553Spatrick
35246035553Spatrickpublic:
35346035553Spatrick    boyer_moore_horspool_searcher(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l,
35446035553Spatrick                _Hash __hf = _Hash(), _BinaryPredicate __pred = _BinaryPredicate())
35546035553Spatrick            : __first_(__f), __last_(__l), __pred_(__pred),
35646035553Spatrick              __pattern_length_(_VSTD::distance(__first_, __last_)),
35746035553Spatrick              __skip_{_VSTD::make_shared<skip_table_type>(__pattern_length_, __pattern_length_, __hf, __pred_)}
35846035553Spatrick        {
35946035553Spatrick    //  build the skip table
36046035553Spatrick            if ( __f != __l )
36146035553Spatrick            {
36246035553Spatrick                __l = __l - 1;
36346035553Spatrick                for ( difference_type __i = 0; __f != __l; ++__f, (void) ++__i )
36446035553Spatrick                    __skip_->insert(*__f, __pattern_length_ - 1 - __i);
36546035553Spatrick            }
36646035553Spatrick        }
36746035553Spatrick
36846035553Spatrick    template <typename _RandomAccessIterator2>
36946035553Spatrick    pair<_RandomAccessIterator2, _RandomAccessIterator2>
37046035553Spatrick    operator ()(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const
37146035553Spatrick    {
372*4bdff4beSrobert        static_assert(__is_same_uncvref<typename std::iterator_traits<_RandomAccessIterator1>::value_type,
373*4bdff4beSrobert                                        typename std::iterator_traits<_RandomAccessIterator2>::value_type>::value,
37446035553Spatrick                      "Corpus and Pattern iterators must point to the same type");
37546035553Spatrick
376*4bdff4beSrobert        if (__f      == __l )    return std::make_pair(__l, __l); // empty corpus
377*4bdff4beSrobert        if (__first_ == __last_) return std::make_pair(__f, __f); // empty pattern
37846035553Spatrick
37946035553Spatrick    //  If the pattern is larger than the corpus, we can't find it!
38046035553Spatrick        if ( __pattern_length_ > _VSTD::distance(__f, __l))
381*4bdff4beSrobert            return std::make_pair(__l, __l);
38246035553Spatrick
38346035553Spatrick    //  Do the search
38446035553Spatrick        return this->__search(__f, __l);
38546035553Spatrick    }
38646035553Spatrick
38746035553Spatrickprivate:
38846035553Spatrick    _RandomAccessIterator1      __first_;
38946035553Spatrick    _RandomAccessIterator1      __last_;
39046035553Spatrick    _BinaryPredicate            __pred_;
39146035553Spatrick    difference_type             __pattern_length_;
39246035553Spatrick    shared_ptr<skip_table_type> __skip_;
39346035553Spatrick
39446035553Spatrick    template <typename _RandomAccessIterator2>
39546035553Spatrick    pair<_RandomAccessIterator2, _RandomAccessIterator2>
39646035553Spatrick    __search ( _RandomAccessIterator2 __f, _RandomAccessIterator2 __l ) const {
39746035553Spatrick        _RandomAccessIterator2 __cur = __f;
39846035553Spatrick        const _RandomAccessIterator2 __last = __l - __pattern_length_;
39946035553Spatrick        const skip_table_type & __skip = *__skip_.get();
40046035553Spatrick
40146035553Spatrick        while (__cur <= __last)
40246035553Spatrick        {
40346035553Spatrick        //  Do we match right where we are?
40446035553Spatrick            difference_type __j = __pattern_length_;
40546035553Spatrick            while (__pred_(__first_[__j-1], __cur[__j-1]))
40646035553Spatrick            {
40746035553Spatrick                __j--;
40846035553Spatrick            //  We matched - we're done!
40946035553Spatrick                if ( __j == 0 )
410*4bdff4beSrobert                    return std::make_pair(__cur, __cur + __pattern_length_);
41146035553Spatrick            }
41246035553Spatrick            __cur += __skip[__cur[__pattern_length_-1]];
41346035553Spatrick        }
41446035553Spatrick
415*4bdff4beSrobert        return std::make_pair(__l, __l);
41646035553Spatrick    }
41746035553Spatrick};
41846035553Spatrick
41946035553Spatricktemplate<class _RandomAccessIterator,
42046035553Spatrick         class _Hash = hash<typename iterator_traits<_RandomAccessIterator>::value_type>,
42146035553Spatrick         class _BinaryPredicate = equal_to<>>
422*4bdff4beSrobert_LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER _LIBCPP_INLINE_VISIBILITY
42346035553Spatrickboyer_moore_horspool_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>
42446035553Spatrickmake_boyer_moore_horspool_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l,
42546035553Spatrick                    _Hash __hf = _Hash(), _BinaryPredicate __p = _BinaryPredicate ())
42646035553Spatrick{
42746035553Spatrick    return boyer_moore_horspool_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>(__f, __l, __hf, __p);
42846035553Spatrick}
42946035553Spatrick
43046035553Spatrick#endif // _LIBCPP_STD_VER > 11
43146035553Spatrick
43246035553Spatrick_LIBCPP_END_NAMESPACE_LFTS
43346035553Spatrick
43446035553Spatrick_LIBCPP_POP_MACROS
43546035553Spatrick
43646035553Spatrick#endif /* _LIBCPP_EXPERIMENTAL_FUNCTIONAL */
437