[libc++] Implement std::boyer_moore{, _horspool}_searcher

This mostly copys the `<experimental/functional>` stuff and updates the code to current libc++ style.

Reviewed By: ldionne, #libc

Spies: nlopes, adamdebreceni, arichardson, libcxx-commits, mgorny

Differential Revision: https://reviews.llvm.org/D121074
This commit is contained in:
Nikolas Klauser 2022-06-17 16:02:53 +02:00
parent e1f1407beb
commit 971e9c80e9
39 changed files with 459 additions and 109 deletions

View File

@ -84,7 +84,7 @@ Status
------------------------------------------------- -----------------
``__cpp_lib_bool_constant`` ``201505L``
------------------------------------------------- -----------------
``__cpp_lib_boyer_moore_searcher`` *unimplemented*
``__cpp_lib_boyer_moore_searcher`` ``201603L``
------------------------------------------------- -----------------
``__cpp_lib_byte`` ``201603L``
------------------------------------------------- -----------------

View File

@ -142,6 +142,10 @@ API Changes
``_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS``, this ensures that the members of
``allocator<void>`` removed in C++20 can be accessed.
- The experimental versions of ``boyer_moore_searcher`` and ``boyer_moore_horspool_searcher``
will be removed in LLVM 17. You can disable the deprecation warnings by defining
``_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS``.
ABI Changes
-----------

View File

@ -258,6 +258,7 @@ set(files
__functional/bind_front.h
__functional/binder1st.h
__functional/binder2nd.h
__functional/boyer_moore_searcher.h
__functional/compose.h
__functional/default_searcher.h
__functional/function.h

View File

@ -789,13 +789,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
# if !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS)
# if __has_attribute(deprecated)
# define _LIBCPP_DEPRECATED __attribute__((deprecated))
# define _LIBCPP_DEPRECATED_(m) __attribute__((deprected(m)))
# elif _LIBCPP_STD_VER > 11
# define _LIBCPP_DEPRECATED [[deprecated]]
# define _LIBCPP_DEPRECATED_(m) [[deprecated(m)]]
# else
# define _LIBCPP_DEPRECATED
# define _LIBCPP_DEPRECATED_(m)
# endif
# else
# define _LIBCPP_DEPRECATED
# define _LIBCPP_DEPRECATED_(m)
# endif
# if !defined(_LIBCPP_CXX03_LANG)
@ -895,8 +899,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
# endif
# ifndef _LIBCPP_HAS_NO_ASAN
extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container(const void*, const void*, const void*,
const void*);
extern "C" _LIBCPP_FUNC_VIS void
__sanitizer_annotate_contiguous_container(const void*, const void*, const void*, const void*);
# endif
// Try to find out if RTTI is disabled.

View File

@ -0,0 +1,313 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___FUNCTIONAL_BOYER_MOORE_SEARCHER_H
#define _LIBCPP___FUNCTIONAL_BOYER_MOORE_SEARCHER_H
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
#include <__algorithm/fill_n.h>
#include <__config>
#include <__functional/hash.h>
#include <__functional/operations.h>
#include <__iterator/distance.h>
#include <__iterator/iterator_traits.h>
#include <__memory/shared_ptr.h>
#include <__utility/pair.h>
#include <array>
#include <unordered_map>
#include <vector>
#if _LIBCPP_STD_VER > 14
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Key,
class _Value,
class _Hash,
class _BinaryPredicate,
bool /*useArray*/>
class _BMSkipTable;
// General case for BM data searching; use a map
template <class _Key,
class _Value,
class _Hash,
class _BinaryPredicate>
class _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, false> {
private:
using value_type = _Value;
using key_type = _Key;
const value_type __default_value_;
unordered_map<_Key, _Value, _Hash, _BinaryPredicate> __table_;
public:
_LIBCPP_HIDE_FROM_ABI
explicit _BMSkipTable(size_t __sz, value_type __default_value, _Hash __hash, _BinaryPredicate __pred)
: __default_value_(__default_value),
__table_(__sz, __hash, __pred) {}
_LIBCPP_HIDE_FROM_ABI void insert(const key_type& __key, value_type __val) {
__table_[__key] = __val;
}
_LIBCPP_HIDE_FROM_ABI value_type operator[](const key_type& __key) const {
auto __it = __table_.find(__key);
return __it == __table_.end() ? __default_value_ : __it->second;
}
};
// Special case small numeric values; use an array
template <class _Key,
class _Value,
class _Hash,
class _BinaryPredicate>
class _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, true> {
private:
using value_type = _Value;
using key_type = _Key;
using unsigned_key_type = make_unsigned_t<key_type>;
std::array<value_type, 256> __table_;
static_assert(numeric_limits<unsigned_key_type>::max() < 256);
public:
_LIBCPP_HIDE_FROM_ABI explicit _BMSkipTable(size_t, value_type __default_value, _Hash, _BinaryPredicate) {
std::fill_n(__table_.data(), __table_.size(), __default_value);
}
_LIBCPP_HIDE_FROM_ABI void insert(key_type __key, value_type __val) {
__table_[static_cast<unsigned_key_type>(__key)] = __val;
}
_LIBCPP_HIDE_FROM_ABI value_type operator[](key_type __key) const {
return __table_[static_cast<unsigned_key_type>(__key)];
}
};
template <class _RandomAccessIterator1,
class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>,
class _BinaryPredicate = equal_to<>>
class _LIBCPP_TEMPLATE_VIS boyer_moore_searcher {
private:
using difference_type = typename std::iterator_traits<_RandomAccessIterator1>::difference_type;
using value_type = typename std::iterator_traits<_RandomAccessIterator1>::value_type;
using __skip_table_type = _BMSkipTable<value_type,
difference_type,
_Hash,
_BinaryPredicate,
is_integral_v<value_type>
&& sizeof(value_type) == 1
&& is_same_v<_Hash, hash<value_type>>
&& is_same_v<_BinaryPredicate, equal_to<>>>;
public:
boyer_moore_searcher(_RandomAccessIterator1 __first,
_RandomAccessIterator1 __last,
_Hash __hash = _Hash(),
_BinaryPredicate __pred = _BinaryPredicate())
: __first_(__first),
__last_(__last),
__pred_(__pred),
__pattern_length_(__last - __first),
__skip_table_(std::make_shared<__skip_table_type>(__pattern_length_, -1, __hash, __pred_)),
__suffix_(std::__allocate_shared_unbounded_array<difference_type[]>(
allocator<difference_type>(), __pattern_length_ + 1)) {
difference_type __i = 0;
while (__first != __last) {
__skip_table_->insert(*__first, __i);
++__first;
++__i;
}
__build_suffix_table(__first_, __last_, __pred_);
}
template <class _RandomAccessIterator2>
pair<_RandomAccessIterator2, _RandomAccessIterator2>
operator()(_RandomAccessIterator2 __first, _RandomAccessIterator2 __last) const {
static_assert(__is_same_uncvref<typename iterator_traits<_RandomAccessIterator1>::value_type,
typename iterator_traits<_RandomAccessIterator2>::value_type>::value,
"Corpus and Pattern iterators must point to the same type");
if (__first == __last)
return std::make_pair(__last, __last);
if (__first_ == __last_)
return std::make_pair(__first, __first);
if (__pattern_length_ > (__last - __first))
return std::make_pair(__last, __last);
return __search(__first, __last);
}
private:
_RandomAccessIterator1 __first_;
_RandomAccessIterator1 __last_;
_BinaryPredicate __pred_;
difference_type __pattern_length_;
shared_ptr<__skip_table_type> __skip_table_;
shared_ptr<difference_type[]> __suffix_;
template <class _RandomAccessIterator2>
pair<_RandomAccessIterator2, _RandomAccessIterator2>
__search(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const {
_RandomAccessIterator2 __current = __f;
const _RandomAccessIterator2 __last = __l - __pattern_length_;
const __skip_table_type& __skip_table = *__skip_table_;
while (__current <= __last) {
difference_type __j = __pattern_length_;
while (__pred_(__first_[__j - 1], __current[__j - 1])) {
--__j;
if (__j == 0)
return std::make_pair(__current, __current + __pattern_length_);
}
difference_type __k = __skip_table[__current[__j - 1]];
difference_type __m = __j - __k - 1;
if (__k < __j && __m > __suffix_[__j])
__current += __m;
else
__current += __suffix_[__j];
}
return std::make_pair(__l, __l);
}
template <class _Iterator, class _Container>
void __compute_bm_prefix(_Iterator __first, _Iterator __last, _BinaryPredicate __pred, _Container& __prefix) {
const size_t __count = __last - __first;
__prefix[0] = 0;
size_t __k = 0;
for (size_t __i = 1; __i != __count; ++__i) {
while (__k > 0 && !__pred(__first[__k], __first[__i]))
__k = __prefix[__k - 1];
if (__pred(__first[__k], __first[__i]))
++__k;
__prefix[__i] = __k;
}
}
void __build_suffix_table(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _BinaryPredicate __pred) {
const size_t __count = __last - __first;
if (__count == 0)
return;
vector<difference_type> __scratch(__count);
__compute_bm_prefix(__first, __last, __pred, __scratch);
for (size_t __i = 0; __i <= __count; ++__i)
__suffix_[__i] = __count - __scratch[__count - 1];
using _ReverseIter = reverse_iterator<_RandomAccessIterator1>;
__compute_bm_prefix(_ReverseIter(__last), _ReverseIter(__first), __pred, __scratch);
for (size_t __i = 0; __i != __count; ++__i) {
const size_t __j = __count - __scratch[__i];
const difference_type __k = __i - __scratch[__i] + 1;
if (__suffix_[__j] > __k)
__suffix_[__j] = __k;
}
}
};
template <class _RandomAccessIterator1,
class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>,
class _BinaryPredicate = equal_to<>>
class _LIBCPP_TEMPLATE_VIS boyer_moore_horspool_searcher {
private:
using difference_type = typename iterator_traits<_RandomAccessIterator1>::difference_type;
using value_type = typename iterator_traits<_RandomAccessIterator1>::value_type;
using __skip_table_type = _BMSkipTable<value_type,
difference_type,
_Hash,
_BinaryPredicate,
is_integral_v<value_type>
&& sizeof(value_type) == 1
&& is_same_v<_Hash, hash<value_type>>
&& is_same_v<_BinaryPredicate, equal_to<>>>;
public:
boyer_moore_horspool_searcher(_RandomAccessIterator1 __first,
_RandomAccessIterator1 __last,
_Hash __hash = _Hash(),
_BinaryPredicate __pred = _BinaryPredicate())
: __first_(__first),
__last_(__last),
__pred_(__pred),
__pattern_length_(__last - __first),
__skip_table_(std::make_shared<__skip_table_type>(__pattern_length_, __pattern_length_, __hash, __pred_)) {
if (__first == __last)
return;
--__last;
difference_type __i = 0;
while (__first != __last) {
__skip_table_->insert(*__first, __pattern_length_ - 1 - __i);
++__first;
++__i;
}
}
template <class _RandomAccessIterator2>
pair<_RandomAccessIterator2, _RandomAccessIterator2>
operator()(_RandomAccessIterator2 __first, _RandomAccessIterator2 __last) const {
static_assert(__is_same_uncvref<typename std::iterator_traits<_RandomAccessIterator1>::value_type,
typename std::iterator_traits<_RandomAccessIterator2>::value_type>::value,
"Corpus and Pattern iterators must point to the same type");
if (__first == __last)
return std::make_pair(__last, __last);
if (__first_ == __last_)
return std::make_pair(__first, __first);
if (__pattern_length_ > __last - __first)
return std::make_pair(__last, __last);
return __search(__first, __last);
}
private:
_RandomAccessIterator1 __first_;
_RandomAccessIterator1 __last_;
_BinaryPredicate __pred_;
difference_type __pattern_length_;
shared_ptr<__skip_table_type> __skip_table_;
template <class _RandomAccessIterator2>
pair<_RandomAccessIterator2, _RandomAccessIterator2>
__search(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const {
_RandomAccessIterator2 __current = __f;
const _RandomAccessIterator2 __last = __l - __pattern_length_;
const __skip_table_type& __skip_table = *__skip_table_;
while (__current <= __last) {
difference_type __j = __pattern_length_;
while (__pred_(__first_[__j - 1], __current[__j - 1])) {
--__j;
if (__j == 0)
return std::make_pair(__current, __current + __pattern_length_);
}
__current += __skip_table[__current[__pattern_length_ - 1]];
}
return std::make_pair(__l, __l);
}
};
_LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP_STD_VER > 14
#endif // _LIBCPP___FUNCTIONAL_BOYER_MOORE_SEARCHER_H

View File

@ -29,17 +29,23 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER > 17
template<class _Tp, class ..._Args, class = decltype(
::new (declval<void*>()) _Tp(declval<_Args>()...)
)>
_LIBCPP_HIDE_FROM_ABI
constexpr _Tp* construct_at(_Tp* __location, _Args&& ...__args) {
_LIBCPP_ASSERT(__location != nullptr, "null pointer given to construct_at");
return ::new (_VSTD::__voidify(*__location)) _Tp(_VSTD::forward<_Args>(__args)...);
template <class _Tp, class... _Args, class = decltype(::new(declval<void*>()) _Tp(declval<_Args>()...))>
_LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* __location, _Args&&... __args) {
_LIBCPP_ASSERT(__location != nullptr, "null pointer given to construct_at");
return ::new (_VSTD::__voidify(*__location)) _Tp(_VSTD::forward<_Args>(__args)...);
}
#endif
template <class _Tp, class... _Args, class = decltype(::new(declval<void*>()) _Tp(declval<_Args>()...))>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* __construct_at(_Tp* __location, _Args&&... __args) {
#if _LIBCPP_STD_VER > 17
return std::construct_at(__location, std::forward<_Args>(__args)...);
#else
return ::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...);
#endif
}
// destroy_at
// The internal functions are available regardless of the language version (with the exception of the `__destroy_at`

View File

@ -964,7 +964,7 @@ shared_ptr<_Tp> make_shared(_Args&& ...__args)
return _VSTD::allocate_shared<_Tp>(allocator<_Tp>(), _VSTD::forward<_Args>(__args)...);
}
#if _LIBCPP_STD_VER > 17
#if _LIBCPP_STD_VER > 14
template <size_t _Alignment>
struct __sp_aligned_storage {
@ -1042,7 +1042,7 @@ template<class _Array, class _Alloc, class... _Arg>
_LIBCPP_HIDE_FROM_ABI
shared_ptr<_Array> __allocate_shared_unbounded_array(const _Alloc& __a, size_t __n, _Arg&& ...__arg)
{
static_assert(is_unbounded_array_v<_Array>);
static_assert(__libcpp_is_unbounded_array<_Array>::value);
// We compute the number of bytes necessary to hold the control block and the
// array elements. Then, we allocate an array of properly-aligned dummy structs
// large enough to hold the control block and array. This allows shifting the
@ -1052,7 +1052,7 @@ shared_ptr<_Array> __allocate_shared_unbounded_array(const _Alloc& __a, size_t _
using _StorageAlloc = __allocator_traits_rebind_t<_Alloc, _AlignedStorage>;
__allocation_guard<_StorageAlloc> __guard(__a, _ControlBlock::__bytes_for(__n) / sizeof(_AlignedStorage));
_ControlBlock* __control_block = reinterpret_cast<_ControlBlock*>(std::addressof(*__guard.__get()));
std::construct_at(__control_block, __a, __n, std::forward<_Arg>(__arg)...);
std::__construct_at(__control_block, __a, __n, std::forward<_Arg>(__arg)...);
__guard.__release_ptr();
return shared_ptr<_Array>::__create_with_control_block(__control_block->__get_data(), __control_block);
}
@ -1105,17 +1105,21 @@ template<class _Array, class _Alloc, class... _Arg>
_LIBCPP_HIDE_FROM_ABI
shared_ptr<_Array> __allocate_shared_bounded_array(const _Alloc& __a, _Arg&& ...__arg)
{
static_assert(is_bounded_array_v<_Array>);
static_assert(__libcpp_is_bounded_array<_Array>::value);
using _ControlBlock = __bounded_array_control_block<_Array, _Alloc>;
using _ControlBlockAlloc = __allocator_traits_rebind_t<_Alloc, _ControlBlock>;
__allocation_guard<_ControlBlockAlloc> __guard(__a, 1);
_ControlBlock* __control_block = reinterpret_cast<_ControlBlock*>(std::addressof(*__guard.__get()));
std::construct_at(__control_block, __a, std::forward<_Arg>(__arg)...);
std::__construct_at(__control_block, __a, std::forward<_Arg>(__arg)...);
__guard.__release_ptr();
return shared_ptr<_Array>::__create_with_control_block(__control_block->__get_data(), __control_block);
}
#endif // _LIBCPP_STD_VER > 14
#if _LIBCPP_STD_VER > 17
template<class _Tp, class _Alloc, class = __enable_if_t<is_bounded_array<_Tp>::value>>
_LIBCPP_HIDE_FROM_ABI
shared_ptr<_Tp> allocate_shared(const _Alloc& __a)

View File

@ -347,10 +347,6 @@ uninitialized_move_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofir
__unreachable_sentinel(), __iter_move);
}
#endif // _LIBCPP_STD_VER > 14
#if _LIBCPP_STD_VER > 17
// Destroys every element in the range [first, last) FROM RIGHT TO LEFT using allocator
// destruction. If elements are themselves C-style arrays, they are recursively destroyed
// in the same manner.
@ -370,7 +366,7 @@ constexpr void __allocator_destroy_multidimensional(_Alloc& __alloc, _BidirIter
return;
if constexpr (is_array_v<_ValueType>) {
static_assert(!is_unbounded_array_v<_ValueType>,
static_assert(!__libcpp_is_unbounded_array<_ValueType>::value,
"arrays of unbounded arrays don't exist, but if they did we would mess up here");
using _Element = remove_extent_t<_ValueType>;
@ -494,7 +490,7 @@ constexpr void __uninitialized_allocator_value_construct_n(_Alloc& __alloc, _Bid
__guard.__complete();
}
#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP_STD_VER > 14
_LIBCPP_END_NAMESPACE_STD

View File

@ -19,6 +19,9 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class> struct _LIBCPP_TEMPLATE_VIS __libcpp_is_bounded_array : false_type {};
template <class _Tp, size_t _Np> struct _LIBCPP_TEMPLATE_VIS __libcpp_is_bounded_array<_Tp[_Np]> : true_type {};
#if _LIBCPP_STD_VER > 17
template <class> struct _LIBCPP_TEMPLATE_VIS is_bounded_array : false_type {};

View File

@ -18,6 +18,9 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class> struct _LIBCPP_TEMPLATE_VIS __libcpp_is_unbounded_array : false_type {};
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS __libcpp_is_unbounded_array<_Tp[]> : true_type {};
#if _LIBCPP_STD_VER > 17
template <class> struct _LIBCPP_TEMPLATE_VIS is_unbounded_array : false_type {};

View File

@ -79,10 +79,20 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_LFTS
#ifdef _LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
# define _LIBCPP_DEPRECATED_DEFAULT_SEARCHER
# define _LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER
# define _LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER
#else
# define _LIBCPP_DEPRECATED_DEFAULT_SEARCHER _LIBCPP_DEPRECATED_("std::exprerimental::default_searcher will be removed in LLVM 17. Use std::default_searcher instead")
# 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")
# 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")
#endif
#if _LIBCPP_STD_VER > 11
// default searcher
template<class _ForwardIterator, class _BinaryPredicate = equal_to<>>
class _LIBCPP_TEMPLATE_VIS default_searcher {
class _LIBCPP_DEPRECATED_DEFAULT_SEARCHER _LIBCPP_TEMPLATE_VIS default_searcher {
public:
_LIBCPP_INLINE_VISIBILITY
default_searcher(_ForwardIterator __f, _ForwardIterator __l,
@ -106,7 +116,7 @@ private:
};
template<class _ForwardIterator, class _BinaryPredicate = equal_to<>>
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_DEPRECATED_DEFAULT_SEARCHER _LIBCPP_INLINE_VISIBILITY
default_searcher<_ForwardIterator, _BinaryPredicate>
make_default_searcher( _ForwardIterator __f, _ForwardIterator __l, _BinaryPredicate __p = _BinaryPredicate ())
{
@ -152,7 +162,7 @@ private:
typedef _Key key_type;
typedef typename make_unsigned<key_type>::type unsigned_key_type;
typedef std::array<value_type, numeric_limits<unsigned_key_type>::max()> skip_map;
typedef std::array<value_type, 256> skip_map;
skip_map __table;
public:
@ -179,7 +189,7 @@ public:
template <class _RandomAccessIterator1,
class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>,
class _BinaryPredicate = equal_to<>>
class _LIBCPP_TEMPLATE_VIS boyer_moore_searcher {
class _LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER _LIBCPP_TEMPLATE_VIS boyer_moore_searcher {
private:
typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type difference_type;
typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type value_type;
@ -291,7 +301,7 @@ private:
vector<difference_type> & __suffix = *__suffix_.get();
if (__count > 0)
{
vector<value_type> __scratch(__count);
vector<difference_type> __scratch(__count);
__compute_bm_prefix(__f, __l, __pred, __scratch);
for ( size_t __i = 0; __i <= __count; __i++ )
@ -316,7 +326,7 @@ private:
template<class _RandomAccessIterator,
class _Hash = hash<typename iterator_traits<_RandomAccessIterator>::value_type>,
class _BinaryPredicate = equal_to<>>
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER _LIBCPP_INLINE_VISIBILITY
boyer_moore_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>
make_boyer_moore_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l,
_Hash __hf = _Hash(), _BinaryPredicate __p = _BinaryPredicate ())
@ -328,7 +338,7 @@ make_boyer_moore_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l,
template <class _RandomAccessIterator1,
class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>,
class _BinaryPredicate = equal_to<>>
class _LIBCPP_TEMPLATE_VIS boyer_moore_horspool_searcher {
class _LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER _LIBCPP_TEMPLATE_VIS boyer_moore_horspool_searcher {
private:
typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type difference_type;
typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type value_type;
@ -409,7 +419,7 @@ private:
template<class _RandomAccessIterator,
class _Hash = hash<typename iterator_traits<_RandomAccessIterator>::value_type>,
class _BinaryPredicate = equal_to<>>
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER _LIBCPP_INLINE_VISIBILITY
boyer_moore_horspool_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>
make_boyer_moore_horspool_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l,
_Hash __hf = _Hash(), _BinaryPredicate __p = _BinaryPredicate ())

View File

@ -502,6 +502,7 @@ POLICY: For non-variadic implementations, the number of arguments is limited
#include <__functional/bind_front.h>
#include <__functional/binder1st.h>
#include <__functional/binder2nd.h>
#include <__functional/boyer_moore_searcher.h>
#include <__functional/compose.h>
#include <__functional/default_searcher.h>
#include <__functional/function.h>

View File

@ -624,6 +624,7 @@ module std [system] {
module bind_front { private header "__functional/bind_front.h" }
module binder1st { private header "__functional/binder1st.h" }
module binder2nd { private header "__functional/binder2nd.h" }
module boyer_moore_searcher { private header "__functional/boyer_moore_searcher.h" }
module compose { private header "__functional/compose.h" }
module default_searcher { private header "__functional/default_searcher.h" }
module function { private header "__functional/function.h" }

View File

@ -237,7 +237,7 @@ __cpp_lib_void_t 201411L <type_traits>
# define __cpp_lib_as_const 201510L
# define __cpp_lib_atomic_is_always_lock_free 201603L
# define __cpp_lib_bool_constant 201505L
// # define __cpp_lib_boyer_moore_searcher 201603L
# define __cpp_lib_boyer_moore_searcher 201603L
# define __cpp_lib_byte 201603L
# define __cpp_lib_chrono 201611L
# define __cpp_lib_clamp 201603L

View File

@ -290,6 +290,7 @@ END-SCRIPT
#include <__functional/bind_front.h> // expected-error@*:* {{use of private header from outside its module: '__functional/bind_front.h'}}
#include <__functional/binder1st.h> // expected-error@*:* {{use of private header from outside its module: '__functional/binder1st.h'}}
#include <__functional/binder2nd.h> // expected-error@*:* {{use of private header from outside its module: '__functional/binder2nd.h'}}
#include <__functional/boyer_moore_searcher.h> // expected-error@*:* {{use of private header from outside its module: '__functional/boyer_moore_searcher.h'}}
#include <__functional/compose.h> // expected-error@*:* {{use of private header from outside its module: '__functional/compose.h'}}
#include <__functional/default_searcher.h> // expected-error@*:* {{use of private header from outside its module: '__functional/default_searcher.h'}}
#include <__functional/function.h> // expected-error@*:* {{use of private header from outside its module: '__functional/function.h'}}

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
// <functional>
@ -34,6 +35,7 @@
#include <experimental/algorithm>
#include <experimental/functional>
#include <cassert>
#include <string>
#include "test_macros.h"
#include "test_iterators.h"
@ -122,9 +124,32 @@ test2()
do_search(Iter1(ij), Iter1(ij+sj), Iter2(ik), Iter2(ik+sk), Iter1(ij+6));
}
template <class Iter1, class Iter2>
void test_large_str() {
std::vector<signed char> data(257, 'a');
data[254] = 'b';
data[255] = 'b';
data[256] = 'b';
const signed char find[] = {'b', 'b', 'b'};
do_search(Iter1(data.data()), Iter1(data.data() + data.size()),
Iter2(find), Iter2(find + 3),
Iter1(data.data() + 254));
}
void test_custom_pred() {
std::string long_string(1024, '0');
auto searcher = std::experimental::make_boyer_moore_searcher(std::begin(long_string), std::end(long_string));
const char str[] = "1234";
auto ret = searcher(std::begin(str), std::end(str));
assert(ret.first == std::end(str));
assert(ret.second == std::end(str));
}
int main(int, char**) {
test<random_access_iterator<const int*>, random_access_iterator<const int*> >();
test2<random_access_iterator<const char*>, random_access_iterator<const char*> >();
test_large_str<random_access_iterator<const signed char*>, random_access_iterator<const signed char*>>();
test_custom_pred();
return 0;
}

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
// <functional>

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
// <functional>

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
// <functional>

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
// <functional>

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
// <functional>

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
// <functional>

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
// <functional>

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
// <functional>

View File

@ -9,6 +9,7 @@
// <functional>
// UNSUPPORTED: c++03, c++11
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
// default searcher
// template<class _ForwardIterator, class _BinaryPredicate = equal_to<>>

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
// <functional>

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
// <functional>

View File

@ -150,17 +150,11 @@
# error "__cpp_lib_bind_front should not be defined before c++20"
# endif
# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should be defined in c++17"
# endif
# if __cpp_lib_boyer_moore_searcher != 201603L
# error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++17"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should not be defined because it is unimplemented in libc++!"
# endif
# ifndef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should be defined in c++17"
# endif
# if __cpp_lib_boyer_moore_searcher != 201603L
# error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++17"
# endif
# ifdef __cpp_lib_constexpr_functional
@ -224,17 +218,11 @@
# error "__cpp_lib_bind_front should have the value 201907L in c++20"
# endif
# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should be defined in c++20"
# endif
# if __cpp_lib_boyer_moore_searcher != 201603L
# error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++20"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should not be defined because it is unimplemented in libc++!"
# endif
# ifndef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should be defined in c++20"
# endif
# if __cpp_lib_boyer_moore_searcher != 201603L
# error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++20"
# endif
# ifndef __cpp_lib_constexpr_functional
@ -322,17 +310,11 @@
# error "__cpp_lib_bind_front should have the value 201907L in c++2b"
# endif
# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should be defined in c++2b"
# endif
# if __cpp_lib_boyer_moore_searcher != 201603L
# error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++2b"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should not be defined because it is unimplemented in libc++!"
# endif
# ifndef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should be defined in c++2b"
# endif
# if __cpp_lib_boyer_moore_searcher != 201603L
# error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++2b"
# endif
# ifndef __cpp_lib_constexpr_functional

View File

@ -1618,17 +1618,11 @@
# error "__cpp_lib_bounded_array_traits should not be defined before c++20"
# endif
# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should be defined in c++17"
# endif
# if __cpp_lib_boyer_moore_searcher != 201603L
# error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++17"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should not be defined because it is unimplemented in libc++!"
# endif
# ifndef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should be defined in c++17"
# endif
# if __cpp_lib_boyer_moore_searcher != 201603L
# error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++17"
# endif
# ifndef __cpp_lib_byte
@ -2579,17 +2573,11 @@
# error "__cpp_lib_bounded_array_traits should have the value 201902L in c++20"
# endif
# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should be defined in c++20"
# endif
# if __cpp_lib_boyer_moore_searcher != 201603L
# error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++20"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should not be defined because it is unimplemented in libc++!"
# endif
# ifndef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should be defined in c++20"
# endif
# if __cpp_lib_boyer_moore_searcher != 201603L
# error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++20"
# endif
# ifndef __cpp_lib_byte
@ -3801,17 +3789,11 @@
# error "__cpp_lib_bounded_array_traits should have the value 201902L in c++2b"
# endif
# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should be defined in c++2b"
# endif
# if __cpp_lib_boyer_moore_searcher != 201603L
# error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++2b"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should not be defined because it is unimplemented in libc++!"
# endif
# ifndef __cpp_lib_boyer_moore_searcher
# error "__cpp_lib_boyer_moore_searcher should be defined in c++2b"
# endif
# if __cpp_lib_boyer_moore_searcher != 201603L
# error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++2b"
# endif
# ifndef __cpp_lib_byte

View File

@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14
// XFAIL: stdlib=libc++
// <functional>
@ -33,8 +32,9 @@
#include <algorithm>
#include <functional>
#include <cassert>
#include <functional>
#include <string>
#include "test_macros.h"
#include "test_iterators.h"
@ -123,9 +123,19 @@ test2()
do_search(Iter1(ij), Iter1(ij+sj), Iter2(ik), Iter2(ik+sk), Iter1(ij+6));
}
void test_custom_pred() {
std::string long_string(1024, '0');
std::boyer_moore_searcher searcher(std::begin(long_string), std::end(long_string));
const char str[] = "1234";
auto ret = searcher(std::begin(str), std::end(str));
assert(ret.first == std::end(str));
assert(ret.second == std::end(str));
}
int main(int, char**) {
test<random_access_iterator<const int*>, random_access_iterator<const int*> >();
test2<random_access_iterator<const char*>, random_access_iterator<const char*> >();
test_custom_pred();
return 0;
}

View File

@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14
// XFAIL: stdlib=libc++
// <functional>
@ -33,8 +32,8 @@
#include <algorithm>
#include <functional>
#include <cassert>
#include <functional>
#include "test_macros.h"
#include "test_iterators.h"

View File

@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14
// XFAIL: stdlib=libc++
// <functional>
@ -33,8 +32,8 @@
#include <algorithm>
#include <functional>
#include <cassert>
#include <functional>
#include "test_macros.h"
#include "test_iterators.h"

View File

@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14
// XFAIL: stdlib=libc++
// <functional>
@ -33,8 +32,8 @@
#include <algorithm>
#include <functional>
#include <cassert>
#include <functional>
#include "test_macros.h"
#include "test_iterators.h"

View File

@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14
// XFAIL: stdlib=libc++
// <functional>

View File

@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14
// XFAIL: stdlib=libc++
// <functional>

View File

@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14
// XFAIL: stdlib=libc++
// <functional>

View File

@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14
// XFAIL: stdlib=libc++
// <functional>

View File

@ -13,6 +13,7 @@
// Test that <optional> provides all of the arithmetic, enum, and pointer
// hash specializations.
#include <functional>
#include <optional>
#include "poisoned_hash_helper.h"

View File

@ -176,7 +176,6 @@ feature_test_macros = [ add_version_header(x) for x in [
"name": "__cpp_lib_boyer_moore_searcher",
"values": { "c++17": 201603 },
"headers": ["functional"],
"unimplemented": True,
}, {
"name": "__cpp_lib_byte",
"values": { "c++17": 201603 },