BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslstl_defaultsearcher.h
Go to the documentation of this file.
1/// @file bslstl_defaultsearcher.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_defaultsearcher.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_DEFAULTSEARCHER
9#define INCLUDED_BSLSTL_DEFAULTSEARCHER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_defaultsearcher bslstl_defaultsearcher
15/// @brief Provide an STL-compliant `default_searcher` class.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_defaultsearcher
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_defaultsearcher-purpose"> Purpose</a>
25/// * <a href="#bslstl_defaultsearcher-classes"> Classes </a>
26/// * <a href="#bslstl_defaultsearcher-description"> Description </a>
27/// * <a href="#bslstl_defaultsearcher-algorithm"> Algorithm </a>
28/// * <a href="#bslstl_defaultsearcher-iterator-requirements"> Iterator Requirements </a>
29/// * <a href="#bslstl_defaultsearcher-comparator-requirements"> Comparator Requirements </a>
30/// * <a href="#bslstl_defaultsearcher-optimizations-for-bslstl-defaultsearcher"> Optimizations for bslstl::DefaultSearcher </a>
31/// * <a href="#bslstl_defaultsearcher-usage"> Usage </a>
32/// * <a href="#bslstl_defaultsearcher-example-1-basic-usage"> Example 1: Basic Usage </a>
33/// * <a href="#bslstl_defaultsearcher-example-2-defining-a-comparator"> Example 2: Defining a Comparator </a>
34/// * <a href="#bslstl_defaultsearcher-example-3-non-char-searches"> Example 3: Non-char Searches </a>
35///
36/// # Purpose {#bslstl_defaultsearcher-purpose}
37/// Provide an STL-compliant @ref default_searcher class.
38///
39/// # Classes {#bslstl_defaultsearcher-classes}
40///
41/// - bsl::default_searcher: class template to search via the "naive" algorithm
42/// - bslstl::DefaultSearcher: class template to search via the "naive" algorithm
43///
44/// **Canonical header:** bsl_functional.h
45///
46/// @see bslstl_boyermoorehorspoolsearcher
47///
48/// # Description {#bslstl_defaultsearcher-description}
49/// This component defines two class templates,
50/// `bsl::default_searcher` and `bslstl::DefaultSearcher`. Both are compliant
51/// with section `[func.search.default]` of the C++ Standard (C++17 and later).
52///
53/// `bsl::default_searcher` is strictly limited to the Standard and is provided
54/// for clients for whom standard compliance is a priority.
55/// `bslstl::DefaultSearcher` provides several additional accessors that are not
56/// mentioned in the Standard.
57///
58/// Except where there is a relevant difference, both are described below as if
59/// they were one.
60///
61/// This class template has two parameters:
62///
63/// `FORWARD_ITR_NEEDLE`:
64/// The iterator type that defines on construction the range of values to be
65/// sought (the "needle"), and
66///
67/// `EQUAL`:
68/// an optional parameter that defines the class used to compare those
69/// values.
70///
71/// The class also provides a functor-style interface that accepts two iterators
72/// that define the range of values to be searched (the "haystack"). Once
73/// constructed the searcher object can be re-used to search multiple haystacks
74/// (for the same needle).
75///
76/// The iterators defining the haystack need not be of the same type as those
77/// that define the needle. Moreover, the search method of the searcher can be
78/// overloaded for an arbitrary different haystack iterators (subject to
79/// {Iterator Requirements}).
80///
81/// ## Algorithm {#bslstl_defaultsearcher-algorithm}
82///
83///
84/// The `bslstl::DefaultSearcher` class uses the classic, "naive" algorithm.
85/// The needle is sought at the beginning of the haystack and, if not found
86/// there, the start position in the haystack is incremented. That is repeated
87/// until the needle is found in the haystack or the end of the haystack is
88/// encountered. The time complexity is `O(M * N)`, where `M` is the length of
89/// the needle and `N` is the length of the haystack.
90///
91/// There are more sophisticated algorithms available; however, those typically
92/// require creating and retaining metadata derived from the needle and/or
93/// haystack. If the needle is short and the haystack of moderate length, the
94/// naive algorithm may be faster than generating that metadata, especially if
95/// the search is one-time and the metadata cost cannot be amortized.
96///
97/// Another advantage of the "default" searcher is that it accepts (relatively
98/// simple) *ForwardIterator*s whereas more sophisticated algorithms typically
99/// require (more fully-featured) *RandomIterator*s.
100///
101/// ## Iterator Requirements {#bslstl_defaultsearcher-iterator-requirements}
102///
103///
104/// The two independent iterator types associated with this class -- one
105/// defining the needle, the other defining the haystack -- must meet the
106/// requirements of *ForwardIterator*.
107///
108/// Additionally:
109/// * These iterators can be constant.
110/// * When dereferenced, they must both refer to the same value type.
111///
112/// Either of the iterator types are allowed to throw exceptions.
113///
114/// Iterators defining needles are required to remain valid as long as the
115/// searcher object might be used.
116///
117/// ## Comparator Requirements {#bslstl_defaultsearcher-comparator-requirements}
118///
119///
120/// The comparator class must meet the requirements of *BinaryPredicate*:
121/// * The class defines an `operator()` method, which, given an
122/// *ForwardIterator*, `iterator`, may be invoked as
123/// `operator()(*iterator, *iterator)`.
124/// * The return value must be contextually convertible to `bool`.
125/// * The supplied iterators can be constant.
126/// * The class must be copyable.
127///
128/// The comparator class is allowed to throw exceptions.
129///
130/// ## Optimizations for bslstl::DefaultSearcher {#bslstl_defaultsearcher-optimizations-for-bslstl-defaultsearcher}
131///
132///
133/// For certain template arguments this implementation improves performance by
134/// utilizing low-level operations. The requirements to do so are:
135/// * Both supplied iterators are pointers.
136/// * The default equality comparison is allowed to default (to
137/// `bsl::equal_to<value_type>`).
138/// * The `value_type` is bitwise-equality-comparable.
139///
140/// Users supplying their own data types are advised to set the
141/// `bslmf::IsBitwiseEqualityComparable` trait when applicable so that
142/// `bslstl::DefaultSearcher` knows that the last optimization condition listed
143/// above is met. See @ref bslmf_isbitwiseequalitycomparable .
144///
145/// ## Usage {#bslstl_defaultsearcher-usage}
146///
147///
148/// In this section we show the intended usage of this component.
149///
150/// ### Example 1: Basic Usage {#bslstl_defaultsearcher-example-1-basic-usage}
151///
152///
153/// The problem of searching a sequence of characters for a particular
154/// sub-sequence arises in many applications. For example, one might need to
155/// know if some document contains a particular word of interest. For example,
156/// suppose we would like to know the first occurrence of the word "United" in
157/// the Declaration of Independence (of the United States):
158///
159/// First, we obtain the text of document and word of interest as sequences of
160/// `char` values.
161/// @code
162/// const char document[] =
163/// " IN CONGRESS, July 4, 1776.\n" // 28
164/// "\n" // 1
165/// " The unanimous Declaration of the thirteen united States of America,\n"
166/// //----^----|----^----|----^----|----^----|---- // 44
167/// // // --
168/// // // 73rd character
169/// //
170/// "\n"
171/// // ...
172/// " declare, That these United Colonies are, and of Right ought to be\n"
173/// // ...
174/// "Honor.";
175///
176/// const char *word = "United";
177/// @endcode
178/// Then, we create a `bsl::default_searcher` object (a functor) using the given
179/// `word`:
180/// @code
181/// bsl::default_searcher<const char*> searchForUnited(
182/// word,
183/// word + bsl::strlen(word));
184/// @endcode
185/// Notice that no equality comparison functor was specified so
186/// `searchForUnited` will use `bsl::equal_to<char>` by default.
187///
188/// Now, we invoke our functor, specifying the range of the document to be
189/// searched:
190/// @code
191/// bsl::pair<const char *, const char *> result = searchForUnited(
192/// document,
193/// document
194/// + sizeof document);
195/// bsl::size_t offset = result.first - document;
196///
197/// assert(120 == offset);
198/// assert(static_cast<bsl::size_t>(result.second - result.first)
199/// == bsl::strlen(word));
200/// @endcode
201/// Finally, we notice that the search correctly ignored the appearance of the
202/// word "united" (all lower case) in the second sentence.
203///
204/// {@ref bslstl_boyermoorehorspoolsearcher |Example 1} shows how the same problem
205/// is addressed using `bsl::boyer_moore_horspool_searcher`.
206///
207/// ### Example 2: Defining a Comparator {#bslstl_defaultsearcher-example-2-defining-a-comparator}
208///
209///
210/// As seen in {Example 1} above, the default equality comparison functor is
211/// case sensitive. If one needs case *in*-sensitive searches, a non-default
212/// equality comparison class must be specified.
213///
214/// First, define (at file scope if using a pre-C++11 compiler) an equality
215/// comparison class that provides the required functor interface:
216/// @code
217/// struct MyCaseInsensitiveCharComparator {
218/// bool operator()(const char& a, const char& b) const {
219/// return bsl::tolower(a) == bsl::tolower(b);
220/// }
221/// };
222/// @endcode
223/// Then, define a new `bsl::default_searcher` type and create a searcher object
224/// to search for `word`:
225/// @code
226/// bsl::default_searcher<const char *,
227/// struct MyCaseInsensitiveCharComparator>
228/// searchForUnitedInsensitive(
229/// word,
230/// word + bsl::strlen(word));
231/// @endcode
232/// Note that the new searcher object will used a default constructed
233/// `MyCaseInsensitiveCharComparator` class. If an equality comparison object
234/// requires state supplied on construction, such an object be explicitly
235/// created and supplied as the final constructor argument.
236///
237/// Now, we invoke our new functor, specifying that the same document searched
238/// in {Example 1}:
239/// @code
240/// bsl::pair<const char *, const char *> resultInsensitive =
241/// searchForUnitedInsensitive(
242/// document,
243/// document
244/// + sizeof document);
245///
246/// bsl::size_t offsetInsensitive = resultInsensitive.first - document;
247///
248/// assert( 72 == offsetInsensitive);
249/// assert(static_cast<bsl::size_t>(resultInsensitive.second
250/// - resultInsensitive.first)
251/// == bsl::strlen(word));
252/// @endcode
253/// Finally, we find the next occurrence of `word` by *reusing* the same
254/// searcher object, this time instructing it to begin its search just after the
255/// previous occurrence of `word` was found:
256/// @code
257/// resultInsensitive = searchForUnitedInsensitive(resultInsensitive.second,
258/// document + sizeof document);
259///
260/// offsetInsensitive = resultInsensitive.first - document;
261///
262/// assert(120 == offsetInsensitive);
263/// assert(static_cast<bsl::size_t>(resultInsensitive.second
264/// - resultInsensitive.first)
265/// == bsl::strlen(word));
266/// @endcode
267/// {@ref bslstl_boyermoorehorspoolsearcher |Example 2} shows how the same problem
268/// is addressed using `bsl::boyer_moore_horspool_searcher`.
269///
270/// ### Example 3: Non-char Searches {#bslstl_defaultsearcher-example-3-non-char-searches}
271///
272///
273/// The "default" searcher class template is not constrained to searching for
274/// `char` values. Searches can be done on other types (see {Iterator
275/// Requirements}). Moreover the container of the sequence being sought (the
276/// "needle") need not the same as the sequence being searched (the "haystack").
277///
278/// Suppose one has data from an instrument that reports `float` values and that
279/// inserts the sequence `{ FLT_MAX, FLT_MIN, FLT_MAX }` as a marker for the
280/// start and end of a test run. We can assume the probably of the instrument
281/// reporting this sequence as readings is negligible and that data reported
282/// outside of the test runs is random noise. Here is how we can search for the
283/// first test run data in the data sequence.
284///
285/// First, we create a representation of the sequence that denotes the limit of
286/// a test run.
287/// @code
288/// const float markerSequence[] = { FLT_MAX , FLT_MIN , FLT_MAX };
289/// const bsl::size_t markerSequenceLength = sizeof markerSequence
290/// / sizeof *markerSequence;
291/// @endcode
292/// Next, we obtain the data to be searched. (In this example, we will use
293/// simulated data.)
294/// @code
295/// bsl::list<float> data; // Container provides bidirectional iterators.
296/// doTestRun(&data);
297/// @endcode
298/// Then, we define and create our searcher object:
299/// @code
300/// bsl::default_searcher<const float *> searchForMarker(markerSequence,
301/// markerSequence
302/// + markerSequenceLength);
303/// @endcode
304/// Notice that no equality comparator was specified so `searchForMarker` will
305/// use `bsl::equal_to<float>` by default.
306///
307/// Now, we invoke our searcher on the instrument data.
308/// @code
309/// typedef bsl::list<float>::const_iterator DataConstItr;
310///
311/// const bsl::pair<DataConstItr, DataConstItr> notFound(data.cend(),
312/// data.cend());
313///
314/// bsl::pair<DataConstItr, DataConstItr> markerPosition = searchForMarker(
315/// data.cbegin(),
316/// data.cend());
317///
318/// assert(notFound != markerPosition);
319///
320/// DataConstItr startOfTestRun = markerPosition.second;
321/// @endcode
322/// Finally, we locate the marker of the end of the first test run and pass the
323/// location of the first test run data to some other function for processing.
324/// @code
325/// markerPosition = searchForMarker(markerPosition.second, data.cend());
326///
327/// assert(notFound != markerPosition);
328///
329/// DataConstItr endOfTestRun = markerPosition.first;
330///
331/// processTestRun(startOfTestRun, endOfTestRun);
332/// @endcode
333///
334/// {@ref bslstl_boyermoorehorspoolsearcher |Example 3} shows how the same problem
335/// is addressed using `bsl::boyer_moore_horspool_searcher`. Notice that other
336/// example uses `data` from a container that provides random access iterators;
337/// whereas here, bidirectional iterators are used (and forward iterators would
338/// have sufficed).
339/// @}
340/** @} */
341/** @} */
342
343/** @addtogroup bsl
344 * @{
345 */
346/** @addtogroup bslstl
347 * @{
348 */
349/** @addtogroup bslstl_defaultsearcher
350 * @{
351 */
352
353#include <bslscm_version.h>
354
355#include <bslstl_equalto.h>
356#include <bslstl_iterator.h>
357#include <bslstl_pair.h>
358
359#include <bslmf_assert.h>
360#include <bslmf_enableif.h>
361#include <bslmf_issame.h>
362
363#include <bsls_assert.h>
364#include <bsls_keyword.h> // for 'BSLS_KEYWORD_CONSTEXPR'
365#include <bsls_libraryfeatures.h>
366#include <bsls_performancehint.h>
367
368#include <cstring> // for 'std::memcmp'
369#include <utility> // for 'std::make_pair'
370
371
372namespace bslstl {
373
374 // =====================
375 // class DefaultSearcher
376 // =====================
377
378/// This class template defines functors that can search for the sequence of
379/// `value_type` values defined on construction (i.e., the "needle") in
380/// sequences of `value_type` values (i.e., "haystacks") passed to the
381/// functor's `operator()`.
382///
383/// See @ref bslstl_defaultsearcher
384template <class FORWARD_ITR_NEEDLE,
385 class EQUAL = bsl::equal_to<
386 typename bsl::iterator_traits<FORWARD_ITR_NEEDLE>::value_type> >
388
389 // PRIVATE TYPES
390
391 /// the type of the values that can be obtained by dereferencing a
392 /// `FORWARD_ITR_NEEDLE` iterator
393 typedef typename bsl::iterator_traits<FORWARD_ITR_NEEDLE>::value_type
394 value_type;
395
396 typedef typename bsl::iterator_traits<FORWARD_ITR_NEEDLE>::
397 iterator_category
398 IteratorCategory;
399 // DATA
400 FORWARD_ITR_NEEDLE d_needleFirst;
401 FORWARD_ITR_NEEDLE d_needleLast;
402 EQUAL d_equal;
403
404 public:
405 // CREATORS
406
407 /// Create a `DefaultSearcher` object that can search for the sequence
408 /// of `value_type` values found in the specified range
409 /// `[needleFirst, needleLast)`. Optionally supply an `equal` functor
410 /// for use by `operator()`. The behavior is undefined unless
411 /// `needleFirst` can be advanced to equal `needleLast`.
412 DefaultSearcher(FORWARD_ITR_NEEDLE needleFirst,
413 FORWARD_ITR_NEEDLE needleLast,
414 EQUAL equal = EQUAL());
415
416 /// Create a `DefaultSearcher` object that has the same state as the
417 /// specified `original` object.
418 DefaultSearcher(const DefaultSearcher& original) = default;
419
420 /// Create a `DefaultSeacher` object having the same state as the
421 /// specified `original` object. The `original` object is left in an
422 /// unspecified (valid) state.
423 DefaultSearcher(DefaultSearcher&& original) = default;
424
425 /// Destroy this `DefaultSearcher` object.
426 ~DefaultSearcher() = default;
427
428 // MANIPULATORS
429
430 /// Assign to this object the state of the specified `rhs` object, and
431 /// return a non-`const` reference to this object.
433
434 /// Assign to this object the state of the specified `rhs` had and
435 /// return a non-`const` reference to this object. The `original`
436 /// object is left in an unspecified (valid) state.
438
439 // ACCESSORS
440
441 /// Search the specified range `[haystackFirst, haystackLast)` for the
442 /// first sequence of `value_type` values specified on construction.
443 /// Return the range where those values are found, or the range
444 /// `[haystackLast, haystackLast)` if that sequence is not found. The
445 /// search is performed using a "naive" algorithm that has time
446 /// complexity of:
447 /// @code
448 /// bsl::distance(needleFirst(), needleLast())
449 /// * bsl::distance(haystackFirst, haystackLast);
450 /// @endcode
451 /// Values of the "needle" sequence and the "haystack" sequence are
452 /// compared using the equality comparison functor specified on
453 /// construction. The behavior is undefined unless `haystackFirst` can
454 /// be advanced to equal `haystackLast` and the iterators used to
455 /// construct this object, `needleFirst()` and `needleLast()`, are still
456 /// valid. Note that if the "needle" sequence is empty, the range
457 /// `[haystackFirst, haystackFirst)` is returned. Also note that if the
458 /// "needle" sequence is longer than the "haystack" sequence -- thus,
459 /// impossible for the "needle" to be found in the "haystack" -- the
460 /// range `[haystackLast, haystackLast)` is returned.
461 template<class FORWARD_ITR_HAYSTACK>
463 FORWARD_ITR_HAYSTACK haystackFirst,
464 FORWARD_ITR_HAYSTACK haystackLast) const;
465
466 // Non-Standard Accessors
467
468 /// Return an iterator referring to the first element of the sequence of
469 /// `value_type` values that can be sought by this searcher object.
470 FORWARD_ITR_NEEDLE needleFirst() const;
471
472 /// Return an iterator referring to one past the last element of the
473 /// sequence of `value_type` values that can be sought by this searcher
474 /// object.
475 FORWARD_ITR_NEEDLE needleLast() const;
476
477 /// Return the functor used by this searcher object to compare
478 /// `value_type` values.
479 EQUAL equal() const;
480};
481
482 // ===================================
483 // struct DefaultSearcher_CanOptimize
484 // ===================================
485
486/// This component-private meta-function `struct` provides a member
487/// enumerator `value` that is `true` if all of the specified
488/// `FORWARD_ITR_NEEDLE,` `EQUAL,` and `FORWARD_ITR_HAYSTACK` meet the
489/// criteria for an optimization of the default searcher, and has the value
490/// `false` otherwise.
491template <class FORWARD_ITR_NEEDLE,
492 class EQUAL,
493 class FORWARD_ITR_HAYSTACK>
495
496 enum {
497
498 value = (
499
502 && bsl::is_same<EQUAL, // 'EQUAL' does 'value_type::operator=='
504 typename
505 bsl::iterator_traits<FORWARD_ITR_NEEDLE>::value_type
506 >
507 >::value
509 typename
510 bsl::iterator_traits<FORWARD_ITR_NEEDLE>::value_type
511 >::value
513 typename
514 bsl::iterator_traits<FORWARD_ITR_HAYSTACK>::value_type
515 >::value
516 )
517 };
518};
519
520 // ===============================
521 // struct DefaultSearcher_ImpUtil
522 // ===============================
523
524/// This component-private utility `struct` provides two mutually exclusive
525/// overloads of the `doSearch` method -- i.e., just one of the two methods
526/// is enabled at any time. Enablement is decided by the
527/// `DefaultSearcher_CanOptimize` meta-function.
529
530 // TYPES
531 template <class FORWARD_ITR_NEEDLE,
532 class EQUAL,
533 class FORWARD_ITR_HAYSTACK>
534 static
535 typename
537 EQUAL,
538 FORWARD_ITR_HAYSTACK>::value
539 , bsl::pair<FORWARD_ITR_HAYSTACK,
540 FORWARD_ITR_HAYSTACK>
541 >::type doSearch(const FORWARD_ITR_HAYSTACK& haystackFirst,
542 const FORWARD_ITR_HAYSTACK& haystackLast,
543 const FORWARD_ITR_NEEDLE& needleFirst,
544 const FORWARD_ITR_NEEDLE& needleLast,
545 const EQUAL& equal);
546
547 /// Search the specified "haystack" sequence of `value_type` values,
548 /// `[haystackFirst, hastackLast)`, for the specified "needle" sequence
549 /// of `value_type` values, `[needleFirst, needleLast)` where the
550 /// `value_type` values are compared using the specified `equal`
551 /// functor. Return the range where the sought sequence of values are
552 /// found, or the range `[haystackLast, haystackLast)` if that sequence
553 /// is not found. The search is performed using a "naive" algorithm
554 /// that has time complexity of:
555 /// @code
556 /// bsl::distance(needleFirst(), needleLast())
557 /// * bsl::distance(haystackFirst, haystackLast);
558 /// @endcode
559 /// Values of the "needle" sequence and the "haystack" sequences are
560 /// compared using the equality comparison functor specified on
561 /// construction except, possibly, if the `DefaultSearcher_CanOptimize`
562 /// metafunction indicates that the template parameters are eligible for
563 /// optimization. The optimized overload is enabled when needle and
564 /// haystack can be validly compared using `std::memcmp`, a
565 /// low-level function that is often highly optimized for its platform.
566 /// The behavior is undefined unless `haystackFirst` can be advanced to
567 /// equal `haystackLast`. Note that if the "needle" sequence is empty,
568 /// the range `[haystackFirst, haystackFirst)` is returned. Also note
569 /// that if the "needle" sequence is longer than the "haystack" sequence
570 /// -- thus, impossible for the "needle" to be found in the "haystack"
571 /// -- the range `[haystackLast, haystackLast)` is returned.
572 template <class FORWARD_ITR_NEEDLE,
573 class EQUAL,
574 class FORWARD_ITR_HAYSTACK>
575 static
576 typename
578 EQUAL,
579 FORWARD_ITR_HAYSTACK>::value
580 , bsl::pair<FORWARD_ITR_HAYSTACK,
581 FORWARD_ITR_HAYSTACK>
582 >::type doSearch(const FORWARD_ITR_HAYSTACK& haystackFirst,
583 const FORWARD_ITR_HAYSTACK& haystackLast,
584 const FORWARD_ITR_NEEDLE& needleFirst,
585 const FORWARD_ITR_NEEDLE& needleLast,
586 const EQUAL& equal);
587};
588
589} // close package namespace
590
591
592#ifndef BSLS_LIBRARYFEATURES_HAS_CPP17_SEARCH_FUNCTORS
593namespace bsl {
594 // ======================
595 // class default_searcher
596 // ======================
597
598// This class template defines functors that can search for the sequence of
599// `value_type` values defined on construction in sequences of `value_type`
600// values passed to the functor's `operator()`.
601template<class ForwardIterator1,
602 class BinaryPredicate = equal_to<
603 typename bsl::iterator_traits<ForwardIterator1>::value_type> >
605
606 //DATA
607 BloombergLP::bslstl::DefaultSearcher<ForwardIterator1,
608 BinaryPredicate> d_imp;
609
610 public:
611 // CREATORS
612
613 /// Create a @ref default_searcher object that can search for the sequence
614 /// of `value_type` values found in the specified range
615 /// `[pat_first, pat_last)`. Optionally supply a `pred` functor for use
616 /// by `operator()`. See {Comparator Requirements}. The behavior is
617 /// undefined unless @ref pat_first can be advanced to equal @ref pat_last .
619 default_searcher(ForwardIterator1 pat_first,
620 ForwardIterator1 pat_last,
621 BinaryPredicate pred = BinaryPredicate());
622
623 /// Create a @ref default_searcher object having same state as the
624 /// specified `original` object.
625 default_searcher(const default_searcher& original) = default;
626
627 /// Create a @ref default_searcher object having same state as the
628 /// specified `original` object. by moving (in constant time) the state
629 /// of `original` to the new searcher. The `original` object is left in
630 /// an unspecified (valid) state.
631 default_searcher(BloombergLP::bslmf::MovableRef<default_searcher>
632 original) = default;
633
634 /// Destroy this @ref default_searcher object.
635 ~default_searcher() = default;
636
637 // MANIPULATORS
638
639 /// Assign to this object the state of the specified `rhs` object, and
640 /// return a non-`const` reference to this searcher.
642
643 /// Assign to this object the state of the specified `rhs` object and
644 /// return a non-`const` reference to this searcher.
646 BloombergLP::bslmf::MovableRef<default_searcher>
647 rhs) = default;
648
649 // ACCESSORS
650
651 /// Search the specified range `[first, last)` for the first sequence of
652 /// `value_type` values specified on construction. Return the range
653 /// where those values are found, or the range `[last, last)` if that
654 /// sequence is not found. The search is performed using a "naive"
655 /// algorithm that has time complexity of:
656 /// @code
657 /// bsl::distance(pat_first, pat_last) * bsl::distance(first, last);
658 /// @endcode
659 /// Values of the two sequences are compared using the equality
660 /// comparison functor specified on construction. The behavior is
661 /// undefined unless `first` can be advanced to equal `last` and the
662 /// iterators used to construct this object are still valid. Note that
663 /// if the sought sequence is empty, the range `[first, first)` is
664 /// returned. Also note that if the sequence sought is longer than the
665 /// sequence searched -- thus the sought sequence cannot be found -- the
666 /// range `[last, last)` is returned.
667 template<class ForwardIterator2>
670 ForwardIterator2 first,
671 ForwardIterator2 last) const;
672};
673
674} // close namespace bsl
675#endif // BSLS_LIBRARYFEATURES_HAS_CPP17_SEARCH_FUNCTORS
676
677// ----------------------------------------------------------------------------
678// INLINE DEFINITIONS
679// ----------------------------------------------------------------------------
680
681
682namespace bslstl {
683
684 // ---------------------
685 // class DefaultSearcher
686 // ---------------------
687
688//CREATORS
689template <class FORWARD_ITR_NEEDLE,
690 class EQUAL>
691inline
692DefaultSearcher<FORWARD_ITR_NEEDLE,
693 EQUAL>::
694DefaultSearcher(FORWARD_ITR_NEEDLE needleFirst,
695 FORWARD_ITR_NEEDLE needleLast,
696 EQUAL equal)
697: d_needleFirst(needleFirst)
698, d_needleLast( needleLast)
699, d_equal(equal)
700{
701 BSLS_ASSERT(0 <= bsl::distance(needleFirst, needleLast));
702}
703
704// ACCESSORS
705template <class FORWARD_ITR_NEEDLE,
706 class EQUAL>
707template <class FORWARD_ITR_HAYSTACK>
708inline
711 FORWARD_ITR_HAYSTACK haystackFirst,
712 FORWARD_ITR_HAYSTACK haystackLast) const
713{
715 typename bsl::iterator_traits<FORWARD_ITR_NEEDLE >::value_type,
716 typename bsl::iterator_traits<FORWARD_ITR_HAYSTACK>::value_type
717 >::value));
718
719 return BloombergLP::bslstl::
720 DefaultSearcher_ImpUtil::doSearch<FORWARD_ITR_NEEDLE,
721 EQUAL,
722 FORWARD_ITR_HAYSTACK>(
723 haystackFirst,
724 haystackLast,
725 d_needleFirst,
726 d_needleLast,
727 d_equal);
728
729}
730
731template <class FORWARD_ITR_NEEDLE, class EQUAL>
732inline
734 const
735{
736 return d_needleFirst;
737}
738
739template <class FORWARD_ITR_NEEDLE, class EQUAL>
740inline
742 const
743{
744 return d_needleLast;
745}
746
747template <class FORWARD_ITR_NEEDLE, class EQUAL>
748inline
750{
751 return d_equal;
752}
753
754 // -----------------------------
755 // class DefaultSearcher_ImpUtil
756 // -----------------------------
757
758// CLASS METHODS
759template <class FORWARD_ITR_NEEDLE, class EQUAL, class FORWARD_ITR_HAYSTACK>
760inline
761typename
763 ! DefaultSearcher_CanOptimize<FORWARD_ITR_NEEDLE,
764 EQUAL,
765 FORWARD_ITR_HAYSTACK>::value
768 const FORWARD_ITR_HAYSTACK& haystackFirst,
769 const FORWARD_ITR_HAYSTACK& haystackLast,
770 const FORWARD_ITR_NEEDLE& needleFirst,
771 const FORWARD_ITR_NEEDLE& needleLast,
772 const EQUAL& equal)
773{
774 BSLS_ASSERT(0 <= bsl::distance(haystackFirst, haystackLast));
775
776 for (FORWARD_ITR_HAYSTACK itrHaystackOuter = haystackFirst;
777 itrHaystackOuter != haystackLast;
778 ++itrHaystackOuter) {
779
780 FORWARD_ITR_HAYSTACK itrHaystackInner = itrHaystackOuter;
781
782 for (FORWARD_ITR_NEEDLE itrNeedle = needleFirst;
783 /* tests below */ ;
784 ++itrNeedle, ++itrHaystackInner) {
785
786 if (needleLast == itrNeedle) { // Needle match in haystack!
787 return std::make_pair(itrHaystackOuter,
788 itrHaystackInner); // RETURN
789 }
790
791 if (haystackLast == itrHaystackInner) { // Hit end of haystack.
792 return std::make_pair(haystackLast,
793 haystackLast); // RETURN
794 }
795
796 if (equal(*itrHaystackInner, *itrNeedle)) {
797 continue; // Needle match still possible.
798 } else {
799 break; // Move starting point in haystack and try again.
800 }
801 }
802 }
803
804 // Ran out of haystack without match.
805
806 return std::make_pair(haystackLast, haystackLast);
807}
808
809template <class FORWARD_ITR_NEEDLE, class EQUAL, class FORWARD_ITR_HAYSTACK>
810inline
811typename
813 DefaultSearcher_CanOptimize<FORWARD_ITR_NEEDLE,
814 EQUAL,
815 FORWARD_ITR_HAYSTACK>::value
818 const FORWARD_ITR_HAYSTACK& haystackFirst,
819 const FORWARD_ITR_HAYSTACK& haystackLast,
820 const FORWARD_ITR_NEEDLE& needleFirst,
821 const FORWARD_ITR_NEEDLE& needleLast,
822 const EQUAL& )
823{
824 ///Implementation Note
825 ///-------------------
826 // This specialization is used only when the 'EQUAL' template parameter
827 // was specified as 'bsl::equal_to<value_type>', the default value. We
828 // ignore that argument and perform its "moral equivalent" for the various
829 // ranges using 'std::memcmp'.
830
831 typedef typename bsl::iterator_traits<FORWARD_ITR_HAYSTACK>::
832 difference_type
833 HaystackDifference;
834
835 typedef typename bsl::iterator_traits<FORWARD_ITR_NEEDLE>::difference_type
836 NeedleDifference;
837
838 const NeedleDifference needleLength = needleLast - needleFirst;
839 const HaystackDifference haystackLength = haystackLast - haystackFirst;
840
841 BSLS_ASSERT(0 <= needleLength);
842 BSLS_ASSERT(0 <= haystackLength);
843
844 if (haystackLength < needleLength) { // Cannot match.
845 return std::make_pair(haystackLast, haystackLast); // RETURN
846 }
847
848 if (0 == needleLength || 0 == haystackLength) {
849 return std::make_pair(haystackFirst, haystackFirst); // RETURN
850 }
851
852 for (FORWARD_ITR_HAYSTACK itr = haystackFirst;
853 itr < haystackLast - needleLength + 1; ++itr) {
854
855 FORWARD_ITR_HAYSTACK itrInner = itr;
856 FORWARD_ITR_NEEDLE needleItrInner = needleFirst;
857 NeedleDifference needleLengthInner = needleLength;
858
859 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(*itr == *needleFirst)) {
860 if (1 == needleLength) {
861 return std::make_pair(itr, itr + needleLength); // RETURN
862 }
863 ++itrInner;
864 ++needleItrInner;
865 --needleLengthInner;
866 } else {
867 continue; // Avoided 'memcmp' call
868 }
869
870 if (0 == std::memcmp( itrInner,
871 needleItrInner,
872 needleLengthInner)) {
873 return std::make_pair(itr, itr + needleLength); // RETURN
874 }
875 }
876
877 // Ran out of haystack without match.
878 return std::make_pair(haystackLast, haystackLast);
879}
880
881} // close package namespace
882
883
884#ifndef BSLS_LIBRARYFEATURES_HAS_CPP17_SEARCH_FUNCTORS
885namespace bsl {
886 // ----------------------
887 // class default_searcher
888 // ----------------------
889
890// CREATORS
891template <class ForwardIterator1,
892 class BinaryPredicate>
893inline
895default_searcher<ForwardIterator1,
896 BinaryPredicate>::default_searcher(ForwardIterator1 pat_first,
897 ForwardIterator1 pat_last,
898 BinaryPredicate pred)
899: d_imp(pat_first, pat_last, pred)
900{
901}
902
903 // ACCESSORS
904template <class ForwardIterator1,
905 class BinaryPredicate>
906template <class ForwardIterator2>
907inline
909pair<ForwardIterator2,
910 ForwardIterator2> default_searcher<ForwardIterator1,
911 BinaryPredicate>::operator()(
912 ForwardIterator2 first,
913 ForwardIterator2 last) const
914{
915 return d_imp(first, last);
916}
917
918} // close namespace bsl
919#endif // BSLS_LIBRARYFEATURES_HAS_CPP17_SEARCH_FUNCTORS
920
921#endif
922
923// ----------------------------------------------------------------------------
924// Copyright 2019 Bloomberg Finance L.P.
925//
926// Licensed under the Apache License, Version 2.0 (the "License");
927// you may not use this file except in compliance with the License.
928// You may obtain a copy of the License at
929//
930// http://www.apache.org/licenses/LICENSE-2.0
931//
932// Unless required by applicable law or agreed to in writing, software
933// distributed under the License is distributed on an "AS IS" BASIS,
934// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
935// See the License for the specific language governing permissions and
936// limitations under the License.
937// ----------------------------- END-OF-FILE ----------------------------------
938
939/** @} */
940/** @} */
941/** @} */
Definition bslstl_defaultsearcher.h:604
default_searcher(const default_searcher &original)=default
default_searcher & operator=(BloombergLP::bslmf::MovableRef< default_searcher > rhs)=default
default_searcher(BloombergLP::bslmf::MovableRef< default_searcher > original)=default
default_searcher & operator=(const default_searcher &rhs)=default
BSLS_KEYWORD_CONSTEXPR pair< ForwardIterator2, ForwardIterator2 > operator()(ForwardIterator2 first, ForwardIterator2 last) const
Definition bslstl_defaultsearcher.h:911
~default_searcher()=default
Destroy this default_searcher object.
Definition bslstl_pair.h:1210
Definition bslstl_defaultsearcher.h:387
~DefaultSearcher()=default
Destroy this DefaultSearcher object.
DefaultSearcher & operator=(const DefaultSearcher &rhs)=default
FORWARD_ITR_NEEDLE needleFirst() const
Definition bslstl_defaultsearcher.h:733
bsl::pair< FORWARD_ITR_HAYSTACK, FORWARD_ITR_HAYSTACK > operator()(FORWARD_ITR_HAYSTACK haystackFirst, FORWARD_ITR_HAYSTACK haystackLast) const
Definition bslstl_defaultsearcher.h:710
FORWARD_ITR_NEEDLE needleLast() const
Definition bslstl_defaultsearcher.h:741
EQUAL equal() const
Definition bslstl_defaultsearcher.h:749
DefaultSearcher(DefaultSearcher &&original)=default
DefaultSearcher(const DefaultSearcher &original)=default
DefaultSearcher & operator=(DefaultSearcher &&rhs)=default
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_CONSTEXPR
Definition bsls_keyword.h:588
#define BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(expr)
Definition bsls_performancehint.h:452
Definition bdlb_printmethods.h:283
Definition bslstl_algorithm.h:82
Definition bslmf_enableif.h:525
Definition bslstl_equalto.h:311
Definition bslmf_ispointer.h:138
Definition bslmf_issame.h:146
Definition bslmf_isbitwiseequalitycomparable.h:499
Definition bslstl_defaultsearcher.h:494
@ value
Definition bslstl_defaultsearcher.h:498
Definition bslstl_defaultsearcher.h:528
static bsl::enable_if< DefaultSearcher_CanOptimize< FORWARD_ITR_NEEDLE, EQUAL, FORWARD_ITR_HAYSTACK >::value, bsl::pair< FORWARD_ITR_HAYSTACK, FORWARD_ITR_HAYSTACK > >::type doSearch(const FORWARD_ITR_HAYSTACK &haystackFirst, const FORWARD_ITR_HAYSTACK &haystackLast, const FORWARD_ITR_NEEDLE &needleFirst, const FORWARD_ITR_NEEDLE &needleLast, const EQUAL &equal)
Definition bslstl_defaultsearcher.h:767
static bsl::enable_if<!DefaultSearcher_CanOptimize< FORWARD_ITR_NEEDLE, EQUAL, FORWARD_ITR_HAYSTACK >::value, bsl::pair< FORWARD_ITR_HAYSTACK, FORWARD_ITR_HAYSTACK > >::type doSearch(const FORWARD_ITR_HAYSTACK &haystackFirst, const FORWARD_ITR_HAYSTACK &haystackLast, const FORWARD_ITR_NEEDLE &needleFirst, const FORWARD_ITR_NEEDLE &needleLast, const EQUAL &equal)