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