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