1 | // <experimental/functional> -*- C++ -*-
|
---|
2 |
|
---|
3 | // Copyright (C) 2014-2021 Free Software Foundation, Inc.
|
---|
4 | //
|
---|
5 | // This file is part of the GNU ISO C++ Library. This library is free
|
---|
6 | // software; you can redistribute it and/or modify it under the
|
---|
7 | // terms of the GNU General Public License as published by the
|
---|
8 | // Free Software Foundation; either version 3, or (at your option)
|
---|
9 | // any later version.
|
---|
10 |
|
---|
11 | // This library is distributed in the hope that it will be useful,
|
---|
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
14 | // GNU General Public License for more details.
|
---|
15 |
|
---|
16 | // Under Section 7 of GPL version 3, you are granted additional
|
---|
17 | // permissions described in the GCC Runtime Library Exception, version
|
---|
18 | // 3.1, as published by the Free Software Foundation.
|
---|
19 |
|
---|
20 | // You should have received a copy of the GNU General Public License and
|
---|
21 | // a copy of the GCC Runtime Library Exception along with this program;
|
---|
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
---|
23 | // <http://www.gnu.org/licenses/>.
|
---|
24 |
|
---|
25 | /** @file experimental/functional
|
---|
26 | * This is a TS C++ Library header.
|
---|
27 | * @ingroup libfund-ts
|
---|
28 | */
|
---|
29 |
|
---|
30 | #ifndef _GLIBCXX_EXPERIMENTAL_FUNCTIONAL
|
---|
31 | #define _GLIBCXX_EXPERIMENTAL_FUNCTIONAL 1
|
---|
32 |
|
---|
33 | #pragma GCC system_header
|
---|
34 |
|
---|
35 | #if __cplusplus >= 201402L
|
---|
36 |
|
---|
37 | #include <functional>
|
---|
38 | #include <tuple>
|
---|
39 | #include <iterator>
|
---|
40 | #include <unordered_map>
|
---|
41 | #include <vector>
|
---|
42 | #include <array>
|
---|
43 | #include <bits/stl_algo.h>
|
---|
44 | #ifdef _GLIBCXX_PARALLEL
|
---|
45 | # include <parallel/algorithm> // For std::__parallel::search
|
---|
46 | #endif
|
---|
47 | #include <experimental/bits/lfts_config.h>
|
---|
48 |
|
---|
49 | namespace std _GLIBCXX_VISIBILITY(default)
|
---|
50 | {
|
---|
51 | _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
---|
52 |
|
---|
53 | namespace experimental
|
---|
54 | {
|
---|
55 | inline namespace fundamentals_v1
|
---|
56 | {
|
---|
57 | // See C++14 20.9.9, Function object binders
|
---|
58 |
|
---|
59 | /// Variable template for std::is_bind_expression
|
---|
60 | template<typename _Tp>
|
---|
61 | constexpr bool is_bind_expression_v = std::is_bind_expression<_Tp>::value;
|
---|
62 |
|
---|
63 | /// Variable template for std::is_placeholder
|
---|
64 | template<typename _Tp>
|
---|
65 | constexpr int is_placeholder_v = std::is_placeholder<_Tp>::value;
|
---|
66 |
|
---|
67 | #define __cpp_lib_experimental_boyer_moore_searching 201411
|
---|
68 |
|
---|
69 | // Searchers
|
---|
70 |
|
---|
71 | template<typename _ForwardIterator1, typename _BinaryPredicate = equal_to<>>
|
---|
72 | class default_searcher
|
---|
73 | {
|
---|
74 | public:
|
---|
75 | default_searcher(_ForwardIterator1 __pat_first,
|
---|
76 | _ForwardIterator1 __pat_last,
|
---|
77 | _BinaryPredicate __pred = _BinaryPredicate())
|
---|
78 | : _M_m(__pat_first, __pat_last, std::move(__pred))
|
---|
79 | { }
|
---|
80 |
|
---|
81 | template<typename _ForwardIterator2>
|
---|
82 | _ForwardIterator2
|
---|
83 | operator()(_ForwardIterator2 __first, _ForwardIterator2 __last) const
|
---|
84 | {
|
---|
85 | return std::search(__first, __last,
|
---|
86 | std::get<0>(_M_m), std::get<1>(_M_m),
|
---|
87 | std::get<2>(_M_m));
|
---|
88 | }
|
---|
89 |
|
---|
90 | private:
|
---|
91 | std::tuple<_ForwardIterator1, _ForwardIterator1, _BinaryPredicate> _M_m;
|
---|
92 | };
|
---|
93 |
|
---|
94 | template<typename _Key, typename _Tp, typename _Hash, typename _Pred>
|
---|
95 | struct __boyer_moore_map_base
|
---|
96 | {
|
---|
97 | template<typename _RAIter>
|
---|
98 | __boyer_moore_map_base(_RAIter __pat, size_t __patlen,
|
---|
99 | _Hash&& __hf, _Pred&& __pred)
|
---|
100 | : _M_bad_char{ __patlen, std::move(__hf), std::move(__pred) }
|
---|
101 | {
|
---|
102 | if (__patlen > 0)
|
---|
103 | for (__diff_type __i = 0; __i < __patlen - 1; ++__i)
|
---|
104 | _M_bad_char[__pat[__i]] = __patlen - 1 - __i;
|
---|
105 | }
|
---|
106 |
|
---|
107 | using __diff_type = _Tp;
|
---|
108 |
|
---|
109 | __diff_type
|
---|
110 | _M_lookup(_Key __key, __diff_type __not_found) const
|
---|
111 | {
|
---|
112 | auto __iter = _M_bad_char.find(__key);
|
---|
113 | if (__iter == _M_bad_char.end())
|
---|
114 | return __not_found;
|
---|
115 | return __iter->second;
|
---|
116 | }
|
---|
117 |
|
---|
118 | _Pred
|
---|
119 | _M_pred() const { return _M_bad_char.key_eq(); }
|
---|
120 |
|
---|
121 | _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred> _M_bad_char;
|
---|
122 | };
|
---|
123 |
|
---|
124 | template<typename _Tp, size_t _Len, typename _Pred>
|
---|
125 | struct __boyer_moore_array_base
|
---|
126 | {
|
---|
127 | template<typename _RAIter, typename _Unused>
|
---|
128 | __boyer_moore_array_base(_RAIter __pat, size_t __patlen,
|
---|
129 | _Unused&&, _Pred&& __pred)
|
---|
130 | : _M_bad_char{ std::array<_Tp, _Len>{}, std::move(__pred) }
|
---|
131 | {
|
---|
132 | std::get<0>(_M_bad_char).fill(__patlen);
|
---|
133 | if (__patlen > 0)
|
---|
134 | for (__diff_type __i = 0; __i < __patlen - 1; ++__i)
|
---|
135 | {
|
---|
136 | auto __ch = __pat[__i];
|
---|
137 | using _UCh = std::make_unsigned_t<decltype(__ch)>;
|
---|
138 | auto __uch = static_cast<_UCh>(__ch);
|
---|
139 | std::get<0>(_M_bad_char)[__uch] = __patlen - 1 - __i;
|
---|
140 | }
|
---|
141 | }
|
---|
142 |
|
---|
143 | using __diff_type = _Tp;
|
---|
144 |
|
---|
145 | template<typename _Key>
|
---|
146 | __diff_type
|
---|
147 | _M_lookup(_Key __key, __diff_type __not_found) const
|
---|
148 | {
|
---|
149 | auto __ukey = static_cast<std::make_unsigned_t<_Key>>(__key);
|
---|
150 | if (__ukey >= _Len)
|
---|
151 | return __not_found;
|
---|
152 | return std::get<0>(_M_bad_char)[__ukey];
|
---|
153 | }
|
---|
154 |
|
---|
155 | const _Pred&
|
---|
156 | _M_pred() const { return std::get<1>(_M_bad_char); }
|
---|
157 |
|
---|
158 | std::tuple<std::array<_Tp, _Len>, _Pred> _M_bad_char;
|
---|
159 | };
|
---|
160 |
|
---|
161 | // Use __boyer_moore_array_base when pattern consists of narrow characters
|
---|
162 | // (or std::byte) and uses std::equal_to as the predicate.
|
---|
163 | template<typename _RAIter, typename _Hash, typename _Pred,
|
---|
164 | typename _Val = typename iterator_traits<_RAIter>::value_type,
|
---|
165 | typename _Diff = typename iterator_traits<_RAIter>::difference_type>
|
---|
166 | using __boyer_moore_base_t
|
---|
167 | = std::conditional_t<std::__is_byte_like<_Val, _Pred>::value,
|
---|
168 | __boyer_moore_array_base<_Diff, 256, _Pred>,
|
---|
169 | __boyer_moore_map_base<_Val, _Diff, _Hash, _Pred>>;
|
---|
170 |
|
---|
171 | template<typename _RAIter, typename _Hash
|
---|
172 | = std::hash<typename std::iterator_traits<_RAIter>::value_type>,
|
---|
173 | typename _BinaryPredicate = std::equal_to<>>
|
---|
174 | class boyer_moore_searcher
|
---|
175 | : __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate>
|
---|
176 | {
|
---|
177 | using _Base = __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate>;
|
---|
178 | using typename _Base::__diff_type;
|
---|
179 |
|
---|
180 | public:
|
---|
181 | boyer_moore_searcher(_RAIter __pat_first, _RAIter __pat_last,
|
---|
182 | _Hash __hf = _Hash(),
|
---|
183 | _BinaryPredicate __pred = _BinaryPredicate());
|
---|
184 |
|
---|
185 | template<typename _RandomAccessIterator2>
|
---|
186 | _RandomAccessIterator2
|
---|
187 | operator()(_RandomAccessIterator2 __first,
|
---|
188 | _RandomAccessIterator2 __last) const;
|
---|
189 |
|
---|
190 | private:
|
---|
191 | bool
|
---|
192 | _M_is_prefix(_RAIter __word, __diff_type __len,
|
---|
193 | __diff_type __pos)
|
---|
194 | {
|
---|
195 | const auto& __pred = this->_M_pred();
|
---|
196 | __diff_type __suffixlen = __len - __pos;
|
---|
197 | for (__diff_type __i = 0; __i < __suffixlen; ++__i)
|
---|
198 | if (!__pred(__word[__i], __word[__pos + __i]))
|
---|
199 | return false;
|
---|
200 | return true;
|
---|
201 | }
|
---|
202 |
|
---|
203 | __diff_type
|
---|
204 | _M_suffix_length(_RAIter __word, __diff_type __len,
|
---|
205 | __diff_type __pos)
|
---|
206 | {
|
---|
207 | const auto& __pred = this->_M_pred();
|
---|
208 | __diff_type __i = 0;
|
---|
209 | while (__pred(__word[__pos - __i], __word[__len - 1 - __i])
|
---|
210 | && __i < __pos)
|
---|
211 | {
|
---|
212 | ++__i;
|
---|
213 | }
|
---|
214 | return __i;
|
---|
215 | }
|
---|
216 |
|
---|
217 | template<typename _Tp>
|
---|
218 | __diff_type
|
---|
219 | _M_bad_char_shift(_Tp __c) const
|
---|
220 | { return this->_M_lookup(__c, _M_pat_end - _M_pat); }
|
---|
221 |
|
---|
222 | _RAIter _M_pat;
|
---|
223 | _RAIter _M_pat_end;
|
---|
224 | _GLIBCXX_STD_C::vector<__diff_type> _M_good_suffix;
|
---|
225 | };
|
---|
226 |
|
---|
227 | template<typename _RAIter, typename _Hash
|
---|
228 | = std::hash<typename std::iterator_traits<_RAIter>::value_type>,
|
---|
229 | typename _BinaryPredicate = std::equal_to<>>
|
---|
230 | class boyer_moore_horspool_searcher
|
---|
231 | : __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate>
|
---|
232 | {
|
---|
233 | using _Base = __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate>;
|
---|
234 | using typename _Base::__diff_type;
|
---|
235 |
|
---|
236 | public:
|
---|
237 | boyer_moore_horspool_searcher(_RAIter __pat,
|
---|
238 | _RAIter __pat_end,
|
---|
239 | _Hash __hf = _Hash(),
|
---|
240 | _BinaryPredicate __pred
|
---|
241 | = _BinaryPredicate())
|
---|
242 | : _Base(__pat, __pat_end - __pat, std::move(__hf), std::move(__pred)),
|
---|
243 | _M_pat(__pat), _M_pat_end(__pat_end)
|
---|
244 | { }
|
---|
245 |
|
---|
246 | template<typename _RandomAccessIterator2>
|
---|
247 | _RandomAccessIterator2
|
---|
248 | operator()(_RandomAccessIterator2 __first,
|
---|
249 | _RandomAccessIterator2 __last) const
|
---|
250 | {
|
---|
251 | const auto& __pred = this->_M_pred();
|
---|
252 | auto __patlen = _M_pat_end - _M_pat;
|
---|
253 | if (__patlen == 0)
|
---|
254 | return __first;
|
---|
255 | auto __len = __last - __first;
|
---|
256 | while (__len >= __patlen)
|
---|
257 | {
|
---|
258 | for (auto __scan = __patlen - 1;
|
---|
259 | __pred(__first[__scan], _M_pat[__scan]); --__scan)
|
---|
260 | if (__scan == 0)
|
---|
261 | return __first;
|
---|
262 | auto __shift = _M_bad_char_shift(__first[__patlen - 1]);
|
---|
263 | __len -= __shift;
|
---|
264 | __first += __shift;
|
---|
265 | }
|
---|
266 | return __last;
|
---|
267 | }
|
---|
268 |
|
---|
269 | private:
|
---|
270 | template<typename _Tp>
|
---|
271 | __diff_type
|
---|
272 | _M_bad_char_shift(_Tp __c) const
|
---|
273 | { return this->_M_lookup(__c, _M_pat_end - _M_pat); }
|
---|
274 |
|
---|
275 | _RAIter _M_pat;
|
---|
276 | _RAIter _M_pat_end;
|
---|
277 | };
|
---|
278 |
|
---|
279 | /// Generator function for default_searcher
|
---|
280 | template<typename _ForwardIterator,
|
---|
281 | typename _BinaryPredicate = std::equal_to<>>
|
---|
282 | inline default_searcher<_ForwardIterator, _BinaryPredicate>
|
---|
283 | make_default_searcher(_ForwardIterator __pat_first,
|
---|
284 | _ForwardIterator __pat_last,
|
---|
285 | _BinaryPredicate __pred = _BinaryPredicate())
|
---|
286 | { return { __pat_first, __pat_last, __pred }; }
|
---|
287 |
|
---|
288 | /// Generator function for boyer_moore_searcher
|
---|
289 | template<typename _RAIter, typename _Hash
|
---|
290 | = std::hash<typename std::iterator_traits<_RAIter>::value_type>,
|
---|
291 | typename _BinaryPredicate = equal_to<>>
|
---|
292 | inline boyer_moore_searcher<_RAIter, _Hash, _BinaryPredicate>
|
---|
293 | make_boyer_moore_searcher(_RAIter __pat_first, _RAIter __pat_last,
|
---|
294 | _Hash __hf = _Hash(),
|
---|
295 | _BinaryPredicate __pred = _BinaryPredicate())
|
---|
296 | { return { __pat_first, __pat_last, std::move(__hf), std::move(__pred) }; }
|
---|
297 |
|
---|
298 | /// Generator function for boyer_moore_horspool_searcher
|
---|
299 | template<typename _RAIter, typename _Hash
|
---|
300 | = std::hash<typename std::iterator_traits<_RAIter>::value_type>,
|
---|
301 | typename _BinaryPredicate = equal_to<>>
|
---|
302 | inline boyer_moore_horspool_searcher<_RAIter, _Hash, _BinaryPredicate>
|
---|
303 | make_boyer_moore_horspool_searcher(_RAIter __pat_first, _RAIter __pat_last,
|
---|
304 | _Hash __hf = _Hash(),
|
---|
305 | _BinaryPredicate __pred
|
---|
306 | = _BinaryPredicate())
|
---|
307 | { return { __pat_first, __pat_last, std::move(__hf), std::move(__pred) }; }
|
---|
308 |
|
---|
309 | template<typename _RAIter, typename _Hash, typename _BinaryPredicate>
|
---|
310 | boyer_moore_searcher<_RAIter, _Hash, _BinaryPredicate>::
|
---|
311 | boyer_moore_searcher(_RAIter __pat, _RAIter __pat_end,
|
---|
312 | _Hash __hf, _BinaryPredicate __pred)
|
---|
313 | : _Base(__pat, __pat_end - __pat, std::move(__hf), std::move(__pred)),
|
---|
314 | _M_pat(__pat), _M_pat_end(__pat_end), _M_good_suffix(__pat_end - __pat)
|
---|
315 | {
|
---|
316 | auto __patlen = __pat_end - __pat;
|
---|
317 | if (__patlen == 0)
|
---|
318 | return;
|
---|
319 | __diff_type __last_prefix = __patlen - 1;
|
---|
320 | for (__diff_type __p = __patlen - 1; __p >= 0; --__p)
|
---|
321 | {
|
---|
322 | if (_M_is_prefix(__pat, __patlen, __p + 1))
|
---|
323 | __last_prefix = __p + 1;
|
---|
324 | _M_good_suffix[__p] = __last_prefix + (__patlen - 1 - __p);
|
---|
325 | }
|
---|
326 | for (__diff_type __p = 0; __p < __patlen - 1; ++__p)
|
---|
327 | {
|
---|
328 | auto __slen = _M_suffix_length(__pat, __patlen, __p);
|
---|
329 | auto __pos = __patlen - 1 - __slen;
|
---|
330 | if (!__pred(__pat[__p - __slen], __pat[__pos]))
|
---|
331 | _M_good_suffix[__pos] = __patlen - 1 - __p + __slen;
|
---|
332 | }
|
---|
333 | }
|
---|
334 |
|
---|
335 | template<typename _RAIter, typename _Hash, typename _BinaryPredicate>
|
---|
336 | template<typename _RandomAccessIterator2>
|
---|
337 | _RandomAccessIterator2
|
---|
338 | boyer_moore_searcher<_RAIter, _Hash, _BinaryPredicate>::
|
---|
339 | operator()(_RandomAccessIterator2 __first,
|
---|
340 | _RandomAccessIterator2 __last) const
|
---|
341 | {
|
---|
342 | auto __patlen = _M_pat_end - _M_pat;
|
---|
343 | if (__patlen == 0)
|
---|
344 | return __first;
|
---|
345 | const auto& __pred = this->_M_pred();
|
---|
346 | __diff_type __i = __patlen - 1;
|
---|
347 | auto __stringlen = __last - __first;
|
---|
348 | while (__i < __stringlen)
|
---|
349 | {
|
---|
350 | __diff_type __j = __patlen - 1;
|
---|
351 | while (__j >= 0 && __pred(__first[__i], _M_pat[__j]))
|
---|
352 | {
|
---|
353 | --__i;
|
---|
354 | --__j;
|
---|
355 | }
|
---|
356 | if (__j < 0)
|
---|
357 | return __first + __i + 1;
|
---|
358 | __i += std::max(_M_bad_char_shift(__first[__i]),
|
---|
359 | _M_good_suffix[__j]);
|
---|
360 | }
|
---|
361 | return __last;
|
---|
362 | }
|
---|
363 | } // namespace fundamentals_v1
|
---|
364 |
|
---|
365 | inline namespace fundamentals_v2
|
---|
366 | {
|
---|
367 | #define __cpp_lib_experimental_not_fn 201406
|
---|
368 |
|
---|
369 | /// [func.not_fn] Function template not_fn
|
---|
370 | template<typename _Fn>
|
---|
371 | inline auto
|
---|
372 | not_fn(_Fn&& __fn)
|
---|
373 | noexcept(std::is_nothrow_constructible<std::decay_t<_Fn>, _Fn&&>::value)
|
---|
374 | {
|
---|
375 | return std::_Not_fn<std::decay_t<_Fn>>{std::forward<_Fn>(__fn), 0};
|
---|
376 | }
|
---|
377 | } // namespace fundamentals_v2
|
---|
378 | } // namespace experimental
|
---|
379 |
|
---|
380 | _GLIBCXX_END_NAMESPACE_VERSION
|
---|
381 | } // namespace std
|
---|
382 |
|
---|
383 | #endif // C++14
|
---|
384 |
|
---|
385 | #endif // _GLIBCXX_EXPERIMENTAL_FUNCTIONAL
|
---|