BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslstl_boyermoorehorspoolsearcher.h
Go to the documentation of this file.
1/// @file bslstl_boyermoorehorspoolsearcher.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_boyermoorehorspoolsearcher.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_BOYERMOOREHORSPOOLSEARCHER
9#define INCLUDED_BSLSTL_BOYERMOOREHORSPOOLSEARCHER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_boyermoorehorspoolsearcher bslstl_boyermoorehorspoolsearcher
15/// @brief Provide an STL-compliant `boyer_moore_horspool_searcher` class.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_boyermoorehorspoolsearcher
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_boyermoorehorspoolsearcher-purpose"> Purpose</a>
25/// * <a href="#bslstl_boyermoorehorspoolsearcher-classes"> Classes </a>
26/// * <a href="#bslstl_boyermoorehorspoolsearcher-description"> Description </a>
27/// * <a href="#bslstl_boyermoorehorspoolsearcher-algorithm"> Algorithm </a>
28/// * <a href="#bslstl_boyermoorehorspoolsearcher-iterator-requirements"> Iterator Requirements </a>
29/// * <a href="#bslstl_boyermoorehorspoolsearcher-requirements-for-hash-and-equal"> Requirements for HASH and EQUAL </a>
30/// * <a href="#bslstl_boyermoorehorspoolsearcher-optimizations-for-bslstl-boyermoorehorspoolsearcher"> Optimizations for bslstl::BoyerMooreHorspoolSearcher </a>
31/// * <a href="#bslstl_boyermoorehorspoolsearcher-usage"> Usage </a>
32/// * <a href="#bslstl_boyermoorehorspoolsearcher-example-1-basic-usage"> Example 1: Basic Usage </a>
33/// * <a href="#bslstl_boyermoorehorspoolsearcher-example-2-defining-a-comparator-and-hash"> Example 2: Defining a Comparator and Hash </a>
34/// * <a href="#bslstl_boyermoorehorspoolsearcher-example-3-non-char-searches"> Example 3: Non-char Searches </a>
35/// * <a href="#bslstl_boyermoorehorspoolsearcher-example-4-caching-searcher-objects"> Example 4: Caching Searcher Objects </a>
36/// * <a href="#bslstl_boyermoorehorspoolsearcher-the-problem"> The Problem </a>
37/// * <a href="#bslstl_boyermoorehorspoolsearcher-design-choices"> Design Choices </a>
38/// * <a href="#bslstl_boyermoorehorspoolsearcher-steps"> Steps </a>
39///
40/// # Purpose {#bslstl_boyermoorehorspoolsearcher-purpose}
41/// Provide an STL-compliant `boyer_moore_horspool_searcher` class.
42///
43/// # Classes {#bslstl_boyermoorehorspoolsearcher-classes}
44///
45/// - bsl::boyer_moore_horspool_searcher: class template to search via BMH
46/// - bslstl::BoyerMooreHorspoolSearcher: class template to search via BMH
47///
48/// **Canonical header:** bsl_functional.h
49///
50/// @see bslstl_defaultsearcher
51///
52/// # Description {#bslstl_boyermoorehorspoolsearcher-description}
53/// This component defines two class templates,
54/// `bsl::boyer_moore_horspool_searcher` and
55/// `bslstl::BoyerMooreHorspoolSearcher`. Both are compliant with section
56/// `[func.search.bmh]` of the C++ Standard (C++17 and later).
57///
58/// `bsl::boyer_moore_horspool_searcher` is strictly limited to the Standard and
59/// is provided for clients for whom standard compliance is a priority.
60/// `bslslt::BoyerMoreHorspoolSearcher` provides several accessors that are not
61/// mentioned in the Standard. Moreover, `bslslt::BoyerMoreHorspoolSearcher` is
62/// "plumbed" for BDE allocators and can be used with BDE standard containers
63/// whereas the compliant strict class always uses the currently installed
64/// default allocator. See {Example 4} below.
65///
66/// Except where there is a relevant difference, both are described below as if
67/// they were one.
68///
69/// This class has several template parameters:
70///
71/// `RNDACC_ITR_NEEDLE`:
72/// The type used to specify (on construction) the range of values
73/// being sought (the "needle").
74///
75/// `HASH`:
76/// The functor type used to hash metadata for the unique values of
77/// the needle. See {Requirements for `HASH` and `EQUAL`}.
78///
79/// `EQUAL`:
80/// The functor type used to compare values when storing/accessing needle
81/// metadata. See {Requirements for `HASH` and `EQUAL`}.
82///
83/// The class also provides a functor-style interface that accepts two iterators
84/// that define the range of values to be searched (the "haystack"). Once
85/// constructed, a single searcher object can be re-used to search multiple
86/// haystacks (for the same needle value).
87///
88/// The iterators defining the haystack need not be of the same type as those
89/// that define the needle. Moreover, the search method of the searcher can be
90/// overloaded for an arbitrary number of different haystack iterators (subject
91/// to {Iterator Requirements}).
92///
93/// ## Algorithm {#bslstl_boyermoorehorspoolsearcher-algorithm}
94///
95///
96/// The search algorithm used is an implementation of the well-known Boyer,
97/// Moore, Horspool (BMH) Algorithm for string matching (see
98/// https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore%E2%80%93Horspool_algorithm).
99/// In the typical case, this algorithm offers complexity of `O(N)` for a
100/// haystack of length `N`.
101///
102/// ## Iterator Requirements {#bslstl_boyermoorehorspoolsearcher-iterator-requirements}
103///
104///
105/// The two independent iterators types associated with this class -- one
106/// defining the needle, the other defining the haystack -- must meet the
107/// requirements of *RandomAccessIterator*.
108///
109/// Additionally:
110/// * The iterators can be constant.
111/// * When dereferenced, both iterator types must refer to the same value type.
112///
113/// The operations of either of the iterator types are allowed to throw
114/// exceptions.
115///
116/// Iterators defining needles are required to remain valid as long as the
117/// searcher object might be used.
118///
119/// ## Requirements for HASH and EQUAL {#bslstl_boyermoorehorspoolsearcher-requirements-for-hash-and-equal}
120///
121///
122/// The comparer class, `EQUAL`, must meet the requirements of
123/// *BinaryPredicate*:
124/// * The class defines an `operator()` method that, given a
125/// *RandomAccessIterator', `iterator`, can be invoked as
126/// `operator()(*iterator, *iterator)`.
127/// * The return value must be contextually convertible to `bool`.
128/// * The supplied iterators can be constant.
129/// * The class must be copyable.
130///
131/// Comparer classes are allowed to throw exceptions.
132///
133/// The behavior is undefined unless two values that are deemed equal by the
134/// `EQUAL` functor generate the same value by the `HASH` functor. That is:
135/// @code
136/// true == searcher.equal()(a, b);
137/// @endcode
138/// implies:
139/// @code
140/// searcher.hash()(a) == searcher.hash()(b);
141/// @endcode
142///
143/// ## Optimizations for bslstl::BoyerMooreHorspoolSearcher {#bslstl_boyermoorehorspoolsearcher-optimizations-for-bslstl-boyermoorehorspoolsearcher}
144///
145///
146/// This implementation handles needle metadata using a fixed size array when
147/// the `value_type` is `char` (either `signed` or `unsigned` flavors). For
148/// needles of typical size, this choice results in somewhat more memory use
149/// than it would have if some dynamically sized container were used; however,
150/// the faster access during searches warrants the tradeoff.
151///
152/// ## Usage {#bslstl_boyermoorehorspoolsearcher-usage}
153///
154///
155/// In this section we show the intended usage of this component.
156///
157/// ### Example 1: Basic Usage {#bslstl_boyermoorehorspoolsearcher-example-1-basic-usage}
158///
159///
160/// The problem of searching a sequence of characters for a particular
161/// sub-sequence arises in many applications. For example, one might need to
162/// know if some document contains a particular word of interest. For example,
163/// suppose we would like to know the first occurrence of the word "United" in
164/// the Declaration of Independence (of the United States):
165///
166/// First, we obtain the text of document and word of interest as sequences of
167/// `char` values.
168/// @code
169/// const char document[] =
170/// " IN CONGRESS, July 4, 1776.\n" // 28
171/// "\n" // 1
172/// " The unanimous Declaration of the thirteen united States of America,\n"
173/// //----^----|----^----|----^----|----^----|---- // 44
174/// // // --
175/// // // 73rd character
176/// //
177/// "\n"
178/// // ...
179/// " declare, That these United Colonies are, and of Right ought to be\n"
180/// // ...
181/// "Honor.";
182///
183/// const char *word = "United";
184/// @endcode
185/// Then, we create a @ref default_searcher object (a functor) using the given
186/// `word`:
187/// @code
188/// bsl::boyer_moore_horspool_searcher<const char *> searchForUnited(
189/// word,
190/// word
191/// + bsl::strlen(word));
192/// @endcode
193/// Notice that no equality comparison functor was specified so
194/// `searchForUnited` will use `bsl::equal_to<char>` by default.
195///
196/// Now, we invoke our functor, specifying the range of the document to be
197/// searched:
198/// @code
199/// bsl::pair<const char *, const char *> result = searchForUnited(
200/// document,
201/// document
202/// + sizeof document);
203///
204/// bsl::size_t offset = result.first - document;
205///
206/// assert(120 == offset);
207/// assert(static_cast<bsl::size_t>(result.second - result.first)
208/// == bsl::strlen(word));
209/// @endcode
210/// Finally, we notice that the search correctly ignored the appearance of the
211/// word "united" (all lower case) in the second sentence.
212///
213/// {@ref bslstl_defaultsearcher |Example 1} shows how the same problem is addressed using
214/// `bsl::default_searcher`.
215///
216/// ### Example 2: Defining a Comparator and Hash {#bslstl_boyermoorehorspoolsearcher-example-2-defining-a-comparator-and-hash}
217///
218///
219/// As seen in {Example 1} above, the default equality comparison functor is
220/// case sensitive. If one needs case *in*-sensitive searches, a non-default
221/// equality comparison class *and* a non-default hash functor must be
222/// specified.
223///
224/// First, define (at file scope if using a pre-C++11 compiler) an equality
225/// comparison class that provides the required functor interface:
226/// @code
227/// struct MyCaseInsensitiveCharComparer {
228/// bool operator()(const char& a, const char& b) const {
229/// return bsl::tolower(a) == bsl::tolower(b);
230/// }
231/// };
232/// @endcode
233/// Then, define (again at file scope, if pre-C++11), a hash functor so that two
234/// values, irrespective of their case, hash to the same value:
235/// @code
236/// struct MyCaseInsensitiveCharHasher {
237/// bool operator()(const char& value) const {
238/// static bsl::hash<char> s_hash;
239/// return s_hash(static_cast<char>(bsl::tolower(value)));
240/// }
241/// };
242/// @endcode
243/// Now, specify `bsl::boyer_moore_horspool_searcher` type for and create a
244/// searcher object to search for `word`:
245/// @code
246/// bsl::boyer_moore_horspool_searcher<const char *,
247/// MyCaseInsensitiveCharHasher,
248/// MyCaseInsensitiveCharComparer>
249/// searchForUnitedInsensitive(
250/// word,
251/// word
252/// + bsl::strlen(word));
253/// @endcode
254/// Note that the new searcher object will use defaulted constructed
255/// `MyCaseInsensitiveCharHasher` and `MyCaseInsensitiveCharComparer` classes.
256/// If stateful functors are required such objects can be passed in the optional
257/// constructor arguments.
258///
259/// Now, we invoke our searcher functor, specifying that the same document
260/// searched in {Example 1}:
261/// @code
262/// bsl::pair<const char *, const char *> resultInsensitive =
263/// searchForUnitedInsensitive(
264/// document,
265/// document
266/// + sizeof document);
267///
268/// bsl::size_t offsetInsensitive = resultInsensitive.first - document;
269///
270/// assert( 72 == offsetInsensitive);
271/// assert(static_cast<bsl::size_t>(resultInsensitive.second
272/// - resultInsensitive.first)
273/// == bsl::strlen(word));
274/// @endcode
275/// Finally, we find the next occurrence of `word` by *reusing* the same
276/// searcher object, this time instructing it to begin its search just after the
277/// previous occurrence of `word` was found:
278/// @code
279/// resultInsensitive = searchForUnitedInsensitive(resultInsensitive.second,
280/// document + sizeof document);
281///
282/// offsetInsensitive = resultInsensitive.first - document;
283///
284/// assert(120 == offsetInsensitive);
285/// assert(static_cast<bsl::size_t>(resultInsensitive.second
286/// - resultInsensitive.first)
287/// == bsl::strlen(word));
288/// @endcode
289///
290/// {@ref bslstl_defaultsearcher |Example 2} shows how the same problem is addressed using
291/// `bsl::default_searcher`.
292///
293/// ### Example 3: Non-char Searches {#bslstl_boyermoorehorspoolsearcher-example-3-non-char-searches}
294///
295///
296/// The BMH searcher class template is not constrained to searching for `char`
297/// values. Searches can be done on other types (see {Iterator Requirements}).
298/// Moreover the container of the sequence being sought (the "needle") need not
299/// the same as the sequence being searched (the "haystack").
300///
301/// Suppose one has data from an instrument that reports `float` values and that
302/// inserts the sequence `{ FLT_MAX, FLT_MIN, FLT_MAX }` as a marker for the
303/// start and end of a test run. We can assume the probably of the instrument
304/// reporting this sequence as readings is negligible and that data reported
305/// outside of the test runs is random noise. Here is how we can search for the
306/// first test run data in the data sequence.
307///
308/// First, we create a representation of the sequence that denotes the limit of
309/// a test run.
310/// @code
311/// const float markerSequence[] = { FLT_MAX , FLT_MIN , FLT_MAX };
312/// const bsl::size_t markerSequenceLength = sizeof markerSequence
313/// / sizeof *markerSequence;
314/// @endcode
315/// Next, we obtain the data to be searched. (In this example, we will use
316/// simulated data.)
317/// @code
318/// bsl::vector<float> data; // Container provides random access iterators.
319/// doTestRun(&data);
320/// @endcode
321/// Then, we define and create our searcher object:
322/// @code
323/// bsl::boyer_moore_horspool_searcher<const float *>
324/// searchForMarker(markerSequence,
325/// markerSequence
326/// + markerSequenceLength);
327/// @endcode
328/// Notice that no equality comparison functor was specified so
329/// `searchForMarker` will use `bsl::equal_to<float>` by default.
330///
331/// Now, we invoke our searcher on the instrument data.
332/// @code
333/// typedef bsl::vector<float>::const_iterator DataConstItr;
334///
335/// const bsl::pair<DataConstItr, DataConstItr> notFound(data.cend(),
336/// data.cend());
337///
338/// bsl::pair<DataConstItr, DataConstItr> markerPosition = searchForMarker(
339/// data.cbegin(),
340/// data.cend());
341///
342/// assert(notFound != markerPosition);
343///
344/// DataConstItr startOfTestRun = markerPosition.second;
345/// @endcode
346/// Finally, we locate the marker of the end of the first test run and pass the
347/// location of the first test run data to some other function for processing.
348/// @code
349/// markerPosition = searchForMarker(markerPosition.second, data.cend());
350///
351/// assert(notFound != markerPosition);
352///
353/// DataConstItr endOfTestRun = markerPosition.first;
354///
355/// processTestRun(startOfTestRun, endOfTestRun);
356/// @endcode
357/// {@ref bslstl_defaultsearcher |Example 3} shows how the same problem is addressed
358/// using `bsl::default_searcher`. Notice that other example uses `data` from a
359/// container that provides bidirectional iterators (and forward iterators would
360/// have sufficed), whereas here random access iterators are required.
361///
362/// ### Example 4: Caching Searcher Objects {#bslstl_boyermoorehorspoolsearcher-example-4-caching-searcher-objects}
363///
364///
365/// The construction of `bsl::boyer_moore_horspool_searcher` objects is small
366/// (the needle must be scanned, meta-data calculated, and results saved) but
367/// can be non-neglibible when one needs a great number of them. When there is
368/// a reasonable chance that one will have to repeat a given search, it can be
369/// worthwhile to cache the searcher objects for reuse.
370///
371/// #### The Problem {#bslstl_boyermoorehorspoolsearcher-the-problem}
372///
373///
374/// Suppose we have a long list of names, each consisting of a given name (first
375/// name) and a surname (last name), and that we wish to identify instances of
376/// reduplication of the given name in the surname. That is, we want to
377/// identify the cases where the given name is a *case-insensitive* substring of
378/// the surname. Examples include "Durand Durand", "James Jameson", "John St.
379/// John", and "Jean Valjean". In this example we will not accept nicknames and
380/// other approximate name forms as matches (e.g., "Joe Joseph", "Jack
381/// Johnson").
382///
383/// Since we want to perform our task as efficiently as possible, and since we
384/// expect many entries to have common given names (e.g., "John"), we decide to
385/// create a cache of searcher objects for those first names so they need not be
386/// reconstructed for each search of a surname.
387///
388/// #### Design Choices {#bslstl_boyermoorehorspoolsearcher-design-choices}
389///
390///
391/// To implement our cache we will use a `bsl::unordered_map` container.
392/// Allocating types must meet certain requirements to work properly with
393/// allocator-enabled containers such as `bsl::unordered_map`.
394/// `bsl::boyer_moore_horspool_searcher` does not, so we will use
395/// `bslstl::BoyerMooreHorspoolSearcher`, which does.
396///
397/// To clarify exposition, our cache will have the simple policy of retaining
398/// searcher objects indefinitely and ignore the real-world concern that our
399/// cache may grow so large that the search time exceeds construction time.
400/// Also, we will forgo techniques that might minimize the number of times data
401/// is copied.
402///
403/// #### Steps {#bslstl_boyermoorehorspoolsearcher-steps}
404///
405///
406/// First, we define our cache class:
407/// @code
408/// // ====================================
409/// // class MyCaseInsensitiveSearcherCache
410/// // ====================================
411///
412/// class MyCaseInsensitiveSearcherCache {
413///
414/// // TYPES
415/// public:
416/// typedef bslstl::BoyerMooreHorspoolSearcher<
417/// bsl::string::const_iterator,
418/// MyCaseInsensitiveCharHasher,
419/// MyCaseInsensitiveCharComparer>
420/// Searcher;
421/// // PRIVATE TYPES
422/// private:
423/// typedef bsl::unordered_map<bsl::string, Searcher> Map;
424///
425/// // DATA
426/// Map d_map;
427///
428/// // PRIVATE MANIPULATORS
429///
430/// /// Insert into this cache a key-value pair where the key is the
431/// /// specified `key` and the value is a `Searcher` object created to
432/// /// seek the needle specified by the key part. Note that this
433/// /// arrangement guarantees that the iterators used by this cached
434/// /// searcher object remain valid for the life of the searcher
435/// /// object.
436/// const Searcher& insertSearcher(const bsl::string& key);
437///
438/// public:
439/// // CREATORS
440///
441/// /// Create an empty `MyCaseInsensitiveSearcherCache` object.
442/// /// Optionally specify a `basicAllocator` used to supply memory. If
443/// /// `basicAllocator` is 0, the currently installed default
444/// /// allocator is used.
445/// explicit MyCaseInsensitiveSearcherCache(bslma::Allocator
446/// *basicAllocator = 0);
447///
448/// // MANIPULATORS
449///
450/// /// Return a `const`-reference to the cached server that can do a
451/// /// case-insensitive search for the specified `needle`. If such a
452/// /// searcher does not exist in the cache on entry, such a searcher
453/// /// is constructed, added to the cache, and returned (by
454/// /// `const`-reference).
455/// const Searcher& getSearcher(const char *needle);
456///
457/// // ACCESSORS
458///
459/// /// Return the number of searcher objects in this cache.
460/// bsl::size_t numSearchers() const;
461/// };
462/// @endcode
463/// Notice (see the `typedef` for `Searcher`) that we reuse the hash functor,
464/// `MyCaseInsensitiveCharHasher`, and equality comparison functor,
465/// `MyCaseInsensitiveCharComparer`, that were defined in {Example 2}.
466///
467/// Note that `MyCaseInsensitiveSearcherCache` itself is an allocating type.
468/// If we needed to make it compatible with BDE containers (e.g., to allow a
469/// cache of caches) a few additional features are needed. As we have no such
470/// need, those features are deferred.
471///
472/// Then, we implement the constructor:
473/// @code
474/// // ------------------------------------
475/// // class MyCaseInsensitiveSearcherCache
476/// // ------------------------------------
477///
478/// // CREATORS
479/// MyCaseInsensitiveSearcherCache::
480/// MyCaseInsensitiveSearcherCache(bslma::Allocator *basicAllocator)
481/// : d_map(basicAllocator)
482/// {
483/// }
484/// @endcode
485///
486/// Notice that `basicAllocator` is simply forwarded to `d_map`.
487///
488/// Next, we implement the public methods:
489/// @code
490/// // MANIPULATORS
491/// const
492/// MyCaseInsensitiveSearcherCache::Searcher&
493/// MyCaseInsensitiveSearcherCache::getSearcher(const char *needle)
494/// {
495/// bsl::string key(needle);
496/// Map::iterator findResult = d_map.find(key);
497///
498/// if (d_map.end() == findResult) {
499/// return insertSearcher(key); // RETURN
500/// } else {
501/// return findResult->second; // RETURN
502/// }
503/// }
504///
505/// // ACCESSORS
506/// bsl::size_t MyCaseInsensitiveSearcherCache::numSearchers() const
507/// {
508/// return d_map.size();
509/// }
510/// @endcode
511/// Then, to complete our class, we implement the cache class private method:
512/// @code
513/// // PRIVATE MANIPULATORS
514/// const
515/// MyCaseInsensitiveSearcherCache::Searcher&
516/// MyCaseInsensitiveSearcherCache::insertSearcher(const bsl::string& key)
517/// {
518/// Searcher dummy(key.begin(), key.begin()); // to be overwritten
519/// Map::value_type value(key, dummy);
520///
521/// bsl::pair<Map::iterator, bool> insertResult = d_map.insert(value);
522/// assert(true == insertResult.second);
523///
524/// Map::iterator iterator = insertResult.first;
525///
526/// iterator->second = Searcher(iterator->first.begin(),
527/// iterator->first.end());
528/// return iterator->second;
529/// }
530/// @endcode
531/// Notice creating our element is a two step process. First, we insert the key
532/// with an arbitrary "dummy" searcher. Once the key (a string) exists in the
533/// map (at an address that is stable for the life of the map) we create a
534/// searcher object that refers to that key string for its search sequence, and
535/// overwrite the "dummy" part of previously inserted element.
536///
537/// Now, we show how the searcher object cache can be used. In this example, a
538/// fixed array represents our source of name entries, in random order:
539/// @code
540/// struct {
541/// const char *d_givenName_p;
542/// const char *d_surname_p;
543/// } DATA[] = {
544/// // GIVEN SURNAME
545/// // -------- ------------
546/// { "Donald" , "McDonald" }
547/// , { "John" , "Johnson" }
548/// , { "John" , "Saint Johns" }
549/// , { "Jon" , "Literjon" }
550/// , { "Jean" , "Valjean" }
551/// , { "James" , "Jameson" }
552/// , { "Will" , "Freewill" }
553/// , { "John" , "Johns" }
554/// , { "John" , "John" }
555/// , { "John" , "Jones" }
556/// , { "J'onn" , "J'onzz" }
557/// , { "Donald" , "Donalds" }
558/// , { "Donald" , "Mac Donald" }
559/// , { "William", "Williams" }
560/// , { "Durand" , "Durand" }
561/// , { "John" , "Johnstown" }
562/// , { "Major" , "Major" }
563/// , { "Donald" , "MacDonald" }
564/// , { "Patrick", "O'Patrick" }
565/// , { "Chris", "Christie" }
566/// , { "Don", "London" }
567/// // ...
568/// , { "Ivan" , "Ivanovich" }
569/// };
570///
571/// bsl::size_t NUM_NAMES = sizeof DATA / sizeof *DATA;
572///
573/// typedef bsl::pair<const char *, const char *> Result;
574///
575/// MyAllocator myAllocator;
576/// MyCaseInsensitiveSearcherCache searcherCache(&myAllocator);
577/// bsl::string output;
578///
579/// for (bsl::size_t ti = 0; ti < NUM_NAMES; ++ti) {
580/// const char * const givenName = DATA[ti].d_givenName_p;
581/// const char * const surname = DATA[ti].d_surname_p;
582///
583/// const MyCaseInsensitiveSearcherCache::Searcher& searcher =
584/// searcherCache.getSearcher(givenName);
585///
586/// assert(&myAllocator == searcher.allocator());
587/// @endcode
588/// Notice that each searcher object in the cache (correctly) uses the same
589/// allocator as we specified for the cache itself.
590///
591/// The rest of the application:
592/// @code
593/// const Result result = searcher(surname,
594/// surname + bsl::strlen(surname));
595///
596/// const Result notFound = bsl::make_pair(surname + bsl::strlen(surname),
597/// surname + bsl::strlen(surname));
598///
599/// char buffer[32];
600///
601/// if (notFound == result) {
602/// sprintf(buffer, "ng: %-10s %-11s\n", givenName, surname);
603/// } else {
604/// sprintf(buffer, "OK: %-10s %-11s\n", givenName, surname);
605/// }
606///
607/// output.append(buffer);
608/// }
609/// @endcode
610/// Finally, we examine the collected `output` and confirm that our code is
611/// properly identifying the names of interest.
612/// @code
613/// assert(0 == bsl::strcmp(output.c_str(),
614/// "OK: Donald McDonald \n"
615/// "OK: John Johnson \n"
616/// "OK: John Saint Johns\n"
617/// "OK: Jon Literjon \n"
618/// "OK: Jean Valjean \n"
619/// "OK: James Jameson \n"
620/// "OK: Will Freewill \n"
621/// "OK: John Johns \n"
622/// "OK: John John \n"
623/// "ng: John Jones \n"
624/// "ng: J'onn J'onzz \n"
625/// "OK: Donald Donalds \n"
626/// "OK: Donald Mac Donald \n"
627/// "OK: William Williams \n"
628/// "OK: Durand Durand \n"
629/// "OK: John Johnstown \n"
630/// "OK: Major Major \n"
631/// "OK: Donald MacDonald \n"
632/// "OK: Patrick O'Patrick \n"
633/// "OK: Chris Christie \n"
634/// "OK: Don London \n"
635/// "OK: Ivan Ivanovich \n"));
636///
637/// assert(searcherCache.numSearchers() < NUM_NAMES);
638/// @endcode
639/// @}
640/** @} */
641/** @} */
642
643/** @addtogroup bsl
644 * @{
645 */
646/** @addtogroup bslstl
647 * @{
648 */
649/** @addtogroup bslstl_boyermoorehorspoolsearcher
650 * @{
651 */
652
653#include <bslscm_version.h>
654
655#include <bslstl_array.h>
656#include <bslstl_equalto.h>
657#include <bslstl_hash.h>
658#include <bslstl_iterator.h>
659#include <bslstl_pair.h>
660#include <bslstl_unorderedmap.h>
661
662#include <bslma_allocator.h>
663#include <bslma_default.h>
664
665#include <bslmf_conditional.h>
668#include <bslmf_issame.h>
669#include <bslmf_movableref.h>
670
671#include <bsls_assert.h>
672#include <bsls_keyword.h>
673#include <bsls_libraryfeatures.h>
674#include <bsls_performancehint.h>
675
676#include <cstring> // 'memcpy'
677
678#include <limits.h> // 'UCHAR_MAX'
679
680
681namespace bslstl {
682
683 // ========================================
684 // class BoyerMooreHorspoolSearcher_CharImp
685 // ========================================
686
687/// This class template implements the same interfaces as the
688/// `BoyerMooreHorspoolSearcher_GeneralImp`; however, the implementation is
689/// specialized for a `value_type` of `char`. Notably, needle metadata is
690/// stored/accessed from a fixed size array, not a dynamically-sized
691/// container.
692///
693/// See @ref bslstl_boyermoorehorspoolsearcher
694template <class RNDACC_ITR_NEEDLE,
695 class HASH,
696 class EQUAL>
698
699 public:
700 // TYPES
701
702 /// the type of the values that can be obtained by dereferencing a
703 /// `RNDACC_ITR_NEEDLE`
704 typedef typename bsl::iterator_traits<RNDACC_ITR_NEEDLE>::value_type
706
707 /// a signed type that can describe the distance between
708 /// `RNDACC_ITR_NEEDLE` iterators
709 typedef typename bsl::iterator_traits<RNDACC_ITR_NEEDLE>::difference_type
711
712 private:
713 // PRIVATE TYPES
714
715 /// This `typedef` is a convenient alias for the utility associated with
716 /// movable references.
717 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
718
719 typedef unsigned char ShortNeedleSkipType;
720 // 'd_needleLength <= UCHAR_MAX'
721
722 typedef difference_type LongNeedleSkipType;
723 // 'UCHAR_MAX < d_needleLength'
724
729
730 // PRIVATE MANIPULATORS
731
732 /// Install in this object a table copied from the specified `object`.
733 /// The behavior is undefined unless `0 == d_table_p` (on entry) and
734 /// `d_needleLength` has been initialized.
735 void privateInstallNewTable(
737
738 /// Copy the table of the specified `object` over the table of this
739 /// object. The behavior is undefined unless this object has a table
740 /// and `privateUseShortNeedleOptimization()` returns the same value for
741 /// `object` and for this object.
742 void privateInstallTableOverOld(
744
745 /// Replace in an exception-safe manner this object's table with a copy
746 /// of the table of the specified `object`. This object's table (on
747 /// entry), if any, is deleted.
748 void privateInstallMismatchedTable(
750
751 /// Destroy and deallocate the `d_table_p` member of this object, and
752 /// set `d_table_p` to 0.
753 void privateDeleteTable();
754
755 // PRIVATE ACCESSORS
756
757 /// Set the specified `object`, the source object of a move operation,
758 /// to a (valid) state that is not specified to users. The behavior is
759 /// undefined if `this == object`.
760 void privateSetPostMoveState(BoyerMooreHorspoolSearcher_CharImp *object)
761 const;
762
763 /// Return `true` if this instantiation should used the "short needle
764 /// (space) optimization", and `false` otherwise. The behavior is
765 /// undefined unless `d_needleLength` has been initialized.
766 bool privateUseShortNeedleOptimization() const;
767
768 /// Return `true` if the specified `object` has the same value for
769 /// `privateUseShortNeedleOptimization()` as this object, and `false`
770 /// otherwise.
771 bool privateHasSameNeedleOptimization(
773 const;
774
775 // DATA
776 std::size_t d_needleLength;
777 BloombergLP::bslma::Allocator *d_allocator_p;
778 void *d_table_p;
779
780 public:
781 // CREATORS
782
783 /// Create a `BoyerMooreHorspoolSearcher_CharImp` object for the
784 /// sequence of `char` values in the specified range
785 /// `[needleFirst, needlelast)`. This implementation is invoked when
786 /// the specified `hash` is `bsl::hash<char>` and the specified `equal`
787 /// is `bsl::equal_to<char>`. Neither functor is used because for the
788 /// special case of `char` the needle metadata is maintained in a fixed
789 /// size array (256 elements). As always, the specified
790 /// `basicAllocator` is used to supply memory. If `basicAllocator` is
791 /// 0, the currently installed default allocator is used. The behavior
792 /// is undefined unless `needleFirst` can be advanced to `needleLast`.
794 RNDACC_ITR_NEEDLE needleFirst,
795 RNDACC_ITR_NEEDLE needleLast,
796 HASH hash,
797 EQUAL equal,
798 BloombergLP::bslma::Allocator *basicAllocator);
799
800 /// Create a `BoyerMooreHorspoolSearcher_CharImp` object having same
801 /// state as the specified `original` object. The allocator of
802 /// `original` is propagated to the new object.
804 const BoyerMooreHorspoolSearcher_CharImp& original);
805
806 /// Create a `BoyerMooreHorspoolSearcher_CharImp` object having same
807 /// state as the specified `original` object by moving (in constant
808 /// time) the state of the original object to the new object. The
809 /// allocator of `original` is propagated to the new object. The
810 /// `original` object is left in an unspecified (valid) state.
812 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher_CharImp>
813 original)
815
816 /// Create a `BoyerMooreHorspoolSearcher_CharImp` object having the same
817 /// state as the specified `original` object and that uses the specified
818 /// `basicAllocator` to supply memory. If `basicAllocator` is 0, the
819 /// currently installed default allocator is used.
822 BloombergLP::bslma::Allocator *basicAllocator);
823
824 /// Create a `BoyerMooreHorspoolSearcher_CharImp` object having the same
825 /// state as the specified `original` object and that uses the specified
826 /// `basicAllocator` to supply memory. The state of `original` is moved
827 /// (in constant time) to the new searcher if
828 /// `basicAllocator == original.allocator()`, and is copied using
829 /// `basicAllocator` otherwise. If `basicAllocator` is 0, the currently
830 /// installed default allocator is used. The `original` object is left
831 /// in an unspecified (valid) state.
833 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher_CharImp>
834 original,
835 BloombergLP::bslma::Allocator *basicAllocator);
836
837 /// Destroy this object;
839
840 // MANIPULATORS
841
842 /// Assign to this object the state of the specified `rhs` object, and
843 /// return a non-`const` reference to this searcher object.
846
847 /// Assign to this object the state of the specified `rhs` object and
848 /// return a non-`const` reference to this searcher. The `rhs` is left
849 /// in an unspecified (valid) state.
851 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher_CharImp>
852 rhs);
853
854 // ACCESSORS
855
856 /// Return the number of positions to advance the search in the haystack
857 /// when the specified `value` is found in the rightmost position of the
858 /// current (unsuccessful) match attempt.
859 difference_type badCharacterSkip(const value_type& value) const;
860
861 /// Return the hashing functor supplied on construction.
862 HASH hash() const;
863
864 /// Return the equality comparison functor supplied on construction.
865 EQUAL equal() const;
866
867 /// Return the allocator supplied on construction.
868 BloombergLP::bslma::Allocator *allocator() const;
869};
870
871 // ===========================================
872 // class BoyerMooreHorspoolSearcher_GeneralImp
873 // ===========================================
874
875/// This class template implements the same interfaces as the
876/// `BoyerMooreHorspoolSearcher_CharImp` for arbitrary `value_type`.
877///
878/// See @ref bslstl_boyermoorehorspoolsearcher
879template <class RNDACC_ITR_NEEDLE,
880 class HASH,
881 class EQUAL>
883
884 // PUBLIC TYPES
885 public:
886 typedef typename bsl::iterator_traits<RNDACC_ITR_NEEDLE>::value_type
888
889 typedef typename bsl::iterator_traits<RNDACC_ITR_NEEDLE>::difference_type
891 private:
892 // PRIVATE TYPES
893 typedef bsl::unordered_map<value_type, // key
894 difference_type, // value
895 HASH,
896 EQUAL> Map; // skip-on-mismatch "table"
897
898 /// This `typedef` is a convenient alias for the utility associated with
899 /// movable references.
900 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
901
902 // DATA
903 difference_type d_needleLength;
904 Map d_map;
905
906 public:
907 // CREATORS
908
909 /// Create a `BoyerMooreHorspoolSearcher_GeneralImp` object for the
910 /// sequence of `value_type` values in the specified range
911 /// `[needleFirst, needlelast)`. The specified `hash` and `equal`
912 /// functors are used to store/access metadata associated with the
913 /// needle. See {Requirements for `HASH` and `EQUAL`}. Optionally
914 /// specify a `basicAllocator` used to supply memory. If
915 /// `basicAllocator` is 0, the currently installed default allocator is
916 /// used. The behavior is undefined unless `needleFirst` can be
917 /// advanced to `needleLast`.
919 RNDACC_ITR_NEEDLE needleFirst,
920 RNDACC_ITR_NEEDLE needleLast,
921 HASH hash,
922 EQUAL equal,
923 BloombergLP::bslma::Allocator *basicAllocator);
924
925 /// Create a `BoyerMooreHorspoolSearcher_GeneralImp` object having same
926 /// state as the specified `original` object. The allocator of
927 /// `original` is propagated to the new object.
930
931 /// Create a `BoyerMooreHorspoolSearcher_GeneralImp` object having same
932 /// state as the specified `original` object by moving (in constant
933 /// time) the state of the original object to the new object. The
934 /// allocator of `original` is propagated to the new object. The
935 /// `original` object is left in an unspecified (valid) state.
937 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher_GeneralImp>
938 original)
940
941 /// Create a `BoyerMooreHorspoolSearcher_GeneralImp` object having the
942 /// same state as the specified `original` object. Optionally specify a
943 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
944 /// the currently installed default allocator is used.
947 BloombergLP::bslma::Allocator *basicAllocator);
948
949 /// Create a `BoyerMooreHorspoolSearcher_GeneralImp` object having same
950 /// state as the specified `original` object and that uses
951 /// `basicAllocator` to supply memory. The state of `original` is moved
952 /// (in constant time) to the new searcher if
953 /// `basicAllocator == original.allocator()`, and is copied using
954 /// `basicAllocator` otherwise. The `original` object is left in an
955 /// unspecified (valid) state.
957 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher_GeneralImp>
958 original,
959 BloombergLP::bslma::Allocator *basicAllocator);
960
961 // MANIPULATORS
962
963 /// Assign to this object the state of the specified `rhs` object, and
964 /// return a non-`const` reference to this searcher object.
967
968 /// Assign to this object the state of the specified `rhs` object and
969 /// return a non-`const` reference to this searcher. The `rhs` is left
970 /// in an unspecified (valid) state.
972 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher_GeneralImp>
973 rhs);
974
975 // ACCESSORS
976
977 /// Return the number of positions to advance the search in the haystack
978 /// when the specified `value` is found in the rightmost position of the
979 /// current (unsuccessful) match attempt.
980 difference_type badCharacterSkip(const value_type& value) const;
981
982 /// Return the hashing functor supplied on construction.
983 HASH hash() const;
984
985 /// Return the equality comparison functor supplied on construction.
986 EQUAL equal() const;
987
988 /// Return the allocator used by this object to supply memory.
989 BloombergLP::bslma::Allocator *allocator() const;
990};
991
992 // ================================
993 // class BoyerMooreHorspoolSearcher
994 // ================================
995
996/// This class template implements an STL-compliant searcher object that
997/// uses the Boyer, Moore, Horspool Algorithm. Several non-standard
998/// accessors are also provided.
999///
1000/// See @ref bslstl_boyermoorehorspoolsearcher
1001template <class RNDACC_ITR_NEEDLE,
1002 class HASH = bsl::hash<
1003 typename bsl::iterator_traits<RNDACC_ITR_NEEDLE>::value_type>,
1004 class EQUAL = bsl::equal_to<
1005 typename bsl::iterator_traits<RNDACC_ITR_NEEDLE>::value_type>
1006 >
1008
1009 public:
1010 // TYPES
1011
1012 /// the type of the values that can be obtained by dereferencing a
1013 /// `RNDACC_ITR_NEEDLE`
1014 typedef typename bsl::iterator_traits<RNDACC_ITR_NEEDLE>::value_type
1016
1017 /// the default type for the `HASH` optional template parameter
1018 typedef bsl::hash<
1019 typename bsl::iterator_traits<RNDACC_ITR_NEEDLE>::value_type>
1021
1022 /// the default type for the `EQUAL` optional template parameter
1023 typedef bsl::equal_to<
1024 typename bsl::iterator_traits<RNDACC_ITR_NEEDLE>::value_type>
1026
1027 private:
1028 // PRIVATE TYPES
1029
1030 /// a signed type that can describe the distance between
1031 /// `RNDACC_ITR_NEEDLE` iterators
1032 typedef typename bsl::iterator_traits<RNDACC_ITR_NEEDLE>::difference_type
1033 difference_type;
1034
1035 /// This `typedef` is a convenient alias for the utility associated with
1036 /// movable references.
1037 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
1038
1039 enum { k_CAN_OPTIMIZE_FOR_CHAR = (
1040 1 == sizeof(value_type)
1045 };
1046
1047 typedef typename bsl::conditional<
1048 k_CAN_OPTIMIZE_FOR_CHAR,
1049
1050 BloombergLP::bslstl::
1051 BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1052 HASH,
1053 EQUAL>,
1054 BloombergLP::bslstl::
1055 BoyerMooreHorspoolSearcher_GeneralImp<RNDACC_ITR_NEEDLE,
1056 HASH,
1057 EQUAL> >::type Imp;
1058
1059 // DATA
1060 RNDACC_ITR_NEEDLE d_needleFirst; // start of needle specified by CTOR
1061 RNDACC_ITR_NEEDLE d_needleLast; // end of needle specified by CTOR
1062 difference_type d_needleLength; // length of needle specified by CTOR
1063
1064 Imp d_imp; // 'char'-optimized or general implementation
1065
1066 // PRIVATE ACCESSORS
1067
1068 /// Set the specified `object`, the source object of a move operation,
1069 /// to a (valid) state that is not specified to users. The behavior is
1070 /// undefined if `this == object`.
1071 void privateSetPostMoveState(BoyerMooreHorspoolSearcher *object) const;
1072
1073 public:
1074 // CREATORS
1075
1076 /// Create a `BoyerMooreHorspoolSearcher` object that can search for the
1077 /// sequence of `value_type` values found in the specified range
1078 /// `[needleFirst, needleLast)`. Generate meta-data and save for use by
1079 /// `operator()`. The complexity of this process is O(M) where M is
1080 /// the length of the "needle". Optionally specify a `hash` functor
1081 /// mapping mis-matched values to the size of the next step in the
1082 /// search -- as large as, `needleLast - needleFirst`. Optionally
1083 /// specify an `equal` functor for use with `hash` and for use by
1084 /// `operator()`. See {Requirements for `HASH` and `EQUAL`}.
1085 /// Optionally specify `basicAllocator` to supply memory. If
1086 /// `basicAllocator` is 0 or not supplied, the currently installed
1087 /// default allocator is used. The behavior is undefined unless
1088 /// `needleFirst` can be advanced to `needleLast`.
1090 RNDACC_ITR_NEEDLE needleFirst,
1091 RNDACC_ITR_NEEDLE needleLast,
1092 HASH hash = HASH(),
1093 EQUAL equal = EQUAL(),
1094 BloombergLP::bslma::Allocator *basicAllocator = 0);
1095
1096 /// Create a `BoyerMooreHorspoolSearcher` object having same state --
1097 /// `needleFirst()`, `needleLast()`, `hash()`, and `equal()` -- as the
1098 /// specified `original` object, and that uses the currently installed
1099 /// default allocator to supply memory.
1101
1102 /// Create a `BoyerMooreHorspoolSearcher` object having same state --
1103 /// `needleFirst()`, `needleLast()`, `hash()`, and `equal()` -- as the
1104 /// specified `original` object by moving (in constant time) the state
1105 /// of `original` to the new searcher. The allocator of `original` is
1106 /// propagated for use in the newly created searcher. The `original`
1107 /// object is left in an unspecified (valid) state.
1109 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher> original)
1111
1112 /// Create a `BoyerMooreHorspoolSearcher` object having same state --
1113 /// `needleFirst()`, `needleLast()`, `hash()`, and `equal()` -- as the
1114 /// specified `original` object. Optionally specify a `basicAllocator`
1115 /// used to supply memory. If `basicAllocator` is 0, the currently
1116 /// installed default allocator is used.
1118 const BoyerMooreHorspoolSearcher& original,
1119 BloombergLP::bslma::Allocator *basicAllocator);
1120
1121 /// Create a `BoyerMooreHorspoolSearcher` object having same state --
1122 /// `needleFirst()`, `needleLast()`, `hash()`, and `equal()` -- as the
1123 /// specified `original` object. The specified `basicAllocator` is used
1124 /// to supply memory. If `basicAllocator` is 0, the currently installed
1125 /// default allocator is used. The state of `original` is moved (in
1126 /// constant time) to the new searcher if
1127 /// `basicAllocator == original.allocator()`, and is move-inserted (in
1128 /// linear time) using `basicAllocator` otherwise. The `original`
1129 /// object is left in an unspecified (valid) state.
1131 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher>
1132 original,
1133 BloombergLP::bslma::Allocator *basicAllocator);
1134
1136 // Destroy this 'BoyerMooreHorspoolSearcher' object.
1137
1138 // MANIPULATORS
1139
1140 /// Assign to this object the state -- `needleFirst()`, `needleLast()`,
1141 /// `hash()`, and `equal()` -- of the specified `rhs` object, and return
1142 /// a non-`const` reference to this searcher.
1144 rhs);
1145
1146 /// Assign to this object the state of the specified `rhs` object --
1147 /// `needleFirst()`, `needleLast()`, `hash()`, and `equal()` -- and
1148 /// return a non-`const` reference to this searcher. The `rhs` is left
1149 /// in an unspecified (valid) state.
1151 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher> rhs);
1152
1153 // ACCESSORS
1154
1155 /// Search the specified range `[haystackFirst, haystackLast)` for the
1156 /// first sequence of `value_type` values specified on construction.
1157 /// Return the range where those values are found, or the range
1158 /// `[haystackLast, haystackLast)` if that sequence is not found. The
1159 /// search is performed using an implementation of the Boyer Moore
1160 /// Horspool algorithm and has a complexity of O(N) for random text.
1161 /// Values of the "needle" sequence and the "haystack" sequence are
1162 /// compared using the equality comparison functor specified on
1163 /// construction. The behavior is undefined unless `haystackFirst` can
1164 /// be advanced to `haystackLast` and the iterators used to construct
1165 /// this object, `needleFirst()` and `needleLast()`, are still valid.
1166 /// Note that if the "needle" sequence is empty, the range
1167 /// `[haystackFirst, haystackFirst)` is returned. Also note that if the
1168 /// "needle" sequence is longer than the "haystack" sequence -- thus,
1169 /// impossible for the "needle" to be found in the "haystack" -- the
1170 /// range `[haystackLast, haystackLast)` is returned.
1171 template<class RNDACC_ITR_HAYSTACK>
1173 RNDACC_ITR_HAYSTACK haystackFirst,
1174 RNDACC_ITR_HAYSTACK haystackLast) const;
1175
1176 // Non-Standard Accessors
1177
1178 /// Return an iterator referring to the first element of the sequence of
1179 /// `value_type` values that can be sought by this searcher object.
1180 RNDACC_ITR_NEEDLE needleFirst() const;
1181
1182 /// Return an iterator referring to one past the last element of the
1183 /// sequence of `value_type` values that can be sought by this searcher
1184 /// object.
1185 RNDACC_ITR_NEEDLE needleLast() const;
1186
1187 /// Return the hashing functor supplied on construction.
1188 HASH hash() const;
1189
1190 /// Return the equality comparison functor supplied on construction.
1191 EQUAL equal() const;
1192
1193 /// Return the allocator used by this object to supply memory.
1194 BloombergLP::bslma::Allocator *allocator() const;
1195};
1196
1197} // close package namespace
1198
1199
1200#ifndef BSLS_LIBRARYFEATURES_HAS_CPP17_SEARCH_FUNCTORS
1201namespace bsl {
1202
1203
1204 // ===================================
1205 // class boyer_moore_horspool_searcher
1206 // ===================================
1207
1208/// This class template implements an STL-compliant searcher object that
1209/// uses the Boyer, Moore, Horspool Algorithm.
1210///
1211/// See @ref bslstl_boyermoorehorspoolsearcher
1212template <class RandomAccessIterator1,
1213 class Hash = hash<
1214 typename iterator_traits<RandomAccessIterator1>::value_type>,
1215 class BinaryPredicate = equal_to<
1216 typename iterator_traits<RandomAccessIterator1>::value_type> >
1217class boyer_moore_horspool_searcher {
1218
1219 private:
1220 // DATA
1221 BloombergLP::bslstl::BoyerMooreHorspoolSearcher<RandomAccessIterator1,
1222 Hash,
1223 BinaryPredicate> d_imp;
1224
1225 public:
1226 // CREATORS
1227
1228 /// Create a `boyer_moore_horspool_searcher` object that can search for
1229 /// the sequence of `value_type` values found in the specified range
1230 /// `[pat_first, pat_last)`. Generate meta-data and save for use by
1231 /// `operator()`. The complexity of this process is O(M) where M is
1232 /// `pat_last - pat_first`. Optionally specify `hf`, a hash functor,
1233 /// that maps mis-matched values to the size of the next step in the
1234 /// search -- as large as, `pat_Last - pat_First`. Optionally specify
1235 /// `pred`, an equality comparison functor for use with `hash` and for
1236 /// use by `operator()`. See {Requirements for `HASH` and `EQUAL`}.
1237 /// The behavior is undefined unless `pat_First` can be advanced to
1238 /// `pat_Last`.
1239 boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first,
1240 RandomAccessIterator1 pat_last,
1241 Hash hf = Hash(),
1242 BinaryPredicate pred =
1243 BinaryPredicate());
1244
1245 boyer_moore_horspool_searcher(
1246 const boyer_moore_horspool_searcher& original)
1247 = default;
1248 // Create a 'boyer_moore_horspool_searcher' object having same state as
1249 // the specified 'original' object.
1250
1251 boyer_moore_horspool_searcher(
1252 BloombergLP::bslmf::MovableRef<boyer_moore_horspool_searcher>
1253 original) = default;
1254 // Create a 'boyer_moore_horspool_searcher' object having same state as
1255 // the specified 'original' object by moving (in constant time) the
1256 // state of 'original' to the new searcher. The 'original' object is
1257 // left in an unspecified (valid) state.
1258
1259 ~boyer_moore_horspool_searcher() = default;
1260 // Destroy this 'boyer_moore_horspool_searcher' object.
1261
1262 // MANIPULATORS
1263 boyer_moore_horspool_searcher& operator=(
1264 const boyer_moore_horspool_searcher& rhs) = default;
1265 // Assign to this object the state of the specified 'rhs' object, and
1266 // return a non-'const' reference to this searcher.
1267
1268 boyer_moore_horspool_searcher& operator=(
1269 BloombergLP::bslmf::MovableRef<boyer_moore_horspool_searcher>
1270 rhs) = default;
1271 // Assign to this object the state of the specified 'rhs' object and
1272 // return a non-'const' reference to this searcher. The 'rhs' is left
1273 // in an unspecified (valid) state.
1274
1275 // ACCESSORS
1276
1277 /// Search the specified range `[first, last)` for the first sequence of
1278 /// the `value_type` values specified on construction. Return the range
1279 /// where those values are found, or the range `[last, last)` if that
1280 /// sequence is not found. The search is performed using an
1281 /// implementation of the Boyer Moore Horspool algorithm and has a
1282 /// complexity of O(N) for random text. The behavior is undefined
1283 /// unless `first` can be advanced to `last` and the iterators used to
1284 /// construct this object are still valid. Note that if the sought
1285 /// sequence is empty, the range `[first, first)` is returned. Also
1286 /// note that if the sought sequence is longer than the searched
1287 /// sequence -- thus, the sought sequence cannot be found -- the range
1288 /// `[last, last)` is returned.
1289 template <class RandomAccessIterator2>
1290 pair<RandomAccessIterator2,
1291 RandomAccessIterator2> operator()(RandomAccessIterator2 first,
1292 RandomAccessIterator2 last) const;
1293};
1294
1295} // close namespace bsl
1296#endif // BSLS_LIBRARYFEATURES_HAS_CPP17_SEARCH_FUNCTORS
1297
1298// ----------------------------------------------------------------------------
1299// INLINE DEFINITIONS
1300// ----------------------------------------------------------------------------
1301
1302
1303namespace bslstl {
1304
1305 // ----------------------------------------
1306 // class BoyerMooreHorspoolSearcher_CharImp
1307 // ----------------------------------------
1308
1309// PRIVATE MANIPULATORS
1310template <class RNDACC_ITR_NEEDLE,
1311 class HASH,
1312 class EQUAL>
1313inline
1314void
1315BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1316 HASH,
1317 EQUAL>::privateInstallNewTable(
1318 const BoyerMooreHorspoolSearcher_CharImp&
1319 object)
1320{
1321 BSLS_ASSERT(0 == d_table_p);
1322
1324 privateUseShortNeedleOptimization())) {
1325 ShortNeedleSkipArray *arrayPtr = new (*d_allocator_p)
1326 ShortNeedleSkipArray;
1327 std::memcpy(
1328 arrayPtr->data(),
1329 static_cast<ShortNeedleSkipArray *>(object.d_table_p)->data(),
1330 UCHAR_MAX + 1);
1331
1332 d_table_p = arrayPtr;
1333 } else {
1334 LongNeedleSkipArray *arrayPtr = new (*d_allocator_p)
1335 LongNeedleSkipArray;
1336
1337 std::copy(
1338 static_cast<LongNeedleSkipArray *>(object.d_table_p)->cbegin(),
1339 static_cast<LongNeedleSkipArray *>(object.d_table_p)->cend(),
1340 arrayPtr->begin());
1341
1342 d_table_p = arrayPtr;
1343 }
1344}
1345
1346template <class RNDACC_ITR_NEEDLE,
1347 class HASH,
1348 class EQUAL>
1349inline
1350void
1351BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1352 HASH,
1353 EQUAL>::privateInstallTableOverOld(
1354 const BoyerMooreHorspoolSearcher_CharImp&
1355 object)
1356{
1357 BSLS_ASSERT(d_table_p);
1358 BSLS_ASSERT(privateHasSameNeedleOptimization(object));
1359
1361 privateUseShortNeedleOptimization())) {
1362 ShortNeedleSkipArray *arrayPtr = static_cast<ShortNeedleSkipArray *>(
1363 d_table_p);
1364 std::memcpy(
1365 arrayPtr->data(),
1366 static_cast<ShortNeedleSkipArray *>(object.d_table_p)->data(),
1367 UCHAR_MAX + 1);
1368
1369 } else {
1370 LongNeedleSkipArray *arrayPtr = static_cast< LongNeedleSkipArray *>(
1371 d_table_p);
1372 std::copy(
1373 static_cast<LongNeedleSkipArray *>(object.d_table_p)->cbegin(),
1374 static_cast<LongNeedleSkipArray *>(object.d_table_p)->cend(),
1375 arrayPtr->begin());
1376 }
1377}
1378
1379template <class RNDACC_ITR_NEEDLE,
1380 class HASH,
1381 class EQUAL>
1382inline
1383void
1384BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1385 HASH,
1386 EQUAL>::privateInstallMismatchedTable(
1387 const BoyerMooreHorspoolSearcher_CharImp&
1388 object)
1389{
1391 object.privateUseShortNeedleOptimization())) {
1392 ShortNeedleSkipArray *arrayPtr = new (*d_allocator_p)
1393 ShortNeedleSkipArray;
1394 std::memcpy(
1395 arrayPtr->data(),
1396 static_cast<ShortNeedleSkipArray *>(object.d_table_p)->data(),
1397 UCHAR_MAX + 1);
1398
1399 privateDeleteTable();
1400
1401 d_table_p = arrayPtr;
1402 } else {
1403 LongNeedleSkipArray *arrayPtr = new (*d_allocator_p)
1404 LongNeedleSkipArray;
1405 std::copy(
1406 static_cast<LongNeedleSkipArray *>(object.d_table_p)->cbegin(),
1407 static_cast<LongNeedleSkipArray *>(object.d_table_p)->cend(),
1408 arrayPtr->begin());
1409 privateDeleteTable();
1410
1411 d_table_p = arrayPtr;
1412 }
1413}
1414
1415template <class RNDACC_ITR_NEEDLE,
1416 class HASH,
1417 class EQUAL>
1418inline
1419void
1420BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1421 HASH,
1422 EQUAL>::privateDeleteTable()
1423{
1425 privateUseShortNeedleOptimization())) {
1426 d_allocator_p->deleteObjectRaw(static_cast<ShortNeedleSkipArray *>(
1427 d_table_p));
1428 } else {
1429 d_allocator_p->deleteObjectRaw(static_cast< LongNeedleSkipArray *>(
1430 d_table_p));
1431 }
1432 d_table_p = 0;
1433}
1434
1435// PRIVATE ACCESSORS
1436template <class RNDACC_ITR_NEEDLE,
1437 class HASH,
1438 class EQUAL>
1439inline
1440void
1441BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1442 HASH,
1443 EQUAL>::privateSetPostMoveState(
1444 BoyerMooreHorspoolSearcher_CharImp *object)
1445 const
1446{
1447 BSLS_ASSERT(0 != object);
1448 BSLS_ASSERT(this != object);
1449
1450 object->d_needleLength = 0;
1451 object->d_table_p = 0;
1452}
1453
1454template <class RNDACC_ITR_NEEDLE,
1455 class HASH,
1456 class EQUAL>
1457inline
1458bool
1459BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1460 HASH,
1461 EQUAL>::privateUseShortNeedleOptimization()
1462 const
1463{
1464 return d_needleLength <= UCHAR_MAX;
1465}
1466
1467template <class RNDACC_ITR_NEEDLE,
1468 class HASH,
1469 class EQUAL>
1470inline
1471bool
1472BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1473 HASH,
1474 EQUAL>::privateHasSameNeedleOptimization(
1475 const BoyerMooreHorspoolSearcher_CharImp&
1476 object)
1477 const
1478{
1479 return this->privateUseShortNeedleOptimization()
1480 == object.privateUseShortNeedleOptimization();
1481}
1482
1483// CREATORS
1484template <class RNDACC_ITR_NEEDLE,
1485 class HASH,
1486 class EQUAL>
1487inline
1488BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1489 HASH,
1490 EQUAL>::
1491BoyerMooreHorspoolSearcher_CharImp(
1492 RNDACC_ITR_NEEDLE needleFirst,
1493 RNDACC_ITR_NEEDLE needleLast,
1494 HASH ,
1495 EQUAL ,
1496 BloombergLP::bslma::Allocator *basicAllocator)
1497: d_needleLength(needleLast - needleFirst)
1498, d_allocator_p(bslma::Default::allocator(basicAllocator))
1499, d_table_p(0)
1500{
1501 BSLS_ASSERT(needleFirst <= needleLast);
1502
1503 if (0 == d_needleLength) {
1504 return; // RETURN
1505 }
1506
1508 privateUseShortNeedleOptimization())) {
1509 ShortNeedleSkipArray *arrayPtr = new (*d_allocator_p)
1511 std::memset(arrayPtr->data(),
1512 static_cast<ShortNeedleSkipType>(d_needleLength),
1513 UCHAR_MAX + 1);
1514 d_table_p = arrayPtr;
1515 } else {
1516 LongNeedleSkipArray *arrayPtr = new (*d_allocator_p)
1518
1519 std::fill(arrayPtr->begin(), arrayPtr->end(), d_needleLength);
1520
1521 d_table_p = arrayPtr;
1522 }
1523
1524 for (RNDACC_ITR_NEEDLE current = needleFirst,
1525 last = needleLast - 1;
1526 last != current; ++current) {
1527
1528 const unsigned char index = static_cast<unsigned char>(*current);
1529 std::size_t skipValue = d_needleLength
1530 - 1
1531 - (current - needleFirst);
1532
1534 privateUseShortNeedleOptimization())) {
1535 BSLS_ASSERT(skipValue <= UCHAR_MAX);
1536
1537 (*static_cast<ShortNeedleSkipArray *>(d_table_p))[index]
1538 = static_cast<ShortNeedleSkipType>(skipValue);
1539 } else {
1540 (*static_cast< LongNeedleSkipArray *>(d_table_p))[index]
1541 = static_cast< LongNeedleSkipType>(skipValue);
1542 }
1543 }
1544}
1545
1546template <class RNDACC_ITR_NEEDLE,
1547 class HASH,
1548 class EQUAL>
1549inline
1550BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1551 HASH,
1552 EQUAL>::
1553BoyerMooreHorspoolSearcher_CharImp(
1554 const BoyerMooreHorspoolSearcher_CharImp& original)
1555: d_needleLength(original.d_needleLength)
1556, d_allocator_p( original.d_allocator_p)
1557, d_table_p(0)
1558{
1559 if (0 < d_needleLength) {
1560 privateInstallNewTable(original);
1561 }
1562}
1563
1564template <class RNDACC_ITR_NEEDLE,
1565 class HASH,
1566 class EQUAL>
1567inline
1568BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1569 HASH,
1570 EQUAL>::
1571BoyerMooreHorspoolSearcher_CharImp(
1572 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher_CharImp>
1573 original)
1575: d_needleLength(MoveUtil::access(original).d_needleLength)
1576, d_allocator_p( MoveUtil::access(original).d_allocator_p)
1577, d_table_p( MoveUtil::access(original).d_table_p)
1578{
1579 privateSetPostMoveState(&MoveUtil::access(original));
1580}
1581
1582template <class RNDACC_ITR_NEEDLE,
1583 class HASH,
1584 class EQUAL>
1585inline
1586BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1587 HASH,
1588 EQUAL>::
1589BoyerMooreHorspoolSearcher_CharImp(
1590 const BoyerMooreHorspoolSearcher_CharImp& original,
1591 BloombergLP::bslma::Allocator *basicAllocator)
1592: d_needleLength(original.d_needleLength)
1593, d_allocator_p(bslma::Default::allocator(basicAllocator))
1594, d_table_p(0)
1595{
1596 if (0 < d_needleLength) {
1597 privateInstallNewTable(original);
1598 }
1599}
1600
1601template <class RNDACC_ITR_NEEDLE,
1602 class HASH,
1603 class EQUAL>
1604inline
1605BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1606 HASH,
1607 EQUAL>::
1608BoyerMooreHorspoolSearcher_CharImp(
1609 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher_CharImp>
1610 original,
1611 BloombergLP::bslma::Allocator *basicAllocator)
1612: d_needleLength(MoveUtil::access(original).d_needleLength)
1613, d_allocator_p( bslma::Default::allocator(basicAllocator))
1614, d_table_p(0)
1615{
1616 if (d_allocator_p == MoveUtil::access(original).d_allocator_p) {
1617
1618 d_table_p = MoveUtil::access(original).d_table_p;
1619
1620 privateSetPostMoveState(&MoveUtil::access(original));
1621 } else {
1622 if (0 < d_needleLength) {
1623 privateInstallNewTable(MoveUtil::access(original));
1624 }
1625 }
1626}
1627
1628template <class RNDACC_ITR_NEEDLE,
1629 class HASH,
1630 class EQUAL>
1631inline
1632BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1633 HASH,
1634 EQUAL>::
1635~BoyerMooreHorspoolSearcher_CharImp()
1636{
1637 privateDeleteTable();
1638}
1639
1640// MANIPULATORS
1641template <class RNDACC_ITR_NEEDLE,
1642 class HASH,
1643 class EQUAL>
1644inline
1645BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1646 HASH,
1647 EQUAL>&
1648BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1649 HASH,
1650 EQUAL>::operator=(
1652 rhs)
1653{
1654 if (0 < rhs.d_needleLength) {
1655 if (d_table_p && privateHasSameNeedleOptimization(rhs)) {
1656 privateInstallTableOverOld(rhs);
1657 } else {
1658 privateInstallMismatchedTable(rhs);
1659 }
1660 } else {
1661 privateDeleteTable();
1662 }
1663
1664 d_needleLength = rhs.d_needleLength;
1665
1666 return *this;
1667}
1668
1669template <class RNDACC_ITR_NEEDLE,
1670 class HASH,
1671 class EQUAL>
1672inline
1673BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1674 HASH,
1675 EQUAL>&
1676BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1677 HASH,
1678 EQUAL>::operator=(
1679 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher_CharImp>
1680 rhs)
1681{
1682 if (d_allocator_p == MoveUtil::access(rhs).d_allocator_p) {
1683 d_allocator_p->deallocate(d_table_p);
1684 d_table_p = MoveUtil::access(rhs).d_table_p;
1685 MoveUtil::access(rhs).d_table_p = 0;
1686 } else {
1687 if (0 < MoveUtil::access(rhs).d_needleLength) {
1688 if (d_table_p && privateHasSameNeedleOptimization(
1689 MoveUtil::access(rhs))) {
1690 privateInstallTableOverOld(rhs);
1691 } else {
1692 privateInstallMismatchedTable(MoveUtil::access(rhs));
1693 }
1694 } else {
1695 privateDeleteTable();
1696 }
1697 }
1698
1699 d_needleLength = MoveUtil::access(rhs).d_needleLength;
1700
1701 return *this;
1702}
1703
1704// ACCESSORS
1705template <class RNDACC_ITR_NEEDLE,
1706 class HASH,
1707 class EQUAL>
1708inline
1709typename
1710BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1711 HASH,
1712 EQUAL>::difference_type
1713BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1714 HASH,
1715 EQUAL>::badCharacterSkip(
1716 const value_type& value)
1717 const
1718{
1719 unsigned char index = static_cast<unsigned char>(value);
1720
1722 privateUseShortNeedleOptimization())) {
1723 return (*static_cast<ShortNeedleSkipArray *>(d_table_p))[index];
1724 // RETURN
1725 } else {
1726 return (*static_cast< LongNeedleSkipArray *>(d_table_p))[index];
1727 // RETURN
1728 }
1729}
1730
1731template <class RNDACC_ITR_NEEDLE,
1732 class HASH,
1733 class EQUAL>
1734inline
1735HASH BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1736 HASH,
1737 EQUAL>::hash() const
1738{
1739 return HASH();
1740}
1741
1742template <class RNDACC_ITR_NEEDLE,
1743 class HASH,
1744 class EQUAL>
1745inline
1746EQUAL BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
1747 HASH,
1748 EQUAL>::equal() const
1749{
1750 return EQUAL();
1751}
1752
1753template <class RNDACC_ITR_NEEDLE,
1754 class HASH,
1755 class EQUAL>
1756inline
1757BloombergLP::bslma::Allocator *BoyerMooreHorspoolSearcher_CharImp<
1758 RNDACC_ITR_NEEDLE,
1759 HASH,
1760 EQUAL>::allocator() const
1761{
1762 return d_allocator_p;
1763}
1764
1765 // -------------------------------------------
1766 // class BoyerMooreHorspoolSearcher_GeneralImp
1767 // -------------------------------------------
1768
1769// CREATORS
1770template <class RNDACC_ITR_NEEDLE,
1771 class HASH,
1772 class EQUAL>
1773inline
1775 HASH,
1776 EQUAL>::
1777BoyerMooreHorspoolSearcher_GeneralImp(
1778 RNDACC_ITR_NEEDLE needleFirst,
1779 RNDACC_ITR_NEEDLE needleLast,
1780 HASH hash,
1781 EQUAL equal,
1782 BloombergLP::bslma::Allocator *basicAllocator)
1783: d_needleLength(needleLast - needleFirst)
1784, d_map(0, hash, equal, basicAllocator)
1785{
1786 BSLS_ASSERT(needleFirst <= needleLast);
1787
1788 if (0 < d_needleLength) {
1789 for (RNDACC_ITR_NEEDLE current = needleFirst,
1790 last = needleLast - 1;
1791 last != current; ++current) {
1792 d_map.insert(std::make_pair(*current,
1793 d_needleLength
1794 - 1
1795 - (current - needleFirst)));
1796 }
1797 }
1798}
1799
1800template <class RNDACC_ITR_NEEDLE,
1801 class HASH,
1802 class EQUAL>
1803inline
1805 HASH,
1806 EQUAL>::
1807BoyerMooreHorspoolSearcher_GeneralImp(
1809: d_needleLength(original.d_needleLength)
1810, d_map(original, original.allocator())
1811{
1812}
1813
1814template <class RNDACC_ITR_NEEDLE,
1815 class HASH,
1816 class EQUAL>
1817inline
1819 HASH,
1820 EQUAL>::
1821BoyerMooreHorspoolSearcher_GeneralImp(
1822 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher_GeneralImp>
1823 original)
1825: d_needleLength(MoveUtil::move(MoveUtil::access(original).d_needleLength))
1826, d_map( MoveUtil::move(MoveUtil::access(original).d_map))
1827{
1828}
1829
1830template <class RNDACC_ITR_NEEDLE,
1831 class HASH,
1832 class EQUAL>
1833inline
1835 HASH,
1836 EQUAL>::
1837BoyerMooreHorspoolSearcher_GeneralImp(
1839 BloombergLP::bslma::Allocator *basicAllocator)
1840: d_needleLength(original.d_needleLength)
1841, d_map(original.d_map, basicAllocator)
1842{
1843}
1844
1845template <class RNDACC_ITR_NEEDLE,
1846 class HASH,
1847 class EQUAL>
1848inline
1850 HASH,
1851 EQUAL>::
1852BoyerMooreHorspoolSearcher_GeneralImp(
1853 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher_GeneralImp>
1854 original,
1855 BloombergLP::bslma::Allocator *basicAllocator)
1856: d_needleLength(MoveUtil::move(MoveUtil::access(original).d_needleLength))
1857, d_map( MoveUtil::move(MoveUtil::access(original).d_map),
1858 basicAllocator)
1859{
1860}
1861
1862// MANIPULATORS
1863template <class RNDACC_ITR_NEEDLE,
1864 class HASH,
1865 class EQUAL>
1866inline
1868 HASH,
1869 EQUAL>&
1871 HASH,
1872 EQUAL>::operator=(
1874{
1875 d_needleLength = rhs.d_needleLength;
1876 d_map = rhs.d_map;
1877
1878 return *this;
1879}
1880
1881template <class RNDACC_ITR_NEEDLE,
1882 class HASH,
1883 class EQUAL>
1884inline
1886 HASH,
1887 EQUAL>&
1889 HASH,
1890 EQUAL>::operator=(
1891 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher_GeneralImp>
1892 rhs)
1893{
1894 d_needleLength = MoveUtil::move(MoveUtil::access(rhs).d_needleLength);
1895 d_map = MoveUtil::move(MoveUtil::access(rhs).d_map);
1896
1897 return *this;
1898}
1899
1900// ACCESSORS
1901template <class RNDACC_ITR_NEEDLE,
1902 class HASH,
1903 class EQUAL>
1904inline
1905typename
1907 HASH,
1908 EQUAL>::difference_type
1910 HASH,
1911 EQUAL>::badCharacterSkip(
1912 const value_type& value) const
1913{
1914 typename Map::const_iterator result = d_map.find(value);
1915
1916 return d_map.cend() == result ? d_needleLength : result->second;
1917}
1918
1919template <class RNDACC_ITR_NEEDLE,
1920 class HASH,
1921 class EQUAL>
1922inline
1923HASH BoyerMooreHorspoolSearcher_GeneralImp<RNDACC_ITR_NEEDLE,
1924 HASH,
1925 EQUAL>::hash() const
1926{
1927 return d_map.hash_function();
1928}
1929
1930template <class RNDACC_ITR_NEEDLE,
1931 class HASH,
1932 class EQUAL>
1933inline
1934EQUAL BoyerMooreHorspoolSearcher_GeneralImp<RNDACC_ITR_NEEDLE,
1935 HASH,
1936 EQUAL>::equal() const
1937{
1938 return d_map.key_eq();
1939}
1940
1941template <class RNDACC_ITR_NEEDLE,
1942 class HASH,
1943 class EQUAL>
1944inline
1945BloombergLP::bslma::Allocator *BoyerMooreHorspoolSearcher_GeneralImp<
1946 RNDACC_ITR_NEEDLE,
1947 HASH,
1948 EQUAL>::allocator() const
1949{
1950 return d_map.get_allocator().mechanism();
1951}
1952
1953 // --------------------------------
1954 // class BoyerMooreHorspoolSearcher
1955 // --------------------------------
1956
1957// PRIVATE ACCESSORS
1958template <class RNDACC_ITR_NEEDLE,
1959 class HASH,
1960 class EQUAL>
1961inline
1962void
1963BoyerMooreHorspoolSearcher<RNDACC_ITR_NEEDLE,
1964 HASH,
1965 EQUAL>::privateSetPostMoveState(
1966 BoyerMooreHorspoolSearcher *object) const
1967{
1968 BSLS_ASSERT(0 != object);
1969 BSLS_ASSERT(this != object);
1970
1971 object->d_needleFirst = d_needleFirst;
1972 object->d_needleLast = d_needleFirst;
1973 object->d_needleLength = 0;
1974}
1975
1976// CREATORS
1977template <class RNDACC_ITR_NEEDLE,
1978 class HASH,
1979 class EQUAL>
1980BoyerMooreHorspoolSearcher<RNDACC_ITR_NEEDLE,
1981 HASH,
1982 EQUAL>::
1983BoyerMooreHorspoolSearcher(RNDACC_ITR_NEEDLE needleFirst,
1984 RNDACC_ITR_NEEDLE needleLast,
1985 HASH hash,
1986 EQUAL equal,
1987 BloombergLP::bslma::Allocator *basicAllocator)
1988: d_needleFirst( needleFirst)
1989, d_needleLast( needleLast)
1990, d_needleLength(bsl::distance(needleFirst, needleLast))
1991, d_imp(needleFirst, needleLast, hash, equal, basicAllocator)
1992{
1994}
1995
1996template <class RNDACC_ITR_NEEDLE,
1997 class HASH,
1998 class EQUAL>
1999BoyerMooreHorspoolSearcher<RNDACC_ITR_NEEDLE,
2000 HASH,
2001 EQUAL>::
2002BoyerMooreHorspoolSearcher(const BoyerMooreHorspoolSearcher& original)
2003: d_needleFirst( original.d_needleFirst)
2004, d_needleLast( original.d_needleLast)
2005, d_needleLength(original.d_needleLength)
2006, d_imp( original.d_imp,
2007 BloombergLP::bslma::Default::defaultAllocator())
2008{
2009}
2010
2011template <class RNDACC_ITR_NEEDLE,
2012 class HASH,
2013 class EQUAL>
2014BoyerMooreHorspoolSearcher<RNDACC_ITR_NEEDLE,
2015 HASH,
2016 EQUAL>::
2017BoyerMooreHorspoolSearcher(
2018 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher> original)
2020: d_needleFirst( MoveUtil::move(MoveUtil::access(original).d_needleFirst))
2021, d_needleLast( MoveUtil::move(MoveUtil::access(original).d_needleLast))
2022, d_needleLength(MoveUtil::move(MoveUtil::access(original).d_needleLength))
2023, d_imp( MoveUtil::move(MoveUtil::access(original).d_imp))
2024{
2025 privateSetPostMoveState(&MoveUtil::access(original));
2026}
2027
2028template <class RNDACC_ITR_NEEDLE,
2029 class HASH,
2030 class EQUAL>
2031BoyerMooreHorspoolSearcher<RNDACC_ITR_NEEDLE,
2032 HASH,
2033 EQUAL>::
2034BoyerMooreHorspoolSearcher(const BoyerMooreHorspoolSearcher& original,
2035 BloombergLP::bslma::Allocator *basicAllocator)
2036: d_needleFirst( original.d_needleFirst)
2037, d_needleLast( original.d_needleLast)
2038, d_needleLength(original.d_needleLength)
2039, d_imp( original.d_imp, basicAllocator)
2040{
2041}
2042
2043template <class RNDACC_ITR_NEEDLE,
2044 class HASH,
2045 class EQUAL>
2046BoyerMooreHorspoolSearcher<RNDACC_ITR_NEEDLE,
2047 HASH,
2048 EQUAL>::
2049BoyerMooreHorspoolSearcher(
2050 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher> original,
2051 BloombergLP::bslma::Allocator *basicAllocator)
2052: d_needleFirst( MoveUtil::move(MoveUtil::access(original).d_needleFirst))
2053, d_needleLast( MoveUtil::move(MoveUtil::access(original).d_needleLast))
2054, d_needleLength(MoveUtil::move(MoveUtil::access(original).d_needleLength))
2055, d_imp( MoveUtil::move(MoveUtil::access(original).d_imp),
2056 basicAllocator)
2057{
2058 privateSetPostMoveState(&MoveUtil::access(original));
2059}
2060
2061// MANIPULATORS
2062template <class RNDACC_ITR_NEEDLE,
2063 class HASH,
2064 class EQUAL>
2065inline
2066BoyerMooreHorspoolSearcher<RNDACC_ITR_NEEDLE,
2067 HASH,
2068 EQUAL>&
2069BoyerMooreHorspoolSearcher<RNDACC_ITR_NEEDLE,
2070 HASH,
2071 EQUAL>::operator=(
2072 const BoyerMooreHorspoolSearcher& rhs)
2073{
2074 d_needleFirst = rhs.d_needleFirst;
2075 d_needleLast = rhs.d_needleLast;
2076 d_needleLength = rhs.d_needleLength;
2077 d_imp = rhs.d_imp;
2078
2079 return *this;
2080}
2081
2082template <class RNDACC_ITR_NEEDLE,
2083 class HASH,
2084 class EQUAL>
2085inline
2086BoyerMooreHorspoolSearcher<RNDACC_ITR_NEEDLE,
2087 HASH,
2088 EQUAL>&
2089BoyerMooreHorspoolSearcher<RNDACC_ITR_NEEDLE,
2090 HASH,
2091 EQUAL>::operator=(
2092 BloombergLP::bslmf::MovableRef<BoyerMooreHorspoolSearcher> rhs)
2093{
2094 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(this != &MoveUtil::access(rhs))) {
2095
2096 d_needleFirst = MoveUtil::move(MoveUtil::access(rhs).d_needleFirst);
2097 d_needleLast = MoveUtil::move(MoveUtil::access(rhs).d_needleLast);
2098 d_needleLength = MoveUtil::move(MoveUtil::access(rhs).d_needleLength);
2099 d_imp = MoveUtil::move(MoveUtil::access(rhs).d_imp);
2100
2101 privateSetPostMoveState(&MoveUtil::access(rhs));
2102 }
2103
2104 return *this;
2105}
2106
2107// ACCESSORS
2108template <class RNDACC_ITR_NEEDLE,
2109 class HASH,
2110 class EQUAL>
2111template <class RNDACC_ITR_HAYSTACK>
2113BoyerMooreHorspoolSearcher<RNDACC_ITR_NEEDLE,
2114 HASH,
2115 EQUAL>::operator()(
2116 RNDACC_ITR_HAYSTACK haystackFirst,
2117 RNDACC_ITR_HAYSTACK haystackLast) const
2118{
2119 BSLS_ASSERT(0 <= haystackLast - haystackFirst);
2120
2121 if (0 == d_needleLength) {
2122 return std::make_pair(haystackFirst, haystackFirst); // RETURN
2123 }
2124
2125 std::size_t haystackLength = haystackLast - haystackFirst;
2126
2127 for (std::size_t possibleMatch = 0;
2128 d_needleLength + possibleMatch <= haystackLength;
2129 possibleMatch += d_imp.badCharacterSkip(haystackFirst[possibleMatch
2130 + d_needleLength
2131 - 1])) {
2132
2133 // Check in reverse order for match.
2134
2135 const EQUAL comparator(equal());
2136
2137 for (std::size_t idx = d_needleLength - 1;
2138 comparator(haystackFirst[possibleMatch + idx],
2139 d_needleFirst[idx]);
2140 --idx) {
2141
2142 if (0 == idx) { // No difference found
2143 return std::make_pair(haystackFirst + possibleMatch,
2144 haystackFirst + possibleMatch
2145 + d_needleLength);
2146 // RETURN
2147 }
2148 }
2149 }
2150
2151 return std::make_pair(haystackLast, haystackLast);
2152}
2153
2154template <class RNDACC_ITR_NEEDLE,
2155 class HASH,
2156 class EQUAL>
2157inline
2158RNDACC_ITR_NEEDLE BoyerMooreHorspoolSearcher<RNDACC_ITR_NEEDLE,
2159 HASH,
2160 EQUAL>::needleFirst() const
2161{
2162 return d_needleFirst;
2163}
2164
2165template <class RNDACC_ITR_NEEDLE,
2166 class HASH,
2167 class EQUAL>
2168inline
2169RNDACC_ITR_NEEDLE BoyerMooreHorspoolSearcher<RNDACC_ITR_NEEDLE,
2170 HASH,
2171 EQUAL>::needleLast() const
2172{
2173 return d_needleLast;
2174}
2175
2176template <class RNDACC_ITR_NEEDLE,
2177 class HASH,
2178 class EQUAL>
2179inline
2180HASH BoyerMooreHorspoolSearcher<RNDACC_ITR_NEEDLE,
2181 HASH,
2182 EQUAL>::hash() const
2183{
2184 return d_imp.hash();
2185}
2186
2187template <class RNDACC_ITR_NEEDLE,
2188 class HASH,
2189 class EQUAL>
2190inline
2191EQUAL BoyerMooreHorspoolSearcher<RNDACC_ITR_NEEDLE,
2192 HASH,
2193 EQUAL>::equal() const
2194{
2195 return d_imp.equal();
2196}
2197
2198template <class RNDACC_ITR_NEEDLE,
2199 class HASH,
2200 class EQUAL>
2201inline
2202BloombergLP::bslma::Allocator *BoyerMooreHorspoolSearcher<
2203 RNDACC_ITR_NEEDLE,
2204 HASH,
2205 EQUAL>::allocator() const
2206{
2207 return d_imp.allocator();
2208}
2209
2210} // close package namespace
2211
2212
2213#ifndef BSLS_LIBRARYFEATURES_HAS_CPP17_SEARCH_FUNCTORS
2214namespace bsl {
2215
2216 // -----------------------------------
2217 // class boyer_moore_horspool_searcher
2218 // -----------------------------------
2219
2220// CREATORS
2221template <class RandomAccessIterator1,
2222 class Hash,
2223 class BinaryPredicate>
2224inline
2225boyer_moore_horspool_searcher<RandomAccessIterator1,
2226 Hash,
2227 BinaryPredicate>::boyer_moore_horspool_searcher(
2228 RandomAccessIterator1 pat_first,
2229 RandomAccessIterator1 pat_last,
2230 Hash hf,
2231 BinaryPredicate pred)
2232: d_imp(pat_first, pat_last, hf, pred)
2233{
2234 BSLS_ASSERT(pat_first <= pat_last);
2235}
2236
2237// ACCESSORS
2238template <class RandomAccessIterator1,
2239 class Hash,
2240 class BinaryPredicate>
2241template <class RandomAccessIterator2>
2242inline
2243pair<RandomAccessIterator2,
2244 RandomAccessIterator2> boyer_moore_horspool_searcher<
2245 RandomAccessIterator1,
2246 Hash,
2247 BinaryPredicate>::operator()(
2248 RandomAccessIterator2 first,
2249 RandomAccessIterator2 last)
2250 const
2251{
2252 BSLS_ASSERT(first <= last);
2253
2254 return d_imp(first, last);
2255}
2256
2257} // close namespace bsl
2258#endif // BSLS_LIBRARYFEATURES_HAS_CPP17_SEARCH_FUNCTORS
2259
2260// ============================================================================
2261// TYPE TRAITS
2262// ============================================================================
2263
2264
2265namespace bslma {
2266
2267template <class RNDACC_ITR_NEEDLE,
2268 class HASH,
2269 class EQUAL>
2271 BloombergLP::bslstl::BoyerMooreHorspoolSearcher<RNDACC_ITR_NEEDLE,
2272 HASH,
2273 EQUAL>
2274 > : bsl::true_type
2275{};
2276
2277template <class RNDACC_ITR_NEEDLE,
2278 class HASH,
2279 class EQUAL>
2282 RNDACC_ITR_NEEDLE,
2283 HASH,
2284 EQUAL>
2285 > : bsl::true_type
2286{};
2287
2288template <class RNDACC_ITR_NEEDLE,
2289 class HASH,
2290 class EQUAL>
2292 BloombergLP::bslstl::BoyerMooreHorspoolSearcher_CharImp<RNDACC_ITR_NEEDLE,
2293 HASH,
2294 EQUAL>
2295 > : bsl::true_type
2296{};
2297
2298} // close namespace bslma
2299
2300
2301#endif
2302
2303// ----------------------------------------------------------------------------
2304// Copyright 2019 Bloomberg Finance L.P.
2305//
2306// Licensed under the Apache License, Version 2.0 (the "License");
2307// you may not use this file except in compliance with the License.
2308// You may obtain a copy of the License at
2309//
2310// http://www.apache.org/licenses/LICENSE-2.0
2311//
2312// Unless required by applicable law or agreed to in writing, software
2313// distributed under the License is distributed on an "AS IS" BASIS,
2314// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2315// See the License for the specific language governing permissions and
2316// limitations under the License.
2317// ----------------------------- END-OF-FILE ----------------------------------
2318
2319/** @} */
2320/** @} */
2321/** @} */
Definition bslstl_pair.h:1210
Definition bslstl_unorderedmap.h:1089
pair< iterator, bool > insert(const value_type &value)
Definition bslstl_unorderedmap.h:3051
BloombergLP::bslstl::HashTableIterator< const value_type, difference_type > const_iterator
Definition bslstl_unorderedmap.h:1160
Definition bslstl_boyermoorehorspoolsearcher.h:697
EQUAL equal() const
Return the equality comparison functor supplied on construction.
Definition bslstl_boyermoorehorspoolsearcher.h:1748
~BoyerMooreHorspoolSearcher_CharImp()
Destroy this object;.
Definition bslstl_boyermoorehorspoolsearcher.h:1635
BloombergLP::bslma::Allocator * allocator() const
Return the allocator supplied on construction.
Definition bslstl_boyermoorehorspoolsearcher.h:1760
difference_type badCharacterSkip(const value_type &value) const
Definition bslstl_boyermoorehorspoolsearcher.h:1715
BoyerMooreHorspoolSearcher_CharImp & operator=(const BoyerMooreHorspoolSearcher_CharImp &rhs)
Definition bslstl_boyermoorehorspoolsearcher.h:1650
bsl::iterator_traits< RNDACC_ITR_NEEDLE >::difference_type difference_type
Definition bslstl_boyermoorehorspoolsearcher.h:710
bsl::iterator_traits< RNDACC_ITR_NEEDLE >::value_type value_type
Definition bslstl_boyermoorehorspoolsearcher.h:705
HASH hash() const
Return the hashing functor supplied on construction.
Definition bslstl_boyermoorehorspoolsearcher.h:1737
Definition bslstl_boyermoorehorspoolsearcher.h:882
difference_type badCharacterSkip(const value_type &value) const
Definition bslstl_boyermoorehorspoolsearcher.h:1911
EQUAL equal() const
Return the equality comparison functor supplied on construction.
Definition bslstl_boyermoorehorspoolsearcher.h:1936
bsl::iterator_traits< RNDACC_ITR_NEEDLE >::value_type value_type
Definition bslstl_boyermoorehorspoolsearcher.h:887
BoyerMooreHorspoolSearcher_GeneralImp & operator=(const BoyerMooreHorspoolSearcher_GeneralImp &rhs)
Definition bslstl_boyermoorehorspoolsearcher.h:1872
bsl::iterator_traits< RNDACC_ITR_NEEDLE >::difference_type difference_type
Definition bslstl_boyermoorehorspoolsearcher.h:890
BloombergLP::bslma::Allocator * allocator() const
Return the allocator used by this object to supply memory.
Definition bslstl_boyermoorehorspoolsearcher.h:1948
HASH hash() const
Return the hashing functor supplied on construction.
Definition bslstl_boyermoorehorspoolsearcher.h:1925
Definition bslstl_boyermoorehorspoolsearcher.h:1007
bsl::pair< RNDACC_ITR_HAYSTACK, RNDACC_ITR_HAYSTACK > operator()(RNDACC_ITR_HAYSTACK haystackFirst, RNDACC_ITR_HAYSTACK haystackLast) const
Definition bslstl_boyermoorehorspoolsearcher.h:2115
BloombergLP::bslma::Allocator * allocator() const
Return the allocator used by this object to supply memory.
Definition bslstl_boyermoorehorspoolsearcher.h:2205
EQUAL equal() const
Return the equality comparison functor supplied on construction.
Definition bslstl_boyermoorehorspoolsearcher.h:2193
bsl::iterator_traits< RNDACC_ITR_NEEDLE >::value_type value_type
Definition bslstl_boyermoorehorspoolsearcher.h:1015
BoyerMooreHorspoolSearcher & operator=(const BoyerMooreHorspoolSearcher &rhs)
Definition bslstl_boyermoorehorspoolsearcher.h:2071
HASH hash() const
Return the hashing functor supplied on construction.
Definition bslstl_boyermoorehorspoolsearcher.h:2182
bsl::equal_to< typename bsl::iterator_traits< RNDACC_ITR_NEEDLE >::value_type > DefaultEqual
the default type for the EQUAL optional template parameter
Definition bslstl_boyermoorehorspoolsearcher.h:1025
RNDACC_ITR_NEEDLE needleLast() const
Definition bslstl_boyermoorehorspoolsearcher.h:2171
bsl::hash< typename bsl::iterator_traits< RNDACC_ITR_NEEDLE >::value_type > DefaultHash
the default type for the HASH optional template parameter
Definition bslstl_boyermoorehorspoolsearcher.h:1020
RNDACC_ITR_NEEDLE needleFirst() const
Definition bslstl_boyermoorehorspoolsearcher.h:2160
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:632
#define BSLS_PERFORMANCEHINT_PREDICT_LIKELY(expr)
Definition bsls_performancehint.h:451
Definition bdlb_printmethods.h:283
T::const_iterator cend(const T &container)
Definition bslstl_iterator.h:1611
T::const_iterator cbegin(const T &container)
Definition bslstl_iterator.h:1553
Definition balxml_encoderoptions.h:68
Definition bslstl_algorithm.h:82
Definition bslstl_array.h:290
BSLS_KEYWORD_CONSTEXPR_CPP14 pointer data() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_array.h:928
BSLS_KEYWORD_CONSTEXPR_CPP14 iterator end() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_array.h:740
void swap(array &rhs) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(bsl BSLS_KEYWORD_CONSTEXPR_CPP14 iterator begin() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_array.h:354
Definition bslmf_conditional.h:120
Definition bslstl_equalto.h:311
Definition bslstl_hash.h:498
Definition bslmf_issame.h:146
Definition bslma_usesbslmaallocator.h:343
Definition bslmf_isbitwisecopyable.h:298
Definition bslmf_isbitwiseequalitycomparable.h:499