A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
hash-fnv.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012 Lawrence Livermore National Laboratory
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Peter D. Barnes, Jr. <pdbarnes@llnl.gov>
7 *
8 * This copyright notice applies strictly to the wrapper material.
9 *
10 * The FNV source code itself is in the public domain. The FNV source
11 * code sections are marked by
12 * // Begin <fnv-file> ---->
13 * and
14 * // End <fnv-file> ---->
15 * comments.
16 *
17 * Code changes from the FNV distribution are marked with `//PDB'
18 * In addition comment blocks have been converted to Doxygen format.
19 */
20
21#include "hash-fnv.h"
22
23#include "log.h"
24
25#include <stdlib.h>
26#include <sys/types.h>
27
28/**
29 * \file
30 * \ingroup hash
31 * \brief ns3::Hash::Function::Fnv1a implementation.
32 */
33
34namespace ns3
35{
36
37NS_LOG_COMPONENT_DEFINE("Hash-Fnv");
38
39namespace Hash
40{
41
42namespace Function
43{
44
45/** FNV hash implementation details. */
46namespace Fnv1aImplementation
47{
48
49/*************************************************
50 ** class FnvHashImplementation
51 ************************************************/
52
53/**
54 * \ingroup hash
55 * \defgroup hash_fnv FNV Hash Implementation
56 */
57/**@{*/
58
59extern "C"
60{
61 // NOLINTBEGIN
62 // clang-format off
63
64// Changes from FNV distribution are marked with `//PDB'
65//
66
67/* Begin fnv.h ----------------------------------------> */
68
69/*
70 * fnv - Fowler/Noll/Vo- hash code
71 *
72 * @(#) $Revision: 5.4 $
73 * @(#) $Id: fnv.h,v 5.4 2009/07/30 22:49:13 chongo Exp $
74 * @(#) $Source: /usr/local/src/cmd/fnv/RCS/fnv.h,v $
75 *
76 ***
77 *
78 * Fowler/Noll/Vo- hash
79 *
80 * The basis of this hash algorithm was taken from an idea sent
81 * as reviewer comments to the IEEE POSIX P1003.2 committee by:
82 *
83 * Phong Vo (http://www.research.att.com/info/kpv/)
84 * Glenn Fowler (http://www.research.att.com/~gsf/)
85 *
86 * In a subsequent ballot round:
87 *
88 * Landon Curt Noll (http://www.isthe.com/chongo/)
89 *
90 * improved on their algorithm. Some people tried this hash
91 * and found that it worked rather well. In an EMail message
92 * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
93 *
94 * FNV hashes are designed to be fast while maintaining a low
95 * collision rate. The FNV speed allows one to quickly hash lots
96 * of data while maintaining a reasonable collision rate. See:
97 *
98 * http://www.isthe.com/chongo/tech/comp/fnv/index.html
99 *
100 * for more details as well as other forms of the FNV hash.
101 *
102 ***
103 *
104 * NOTE: The FNV-0 historic hash is not recommended. One should use
105 * the FNV-1 hash instead.
106 *
107 * To use the 32 bit FNV-0 historic hash, pass FNV0_32_INIT as the
108 * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str().
109 *
110 * To use the 64 bit FNV-0 historic hash, pass FNV0_64_INIT as the
111 * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str().
112 *
113 * To use the recommended 32 bit FNV-1 hash, pass FNV1_32_INIT as the
114 * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str().
115 *
116 * To use the recommended 64 bit FNV-1 hash, pass FNV1_64_INIT as the
117 * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str().
118 *
119 * To use the recommended 32 bit FNV-1a hash, pass FNV1_32A_INIT as the
120 * Fnv32_t hashval argument to fnv_32a_buf() or fnv_32a_str().
121 *
122 * To use the recommended 64 bit FNV-1a hash, pass FNV1A_64_INIT as the
123 * Fnv64_t hashval argument to fnv_64a_buf() or fnv_64a_str().
124 *
125 ***
126 *
127 * Please do not copyright this code. This code is in the public domain.
128 *
129 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
130 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
131 * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
132 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
133 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
134 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
135 * PERFORMANCE OF THIS SOFTWARE.
136 *
137 * By:
138 * chongo <Landon Curt Noll> /\oo/\
139 * http://www.isthe.com/chongo/
140 *
141 * Share and Enjoy! :-)
142 */
143
144#if !defined(__FNV_H__)
145/** Include guard from the original fnv.h. */
146#define __FNV_H__
147
148
149//#include <sys/types.h> //PDB
150
151#define FNV_VERSION "5.0.2" /**< @(#) FNV Version */
152
153
154/**
155 * 32 bit FNV-0 hash type
156 */
157typedef uint32_t Fnv32_t; //PDB
158
159
160/**
161 * 32 bit FNV-0 zero initial basis
162 *
163 * This historic hash is not recommended. One should use
164 * the FNV-1 hash and initial basis instead.
165 */
166// Use fully qualified type so this define works outside this scope //PDB
167#define FNV0_32_INIT ((Fnv1aImplementation::Fnv32_t)0)
168
169
170/**
171 * 32 bit FNV-1 and FNV-1a non-zero initial basis
172 *
173 * The FNV-1 initial basis is the FNV-0 hash of the following 32 octets:
174 *
175 * chongo <Landon Curt Noll> /\../\
176 *
177 * \note The \'s above are not back-slashing escape characters.
178 * They are literal ASCII backslash 0x5c characters.
179 *
180 * \note The FNV-1a initial basis is the same value as FNV-1 by definition.
181 */
182// Use fully qualified type so this define works outside this scope //PDB
183#define FNV1_32_INIT ((Fnv1aImplementation::Fnv32_t)0x811c9dc5)
184/** \copydoc FNV1_32_INIT */
185#define FNV1_32A_INIT FNV1_32_INIT
186
187
188/**
189 * Determine how 64 bit unsigned values are represented
190 */
191//#include "longlong.h" //PDB - assume `unsigned long long' is 64 bit
192#define HAVE_64BIT_LONG_LONG
193
194
195
196/**
197 * 64 bit FNV-0 hash
198 */
199#if defined(HAVE_64BIT_LONG_LONG)
200typedef uint64_t Fnv64_t; //PDB
201#else /* HAVE_64BIT_LONG_LONG */
202typedef struct {
203 uint32_t w32[2]; /* w32[0] is low order, w32[1] is high order word */ //PDB
204} Fnv64_t;
205#endif /* HAVE_64BIT_LONG_LONG */
206
207
208/**
209 * 64 bit FNV-0 zero initial basis
210 *
211 * This historic hash is not recommended. One should use
212 * the FNV-1 hash and initial basis instead.
213 */
214// Use fully qualified type so this define works outside this scope //PDB
215#if defined(HAVE_64BIT_LONG_LONG)
216#define FNV0_64_INIT ((Fnv1aImplementation::Fnv64_t)0)
217#else /* HAVE_64BIT_LONG_LONG */
218extern const Fnv64_t fnv0_64_init;
219#define FNV0_64_INIT (Fnv1aImplementation::fnv0_64_init)
220#endif /* HAVE_64BIT_LONG_LONG */
221
222
223/**
224 * 64 bit FNV-1 non-zero initial basis
225 *
226 * The FNV-1 initial basis is the FNV-0 hash of the following 32 octets:
227 *
228 * chongo <Landon Curt Noll> /\../\
229 *
230 * \note The \'s above are not back-slashing escape characters.
231 * They are literal ASCII backslash 0x5c characters.
232 *
233 * \note The FNV-1a initial basis is the same value as FNV-1 by definition.
234 */
235#if defined(HAVE_64BIT_LONG_LONG)
236#define FNV1_64_INIT ((Fnv1aImplementation::Fnv64_t)0xcbf29ce484222325ULL)
237/** \copydoc FNV1_64_INIT */
238#define FNV1A_64_INIT FNV1_64_INIT
239#else /* HAVE_64BIT_LONG_LONG */
240extern const fnv1_64_init;
241extern const Fnv64_t fnv1a_64_init;
242#define FNV1_64_INIT (fnv1_64_init)
243/** \copydoc FNV1_64_INIT */
244#define FNV1A_64_INIT (fnv1a_64_init)
245#endif /* HAVE_64BIT_LONG_LONG */
246
247
248/**
249 * FNV hash types
250 */
252 FNV_NONE = 0, /**< invalid FNV hash type */
253 FNV0_32 = 1, /**< FNV-0 32 bit hash */
254 FNV1_32 = 2, /**< FNV-1 32 bit hash */
255 FNV1a_32 = 3, /**< FNV-1a 32 bit hash */
256 FNV0_64 = 4, /**< FNV-0 64 bit hash */
257 FNV1_64 = 5, /**< FNV-1 64 bit hash */
258 FNV1a_64 = 6, /**< FNV-1a 64 bit hash */
259};
260
261//PDB test vector declarations deleted
262
263/*
264 * external functions //PDB converted to forward declarations
265 */
266/** \copydoc fnv_32a_buf() */
267/* extern */ Fnv32_t fnv_32_buf(void *buf, size_t len, Fnv32_t hval);
268/** \copydoc fnv_32a_str() */
269/* extern */ Fnv32_t fnv_32_str(char *str, Fnv32_t hval);
270
271/* hash_32a.c */
272/* extern */ Fnv32_t fnv_32a_buf(void *buf, size_t len, Fnv32_t hashval);
273/* extern */ Fnv32_t fnv_32a_str(char *buf, Fnv32_t hashval);
274
275/* hash_64.c */
276/** \copydoc fnv_64a_buf() */
277/* extern */ Fnv64_t fnv_64_buf(void *buf, size_t len, Fnv64_t hval);
278/** \copydoc fnv_64a_str() */
279/* extern */ Fnv64_t fnv_64_str(char *str, Fnv64_t hval);
280
281/* hash_64a.c */
282/* extern */ Fnv64_t fnv_64a_buf(void *buf, size_t len, Fnv64_t hashval);
283/* extern */ Fnv64_t fnv_64a_str(char *buf, Fnv64_t hashval);
284
285//PDB test vector declarations deleted
286
287
288#endif /* __FNV_H__ */
289
290/* End fnv.h ------------------------------------------> */
291
292/* Begin hash_32a.c -----------------------------------> */
293
294/*
295 * hash_32 - 32 bit Fowler/Noll/Vo FNV-1a hash code
296 *
297 * @(#) $Revision: 5.1 $
298 * @(#) $Id: hash_32a.c,v 5.1 2009/06/30 09:13:32 chongo Exp $
299 * @(#) $Source: /usr/local/src/cmd/fnv/RCS/hash_32a.c,v $
300 *
301 ***
302 *
303 * Fowler/Noll/Vo hash
304 *
305 * The basis of this hash algorithm was taken from an idea sent
306 * as reviewer comments to the IEEE POSIX P1003.2 committee by:
307 *
308 * Phong Vo (http://www.research.att.com/info/kpv/)
309 * Glenn Fowler (http://www.research.att.com/~gsf/)
310 *
311 * In a subsequent ballot round:
312 *
313 * Landon Curt Noll (http://www.isthe.com/chongo/)
314 *
315 * improved on their algorithm. Some people tried this hash
316 * and found that it worked rather well. In an EMail message
317 * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
318 *
319 * FNV hashes are designed to be fast while maintaining a low
320 * collision rate. The FNV speed allows one to quickly hash lots
321 * of data while maintaining a reasonable collision rate. See:
322 *
323 * http://www.isthe.com/chongo/tech/comp/fnv/index.html
324 *
325 * for more details as well as other forms of the FNV hash.
326 ***
327 *
328 * To use the recommended 32 bit FNV-1a hash, pass FNV1_32A_INIT as the
329 * Fnv32_t hashval argument to fnv_32a_buf() or fnv_32a_str().
330 *
331 ***
332 *
333 * Please do not copyright this code. This code is in the public domain.
334 *
335 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
336 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
337 * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
338 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
339 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
340 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
341 * PERFORMANCE OF THIS SOFTWARE.
342 *
343 * By:
344 * chongo <Landon Curt Noll> /\oo/\
345 * http://www.isthe.com/chongo/
346 *
347 * Share and Enjoy! :-)
348 */
349
350//#include <stdlib.h> //PDB
351//#include "fnv.h" //PDB
352
353
354/**
355 * 32 bit magic FNV-1a prime
356 */
357#define FNV_32_PRIME ((Fnv1aImplementation::Fnv32_t)0x01000193)
358
359
360/**
361 * fnv_32a_buf - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a buffer
362 *
363 * input:
364 * \param [in] buf start of buffer to hash
365 * \param [in] len length of buffer in octets
366 * \param [in] hval previous hash value or 0 if first call
367 *
368 * \returns 32 bit hash as a static hash type.
369 *
370 * \note To use the recommended 32 bit FNV-1a hash, use FNV1_32A_INIT as the
371 * hval arg on the first call to either fnv_32a_buf() or fnv_32a_str().
372 */
374fnv_32a_buf(void *buf, size_t len, Fnv32_t hval)
375{
376 unsigned char *bp = (unsigned char *)buf; /* start of buffer */
377 unsigned char *be = bp + len; /* beyond end of buffer */
378
379 /*
380 * FNV-1a hash each octet in the buffer
381 */
382 while (bp < be) {
383
384 /* xor the bottom with the current octet */
385 hval ^= (Fnv32_t)*bp++;
386
387 /* multiply by the 32 bit FNV magic prime mod 2^32 */
388#if defined(NO_FNV_GCC_OPTIMIZATION)
389 hval *= FNV_32_PRIME;
390#else
391 hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
392#endif
393 }
394
395 /* return our new hash value */
396 return hval;
397}
398
399
400/**
401 * fnv_32a_str - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a string
402 *
403 * input:
404 * \param [in] str string to hash
405 * \param [in] hval previous hash value or 0 if first call
406 *
407 * \returns 32 bit hash as a static hash type
408 *
409 * \note To use the recommended 32 bit FNV-1a hash, use FNV1_32A_INIT as the
410 * hval arg on the first call to either fnv_32a_buf() or fnv_32a_str().
411 */
413fnv_32a_str(char *str, Fnv32_t hval)
414{
415 unsigned char *s = (unsigned char *)str; /* unsigned string */
416
417 /*
418 * FNV-1a hash each octet in the buffer
419 */
420 while (*s) {
421
422 /* xor the bottom with the current octet */
423 hval ^= (Fnv32_t)*s++;
424
425 /* multiply by the 32 bit FNV magic prime mod 2^32 */
426#if defined(NO_FNV_GCC_OPTIMIZATION)
427 hval *= FNV_32_PRIME;
428#else
429 hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
430#endif
431 }
432
433 /* return our new hash value */
434 return hval;
435}
436
437/* End hash_32a.c -------------------------------------> */
438
439/* Begin hash_64a.c -----------------------------------> */
440
441/*
442 * hash_64 - 64 bit Fowler/Noll/Vo-0 FNV-1a hash code
443 *
444 * @(#) $Revision: 5.1 $
445 * @(#) $Id: hash_64a.c,v 5.1 2009/06/30 09:01:38 chongo Exp $
446 * @(#) $Source: /usr/local/src/cmd/fnv/RCS/hash_64a.c,v $
447 *
448 ***
449 *
450 * Fowler/Noll/Vo hash
451 *
452 * The basis of this hash algorithm was taken from an idea sent
453 * as reviewer comments to the IEEE POSIX P1003.2 committee by:
454 *
455 * Phong Vo (http://www.research.att.com/info/kpv/)
456 * Glenn Fowler (http://www.research.att.com/~gsf/)
457 *
458 * In a subsequent ballot round:
459 *
460 * Landon Curt Noll (http://www.isthe.com/chongo/)
461 *
462 * improved on their algorithm. Some people tried this hash
463 * and found that it worked rather well. In an EMail message
464 * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
465 *
466 * FNV hashes are designed to be fast while maintaining a low
467 * collision rate. The FNV speed allows one to quickly hash lots
468 * of data while maintaining a reasonable collision rate. See:
469 *
470 * http://www.isthe.com/chongo/tech/comp/fnv/index.html
471 *
472 * for more details as well as other forms of the FNV hash.
473 *
474 ***
475 *
476 * To use the recommended 64 bit FNV-1a hash, pass FNV1A_64_INIT as the
477 * Fnv64_t hashval argument to fnv_64a_buf() or fnv_64a_str().
478 *
479 ***
480 *
481 * Please do not copyright this code. This code is in the public domain.
482 *
483 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
484 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
485 * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
486 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
487 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
488 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
489 * PERFORMANCE OF THIS SOFTWARE.
490 *
491 * By:
492 * chongo <Landon Curt Noll> /\oo/\
493 * http://www.isthe.com/chongo/
494 *
495 * Share and Enjoy! :-)
496 */
497
498//#include <stdlib.h> //PDB
499//#include "fnv.h" //PDB
500
501
502/**
503 * FNV-1a defines the initial basis to be non-zero
504 */
505#if !defined(HAVE_64BIT_LONG_LONG)
506const Fnv64_t fnv1a_64_init = { 0x84222325, 0xcbf29ce4 };
507#endif /* ! HAVE_64BIT_LONG_LONG */
508
509
510/**
511 * 64 bit magic FNV-1a prime
512 */
513/**@{*/
514#if defined(HAVE_64BIT_LONG_LONG)
515#define FNV_64_PRIME ((Fnv1aImplementation::Fnv64_t)0x100000001b3ULL)
516#else /* HAVE_64BIT_LONG_LONG */
517#define FNV_64_PRIME_LOW ((unsigned long)0x1b3) /* lower bits of FNV prime */
518#define FNV_64_PRIME_SHIFT (8) /* top FNV prime shift above 2^32 */
519#endif /* HAVE_64BIT_LONG_LONG */
520/**@}*/
521
522
523/**
524 * fnv_64a_buf - perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
525 *
526 * input:
527 * \param [in] buf start of buffer to hash
528 * \param [in] len length of buffer in octets
529 * \param [in] hval previous hash value or 0 if first call
530 *
531 * \returns 64 bit hash as a static hash type
532 *
533 * \note To use the recommended 64 bit FNV-1a hash, use FNV1A_64_INIT as the
534 * hval arg on the first call to either fnv_64a_buf() or fnv_64a_str().
535 */
537fnv_64a_buf(void *buf, size_t len, Fnv64_t hval)
538{
539 unsigned char *bp = (unsigned char *)buf; /* start of buffer */
540 unsigned char *be = bp + len; /* beyond end of buffer */
541
542#if defined(HAVE_64BIT_LONG_LONG)
543 /*
544 * FNV-1a hash each octet of the buffer
545 */
546 while (bp < be) {
547
548 /* xor the bottom with the current octet */
549 hval ^= (Fnv64_t)*bp++;
550
551 /* multiply by the 64 bit FNV magic prime mod 2^64 */
552#if defined(NO_FNV_GCC_OPTIMIZATION)
553 hval *= FNV_64_PRIME;
554#else /* NO_FNV_GCC_OPTIMIZATION */
555 hval += (hval << 1) + (hval << 4) + (hval << 5) +
556 (hval << 7) + (hval << 8) + (hval << 40);
557#endif /* NO_FNV_GCC_OPTIMIZATION */
558 }
559
560#else /* HAVE_64BIT_LONG_LONG */
561
562 unsigned long val[4]; /* hash value in base 2^16 */
563 unsigned long tmp[4]; /* tmp 64 bit value */
564
565 /*
566 * Convert Fnv64_t hval into a base 2^16 array
567 */
568 val[0] = hval.w32[0];
569 val[1] = (val[0] >> 16);
570 val[0] &= 0xffff;
571 val[2] = hval.w32[1];
572 val[3] = (val[2] >> 16);
573 val[2] &= 0xffff;
574
575 /*
576 * FNV-1a hash each octet of the buffer
577 */
578 while (bp < be) {
579
580 /* xor the bottom with the current octet */
581 val[0] ^= (unsigned long)*bp++;
582
583 /*
584 * multiply by the 64 bit FNV magic prime mod 2^64
585 *
586 * Using 0x100000001b3 we have the following digits base 2^16:
587 *
588 * 0x0 0x100 0x0 0x1b3
589 *
590 * which is the same as:
591 *
592 * 0x0 1<<FNV_64_PRIME_SHIFT 0x0 FNV_64_PRIME_LOW
593 */
594 /* multiply by the lowest order digit base 2^16 */
595 tmp[0] = val[0] * FNV_64_PRIME_LOW;
596 tmp[1] = val[1] * FNV_64_PRIME_LOW;
597 tmp[2] = val[2] * FNV_64_PRIME_LOW;
598 tmp[3] = val[3] * FNV_64_PRIME_LOW;
599 /* multiply by the other non-zero digit */
600 tmp[2] += val[0] << FNV_64_PRIME_SHIFT; /* tmp[2] += val[0] * 0x100 */
601 tmp[3] += val[1] << FNV_64_PRIME_SHIFT; /* tmp[3] += val[1] * 0x100 */
602 /* propagate carries */
603 tmp[1] += (tmp[0] >> 16);
604 val[0] = tmp[0] & 0xffff;
605 tmp[2] += (tmp[1] >> 16);
606 val[1] = tmp[1] & 0xffff;
607 val[3] = tmp[3] + (tmp[2] >> 16);
608 val[2] = tmp[2] & 0xffff;
609 /*
610 * Doing a val[3] &= 0xffff; is not really needed since it simply
611 * removes multiples of 2^64. We can discard these excess bits
612 * outside of the loop when we convert to Fnv64_t.
613 */
614 }
615
616 /*
617 * Convert base 2^16 array back into an Fnv64_t
618 */
619 hval.w32[1] = ((val[3]<<16) | val[2]);
620 hval.w32[0] = ((val[1]<<16) | val[0]);
621
622#endif /* HAVE_64BIT_LONG_LONG */
623
624 /* return our new hash value */
625 return hval;
626}
627
628
629/**
630 * fnv_64a_str - perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
631 *
632 * input:
633 * \param [in] str string to hash
634 * \param [in] hval previous hash value or 0 if first call
635 *
636 * \returns 64 bit hash as a static hash type
637 *
638 * \note To use the recommended 64 bit FNV-1a hash, use FNV1A_64_INIT as the
639 * hval arg on the first call to either fnv_64a_buf() or fnv_64a_str().
640 */
642fnv_64a_str(char *str, Fnv64_t hval)
643{
644 unsigned char *s = (unsigned char *)str; /* unsigned string */
645
646#if defined(HAVE_64BIT_LONG_LONG)
647
648 /*
649 * FNV-1a hash each octet of the string
650 */
651 while (*s) {
652
653 /* xor the bottom with the current octet */
654 hval ^= (Fnv64_t)*s++;
655
656 /* multiply by the 64 bit FNV magic prime mod 2^64 */
657#if defined(NO_FNV_GCC_OPTIMIZATION)
658 hval *= FNV_64_PRIME;
659#else /* NO_FNV_GCC_OPTIMIZATION */
660 hval += (hval << 1) + (hval << 4) + (hval << 5) +
661 (hval << 7) + (hval << 8) + (hval << 40);
662#endif /* NO_FNV_GCC_OPTIMIZATION */
663 }
664
665#else /* !HAVE_64BIT_LONG_LONG */
666
667 unsigned long val[4]; /* hash value in base 2^16 */
668 unsigned long tmp[4]; /* tmp 64 bit value */
669
670 /*
671 * Convert Fnv64_t hval into a base 2^16 array
672 */
673 val[0] = hval.w32[0];
674 val[1] = (val[0] >> 16);
675 val[0] &= 0xffff;
676 val[2] = hval.w32[1];
677 val[3] = (val[2] >> 16);
678 val[2] &= 0xffff;
679
680 /*
681 * FNV-1a hash each octet of the string
682 */
683 while (*s) {
684
685 /* xor the bottom with the current octet */
686
687 /*
688 * multiply by the 64 bit FNV magic prime mod 2^64
689 *
690 * Using 1099511628211, we have the following digits base 2^16:
691 *
692 * 0x0 0x100 0x0 0x1b3
693 *
694 * which is the same as:
695 *
696 * 0x0 1<<FNV_64_PRIME_SHIFT 0x0 FNV_64_PRIME_LOW
697 */
698 /* multiply by the lowest order digit base 2^16 */
699 tmp[0] = val[0] * FNV_64_PRIME_LOW;
700 tmp[1] = val[1] * FNV_64_PRIME_LOW;
701 tmp[2] = val[2] * FNV_64_PRIME_LOW;
702 tmp[3] = val[3] * FNV_64_PRIME_LOW;
703 /* multiply by the other non-zero digit */
704 tmp[2] += val[0] << FNV_64_PRIME_SHIFT; /* tmp[2] += val[0] * 0x100 */
705 tmp[3] += val[1] << FNV_64_PRIME_SHIFT; /* tmp[3] += val[1] * 0x100 */
706 /* propagate carries */
707 tmp[1] += (tmp[0] >> 16);
708 val[0] = tmp[0] & 0xffff;
709 tmp[2] += (tmp[1] >> 16);
710 val[1] = tmp[1] & 0xffff;
711 val[3] = tmp[3] + (tmp[2] >> 16);
712 val[2] = tmp[2] & 0xffff;
713 /*
714 * Doing a val[3] &= 0xffff; is not really needed since it simply
715 * removes multiples of 2^64. We can discard these excess bits
716 * outside of the loop when we convert to Fnv64_t.
717 */
718 val[0] ^= (unsigned long)(*s++);
719 }
720
721 /*
722 * Convert base 2^16 array back into an Fnv64_t
723 */
724 hval.w32[1] = ((val[3]<<16) | val[2]);
725 hval.w32[0] = ((val[1]<<16) | val[0]);
726
727#endif /* !HAVE_64BIT_LONG_LONG */
728
729 /* return our new hash value */
730 return hval;
731}
732
733/* End hash_64a.c -------------------------------------> */
734
735 // clang-format on
736 // NOLINTEND
737
738} /* extern "C" */
739
740//-----------------------------------------------------------------------------
741
742/**@}*/ // \defgroup hash_fnv
743
744} // namespace Fnv1aImplementation
745
747{
748 clear();
749}
750
752Fnv1a::GetHash32(const char* buffer, const std::size_t size)
753{
754 m_hash32 = Fnv1aImplementation::fnv_32a_buf((void*)buffer, size, m_hash32);
755 return m_hash32;
756}
757
758uint64_t
759Fnv1a::GetHash64(const char* buffer, const std::size_t size)
760{
761 m_hash64 = Fnv1aImplementation::fnv_64a_buf((void*)buffer, size, m_hash64);
762 return m_hash64;
763}
764
765void
771
772} // namespace Function
773
774} // namespace Hash
775
776} // namespace ns3
uint32_t m_hash32
Cache last hash value, for incremental hashing.
Definition hash-fnv.h:94
uint32_t GetHash32(const char *buffer, const size_t size) override
Compute 32-bit hash of a byte buffer.
Definition hash-fnv.cc:752
uint64_t GetHash64(const char *buffer, const size_t size) override
Compute 64-bit hash of a byte buffer.
Definition hash-fnv.cc:759
uint64_t m_hash64
Cache last hash value, for incremental hashing.
Definition hash-fnv.h:95
void clear() override
Restore initial state.
Definition hash-fnv.cc:766
uint64_t Fnv64_t
64 bit FNV-0 hash
Definition hash-fnv.cc:200
#define FNV1A_64_INIT
64 bit FNV-1 non-zero initial basis
Definition hash-fnv.cc:238
#define FNV1_32A_INIT
32 bit FNV-1 and FNV-1a non-zero initial basis
Definition hash-fnv.cc:185
Fnv32_t fnv_32_str(char *str, Fnv32_t hval)
fnv_32a_str - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a string
Fnv64_t fnv_64_str(char *str, Fnv64_t hval)
fnv_64a_str - perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
Fnv32_t fnv_32a_str(char *buf, Fnv32_t hashval)
fnv_32a_str - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a string
Definition hash-fnv.cc:413
#define FNV_64_PRIME
FNV-1a defines the initial basis to be non-zero.
Definition hash-fnv.cc:515
uint32_t Fnv32_t
32 bit FNV-0 hash type
Definition hash-fnv.cc:157
Fnv64_t fnv_64_buf(void *buf, size_t len, Fnv64_t hval)
fnv_64a_buf - perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
Fnv64_t fnv_64a_str(char *buf, Fnv64_t hashval)
fnv_64a_str - perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
Definition hash-fnv.cc:642
Fnv32_t fnv_32_buf(void *buf, size_t len, Fnv32_t hval)
fnv_32a_buf - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a buffer
#define FNV_32_PRIME
32 bit magic FNV-1a prime
Definition hash-fnv.cc:357
Fnv32_t fnv_32a_buf(void *buf, size_t len, Fnv32_t hashval)
fnv_32a_buf - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a buffer
Definition hash-fnv.cc:374
Fnv64_t fnv_64a_buf(void *buf, size_t len, Fnv64_t hashval)
fnv_64a_buf - perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
Definition hash-fnv.cc:537
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
ns3::Hash::Function::Fnv1a declaration.
Debug message logging.
Every class exported by the ns3 library is enclosed in the ns3 namespace.