1205c333cSMarshall Clow// -*- C++ -*-
2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===//
3205c333cSMarshall Clow//
457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information.
657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7205c333cSMarshall Clow//
8205c333cSMarshall Clow//===----------------------------------------------------------------------===//
9205c333cSMarshall Clow
10205c333cSMarshall Clow#ifndef _LIBCPP_EXPERIMENTAL_FUNCTIONAL
11205c333cSMarshall Clow#define _LIBCPP_EXPERIMENTAL_FUNCTIONAL
12205c333cSMarshall Clow
13205c333cSMarshall Clow/*
14205c333cSMarshall Clow   experimental/functional synopsis
15205c333cSMarshall Clow
16205c333cSMarshall Clow#include <algorithm>
17205c333cSMarshall Clow
18205c333cSMarshall Clownamespace std {
19205c333cSMarshall Clownamespace experimental {
20205c333cSMarshall Clowinline namespace fundamentals_v1 {
21205c333cSMarshall Clow    // 4.3, Searchers
22205c333cSMarshall Clow    template<class ForwardIterator, class BinaryPredicate = equal_to<>>
23205c333cSMarshall Clow      class default_searcher;
24205c333cSMarshall Clow
25205c333cSMarshall Clow    template<class RandomAccessIterator,
26205c333cSMarshall Clow             class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
27205c333cSMarshall Clow             class BinaryPredicate = equal_to<>>
28205c333cSMarshall Clow      class boyer_moore_searcher;
29205c333cSMarshall Clow
30205c333cSMarshall Clow    template<class RandomAccessIterator,
31205c333cSMarshall Clow             class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
32205c333cSMarshall Clow             class BinaryPredicate = equal_to<>>
33205c333cSMarshall Clow      class boyer_moore_horspool_searcher;
34205c333cSMarshall Clow
35205c333cSMarshall Clow    template<class ForwardIterator, class BinaryPredicate = equal_to<>>
36205c333cSMarshall Clow    default_searcher<ForwardIterator, BinaryPredicate>
37205c333cSMarshall Clow    make_default_searcher(ForwardIterator pat_first, ForwardIterator pat_last,
38205c333cSMarshall Clow                          BinaryPredicate pred = BinaryPredicate());
39205c333cSMarshall Clow
40205c333cSMarshall Clow    template<class RandomAccessIterator,
41205c333cSMarshall Clow             class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
42205c333cSMarshall Clow             class BinaryPredicate = equal_to<>>
43205c333cSMarshall Clow    boyer_moore_searcher<RandomAccessIterator, Hash, BinaryPredicate>
44205c333cSMarshall Clow    make_boyer_moore_searcher(
45205c333cSMarshall Clow        RandomAccessIterator pat_first, RandomAccessIterator pat_last,
46205c333cSMarshall Clow        Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
47205c333cSMarshall Clow
48205c333cSMarshall Clow    template<class RandomAccessIterator,
49205c333cSMarshall Clow             class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
50205c333cSMarshall Clow             class BinaryPredicate = equal_to<>>
51205c333cSMarshall Clow    boyer_moore_horspool_searcher<RandomAccessIterator, Hash, BinaryPredicate>
52205c333cSMarshall Clow    make_boyer_moore_horspool_searcher(
53205c333cSMarshall Clow        RandomAccessIterator pat_first, RandomAccessIterator pat_last,
54205c333cSMarshall Clow        Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
55205c333cSMarshall Clow
56205c333cSMarshall Clow  } // namespace fundamentals_v1
57205c333cSMarshall Clow  } // namespace experimental
58205c333cSMarshall Clow
59205c333cSMarshall Clow} // namespace std
60205c333cSMarshall Clow
61205c333cSMarshall Clow*/
62205c333cSMarshall Clow
63385cc25aSLouis Dionne#include <__assert> // all public C++ headers provide the assertion handler
644d81a46fSArthur O'Dwyer#include <__debug>
65*101d1e9bSNikolas Klauser#include <__functional/identity.h>
66050b064fSChristopher Di Bella#include <__memory/uses_allocator.h>
674d81a46fSArthur O'Dwyer#include <array>
68205c333cSMarshall Clow#include <experimental/__config>
69205c333cSMarshall Clow#include <functional>
70f44bd93bSMarshall Clow#include <type_traits>
71f44bd93bSMarshall Clow#include <unordered_map>
724d81a46fSArthur O'Dwyer#include <vector>
73205c333cSMarshall Clow
74205c333cSMarshall Clow#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
75205c333cSMarshall Clow#  pragma GCC system_header
76205c333cSMarshall Clow#endif
77205c333cSMarshall Clow
78a016efb1SEric Fiselier_LIBCPP_PUSH_MACROS
79a016efb1SEric Fiselier#include <__undef_macros>
80a016efb1SEric Fiselier
81205c333cSMarshall Clow_LIBCPP_BEGIN_NAMESPACE_LFTS
82205c333cSMarshall Clow
83971e9c80SNikolas Klauser#ifdef _LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
84971e9c80SNikolas Klauser#  define _LIBCPP_DEPRECATED_DEFAULT_SEARCHER
85971e9c80SNikolas Klauser#  define _LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER
86971e9c80SNikolas Klauser#  define _LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER
87971e9c80SNikolas Klauser#else
88971e9c80SNikolas Klauser#  define _LIBCPP_DEPRECATED_DEFAULT_SEARCHER _LIBCPP_DEPRECATED_("std::exprerimental::default_searcher will be removed in LLVM 17. Use std::default_searcher instead")
89971e9c80SNikolas Klauser#  define _LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER _LIBCPP_DEPRECATED_("std::exprerimental::boyer_moore_searcher will be removed in LLVM 17. Use std::boyer_moore_searcher instead")
90971e9c80SNikolas Klauser#  define _LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER _LIBCPP_DEPRECATED_("std::exprerimental::boyer_moore_horspool_searcher will be removed in LLVM 17. Use std::boyer_moore_horspool_searcher instead")
91971e9c80SNikolas Klauser#endif
92971e9c80SNikolas Klauser
93f44bd93bSMarshall Clow#if _LIBCPP_STD_VER > 11
94205c333cSMarshall Clow// default searcher
95205c333cSMarshall Clowtemplate<class _ForwardIterator, class _BinaryPredicate = equal_to<>>
96971e9c80SNikolas Klauserclass _LIBCPP_DEPRECATED_DEFAULT_SEARCHER _LIBCPP_TEMPLATE_VIS default_searcher {
97205c333cSMarshall Clowpublic:
98f44bd93bSMarshall Clow    _LIBCPP_INLINE_VISIBILITY
99205c333cSMarshall Clow    default_searcher(_ForwardIterator __f, _ForwardIterator __l,
100205c333cSMarshall Clow                       _BinaryPredicate __p = _BinaryPredicate())
101205c333cSMarshall Clow        : __first_(__f), __last_(__l), __pred_(__p) {}
102205c333cSMarshall Clow
103205c333cSMarshall Clow    template <typename _ForwardIterator2>
104f44bd93bSMarshall Clow    _LIBCPP_INLINE_VISIBILITY
10528cc4ddeSMarshall Clow    pair<_ForwardIterator2, _ForwardIterator2>
10628cc4ddeSMarshall Clow    operator () (_ForwardIterator2 __f, _ForwardIterator2 __l) const
107f44bd93bSMarshall Clow    {
108*101d1e9bSNikolas Klauser        auto __proj = __identity();
109*101d1e9bSNikolas Klauser        return std::__search_impl(__f, __l, __first_, __last_, __pred_, __proj, __proj);
110205c333cSMarshall Clow    }
111205c333cSMarshall Clow
112205c333cSMarshall Clowprivate:
113205c333cSMarshall Clow    _ForwardIterator __first_;
114205c333cSMarshall Clow    _ForwardIterator __last_;
115205c333cSMarshall Clow    _BinaryPredicate __pred_;
116205c333cSMarshall Clow    };
117205c333cSMarshall Clow
118205c333cSMarshall Clowtemplate<class _ForwardIterator, class _BinaryPredicate = equal_to<>>
119971e9c80SNikolas Klauser_LIBCPP_DEPRECATED_DEFAULT_SEARCHER _LIBCPP_INLINE_VISIBILITY
120205c333cSMarshall Clowdefault_searcher<_ForwardIterator, _BinaryPredicate>
121205c333cSMarshall Clowmake_default_searcher( _ForwardIterator __f, _ForwardIterator __l, _BinaryPredicate __p = _BinaryPredicate ())
122205c333cSMarshall Clow{
123205c333cSMarshall Clow    return default_searcher<_ForwardIterator, _BinaryPredicate>(__f, __l, __p);
124205c333cSMarshall Clow}
125205c333cSMarshall Clow
126f44bd93bSMarshall Clowtemplate<class _Key, class _Value, class _Hash, class _BinaryPredicate, bool /*useArray*/> class _BMSkipTable;
127f44bd93bSMarshall Clow
128f44bd93bSMarshall Clow//  General case for BM data searching; use a map
129f44bd93bSMarshall Clowtemplate<class _Key, typename _Value, class _Hash, class _BinaryPredicate>
130f44bd93bSMarshall Clowclass _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, false> {
131f44bd93bSMarshall Clow    typedef _Value value_type;
132f44bd93bSMarshall Clow    typedef _Key   key_type;
133f44bd93bSMarshall Clow
134f44bd93bSMarshall Clow    const _Value __default_value_;
135f44bd93bSMarshall Clow    std::unordered_map<_Key, _Value, _Hash, _BinaryPredicate> __table;
136f44bd93bSMarshall Clow
137f44bd93bSMarshall Clowpublic:
138f44bd93bSMarshall Clow    _LIBCPP_INLINE_VISIBILITY
1390b8da5faSArthur O'Dwyer    _BMSkipTable(size_t __sz, _Value __default, _Hash __hf, _BinaryPredicate __pred)
140f44bd93bSMarshall Clow        : __default_value_(__default), __table(__sz, __hf, __pred) {}
141f44bd93bSMarshall Clow
142f44bd93bSMarshall Clow    _LIBCPP_INLINE_VISIBILITY
143f44bd93bSMarshall Clow    void insert(const key_type &__key, value_type __val)
144f44bd93bSMarshall Clow    {
145f44bd93bSMarshall Clow        __table [__key] = __val;    // Would skip_.insert (val) be better here?
146f44bd93bSMarshall Clow    }
147f44bd93bSMarshall Clow
148f44bd93bSMarshall Clow    _LIBCPP_INLINE_VISIBILITY
149f44bd93bSMarshall Clow    value_type operator [](const key_type & __key) const
150f44bd93bSMarshall Clow    {
151f44bd93bSMarshall Clow        auto __it = __table.find (__key);
152f44bd93bSMarshall Clow        return __it == __table.end() ? __default_value_ : __it->second;
153f44bd93bSMarshall Clow    }
154f44bd93bSMarshall Clow};
155f44bd93bSMarshall Clow
156f44bd93bSMarshall Clow
157f44bd93bSMarshall Clow//  Special case small numeric values; use an array
158f44bd93bSMarshall Clowtemplate<class _Key, typename _Value, class _Hash, class _BinaryPredicate>
159f44bd93bSMarshall Clowclass _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, true> {
160f44bd93bSMarshall Clowprivate:
161f44bd93bSMarshall Clow    typedef _Value value_type;
162f44bd93bSMarshall Clow    typedef _Key   key_type;
163f44bd93bSMarshall Clow
1640b8da5faSArthur O'Dwyer    typedef typename make_unsigned<key_type>::type unsigned_key_type;
165971e9c80SNikolas Klauser    typedef std::array<value_type, 256> skip_map;
166f44bd93bSMarshall Clow    skip_map __table;
167f44bd93bSMarshall Clow
168f44bd93bSMarshall Clowpublic:
169f44bd93bSMarshall Clow    _LIBCPP_INLINE_VISIBILITY
1700b8da5faSArthur O'Dwyer    _BMSkipTable(size_t /*__sz*/, _Value __default, _Hash /*__hf*/, _BinaryPredicate /*__pred*/)
171f44bd93bSMarshall Clow    {
172f44bd93bSMarshall Clow        std::fill_n(__table.begin(), __table.size(), __default);
173f44bd93bSMarshall Clow    }
174f44bd93bSMarshall Clow
175f44bd93bSMarshall Clow    _LIBCPP_INLINE_VISIBILITY
176f44bd93bSMarshall Clow    void insert(key_type __key, value_type __val)
177f44bd93bSMarshall Clow    {
178f44bd93bSMarshall Clow        __table[static_cast<unsigned_key_type>(__key)] = __val;
179f44bd93bSMarshall Clow    }
180f44bd93bSMarshall Clow
181f44bd93bSMarshall Clow    _LIBCPP_INLINE_VISIBILITY
182f44bd93bSMarshall Clow    value_type operator [](key_type __key) const
183f44bd93bSMarshall Clow    {
184f44bd93bSMarshall Clow        return __table[static_cast<unsigned_key_type>(__key)];
185f44bd93bSMarshall Clow    }
186f44bd93bSMarshall Clow};
187f44bd93bSMarshall Clow
188f44bd93bSMarshall Clow
189f44bd93bSMarshall Clowtemplate <class _RandomAccessIterator1,
190f44bd93bSMarshall Clow          class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>,
191f44bd93bSMarshall Clow          class _BinaryPredicate = equal_to<>>
192971e9c80SNikolas Klauserclass _LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER _LIBCPP_TEMPLATE_VIS boyer_moore_searcher {
193f44bd93bSMarshall Clowprivate:
194f44bd93bSMarshall Clow    typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type difference_type;
195f44bd93bSMarshall Clow    typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type      value_type;
196f44bd93bSMarshall Clow    typedef _BMSkipTable<value_type, difference_type, _Hash, _BinaryPredicate,
1976491d99eSArthur O'Dwyer                    is_integral<value_type>::value && // what about enums?
198f44bd93bSMarshall Clow                    sizeof(value_type) == 1 &&
199f44bd93bSMarshall Clow                    is_same<_Hash, hash<value_type>>::value &&
200f44bd93bSMarshall Clow                    is_same<_BinaryPredicate, equal_to<>>::value
201f44bd93bSMarshall Clow            > skip_table_type;
202f44bd93bSMarshall Clow
203f44bd93bSMarshall Clowpublic:
204f44bd93bSMarshall Clow    boyer_moore_searcher(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l,
205f44bd93bSMarshall Clow                _Hash __hf = _Hash(), _BinaryPredicate __pred = _BinaryPredicate())
206f44bd93bSMarshall Clow            : __first_(__f), __last_(__l), __pred_(__pred),
207f44bd93bSMarshall Clow              __pattern_length_(_VSTD::distance(__first_, __last_)),
208f44bd93bSMarshall Clow              __skip_{make_shared<skip_table_type>(__pattern_length_, -1, __hf, __pred_)},
209f44bd93bSMarshall Clow              __suffix_{make_shared<vector<difference_type>>(__pattern_length_ + 1)}
210f44bd93bSMarshall Clow        {
211f44bd93bSMarshall Clow    //  build the skip table
212f44bd93bSMarshall Clow        for ( difference_type __i = 0; __f != __l; ++__f, (void) ++__i )
213f44bd93bSMarshall Clow            __skip_->insert(*__f, __i);
214f44bd93bSMarshall Clow
215f44bd93bSMarshall Clow        this->__build_suffix_table ( __first_, __last_, __pred_ );
216f44bd93bSMarshall Clow        }
217f44bd93bSMarshall Clow
218f44bd93bSMarshall Clow    template <typename _RandomAccessIterator2>
21928cc4ddeSMarshall Clow    pair<_RandomAccessIterator2, _RandomAccessIterator2>
220f44bd93bSMarshall Clow    operator ()(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const
221f44bd93bSMarshall Clow    {
222f7558068SNikolas Klauser        static_assert(__is_same_uncvref<typename iterator_traits<_RandomAccessIterator1>::value_type,
223f7558068SNikolas Klauser                                        typename iterator_traits<_RandomAccessIterator2>::value_type>::value,
224f44bd93bSMarshall Clow                      "Corpus and Pattern iterators must point to the same type");
225f44bd93bSMarshall Clow
22628cc4ddeSMarshall Clow        if (__f      == __l )    return make_pair(__l, __l); // empty corpus
22728cc4ddeSMarshall Clow        if (__first_ == __last_) return make_pair(__f, __f); // empty pattern
228f44bd93bSMarshall Clow
229f44bd93bSMarshall Clow    //  If the pattern is larger than the corpus, we can't find it!
230f44bd93bSMarshall Clow        if ( __pattern_length_ > _VSTD::distance(__f, __l))
23128cc4ddeSMarshall Clow            return make_pair(__l, __l);
232f44bd93bSMarshall Clow
233f44bd93bSMarshall Clow    //  Do the search
234f44bd93bSMarshall Clow        return this->__search(__f, __l);
235f44bd93bSMarshall Clow    }
236f44bd93bSMarshall Clow
23766dea85bSJoe Loserprivate:
238f44bd93bSMarshall Clow    _RandomAccessIterator1               __first_;
239f44bd93bSMarshall Clow    _RandomAccessIterator1               __last_;
240f44bd93bSMarshall Clow    _BinaryPredicate                     __pred_;
241f44bd93bSMarshall Clow    difference_type                      __pattern_length_;
242f44bd93bSMarshall Clow    shared_ptr<skip_table_type>          __skip_;
243f44bd93bSMarshall Clow    shared_ptr<vector<difference_type>>  __suffix_;
244f44bd93bSMarshall Clow
245f44bd93bSMarshall Clow    template <typename _RandomAccessIterator2>
24628cc4ddeSMarshall Clow    pair<_RandomAccessIterator2, _RandomAccessIterator2>
24728cc4ddeSMarshall Clow    __search(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const
248f44bd93bSMarshall Clow    {
249f44bd93bSMarshall Clow        _RandomAccessIterator2 __cur = __f;
250f44bd93bSMarshall Clow        const _RandomAccessIterator2 __last = __l - __pattern_length_;
251f44bd93bSMarshall Clow        const skip_table_type &         __skip   = *__skip_.get();
252f44bd93bSMarshall Clow        const vector<difference_type> & __suffix = *__suffix_.get();
253f44bd93bSMarshall Clow
254f44bd93bSMarshall Clow        while (__cur <= __last)
255f44bd93bSMarshall Clow        {
256f44bd93bSMarshall Clow
257f44bd93bSMarshall Clow        //  Do we match right where we are?
258f44bd93bSMarshall Clow            difference_type __j = __pattern_length_;
259f44bd93bSMarshall Clow            while (__pred_(__first_ [__j-1], __cur [__j-1])) {
260f44bd93bSMarshall Clow                __j--;
261f44bd93bSMarshall Clow            //  We matched - we're done!
262f44bd93bSMarshall Clow                if ( __j == 0 )
26328cc4ddeSMarshall Clow                    return make_pair(__cur, __cur + __pattern_length_);
264f44bd93bSMarshall Clow                }
265f44bd93bSMarshall Clow
266f44bd93bSMarshall Clow        //  Since we didn't match, figure out how far to skip forward
267f44bd93bSMarshall Clow            difference_type __k = __skip[__cur [ __j - 1 ]];
268f44bd93bSMarshall Clow            difference_type __m = __j - __k - 1;
269f44bd93bSMarshall Clow            if (__k < __j && __m > __suffix[ __j ])
270f44bd93bSMarshall Clow                __cur += __m;
271f44bd93bSMarshall Clow            else
272f44bd93bSMarshall Clow                __cur += __suffix[ __j ];
273f44bd93bSMarshall Clow        }
274f44bd93bSMarshall Clow
27528cc4ddeSMarshall Clow        return make_pair(__l, __l);     // We didn't find anything
276f44bd93bSMarshall Clow    }
277f44bd93bSMarshall Clow
278f44bd93bSMarshall Clow
279f44bd93bSMarshall Clow    template<typename _Iterator, typename _Container>
280f44bd93bSMarshall Clow    void __compute_bm_prefix ( _Iterator __f, _Iterator __l, _BinaryPredicate __pred, _Container &__prefix )
281f44bd93bSMarshall Clow    {
2820b8da5faSArthur O'Dwyer        const size_t __count = _VSTD::distance(__f, __l);
283f44bd93bSMarshall Clow
284f44bd93bSMarshall Clow        __prefix[0] = 0;
2850b8da5faSArthur O'Dwyer        size_t __k = 0;
2860b8da5faSArthur O'Dwyer        for ( size_t __i = 1; __i < __count; ++__i )
287f44bd93bSMarshall Clow        {
288f44bd93bSMarshall Clow            while ( __k > 0 && !__pred ( __f[__k], __f[__i] ))
289f44bd93bSMarshall Clow                __k = __prefix [ __k - 1 ];
290f44bd93bSMarshall Clow
291f44bd93bSMarshall Clow            if ( __pred ( __f[__k], __f[__i] ))
292f44bd93bSMarshall Clow                __k++;
293f44bd93bSMarshall Clow            __prefix [ __i ] = __k;
294f44bd93bSMarshall Clow        }
295f44bd93bSMarshall Clow    }
296f44bd93bSMarshall Clow
297f44bd93bSMarshall Clow    void __build_suffix_table(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l,
298f44bd93bSMarshall Clow                                                    _BinaryPredicate __pred)
299f44bd93bSMarshall Clow    {
3000b8da5faSArthur O'Dwyer        const size_t __count = _VSTD::distance(__f, __l);
301f44bd93bSMarshall Clow        vector<difference_type> & __suffix = *__suffix_.get();
302f44bd93bSMarshall Clow        if (__count > 0)
303f44bd93bSMarshall Clow        {
304971e9c80SNikolas Klauser            vector<difference_type> __scratch(__count);
305f44bd93bSMarshall Clow
306f44bd93bSMarshall Clow            __compute_bm_prefix(__f, __l, __pred, __scratch);
3070b8da5faSArthur O'Dwyer            for ( size_t __i = 0; __i <= __count; __i++ )
308f44bd93bSMarshall Clow                __suffix[__i] = __count - __scratch[__count-1];
309f44bd93bSMarshall Clow
3106491d99eSArthur O'Dwyer            typedef reverse_iterator<_RandomAccessIterator1> _RevIter;
311f44bd93bSMarshall Clow            __compute_bm_prefix(_RevIter(__l), _RevIter(__f), __pred, __scratch);
312f44bd93bSMarshall Clow
3130b8da5faSArthur O'Dwyer            for ( size_t __i = 0; __i < __count; __i++ )
314f44bd93bSMarshall Clow            {
3150b8da5faSArthur O'Dwyer                const size_t     __j = __count - __scratch[__i];
316f44bd93bSMarshall Clow                const difference_type __k = __i     - __scratch[__i] + 1;
317f44bd93bSMarshall Clow
318f44bd93bSMarshall Clow                if (__suffix[__j] > __k)
319f44bd93bSMarshall Clow                    __suffix[__j] = __k;
320f44bd93bSMarshall Clow            }
321f44bd93bSMarshall Clow        }
322f44bd93bSMarshall Clow    }
323f44bd93bSMarshall Clow
324f44bd93bSMarshall Clow};
325f44bd93bSMarshall Clow
326f44bd93bSMarshall Clowtemplate<class _RandomAccessIterator,
327f44bd93bSMarshall Clow         class _Hash = hash<typename iterator_traits<_RandomAccessIterator>::value_type>,
328f44bd93bSMarshall Clow         class _BinaryPredicate = equal_to<>>
329971e9c80SNikolas Klauser_LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER _LIBCPP_INLINE_VISIBILITY
330f44bd93bSMarshall Clowboyer_moore_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>
331f44bd93bSMarshall Clowmake_boyer_moore_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l,
332f44bd93bSMarshall Clow                    _Hash __hf = _Hash(), _BinaryPredicate __p = _BinaryPredicate ())
333f44bd93bSMarshall Clow{
334f44bd93bSMarshall Clow    return boyer_moore_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>(__f, __l, __hf, __p);
335f44bd93bSMarshall Clow}
336f44bd93bSMarshall Clow
337f44bd93bSMarshall Clow// boyer-moore-horspool
338f44bd93bSMarshall Clowtemplate <class _RandomAccessIterator1,
339f44bd93bSMarshall Clow          class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>,
340f44bd93bSMarshall Clow          class _BinaryPredicate = equal_to<>>
341971e9c80SNikolas Klauserclass _LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER _LIBCPP_TEMPLATE_VIS boyer_moore_horspool_searcher {
342f44bd93bSMarshall Clowprivate:
343f44bd93bSMarshall Clow    typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type difference_type;
344f44bd93bSMarshall Clow    typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type      value_type;
345f44bd93bSMarshall Clow    typedef _BMSkipTable<value_type, difference_type, _Hash, _BinaryPredicate,
3466491d99eSArthur O'Dwyer                    is_integral<value_type>::value && // what about enums?
347f44bd93bSMarshall Clow                    sizeof(value_type) == 1 &&
348f44bd93bSMarshall Clow                    is_same<_Hash, hash<value_type>>::value &&
349f44bd93bSMarshall Clow                    is_same<_BinaryPredicate, equal_to<>>::value
350f44bd93bSMarshall Clow            > skip_table_type;
351f44bd93bSMarshall Clow
352f44bd93bSMarshall Clowpublic:
353f44bd93bSMarshall Clow    boyer_moore_horspool_searcher(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l,
354f44bd93bSMarshall Clow                _Hash __hf = _Hash(), _BinaryPredicate __pred = _BinaryPredicate())
355f44bd93bSMarshall Clow            : __first_(__f), __last_(__l), __pred_(__pred),
356f44bd93bSMarshall Clow              __pattern_length_(_VSTD::distance(__first_, __last_)),
357f44bd93bSMarshall Clow              __skip_{_VSTD::make_shared<skip_table_type>(__pattern_length_, __pattern_length_, __hf, __pred_)}
358f44bd93bSMarshall Clow        {
359f44bd93bSMarshall Clow    //  build the skip table
360f44bd93bSMarshall Clow            if ( __f != __l )
361f44bd93bSMarshall Clow            {
362f44bd93bSMarshall Clow                __l = __l - 1;
363f44bd93bSMarshall Clow                for ( difference_type __i = 0; __f != __l; ++__f, (void) ++__i )
364f44bd93bSMarshall Clow                    __skip_->insert(*__f, __pattern_length_ - 1 - __i);
365f44bd93bSMarshall Clow            }
366f44bd93bSMarshall Clow        }
367f44bd93bSMarshall Clow
368f44bd93bSMarshall Clow    template <typename _RandomAccessIterator2>
36928cc4ddeSMarshall Clow    pair<_RandomAccessIterator2, _RandomAccessIterator2>
370f44bd93bSMarshall Clow    operator ()(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const
371f44bd93bSMarshall Clow    {
372f7558068SNikolas Klauser        static_assert(__is_same_uncvref<typename std::iterator_traits<_RandomAccessIterator1>::value_type,
373f7558068SNikolas Klauser                                        typename std::iterator_traits<_RandomAccessIterator2>::value_type>::value,
374f44bd93bSMarshall Clow                      "Corpus and Pattern iterators must point to the same type");
375f44bd93bSMarshall Clow
37628cc4ddeSMarshall Clow        if (__f      == __l )    return make_pair(__l, __l); // empty corpus
37728cc4ddeSMarshall Clow        if (__first_ == __last_) return make_pair(__f, __f); // empty pattern
378f44bd93bSMarshall Clow
379f44bd93bSMarshall Clow    //  If the pattern is larger than the corpus, we can't find it!
380f44bd93bSMarshall Clow        if ( __pattern_length_ > _VSTD::distance(__f, __l))
38128cc4ddeSMarshall Clow            return make_pair(__l, __l);
382f44bd93bSMarshall Clow
383f44bd93bSMarshall Clow    //  Do the search
384f44bd93bSMarshall Clow        return this->__search(__f, __l);
385f44bd93bSMarshall Clow    }
386f44bd93bSMarshall Clow
387f44bd93bSMarshall Clowprivate:
388f44bd93bSMarshall Clow    _RandomAccessIterator1      __first_;
389f44bd93bSMarshall Clow    _RandomAccessIterator1      __last_;
390f44bd93bSMarshall Clow    _BinaryPredicate            __pred_;
391f44bd93bSMarshall Clow    difference_type             __pattern_length_;
392f44bd93bSMarshall Clow    shared_ptr<skip_table_type> __skip_;
393f44bd93bSMarshall Clow
394f44bd93bSMarshall Clow    template <typename _RandomAccessIterator2>
39528cc4ddeSMarshall Clow    pair<_RandomAccessIterator2, _RandomAccessIterator2>
39628cc4ddeSMarshall Clow    __search ( _RandomAccessIterator2 __f, _RandomAccessIterator2 __l ) const {
397f44bd93bSMarshall Clow        _RandomAccessIterator2 __cur = __f;
398f44bd93bSMarshall Clow        const _RandomAccessIterator2 __last = __l - __pattern_length_;
399f44bd93bSMarshall Clow        const skip_table_type & __skip = *__skip_.get();
400f44bd93bSMarshall Clow
401f44bd93bSMarshall Clow        while (__cur <= __last)
402f44bd93bSMarshall Clow        {
403f44bd93bSMarshall Clow        //  Do we match right where we are?
404f44bd93bSMarshall Clow            difference_type __j = __pattern_length_;
405f44bd93bSMarshall Clow            while (__pred_(__first_[__j-1], __cur[__j-1]))
406f44bd93bSMarshall Clow            {
407f44bd93bSMarshall Clow                __j--;
408f44bd93bSMarshall Clow            //  We matched - we're done!
409f44bd93bSMarshall Clow                if ( __j == 0 )
41028cc4ddeSMarshall Clow                    return make_pair(__cur, __cur + __pattern_length_);
411f44bd93bSMarshall Clow            }
412f44bd93bSMarshall Clow            __cur += __skip[__cur[__pattern_length_-1]];
413f44bd93bSMarshall Clow        }
414f44bd93bSMarshall Clow
41528cc4ddeSMarshall Clow        return make_pair(__l, __l);
416f44bd93bSMarshall Clow    }
417f44bd93bSMarshall Clow};
418f44bd93bSMarshall Clow
419f44bd93bSMarshall Clowtemplate<class _RandomAccessIterator,
420f44bd93bSMarshall Clow         class _Hash = hash<typename iterator_traits<_RandomAccessIterator>::value_type>,
421f44bd93bSMarshall Clow         class _BinaryPredicate = equal_to<>>
422971e9c80SNikolas Klauser_LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER _LIBCPP_INLINE_VISIBILITY
423f44bd93bSMarshall Clowboyer_moore_horspool_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>
424f44bd93bSMarshall Clowmake_boyer_moore_horspool_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l,
425f44bd93bSMarshall Clow                    _Hash __hf = _Hash(), _BinaryPredicate __p = _BinaryPredicate ())
426f44bd93bSMarshall Clow{
427f44bd93bSMarshall Clow    return boyer_moore_horspool_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>(__f, __l, __hf, __p);
428f44bd93bSMarshall Clow}
429f44bd93bSMarshall Clow
430f44bd93bSMarshall Clow#endif // _LIBCPP_STD_VER > 11
431205c333cSMarshall Clow
432205c333cSMarshall Clow_LIBCPP_END_NAMESPACE_LFTS
433205c333cSMarshall Clow
434a016efb1SEric Fiselier_LIBCPP_POP_MACROS
435a016efb1SEric Fiselier
436205c333cSMarshall Clow#endif /* _LIBCPP_EXPERIMENTAL_FUNCTIONAL */
437