BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslh.h
Go to the documentation of this file.
1/// @file bslh.h
2///
3///
4/// @defgroup bslh Package bslh
5/// @brief Basic Standard Library Hashing (bslh)
6/// @addtogroup bsl
7/// @{
8/// @addtogroup bslh
9/// @{
10/// * <a href="#bslh-purpose"> Purpose</a>
11/// * <a href="#bslh-mnemonic"> Mnemonic </a>
12/// * <a href="#bslh-description"> Description </a>
13/// * <a href="#bslh-table-of-contents"> Table of Contents </a>
14/// * <a href="#bslh-terminology"> Terminology </a>
15/// * <a href="#bslh-avalanche"> Avalanche </a>
16/// * <a href="#bslh-denial-of-service"> Denial of Service (DoS) </a>
17/// * <a href="#bslh-funneling"> Funneling </a>
18/// * <a href="#bslh-salient-to-hashing"> Salient to Hashing </a>
19/// * <a href="#bslh-why-use-this-system"> Why Use This System </a>
20/// * <a href="#bslh-better-and-more-predictable-performance"> Better and More Predictable Performance </a>
21/// * <a href="#bslh-less-code-duplication"> Less Code Duplication </a>
22/// * <a href="#bslh-easier-to-make-types-hashable"> Easier to Make Types Hashable </a>
23/// * <a href="#bslh-hash-combining"> Hash Combining </a>
24/// * <a href="#bslh-swappable-algorithms"> Swappable Algorithms </a>
25/// * <a href="#bslh-type-implementers"> Type Implementers </a>
26/// * <a href="#bslh-hashappend"> hashAppend </a>
27/// * <a href="#bslh-determining-what-to-hash"> Determining what to Hash </a>
28/// * <a href="#bslh-hashing-other-user-defined-types"> Hashing Other User Defined Types </a>
29/// * <a href="#bslh-hashing-pointers"> Hashing Pointers (especially const char ) </a>
30/// * <a href="#bslh-converting-existing-types"> Converting Existing Types </a>
31/// * <a href="#bslh-type-users"> Type Users </a>
32/// * <a href="#bslh-bsl-hash"> bsl::hash </a>
33/// * <a href="#bslh-bslh-hash"> bslh::Hash </a>
34/// * <a href="#bslh-bslh-seededhash-bslh-seedgenerator-and-secure-hashing"> bslh::SeededHash, bslh::SeedGenerator, and Secure Hashing </a>
35/// * <a href="#bslh-seeded-algorithms"> Seeded Algorithms </a>
36/// * <a href="#bslh-bslh-seedgenerator"> bslh::SeedGenerator </a>
37/// * <a href="#bslh-bslh-seededhash"> bslh::SeededHash </a>
38/// * <a href="#bslh-hashing-performance-and-fundamental-integer-types"> Hashing Performance and Fundamental Integer Types </a>
39/// * <a href="#bslh-choosing-a-hashing-algorithm"> Choosing a Hashing Algorithm </a>
40/// * <a href="#bslh-extending-the-system"> Extending the System </a>
41/// * <a href="#bslh-hashing-algorithm-functors"> Hashing Algorithm Functors </a>
42/// * <a href="#bslh-hashing-algorithm-wrappers"> Hashing Algorithm Wrappers (bslh::Hash) </a>
43/// * <a href="#bslh-seed-generator"> Seed Generator </a>
44/// * <a href="#bslh-hierarchical-synopsis"> Hierarchical Synopsis </a>
45/// * <a href="#bslh-component-synopsis"> Component Synopsis </a>
46/// * <a href="#bslh-component-overview"> Component Overview </a>
47/// * <a href="#bslh-bslh_defaulthashalgorithm"> bslh_defaulthashalgorithm </a>
48/// * <a href="#bslh-bslh_defaultseededhashalgorithm"> bslh_defaultseededhashalgorithm </a>
49/// * <a href="#bslh-bslh_hash"> bslh_hash </a>
50/// * <a href="#bslh-bslh_seededhash"> bslh_seededhash </a>
51/// * <a href="#bslh-bslh_seedgenerator"> bslh_seedgenerator </a>
52/// * <a href="#bslh-bslh_siphashalgorithm"> bslh_siphashalgorithm </a>
53/// * <a href="#bslh-bslh_spookyhashalgorithm"> bslh_spookyhashalgorithm </a>
54/// * <a href="#bslh-bslh_spookyhashalgorithmimp"> bslh_spookyhashalgorithmimp </a>
55/// * <a href="#bslh-bslh_wyhashincrementalalgorithm"> bslh_wyhashincrementalalgorithm </a>
56///
57/// # Purpose {#bslh-purpose}
58/// Provide a framework for hashing types using swappable algorithms.
59///
60/// # Mnemonic {#bslh-mnemonic}
61/// Basic Standard Library Hashing (bslh)
62///
63/// # Description {#bslh-description}
64/// The 'bslh' package provides components for a more modular hashing
65/// implementation than is found in the standard. This implementation is based on
66/// ISO C++ Proposal N3980. An internal proposal for this is available at {TEAM
67/// BDE:MODULAR HASHING<GO>}. This package provides hashing algorithms as well as
68/// 'Hash' and 'SeededHash' structs which allow different algorithms to be applied
69/// to any type that has a 'hashAppend' function. This document will explain the
70/// overall benefits of the system, what type implementers need to do to make
71/// their types hashable in this system, what type users need to do to hash
72/// different types, how to extend different pieces of this system, and will
73/// provide a summary of all the components in this package. All sections are
74/// independent and can be read and used without having read the other sections.
75///
76/// ## Table of Contents {#bslh-table-of-contents}
77///
78/// * Terminology
79/// * Avalanche
80/// * Denial of Service (DoS)
81/// * Funneling
82/// * Salient to Hashing
83///
84/// * Why Use This System?
85/// * Better and More Predictable Performance
86/// * Less Code Duplication
87/// * Easier to Make Types Hashable
88/// * Hash Combining
89/// * Swappable Algorithms
90///
91/// * Type Implementers
92/// * 'hashAppend'
93/// * Determining what to Hash
94/// * Hashing Other User Defined Types
95/// * Hashing Pointers (especially 'const char *')
96/// * Converting Existing Types
97///
98/// * Type Users
99/// * bsl::hash
100/// * bslh::Hash
101/// * bslh::SeededHash, bslh::SeedGenerator, and Secure Hashing
102/// * Seeded Algorithms
103/// * bslh::SeedGenerator
104/// * bslh::SeededHash
105/// * Hashing Performance and Fundamental Integer Types
106/// * Choosing a Hashing Algorithm
107///
108/// * Extending the System
109/// * Hashing Algorithm Functors
110/// * Hashing Algorithm Wrappers (bslh::Hash)
111/// * Seed Generator
112///
113/// * Hierarchical Synopsis
114///
115/// * Component Synopsis
116///
117/// * Component Overview
118/// * @ref bslh_defaulthashalgorithm
119/// * @ref bslh_defaultseededhashalgorithm
120/// * @ref bslh_hash
121/// * @ref bslh_seededhash
122/// * @ref bslh_seedgenerator
123/// * @ref bslh_siphashalgorithm
124/// * @ref bslh_spookyhashalgorithm
125/// * @ref bslh_spookyhashalgorithmimp
126/// * @ref bslh_wyhashincrementalalgorithm
127///
128/// ## Terminology {#bslh-terminology}
129///
130///
131/// ### Avalanche {#bslh-avalanche}
132///
133/// Changing one bit in the input to the hashing algorithm results in an
134/// "avalanche", which causes each output bit to have a 50% probability of
135/// changing. The avalanche property means that two very similar values will
136/// produce completely dissimilar hashes.
137///
138/// ### Denial of Service (DoS) {#bslh-denial-of-service}
139///
140/// Within the context of hash tables, Denial of Service (DoS) attacks refer to an
141/// attacker causing many hash table keys to collide to the same bucket. These
142/// collisions cause look-ups in the hash table to become very time consuming
143/// linear searches.
144///
145/// ### Funneling {#bslh-funneling}
146///
147/// An undesirable property of hashing algorithms that results in a large number
148/// of collisions when the inputs differ by only a few bits. Funneling is related
149/// to the avalanche property of a hashing algorithm and is essentially the
150/// opposite of avalanche. More information can be found at
151/// 'http://burtleburtle.net/bob/hash/evahash.html'.
152///
153/// ### Salient to Hashing {#bslh-salient-to-hashing}
154///
155/// A property of attributes (or fields) of a type. An attribute is considered
156/// salient to hashing if it should be incorporated into the bytes that are used
157/// to produce a hash of a given object. As a general rule is that every
158/// attribute used in 'operator==' is usually salient to hashing. This term is
159/// explored more in depth later.
160///
161/// ## Why Use This System {#bslh-why-use-this-system}
162///
163/// There are numerous benefits to both type creators and users in this new
164/// system:
165///
166/// ### Better and More Predictable Performance {#bslh-better-and-more-predictable-performance}
167///
168/// This modular hashing system allows users to use known good hashing algorithms
169/// to avoid performance issues. The graph below depicts 'unordered_map'
170/// (expected case O(1)) taking longer to find elements that map. This is a
171/// real-world benchmark. Internal users can read more about these tests at {TEAM
172/// BDE:FLAT MAP<GO>}. The anomalous behavior arose from the use of a poorly
173/// written, non-standard, hashing algorithm, which caused similar strings to hash
174/// to the same value resulting in many collisions:
175/// @code
176/// Time to Find a pair<string, string> in map vs unordered_map
177///
178/// 18 |
179/// | O = map X = unordered_map
180/// 16 |
181/// T | X
182/// i 14 | |
183/// m | /
184/// e 12 | /-O
185/// | /
186/// i 10 | - /
187/// n | - /
188/// 8 | O /
189/// S | -- /
190/// e 6 | - /
191/// c | -- /
192/// o 4 | ----O X
193/// n | ----O--- --
194/// d 2 | ---O----- ----
195/// s | XO-------XO-------X--------X--------X
196/// |____________________________________________________________________
197/// | | | | | | |
198/// 1 10 100 1000 10000 100000 1000000
199/// Elements in Collection
200/// @endcode
201///
202/// ### Less Code Duplication {#bslh-less-code-duplication}
203///
204/// In the standard C++03 hashing system, hashing algorithms were often copied
205/// into the 'bsl::hash' template specialization on each type. This resulted in
206/// lots of code duplication. In the new system, algorithms are not implemented
207/// directly on the type, so no algorithm duplication occurs. The little bit of
208/// code that is written on the type is specific to that type and wouldn't be
209/// copied elsewhere.
210///
211/// ### Easier to Make Types Hashable {#bslh-easier-to-make-types-hashable}
212///
213/// In the standard C++03 hashing system, type implementers had to worry about
214/// writing a hashing algorithm for their type. This required figuring out what
215/// constituted a good hash value and how to generate one with a given set of data
216/// members. Thinking about what makes a good hash is no longer the job of the
217/// type implementer. They simply have to declare what data members they want to
218/// contribute the hash and then they are done.
219///
220/// ### Hash Combining {#bslh-hash-combining}
221///
222/// In the standard C++03 hashing system, if a type needed to use more than one
223/// data member in its hash calculation, there was no proper way for them to
224/// combine the hashes from multiple data members into one final hash. Poor
225/// methods of hash combining such as XORing could result in huge numbers of
226/// collisions. The new, modular hashing system offers 'hashAppend' to combine an
227/// unlimited number of data members into one, good, hash.
228///
229/// ### Swappable Algorithms {#bslh-swappable-algorithms}
230///
231/// In the standard C++03 hashing system, anyone who wanted to hash a type had to
232/// use the algorithm written by the type implementer, or they had to write their
233/// own algorithm in a functor (without access to private data members of course).
234/// Unfortunately, hashing algorithms are not one size fits all. In some cases, a
235/// fast identity hash is fine. In other cases a slower hash that is secure
236/// against Denial of Service (DoS) attacks is required. The new, modular hashing
237/// system offers a suite of hashing algorithms that have been vetted and are know
238/// to have good characteristics for different situations. Swapping out one
239/// algorithm for another only requires a type's users to change one line of code,
240/// as shown here:
241/// @code
242/// // Uses implicitly 'DefaultHashAlgorithm'.
243/// bsl::unordered_map<MyType, int, bslh::Hash<>> unorderedMap;
244///
245/// // Only a single line change is required to use 'SpookyHashAlgorithm'
246/// bsl::unordered_map<MyType,
247/// int,
248/// bslh::Hash<bslh::SpookyHashAlgorithm>> unorderedMap;
249/// @endcode
250///
251/// ## Type Implementers {#bslh-type-implementers}
252///
253/// It is the type implementer's job to implement 'hashAppend' (explained below)
254/// on their type, much like they have to implement 'swap' on their type. It is
255/// important to note that implementing 'hashAppend' on 'MyType' is fully backward
256/// compatible with 'bsl::hash<MyType>'. That means that when you implement
257/// 'hashAppend' on 'MyNewType', 'bsl::hash<MyNewType>' will automatically pick it
258/// up without you ever having to write your own template specialization. For
259/// existing types that already have a 'bsl::hash<MyExistingType>' specialization,
260/// it is recommended that type implementers delete 'bsl::hash<MyExistingType>'
261/// once they have implemented 'hashAppend'. Deleting the 'bsl::hash' template
262/// specialization for 'MyExistingType' will not break any code because
263/// 'bsl::hash<TYPE>' automatically redirects to 'bslh::Hash<>'. Note that
264/// deleting the 'bsl::hash' template specialization for 'MyExistingType' will
265/// cause the hash value returned by calls to 'bsl::hash<MyExistingType>' to
266/// change, but this is explicitly allowed in the 'bsl::hash' contract.
267///
268/// ### hashAppend {#bslh-hashappend}
269///
270/// The fundamental piece of this system, at least for type implementers, is the
271/// 'hashAppend' free function. What this free function does is pass the data
272/// members of a class which need to be hashed, into a hashing algorithm. It
273/// removes the need for the type implementer to actually write the hashing
274/// algorithm. An example implementation can be seen below:
275/// @code
276/// namespace BloombergLP {
277/// namespace NamespaceForBoxes {
278///
279/// class Box {
280/// // A value semantic type that represents a box drawn on to a Cartesian
281/// // plane.
282/// private:
283/// Point d_position;
284/// int d_length;
285/// int d_width;
286/// public:
287/// Box(Point position, int length, int width);
288/// // Create a box with the specified 'length' and 'width', with its
289/// // upper left corner at the specified 'position'
290///
291/// friend bool operator==(const Box &left, const Box &right);
292///
293/// template <class HASH_ALGORITHM>
294/// friend
295/// void hashAppend(HASH_ALGORITHM &hashAlg, const Box &box);
296/// // Apply the specified 'hashAlg' to the specified 'box'
297/// };
298///
299/// Box::Box(Point position, int length, int width)
300/// : d_position(position)
301/// , d_length(length)
302/// , d_width(width)
303/// {
304/// }
305///
306/// bool operator==(const Box &left, const Box &right)
307/// {
308/// return (left.d_position == right.d_position)
309/// && (left.d_length == right.d_length)
310/// && (left.d_width == right.d_width);
311/// }
312///
313/// template <class HASH_ALGORITHM>
314/// void hashAppend(HASH_ALGORITHM &hashAlg, const Box &box)
315/// {
316/// using bslh::hashAppend;
317/// hashAppend(hashAlg, box.d_position);
318/// hashAppend(hashAlg, box.d_length);
319/// hashAppend(hashAlg, box.d_width);
320/// }
321///
322/// } // close package namespace
323/// } // close enterprise namespace
324/// @endcode
325/// A few key features of the 'hashAppend' function:
326///
327/// 1. 'hashAppend' is a free function that can be picked up through argument
328/// dependent look-up (ADL).
329///
330/// 1. In order to ensure 'hashAppend' can be found through ADL, the function
331/// must begin with 'using bslh::hashAppend'. Note that most of the time
332/// this isn't required because most 'HASH_ALGORITHM's will be implemented in
333/// 'bslh' and thus ADL will already be looking in 'bslh'. The using
334/// statement is still required, however, to support algorithms that are
335/// implemented outside of 'blsh'.
336///
337/// 2. 'hashAppend' is defined the header file of the type for which it is
338/// implemented.
339///
340/// 3. If 'hashAppend' requires access to private data, it is declared as a friend
341/// to the type which it is hashing.
342///
343/// 4. 'hashAppend' accepts a reference to a templated hashing algorithm functor,
344/// and a 'const' reference to the type which it is hashing.
345///
346/// 5. 'hashAppend' recursively calls 'hashAppend' on each of the
347/// salient-attributes of the type that it is hashing, propagating the hash
348/// algorithm functor with each invocation.
349///
350/// This is the extent of the work for a type implementer. Once a type
351/// implementer knows what members need to contribute to a hash value, the type
352/// implementer simply calls 'hashAppend' on members as shown above. Those
353/// members will then be passed into and used by whatever algorithm a consumer of
354/// the type wants to apply.
355///
356/// ### Determining what to Hash {#bslh-determining-what-to-hash}
357///
358/// Type implementers should be familiar with the rules for hash functions. There
359/// are two main rules:
360///
361/// 1. If 'x == y', then both 'x' and 'y' shall produce the same hash.
362///
363/// 2. If 'x != y', then 'x' and 'y' should not produce the same hash.
364///
365/// For example, if the first rule is violated, 'unordered_map' will encounter
366/// runtime errors. If the second rule is violated, collisions will occur and the
367/// performance of 'unordered_map' will suffer.
368///
369/// Since the rule about hashing are predicated on 'operator==', the easiest way
370/// to determine what to hash is to look at 'operator=='. For example, lets
371/// reexamine 'operator==' from our earlier code sample:
372/// @code
373/// bool operator==(const Box &left, const Box &right)
374/// {
375/// return (left.d_position == right.d_position)
376/// && (left.d_length == right.d_length)
377/// && (left.d_width == right.d_width);
378/// }
379/// @endcode
380/// In order to ensure that the first rule of hashing if followed, we must only
381/// include data members in our hash if one of the following is true:
382///
383/// * The data member is used in the 'operator==' comparison.
384///
385/// * The data member is a entirely dependent on data that is used in the
386/// 'operator==' comparison.
387///
388/// * The data member is constant.
389///
390/// If we do not meet any of the above criteria, we open ourselves to the
391/// possibility that two objects that compare equal will hash to different values.
392/// If two equal objects hash to different values, hash-based data structures
393/// ('unordered_map' being the primary concern) will break. And example of
394/// something not to include in 'hashAppend' would be the 'capacity()' of a
395/// vector.
396///
397/// In order to make the second rule of hashing remain true, we should include
398/// everything that appears in 'operator==' in our hash. The more data we can put
399/// into the hashing algorithm, the higher the chances of us getting unique
400/// outputs. By following these suggestions, we produced the 'hashAppend'
401/// function from our earlier code example:
402/// @code
403/// template <class HASH_ALGORITHM>
404/// void hashAppend(HASH_ALGORITHM &hashAlg, const Box &box)
405/// {
406/// using bslh::hashAppend;
407/// hashAppend(hashAlg, box.d_position);
408/// hashAppend(hashAlg, box.d_length);
409/// hashAppend(hashAlg, box.d_width);
410/// }
411/// @endcode
412/// It is worth noting that sometimes even data members that don't actually
413/// contribute entropy can still help us produce a more unique unique outputs.
414/// For example consider 'vector<vector<int> >'. If we just hashed the elements
415/// in the vector, then an empty 'vector<vector<int> >' would generate the same
416/// hash value as a 'vector<vector<int> >' containing one (or more) empty
417/// 'vector<int>' objects. This violates the second rule of hashing (above). By
418/// also passing 'vector.length()' (which is used in equality) into the algorithm,
419/// the two vectors will hash to different values.
420///
421/// ### Hashing Other User Defined Types {#bslh-hashing-other-user-defined-types}
422///
423/// As we can see in code sample above showing 'hashAppend', 'hashAppend' is
424/// called on a data member of the user-defined type, 'Point'. This code will not
425/// compile if 'Point' is a type for which 'hashAppend' has not been implemented.
426/// The best route to take is to have the creator of 'Point' go back and add a
427/// 'hashAppend' function. If the creator, or somebody knowledgeable about the
428/// type, is not available to add the 'hashAppend' function, there is a work
429/// around. Assuming 'Point' supports the old system and has a 'bsl::hash<Point>'
430/// specialization, you can just hash the 'Point' and then pass the resulting
431/// 'size_t' into 'hashAppend' just like you would with any other integer data
432/// member. The following code sample shows how we can modify 'Box's 'hashAppend'
433/// function to handle 'Point' without a 'hashAppend' free function for 'Point':
434/// @code
435/// template <class HASH_ALGORITHM>
436/// void hashAppend(HASH_ALGORITHM &hashAlg, const Box &box)
437/// {
438/// using bslh::hashAppend;
439/// hashAppend(hashAlg, bsl::hash<Point>()(box.d_position));
440/// hashAppend(hashAlg, box.d_length);
441/// hashAppend(hashAlg, box.d_width);
442/// }
443/// @endcode
444/// In the above code sample, the first call to 'hashAppend' is now effectively
445/// calling 'hashAppend' on an integer type (the resulting hash from 'bsl::hash'),
446/// rather than on 'Point'. This trick allows new development to use this modular
447/// hashing system without having to wait for existing code to be upgraded.
448///
449/// ### Hashing Pointers (especially const char ) {#bslh-hashing-pointers}
450///
451/// Pointers, particularly C-Strings (in the 'const char *' form), are an
452/// unfortunate exception in hashing. Because the standard mandates that we must
453/// be able to hash pointers, there is no way to distinguish a null terminated
454/// 'const char *' (C-String) from a regular pointer to a 'char'. Because of
455/// this, hashing C-Strings has slightly different semantics. Instead of calling
456/// 'hashAppend' on the pointer, we must pass our C-String directly into the
457/// hashing algorithm functor. All of the hashing algorithm functors in 'bslh'
458/// have the function signature shown below:
459/// @code
460/// /// Incorporates the specified `data` of `length` bytes into the internal
461/// /// state of the hashing algorithm.
462/// void operator()(const char *data, size_t length);
463/// @endcode
464/// As we can see, the hashing algorithm functor takes a pointer to the start of
465/// the data and a length in bytes. To hash a C-String, we call the hashing
466/// algorithm functor with our pointer and the length of the C-String which we
467/// have stored or pre-calculated. An example of this is the 'hashAppend'
468/// function for string, shown here:
469/// @code
470/// template <class HASHALG,
471/// class CHAR_TYPE,
472/// class CHAR_TRAITS,
473/// class ALLOCATOR>
474/// void hashAppend(HASHALG& hashAlg,
475/// const basic_string<CHAR_TYPE,
476/// CHAR_TRAITS,
477/// ALLOCATOR>& input)
478/// {
479/// using bslh::hashAppend;
480/// hashAlg(input.data(), sizeof(CHAR_TYPE)*input.size());
481/// }
482/// @endcode
483/// This technique can be applied to any case where you want to hash contiguous
484/// data. It is especially important that the your data is completely contiguous,
485/// because padding bits and the like could result in the same data hashing to
486/// different values, which violates the first rule of hashing.
487///
488/// ### Converting Existing Types {#bslh-converting-existing-types}
489///
490/// The same process as above should be followed when implementing 'hashAppend' on
491/// user defined types which already specialize 'bsl::hash'. One extra step that
492/// is required is the 'bsl::hash' template specialization must be removed once
493/// 'hashAppend' has been implemented. 'unordered_map's will still function after
494/// the 'bsl::hash' specialization has been removed, since 'bsl::hash<TYPE>'
495/// automatically calls 'bslh::Hash<>' when no specialization exists. Note that
496/// deleting the 'bsl::hash' template specialization will cause the hash value
497/// returned by 'bsl::hash<YourType>' to change, however, this is explicitly
498/// allowed by the contract of 'bsl::hash'.
499///
500/// ## Type Users {#bslh-type-users}
501///
502/// The primary use case for 'bslh::Hash' is producing hash values for hash tables
503/// ('unordered_map's), so we will be focusing on that for the next example, but
504/// this section does apply generally to any use of the modular hashing system.
505/// The basic background knowledge required for this section is:
506///
507/// * 'hashAppend' is a free function, implemented by type implementers, which
508/// makes a type hashable.
509///
510/// * 'bslh::Hash<>' is a hashing functor that has the same interface as
511/// 'bsl::hash<SomeType>', but allows you to supply a hashing algorithm as a
512/// template parameter.
513///
514/// * Standard hashing algorithm functors are available in the 'bslh' package.
515///
516/// Beyond this basic summary, some knowledge of how 'bslh::Hash' and 'bsl::hash'
517/// interact is required for type users to get the most out of this system.
518///
519/// ### bsl::hash {#bslh-bsl-hash}
520///
521/// Unfortunately, 'bsl::hash' is impossible to completely escape, even with the
522/// modular hashing system. The standard mandates that 'unordered_map's with a
523/// key of 'SomeType' will call 'bsl::hash<SomeType>' by default. We have done
524/// our best to make 'bsl::hash' and 'bslh::Hash' interact nicely in most
525/// scenarios, and the section below shows what behavior can be expected from
526/// calling 'bsl::hash<SomeType>'.
527///
528/// * 'bsl::hash' is specialized for 'SomeType' *and* 'hashAppend' is implemented
529/// for 'SomeType'.
530///
531/// * Calling 'bsl::hash<SomeType>' will go to the 'bsl::hash' template
532/// specialization. Note that 'bsl::hash<SomeType>' should normally be
533/// deleted once 'hashAppend' has been implemented on 'SomeType'. If
534/// 'bsl::hash<SomeType>' has not been deleted, please contact the type's
535/// creator and ask them to do so.
536///
537/// * 'bslh::Hash<AnyImplementedAlgorithm>' can be called directly
538///
539/// * 'bsl::hash' is not specialized for 'SomeType' *and* 'hashAppend' is
540/// implemented for 'SomeType'.
541///
542/// * Calling 'bsl::hash<SomeType>' will automatically redirect to
543/// 'bslh::Hash<>'.
544///
545/// * 'bslh::Hash<AnyImplementedAlgorithm>' can be called directly
546///
547/// * 'bsl::hash' is specialized for 'SomeType' *and* 'hashAppend' is not
548/// implemented for 'SomeType'.
549///
550/// * Calling 'bsl::hash<SomeType>' will go to the 'bsl::hash' template
551/// specialization. Please implement 'hashAppend' on 'SomeType'.
552///
553/// * 'bsl::hash' is not specialized for 'SomeType' *and* 'hashAppend' is not
554/// implemented for 'SomeType'.
555///
556/// * Does not compile, please implement 'hashAppend' on 'SomeType'.
557///
558/// Note that when 'bsl::hash<SomeType>' redirects to 'bslh::Hash<>',
559/// 'bslh::Hash<>' is always using the defualt hashing algorithm. This is fine
560/// for most use cases, but if we need to use a special algorithm, such as a
561/// secure one to prevent Denial of Service (DoS) attacks in a hash table, we must
562/// directly use 'bslh::Hash' in order to swap out the algorithm template
563/// parameter.
564///
565/// ### bslh::Hash {#bslh-bslh-hash}
566///
567/// There are various algorithms that can be swapped into 'bslh::Hash' as template
568/// parameters. Algorithms such as SipHash and SpookyHash
569/// ('bslh::SipHashAlgorithm' and 'bslh::SpookyHashAlgorithm' respectively) are
570/// implemented and can be swapped into 'bslh::Hash'. There are also a number of
571/// wrapper classes such as 'bslh::DefaultHashAlgorithm' and
572/// 'balh::DefaultSeededHashAlgorithm' which are named to allow you to pick them
573/// based on what you need, meaning you don't need an in depth knowledge of the
574/// individual hashing algorithms. The usage of these algorithms can be seen
575/// below:
576/// @code
577/// // Implicitly uses 'bsl::hash<MyType>', may or may not redirect to
578/// // 'bslh::Hash<>'.
579/// bsl::unordered_map<MyType, int> unorderedMap;
580///
581/// // Implicitly uses 'bslh::DefaultHashAlgorithm', which redirects to the
582/// // current best default algorithm for hashing.
583/// bsl::unordered_map<MyType, int, bslh::Hash<>> unorderedMap;
584///
585/// // Explicitly uses 'bslh::DefaultHashAlgorithm', which redirects to the
586/// // current best default algorithm for hashing.
587/// bsl::unordered_map<MyType, int, bslh::Hash<bslh::DefaultHashAlgorithm>>
588/// unorderedMap;
589///
590/// // Explicitly uses 'bslh::SpookyHashAlgorithm', one of the algorithms
591/// // available in 'bslh'.
592/// bsl::unordered_map<MyType, int, bslh::Hash<bslh::SpookyHashAlgorithm>>
593/// unorderedMap;
594/// @endcode
595///
596/// ### bslh::SeededHash, bslh::SeedGenerator, and Secure Hashing {#bslh-bslh-seededhash-bslh-seedgenerator-and-secure-hashing}
597///
598/// Some hashing algorithms, such as 'bslh::SipHashAlgorithm', require seeds to
599/// function. 'bslh::SipHashAlgorithm' was designed by its creators to provide
600/// protection against hash table DoS attacks. In order to get the most
601/// protection, 'bslh::SipHashAlgorithm' requires a cryptographically secure
602/// random number in order to produce hashes that will be secure against an
603/// attacker. 'bslh::SeededHash' and 'bslh::SeedGenerator' exist to facilitate
604/// passing seeds into hashing algorithms.
605///
606/// #### Seeded Algorithms {#bslh-seeded-algorithms}
607///
608/// Different algorithms have different seed requirements. Some require a seed to
609/// function and others take one optionally. The table below shows the seed
610/// requirements of the algorithms in 'bslh':
611/// @code
612///+-----------------------------------+-----------------------------------------+
613///| Algorithm | Takes Seed? | Requires Seed? | Crypto?* |
614///+-----------------------------------+-------------+----------------+----------+
615///|'bslh::DefaultHashAlgorithm' | N | N | N |
616///+-----------------------------------+-----------------------------------------+
617///|'bslh::DefaultSeededHashAlgorithm' | Y | Y | N |
618///+-----------------------------------+-----------------------------------------+
619///|'bslh::SipHashAlgorithm' | Y | Y | Y |
620///+-----------------------------------+-----------------------------------------+
621///|'bslh::SpookyHashAlgorithm' | Y | N | N |
622///+-----------------------------------+-----------------------------------------+
623/// [*] "Crypto" is reverting to the requirement on the seed, not the quality of
624/// the algorithm. I.e., 'bslh::SipHashAlgorithm' is not a cryptographically
625/// secure algorithm, but it *is* a cryptographically strong pseudo-random
626/// function, *if* it's provided a cryptographically secure seed (see
627/// 'bslh_siphashalgorithm' for more information).
628/// @endcode
629/// Algorithms can require different sized seeds, and different quality of seeds.
630/// These variances are handled by 'bslh::SeedGenerator'.
631///
632/// #### bslh::SeedGenerator {#bslh-bslh-seedgenerator}
633///
634/// bslh::SeedGenerator allows users to choose their Random Number Generator (RNG)
635/// and then handles the actual seed generation for algorithms. It presents the
636/// following interface:
637/// @code
638/// template<class RANDOM_NUM_GEN>
639/// class SeedGenerator : private RANDOM_NUM_GEN {
640/// private:
641/// // PRIVATE TYPES
642/// typedef typename RANDOM_NUM_GEN::result_type result_type;
643///
644/// // DATA
645/// enum { k_RNGOUTPUTSIZE = sizeof(typename RANDOM_NUM_GEN::result_type)};
646///
647/// public:
648/// // CREATORS
649/// SeedGenerator();
650///
651/// explicit SeedGenerator(const RANDOM_NUM_GEN &randomNumberGenerator);
652///
653/// // MANIPULATORS
654/// void generateSeed(char *seedLocation, size_t seedLength);
655/// };
656/// @endcode
657/// Note that 'bslh::SeedGenerator' takes advantage of the empty base optimization
658/// when possible.
659///
660/// 'bslh::SeedGenerator' takes a RNG as a template parameter. The quality of
661/// this RNG will determine the quality of the seed produced. That is, if the RNG
662/// is cryptographically secure, the seed will be as well. 'bslh::SeedGenerator'
663/// can be either default constructed or constructed with an instance of the
664/// (template parameter) type 'RANDOM_NUM_GEN'. Default construction is preferred
665/// if possible, but the parameterized constructor exists for cases when
666/// 'RANDOM_NUM_GEN' is not default constructable, or when you need to pass in an
667/// instance of 'RANDOM_NUM_GEN' with a particular state.
668///
669/// The 'generateSeed' method will be used by 'bslh::SeededHash' to generate seeds
670/// for any algorithm that takes a seed.
671///
672/// #### bslh::SeededHash {#bslh-bslh-seededhash}
673///
674/// 'bslh::SeededHash' is very similar to 'bslh::Hash'. Both are wrappers for the
675/// hashing algorithm functors in 'bslh and both present an interface that meets
676/// the requirements of the standard for 'std::hash'. The interface of
677/// 'bslh::SeededHash' can be seen below.
678/// @code
679/// template <class SEED_GENERATOR, class HASH_ALGORITHM =
680/// bslh::DefaultSeededHashAlgorithm>
681/// struct SeededHash {
682/// private:
683/// // DATA
684/// char seed[HASH_ALGORITHM::k_SEED_LENGTH];
685///
686/// public:
687/// // TYPES
688/// typedef size_t result_type;
689///
690/// // CREATORS
691/// SeededHash();
692///
693/// explicit SeededHash(SEED_GENERATOR& seedGenerator);
694///
695/// // ACCESSORS
696/// template <class TYPE>
697/// result_type operator()(const TYPE& type) const;
698/// };
699/// @endcode
700/// Like 'bslh::SeedGenerator', 'bslh::SeededHash' has both default and
701/// parameterized constructors. If the (template parameter) type 'SEED_GENERATOR'
702/// is default constructible, then 'bslh:SeededHash' will be default
703/// constructible, and it can be used in the exact same way as 'bslh::Hash', as
704/// shown here:
705/// @code
706/// // Construct an unordered map with a secure hashing algorithm
707/// bsl::unordered_map<MyType,
708/// int,
709/// bslh::SeededHash<bslh::SeedGenerator<CryptoRNG>,
710/// bslh::SecureHashAlgorithm> > unorderedMap;
711/// @endcode
712/// If 'bslh::SeededHash' is not default constructable, or you want to use a
713/// specific instance of a RNG or seed generator, then 'unordered_map' can no
714/// longer be default constructed as previously shown. Instead,
715/// 'bslh::SeededHash' must be passed through the constructor of the unordered
716/// map, seen here:
717/// @code
718/// // typedefs to make the code smaller
719/// typedef bslh::SeedGenerator<CryptoRNG> CryptoSeedGen;
720/// typedef bslh::SeededHash<CryptoSeedGen, bslh::SecureHashAlgorithm>
721/// CryptoHasher;
722///
723/// // Construct the required seed generator and hashing algorithm wrapper from
724/// // 'someRNGObject'
725/// CryptoSeedGen seedGenerator(someRNGObject);
726/// CryptoHasher hashAlg(seedGenerator);
727///
728/// // Construct our unordered map
729/// bsl::unordered_map<MyType, int, CryptoHasher> secureUnorderedMap(
730/// startIterator,
731/// endIterator,
732/// hashAlg);
733/// @endcode
734/// One important difference between 'bslh::Hash' and 'bslh::SeededHash' is that
735/// 'bslh::SeededHash' needs to hold the seed, so it can not benefit from the
736/// empty base optimization.
737///
738/// ### Hashing Performance and Fundamental Integer Types {#bslh-hashing-performance-and-fundamental-integer-types}
739///
740/// Fundamental integer types are a notable exception to the pattern of
741/// redirecting 'bsl::hash' specializations to 'bslh::Hash'. Fundamental integer
742/// types will retain their 'bsl::hash' template specializations that are identity
743/// functions (they return the supplied integer value its own hash value). This
744/// is done for performance reasons, as identity hashing is the fastest possible
745/// hash. Please note that this is not a good hashing algorithm and should only
746/// be used in cases where performance is critical and the data is predicable
747/// enough that we know minimal numbers of bucket collisions will occur.
748///
749/// ### Choosing a Hashing Algorithm {#bslh-choosing-a-hashing-algorithm}
750///
751/// For most purposes, the default supplied hashing algorithm will be best. It
752/// has a good combination of speed and key distribution. In cases where user
753/// input is directly included in the 'unordered_map', it is recommended to use a
754/// secure hashing algorithm instead, to prevent Denial of Service (DoS) attacks
755/// where an attacker causes all of the keys to collide to the same bucket. Make
756/// sure to read the component level documentation when looking for an algorithm,
757/// to be sure that a hashing algorithm has the right trade offs for your use
758/// case.
759///
760/// ## Extending the System {#bslh-extending-the-system}
761///
762/// Every piece of the modular hashing system can be extended and swapped out in
763/// favor of user defined pieces. This section defines how to extend the various
764/// pieces, and the canonical interfaces that must be adhered to. Both type
765/// implementers and users may have need of this section.
766///
767/// ### Hashing Algorithm Functors {#bslh-hashing-algorithm-functors}
768///
769/// Users are free write their own hashing algorithms and make them available via
770/// functors. In order to plug into 'bslh::Hash' the algorithms must implement
771/// the following interface:
772/// @code
773/// class SomeHashAlgorithm
774/// {
775/// public:
776/// // TYPES
777/// typedef uint64 result_type;
778///
779/// // CREATORS
780/// SomeHashAlgorithm();
781///
782/// // MANIPULATORS
783/// void operator()(const char * key, size_t len);
784///
785/// result_type computeHash();
786/// };
787/// @endcode
788/// The 'result_type' 'typedef' must define the return type of this particular
789/// algorithm. A default constructor (either implicit or explicit) must be
790/// supplied that creates an algorithm functor that is in a usable state. An
791/// 'operator()' must be supplied that takes a 'const char' pointer to the data to
792/// be hashed and a 'size_t' length of bytes to be hashed. This operator must
793/// operate on all data uniformly, meaning that regardless of whether data is
794/// passed in all at once, or one byte at a time, the result returned by
795/// 'computeHash()' will be the same. 'computeHash()' will return the final
796/// result of the hashing algorithm, in the form of a 'result_type'.
797/// 'computeHash()' is allowed to modify the internal state of the algorithm,
798/// meaning calling 'computeHash()' more than once might not return the correct
799/// value.
800///
801/// Hashing algorithm functors containing algorithms that require seeds must
802/// implement the interface shown above, with the exception of the default
803/// constructor. Seeded algorithm functors must also implement the following
804/// interface:
805/// @code
806/// class SomeHashAlgorithm
807/// {
808/// public:
809/// // CONSTANTS
810/// enum { k_SEED_LENGTH = XXX };
811///
812/// // CREATORS
813/// explicit SomeHashAlgorithm(const char *seed);
814/// };
815/// @endcode
816/// The 'k_SEED_LENGTH' enum must be in the public interface, and 'XXX' must be
817/// replaced with an integer literal indicating the number of bytes of seed the
818/// algorithm requires. The parameterized constructor must accept a 'const char'
819/// pointer. This pointer will point to a seed of 'XXX' bytes in size.
820///
821/// ### Hashing Algorithm Wrappers (bslh::Hash) {#bslh-hashing-algorithm-wrappers}
822///
823/// Users are free to write their own versions of 'bslh::Hash<>' for whatever use
824/// case they require (in fact, 'bslh::SeededHash<>' is one such example).
825/// Because no other parts of the modular hashing system rely on 'bslh::Hash<>',
826/// you are free to use whatever interface is necessary. The recommended
827/// interface for maintaining compatibility with components that previously used
828/// 'bsl::hash<>' can be seen here:
829/// @code
830/// template <class HASH_ALGORITHM>
831/// struct YourHash
832/// {
833/// // TYPES
834/// typedef size_t result_type;
835///
836/// // ACCESSORS
837/// template <class TYPE>
838/// result_type operator()(TYPE const& type) const;
839/// };
840/// @endcode
841/// The hashing algorithm wrapper that you create to replace 'blsh::Hash<>' should
842/// be templated to operate using various 'HASH_ALGORITHM's. Whether or not there
843/// is a default option for the template is optional. The 'result_type' should
844/// define the type of the hash value that you will return. The 'operator()'
845/// should be templated to operate on any 'TYPE'. 'operator()' should take a
846/// single 'const' reference to 'TYPE' and should return a 'result_type'. Given
847/// two 'TYPEs' that compare equal with 'operator==', 'operator()' *must* return
848/// the same hash.
849///
850/// ### Seed Generator {#bslh-seed-generator}
851///
852/// Users are free to write their own seed generator, a class of component
853/// required by 'bslh::SeededHash'. The seed generator must conform to the
854/// interface shown here:
855/// @code
856/// class YourSeedGenerator
857/// {
858/// // ACCESSORS
859/// void generateSeed(char *seedLocation, size_t seedLength);
860/// };
861/// @endcode
862/// The only mandatory piece of the seed generator interface is the 'generateSeed'
863/// method which accepts a 'char' pointer to memory to be written and a 'size_t'
864/// length in bytes. The generateSeed method must fill the size_t bytes of the
865/// memory pointed to by the 'char' pointer with a seed. If possible, it is
866/// better for the seed generator to be default constructible, however, any sort
867/// of constructor is acceptable because the seed generator can be constructed and
868/// passed directly into 'bslh::SeededHash' if required. Be aware that having a
869/// non-default constructor makes it more difficult to use the seed generator (see
870/// the 'bslh::SeededHash' section above to see the difference).
871///
872/// ## Hierarchical Synopsis {#bslh-hierarchical-synopsis}
873///
874/// The 'bslh' package currently has 16 components having 4 levels of physical
875/// dependency. The list below shows the hierarchical ordering of the components.
876/// The order of components within each level is not architecturally significant,
877/// just alphabetical.
878/// @code
879/// 4. bslh_filesystem
880/// bslh_hashoptional
881/// bslh_hashpair
882/// bslh_hashthreadid
883/// bslh_hashtuple
884/// bslh_hashvariant
885/// bslh_seededhash
886///
887/// 3. bslh_hash
888///
889/// 2. bslh_defaulthashalgorithm
890/// bslh_defaultseededhashalgorithm
891/// bslh_spookyhashalgorithm
892///
893/// 1. bslh_fibonaccibadhashwrapper
894/// bslh_seedgenerator
895/// bslh_siphashalgorithm
896/// bslh_spookyhashalgorithmimp
897/// bslh_wyhashincrementalalgorithm
898/// @endcode
899///
900/// ## Component Synopsis {#bslh-component-synopsis}
901///
902/// @ref bslh_defaulthashalgorithm :
903/// Provide a reasonable hashing algorithm for default use.
904///
905/// @ref bslh_defaultseededhashalgorithm :
906/// Provide a reasonable seeded hashing algorithm for default use.
907///
908/// @ref bslh_fibonaccibadhashwrapper :
909/// Provide a wrapper to improve "bad" hash algorithms.
910///
911/// @ref bslh_filesystem :
912/// Provide `hash` for `std::filesystem::path`.
913///
914/// @ref bslh_hash :
915/// Provide a struct to run `bslh` hash algorithms on supported types.
916///
917/// @ref bslh_hashoptional :
918/// Provide `hashAppend` for `std::optional`.
919///
920/// @ref bslh_hashpair :
921/// Provide `hashAppend` for `std::pair`.
922///
923/// @ref bslh_hashthreadid :
924/// Provide `hashAppend` for `std::thread::id`.
925///
926/// @ref bslh_hashtuple :
927/// Provide `hashAppend` for `std::tuple`.
928///
929/// @ref bslh_hashvariant :
930/// Provide `hashAppend` for `std::variant`.
931///
932/// @ref bslh_seededhash :
933/// Provide a struct to run seeded `bslh` hash algorithms on types.
934///
935/// @ref bslh_seedgenerator :
936/// Provide a class to generate arbitrary length seeds for algorithms.
937///
938/// @ref bslh_siphashalgorithm :
939/// Provide an implementation of the SipHash algorithm.
940///
941/// @ref bslh_spookyhashalgorithm :
942/// Provide an implementation of the SpookyHash algorithm.
943///
944/// @ref bslh_spookyhashalgorithmimp :
945/// Provide BDE style encapsulation of 3rd party SpookyHash code.
946///
947/// @ref bslh_wyhashincrementalalgorithm :
948/// Provide an implementation of the WyHash algorithm final v3.
949///
950/// ## Component Overview {#bslh-component-overview}
951///
952/// This section provides a brief introduction to each of the components in the
953/// `bslh` package. Full details are available in the documentation of each
954/// component.
955///
956/// ### bslh_defaulthashalgorithm {#bslh-bslh_defaulthashalgorithm}
957///
958/// The @ref bslh_defaulthashalgorithm component provides an unspecified default
959/// hashing algorithm. The supplied algorithm is suitable for general purpose use
960/// in a hash table. The underlying algorithm is subject to change in future
961/// releases.
962///
963/// This class satisfies the requirements for regular `bslh` hashing algorithms,
964/// as defined in @ref bslh_hash .
965///
966/// ### bslh_defaultseededhashalgorithm {#bslh-bslh_defaultseededhashalgorithm}
967///
968/// The @ref bslh_defaultseededhashalgorithm component provides an unspecified
969/// default seeded hashing algorithm. The supplied algorithm is suitable for
970/// general purpose use in a hash table. The underlying algorithm is subject to
971/// change in future releases.
972///
973/// This class satisfies the requirements for seeded `bslh` hashing algorithms, as
974/// defined in @ref bslh_seededhash .
975///
976/// ### bslh_hash {#bslh-bslh_hash}
977///
978/// The @ref bslh_hash component provides a templated `struct`, `bslh::Hash`, which
979/// provides hashing functionality. This struct is a drop in replacement for
980/// `bsl::hash`. `bslh::Hash` is a wrapper that adapts hashing algorithms from
981/// `bslh` and `hashAppend` free functions to match the interface of `bsl::hash`.
982/// This component also contains `hashAppend` definitions for fundamental types,
983/// which are required to make the hashing algorithms in `bslh` work.
984///
985/// ### bslh_seededhash {#bslh-bslh_seededhash}
986///
987/// The @ref bslh_seededhash component provides a templated struct,
988/// `bslh::SeededHash`, which provides hashing functionality. This `struct` is a
989/// drop in replacement for `bsl::hash`. It is similar to `bslh::Hash`, however,
990/// it is meant for hashes that require a seed. It takes a seed generator and
991/// uses that to create seeds to give the hashing algorithm. `bslh::SeededHash`
992/// is a wrapper which adapts hashing algorithms from `bslh` to match the
993/// interface of `bsl::hash`. `bslh::SeededHash` is a universal hashing functor
994/// that will hash any type that implements `hashAppend` using the hashing
995/// algorithm provided as a template parameter.
996///
997/// ### bslh_seedgenerator {#bslh-bslh_seedgenerator}
998///
999/// The @ref bslh_seedgenerator component provides a class, `bslh::SeedGenerator`,
1000/// which utilizes a user-supplied random number generator (RNG) to generate
1001/// arbitrary length seeds. The quality of the seeds will only be as good as the
1002/// quality of the supplied RNG. A cryptographically secure RNG must be supplied
1003/// in order for `SeedGenerator` to produce seeds suitable for a cryptographically
1004/// secure algorithm.
1005///
1006/// This class satisfies the requirements for a seed generator, as defined in
1007/// @ref bslh_seededhash .
1008///
1009/// ### bslh_siphashalgorithm {#bslh-bslh_siphashalgorithm}
1010///
1011/// The @ref bslh_siphashalgorithm component provides an implementation of the
1012/// SipHash algorithm. SipHash is an algorithm designed for speed and security.
1013/// A primary use case for this algorithm is to provide an extra line of defense
1014/// in hash tables (such as the underlying implementation of `unordered_map`)
1015/// against malicious input that could cause Denial of Service (DoS) attacks. It
1016/// is based on one of the finalists for the SHA-3 cryptographic hash standard.
1017/// Full details of the hash function can be found here:
1018/// https://131002.net/siphash/siphash.pdf. This particular implementation
1019/// has been derived from `siphash.h` in Howard Hinnant's work here:
1020/// https://github.com/HowardHinnant/hash_append and as much of the original
1021/// code as possible, including comment headers, has been preserved.
1022///
1023/// This class satisfies the requirements for seeded `bslh` hashing algorithms, as
1024/// defined in @ref bslh_seededhash .
1025///
1026/// ### bslh_spookyhashalgorithm {#bslh-bslh_spookyhashalgorithm}
1027///
1028/// The @ref bslh_spookyhashalgorithm component provides an implementation of the
1029/// SpookyHash algorithm by Bob Jenkins. This algorithm is a general purpose
1030/// algorithm that is known to quickly reach good avalanche performance and
1031/// execute in time that is comparable to or faster than other industry standard
1032/// algorithms such as CityHash. It is a good default choice for hashing values
1033/// in unordered associative containers. For more information, see
1034/// http://burtleburtle.net/bob/hash/spooky.html.
1035///
1036/// This class satisfies the requirements for regular `bslh` hashing algorithms
1037/// and seeded `bslh` hashing algorithms, as defined in @ref bslh_hash and
1038/// @ref bslh_seededhash respectively.
1039///
1040/// ### bslh_spookyhashalgorithmimp {#bslh-bslh_spookyhashalgorithmimp}
1041///
1042/// The @ref bslh_spookyhashalgorithmimp component provides BDE-style encapsulation
1043/// of Bob Jenkins canonical SpookyHash implementation. SpookyHash provides a way
1044/// to hash contiguous data all at once, or non-contiguous data in pieces. More
1045/// information is available at http://burtleburtle.net/bob/hash/spooky.html.
1046///
1047/// ### bslh_wyhashincrementalalgorithm {#bslh-bslh_wyhashincrementalalgorithm}
1048///
1049/// The `WyHash` algorithm, @ref wyhash_final_version_3 with the `incremental`
1050/// property added, meaning that hashing a segment in a single pass will yield the
1051/// same result as hashing it in contiguous pieces, but, unlike the original
1052/// `WyHash`, this algorithm yields different results depending on the byte order
1053/// of the host.
1054///
1055/// @}
1056/** @} */