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
/** @} */
doxygen_input
bde
groups
bsl
bslh
doc
bslh.h
Generated by
1.9.8