rfc9923v1.txt   rfc9923.txt 
skipping to change at line 181 skipping to change at line 181
* the "calc" C-style calculator [calc], * the "calc" C-style calculator [calc],
* netnews history file Message-ID lookup functions, * netnews history file Message-ID lookup functions,
* [FRET] - a tool to identify file data structures / help understand * [FRET] - a tool to identify file data structures / help understand
file formats, file formats,
* anti-spam filters, * anti-spam filters,
* used in an implementation of libketama for use in items such as * used in an implementation of libketama [libketama] for use in
[memcache], items such as [memcache],
* a spellchecker programmed in Ada 95, * a spellchecker programmed in Ada 95,
* used in the BSD IDE project [fasmlab], * used in the BSD Integrated Development Environments (IDE) project
[fasmlab],
* non-cryptographic file fingerprints, * non-cryptographic file fingerprints,
* used in the deliantra game server for its shared string * used in the deliantra game server for its shared string
implementation [deliantra], implementation [deliantra],
* computing Unique IDs in DASM (DTN (Delay Tolerant Networking) * computing Unique IDs in DASM (DTN (Delay Tolerant Networking)
Applications for Symbian Mobile-phones), Applications for Symbian Mobile-phones),
* Microsoft's hash_map implementation for VC++ 2005, * Microsoft's hash_map implementation for VC++ 2005,
* the realpath cache in PHP 5.x (php-5.2.3/TSRM/tsrm_virtual_cwd.c), * the realpath cache in PHP 5.x (php-5.2.3/TSRM/tsrm_virtual_cwd.c),
* DNS (Domain Name System) servers, * DNS (Domain Name System) servers,
* used to improve [Leprechaun], an extremely fast wordlist creator, * used to improve [Leprechaun], an extremely fast wordlist creator,
* the Vely framework [Vely] for the C language, * the Smash utility [Smash] for rapidly finding duplicate files,
* Golf language hash tables [GolfHash], * Golf language hash tables [RimStone],
* the libsir logging library [libsir], * the libsir logging library [libsir],
* a standard library for modern Fortran [Fortran], * a standard library for modern Fortran [Fortran],
* to help with seeding a pseudorandom number generator [Vortetty],
and many other uses. It is also referenced in the following and many other uses. It is also referenced in the following
standards documents: [RFC7357], [RFC7873], and [IEEE8021Qbp]. standards documents: [RFC7357], [RFC7873], and [IEEE8021Q-2022].
A study has recommended FNV in connection with the IPv6 Flow Label A study has recommended FNV in connection with the IPv6 flow label
field [IPv6flow]. Additionally, there was a proposal to use FNV for value [IPv6flow]. Additionally, there was a proposal to use FNV for
BFD sequence number generation [ISAAC-Auth] and a recent article and Bidirectional Forwarding Detection (BFD) sequence number generation
study on non-cryptographic hash functions [NCHF]. [BFDseq]. [NCHF] discusses criteria for evaluating non-cryptographic
hash functions.
If you use an FNV function in an application, you are kindly If you use an FNV function in an application, you are kindly
requested to send an email about it to <fnvhash-mail@asthe.com> with requested to send an email about it to <fnvhash-mail@asthe.com> with
"FNV hash function" forming part of the subject line. "FNV hash function" forming part of the subject line.
1.4. Why Is FNV Non-Cryptographic? 1.4. Why Is FNV Non-Cryptographic?
A full discussion of cryptographic hash requirements and strength is A full discussion of cryptographic hash requirements and strength is
beyond the scope of this document. However, here are three beyond the scope of this document. However, here are three
characteristics of FNV that would generally be considered to make it characteristics of FNV that would generally be considered to make it
skipping to change at line 279 skipping to change at line 279
practice for the many non-cryptographic applications of FNV (see practice for the many non-cryptographic applications of FNV (see
Section 1.3). Section 1.3).
2. FNV Basics 2. FNV Basics
This document focuses on the FNV-1a function, whose pseudocode is as This document focuses on the FNV-1a function, whose pseudocode is as
follows: follows:
hash = offset_basis hash = offset_basis
for each octet_of_data to be hashed for each octet_of_data to be hashed
hash = hash xor octet_of_data hash = hash XOR octet_of_data
hash = hash * FNV_Prime mod 2**HashSize hash = hash * FNV_Prime mod 2**HashSize
return hash return hash
In the pseudocode above, hash is a power-of-2 number of bits In the pseudocode above, hash is a power-of-2 number of bits
(HashSize is 32, 64, 128, 256, 512, or 1024), and offset_basis and (HashSize is 32, 64, 128, 256, 512, or 1024), and offset_basis and
FNV_Prime depend on the size of hash. FNV_Prime depend on the size of hash.
The FNV-1 algorithm is the same, including the values of offset_basis The FNV-1 algorithm is the same, including the values of offset_basis
and FNV_Prime, except that the order of the two lines with the "xor" and FNV_Prime, except that the order of the two lines with the "XOR"
and multiply operations is reversed. Operational experience and multiply operations is reversed. Operational experience
indicates better hash dispersion for small amounts of data with FNV- indicates better hash dispersion for small amounts of data with FNV-
1a. FNV-0 is the same as FNV-1 but with offset_basis set to zero. 1a. FNV-0 is the same as FNV-1 but with offset_basis set to zero.
FNV-1a is suggested for general use. FNV-1a is suggested for general use.
2.1. FNV Primes 2.1. FNV Primes
The theory behind FNV_Primes is beyond the scope of this document, The theory behind FNV_Primes is beyond the scope of this document,
but the basic property to look for is how an FNV_Prime would impact but the basic property to look for is how an FNV_Prime would impact
dispersion. Now, consider any n-bit FNV hash where n >= 32 and is dispersion. Now, consider any n-bit FNV hash where n >= 32 and is
skipping to change at line 311 skipping to change at line 311
* When s is an integer and 4 < s < 11, FNV_Prime is the smallest * When s is an integer and 4 < s < 11, FNV_Prime is the smallest
prime p of the form: prime p of the form:
256**int((5 + 2**s)/12) + 2**8 + b 256**int((5 + 2**s)/12) + 2**8 + b
* where b is an integer such that: * where b is an integer such that:
0 < b < 2**8 0 < b < 2**8
* The number of one-bits in b is four or five * The number of one bits in b is four or five
* and where * and where
( p mod (2**40 - 2**24 - 1) ) > ( 2**24 + 2**8 + 2**7 ) ( p mod (2**40 - 2**24 - 1) ) > ( 2**24 + 2**8 + 2**7 )
Experimentally, FNV_Primes matching the above constraints tend to Experimentally, FNV_Primes matching the above constraints tend to
have better dispersion properties. They improve the polynomial have better dispersion properties. They improve the polynomial
feedback characteristic when an FNV_Prime multiplies an intermediate feedback characteristic when an FNV_Prime multiplies an intermediate
hash value. As such, the hash values produced are more scattered hash value. As such, the hash values produced are more scattered
throughout the n-bit hash space. throughout the n-bit hash space.
The case where s < 5 is not considered due to the resulting low hash The case where s < 5 is not considered due to the resulting low hash
quality. Such small hashes can, if desired, be derived from a 32-bit quality. Such small hashes can, if desired, be derived from a 32-bit
FNV hash by XOR folding (see Section 3). The case where s > 10 is FNV hash by XOR folding (see Section 3). The case where s > 10 is
not considered because of the doubtful utility of such large FNV not considered because of the doubtful utility of such large FNV
hashes and because the criteria for such large FNV_Primes is more hashes and because the criteria for such large FNV_Primes would be
complex, due to the sparsity of such large primes, and would more complex, due to the sparsity of such large primes, and would
needlessly clutter the criteria given above. needlessly clutter the criteria given above.
Per the above constraints, an FNV_Prime should have only six or seven Per the above constraints, an FNV_Prime should have only six or seven
one-bits in it: one relatively high-order one bit, the 2**9 bit, and one bits in it: one relatively high-order one bit, the 2**9 bit, and
four or five one bits in the low-order byte. Therefore, some four or five one bits in the low-order byte. Therefore, some
compilers may seek to improve the performance of a multiplication compilers may seek to improve the performance of a multiplication
with an FNV_Prime by replacing the multiplication with shifts and with an FNV_Prime by replacing the multiplication with shifts and
adds. However, the performance of this substitution is highly adds. However, the performance of this substitution is highly
hardware dependent and should be done with care. The selection of hardware dependent and should be done with care. The selection of
FNV_Primes prioritizes the quality of the resulting hash function, FNV_Primes prioritizes the quality of the resulting hash function,
not compiler optimization considerations. not compiler optimization considerations.
2.2. FNV offset_basis 2.2. FNV offset_basis
skipping to change at line 359 skipping to change at line 359
or, in C notation [C], the following string: or, in C notation [C], the following string:
"chongo <Landon Curt Noll> /\\../\\" "chongo <Landon Curt Noll> /\\../\\"
In the general case, almost any offset_basis would serve as long as In the general case, almost any offset_basis would serve as long as
it is non-zero. However, FNV hashes calculated with different it is non-zero. However, FNV hashes calculated with different
offset_basis values will not interoperate. The choice of a non- offset_basis values will not interoperate. The choice of a non-
standard offset_basis may be beneficial in some limited circumstances standard offset_basis may be beneficial in some limited circumstances
to defend against attacks that try to induce hash collisions as to defend against attacks that try to induce hash collisions as
discussed in Section 6.1. Any entity that can observe the FNV hash discussed in Section 6.1. Any entity that can observe the FNV hash
output, and can cause the null string (the string of length zero) to output and can cause the null string (the string of length zero) to
be hashed, will thereby be able to directly observe the offset_basis be hashed will thereby be able to directly observe the offset_basis
which will be the hash output. which will be the hash output.
2.3. FNV Endianism 2.3. FNV Endianism
For persistent storage or interoperability between different hardware For persistent storage or interoperability between different hardware
platforms, an FNV hash shall be represented in the little endian platforms, an FNV hash shall be represented in the little-endian
format [IEN137]. That is, the FNV hash will be stored in an array format [IEN137]. That is, the FNV hash will be stored in an array
hash[N] with N bytes such that its integer value can be retrieved as hash[N] with N bytes such that its integer value can be retrieved as
follows: follows:
unsigned char hash[N]; unsigned char hash[N];
for ( i = N-1, value = 0; i >= 0; --i ) for ( i = N-1, value = 0; i >= 0; --i )
value = ( value << 8 ) + hash[i]; value = ( value << 8 ) + hash[i];
However, when FNV hashes are used in a single process or a group of However, when FNV hashes are used in a single process or a group of
processes sharing memory on processors with compatible endianness, processes sharing memory on processors with compatible endianness,
the natural endianness of those processors can be used, as long as it the natural endianness of those processors can be used, as long as it
is used consistently, regardless of its type -- little, big, or some is used consistently, regardless of its type -- little, big, or some
other exotic form. other exotic form.
The code provided in Section 6 has FNV hash functions that return a The code provided in Section 8 has FNV hash functions that return a
little endian byte vector for all lengths. Because they are more little-endian byte vector for all lengths. Because they are more
efficient, the code also provides functions that return FNV hashes as efficient, the code also provides functions that return FNV hashes as
32-bit integers or, where supported, 64-bit integers, for those sizes 32-bit integers or, where supported, 64-bit integers, for those sizes
of FNV hash. Such integers are compatible with the same-size byte of FNV hash. Such integers are compatible with the same-size byte
vectors on little endian computers, but the use of the functions vectors on little-endian computers, but the use of the functions
returning integers on big endian or other non-little-endian machines returning integers on big-endian or other non-little-endian machines
will be byte-reversed or otherwise incompatible with the byte vector will be byte-reversed or otherwise incompatible with the byte vector
return values. return values.
3. Other Hash Sizes and XOR Folding 3. Other Hash Sizes and XOR Folding
Many hash uses require a hash that is not one of the FNV sizes for Many hash uses require a hash that is not one of the FNV sizes for
which constants are provided in Section 5. If a larger hash size is which constants are provided in Section 5. If a larger hash size is
needed, please contact the authors of this document. needed, please contact the authors of this document.
For scenarios where a fixed-size binary field of k bits is desired For scenarios where a fixed-size binary field of k bits is desired
with k < 1024 but not among the constants provided in Section 5, the with k < 1024 but not among the constants provided in Section 5, the
recommended approach involves using the smallest FNV hash of size S recommended approach involves using the smallest FNV hash of size S
where S > k and employing xor folding, as shown below. The final where S > k and employing XOR folding, as shown below. The final
bit-masking operation is logically unnecessary if the size of the bit-masking operation is logically unnecessary if the size of the
variable k-bit-hash is exactly k bits. variable k-bit-hash is exactly k bits.
temp = FNV_S ( data-to-be-hashed ) temp = FNV_S ( data-to-be-hashed )
k-bit-hash = ( temp xor temp>>k ) bitwise-and ( 2**k - 1 ) k-bit-hash = ( temp XOR temp>>k ) bitwise-and ( 2**k - 1 )
A somewhat stronger hash may be obtained for exact FNV sizes by A somewhat stronger hash may be obtained for exact FNV sizes by
calculating an FNV twice as long as the desired output ( S = 2*k ) calculating an FNV twice as long as the desired output ( S = 2*k )
and performing such xor data folding using a k equal to the size of and performing such XOR data folding using a k equal to the size of
the desired output. However, if a much stronger hash is desired, the desired output. However, if a much stronger hash is desired,
cryptographic algorithms, such as those specified in [FIPS202] or cryptographic algorithms, such as those specified in [FIPS202] or
[RFC6234], should be used. [RFC6234], should be used.
If it is desired to obtain a hash result that is a value between 0 If it is desired to obtain a hash result that is a value between 0
and max, where max+1 is not a power of 2, simply choose an FNV hash and max, where max+1 is not a power of 2, simply choose an FNV hash
size S such that 2**S > max. Then, calculate the following: size S such that 2**S > max. Then, calculate the following:
FNV_S mod ( max+1 ) FNV_S mod ( max+1 )
skipping to change at line 449 skipping to change at line 449
where the vertical bar character ("|") represents string where the vertical bar character ("|") represents string
concatenation. If the components being combined are of variable concatenation. If the components being combined are of variable
length, some information is lost by simple concatenation. For length, some information is lost by simple concatenation. For
example, X = "12" and Y = "345" would not be distinguished from X = example, X = "12" and Y = "345" would not be distinguished from X =
"123" and Y = "45". To preserve that information, each component "123" and Y = "45". To preserve that information, each component
should be preceded by an encoding of its length or should end with should be preceded by an encoding of its length or should end with
some sequence that cannot occur within the component, or some similar some sequence that cannot occur within the component, or some similar
technique should be used. technique should be used.
For FNV, the same hash results if X, Y, and Z are actually For FNV, the same hash results if 1) X, Y, and Z are actually
concatenated and the FNV hash applied to the resulting string or if concatenated and the FNV hash is applied to the resulting string or
FNV is calculated on an initial substring and the result used as the 2) FNV is calculated on an initial substring and the result is used
offset_basis when calculating the FNV hash of the remainder of the as the offset_basis when calculating the FNV hash of the remainder of
string. This can be done several times. Assuming that the string. This can be done several times. Assuming that
FNVoffset_basis ( v, w ) is the FNV of w using v as the offset_basis, FNVoffset_basis ( v, w ) is the FNV of w using v as the offset_basis,
then in the example above, fnvx = FNV ( X ) could be calculated and then in the example above, fnvx = FNV ( X ) could be calculated and
then fnvxy = FNVoffset_basis ( fnvx, Y ), and finally fnvxyz = then fnvxy = FNVoffset_basis ( fnvx, Y ), and finally fnvxyz =
FNVoffset_basis ( fnvxy, Z ). The resulting fnvxyz would be the same FNVoffset_basis ( fnvxy, Z ). The resulting fnvxyz would be the same
as FNV ( X | Y | Z ). as FNV ( X | Y | Z ).
This means that if you have the value of FNV ( X ) and you want to This means that if you have the value of FNV ( X ) and you want to
calculate FNV ( X | Y ), you do not need to find X. You can simply calculate FNV ( X | Y ), you do not need to find X. You can simply
calculate FNVoffset_basis ( FNV ( X ), Y ) and thereby get FNV ( X | calculate FNVoffset_basis ( FNV ( X ), Y ) and thereby get FNV ( X |
Y ). Y ).
Sometimes, such a hash needs to be repeatedly calculated; the Sometimes, such a hash needs to be repeatedly calculated; the
component values vary, but some vary more frequently than others. component values vary, but some vary more frequently than others.
For example, assume that some sort of computer network traffic flow For example, assume that some sort of computer network traffic flow
ID, such as the IPv6 flow ID [RFC6437], is to be calculated for ID, such as the IPv6 Flow Label [RFC6437], is to be calculated for
network packets based on the source and destination IPv6 addresses network packets based on the source and destination IPv6 addresses
and the Traffic Class [RFC8200]. If the Flow ID is calculated in the and the Traffic Class [RFC8200]. If the Flow Label is calculated in
originating host, the source IPv6 address would likely always be the the originating host, the source IPv6 address would likely always be
same or would perhaps assume one of a very small number of values. the same or would perhaps assume one of a very small number of
By placing this quasi-constant IPv6 source address first in the values. By placing this quasi-constant IPv6 source address first in
string being FNV-hashed, FNV ( IPv6source ) could be calculated and the string being FNV-hashed, FNV ( IPv6source ) could be calculated
used as the offset_basis for calculating the FNV of the IPv6 and used as the offset_basis for calculating the FNV of the IPv6
destination address and Traffic Class for each packet. As a result, destination address and Traffic Class for each packet. As a result,
the per-packet hash would be over 17 bytes rather than over 33 bytes, the per-packet hash would be over 17 bytes rather than over 33 bytes,
saving computational resources. The source code in this document saving computational resources. The source code in this document
includes functions facilitating the use of a non-standard includes functions facilitating the use of a non-standard
offset_basis. offset_basis.
An alternative method of hashing multiple values is to concatenate An alternative method of hashing multiple values is to concatenate
the hashes of those values and then hash the concatenation -- that the hashes of those values and then hash the concatenation -- that
is, compute something like is, compute something like
skipping to change at line 774 skipping to change at line 774
replacing "xxx" with "64INT". Versions providing an integer hash replacing "xxx" with "64INT". Versions providing an integer hash
will not be compatible between systems of different endianness (see will not be compatible between systems of different endianness (see
Section 2.3). Section 2.3).
If you want to copy the source code from this document, note that it If you want to copy the source code from this document, note that it
is indented by three spaces in the ".txt" version. It may be is indented by three spaces in the ".txt" version. It may be
simplest to copy from the ".html" version of this document. simplest to copy from the ".html" version of this document.
FNVxxxstring, FNVxxxblock, FNVxxxfile: FNVxxxstring, FNVxxxblock, FNVxxxfile:
FNVxxxstringBase, FNVxxxblockBase, FNVxxxfileBase: FNVxxxstringBasis, FNVxxxblockBasis, FNVxxxfileBasis:
FNVxxxINTstring, FNVxxxINTblock, FNVxxxINTfile: FNVxxxINTstring, FNVxxxINTblock, FNVxxxINTfile:
FNVxxxINTstringBase, FNVxxxINTblockBase, FNVxxxINTfileBase: These FNVxxxINTstringBasis, FNVxxxINTblockBasis, FNVxxxINTfileBasis: These
are simple functions for directly returning the FNV hash of a are simple functions for directly returning the FNV hash of a
zero-terminated byte string not including that zero byte, the FNV zero-terminated byte string not including that zero byte, the FNV
hash of a counted block of bytes, and the FNV of a file, hash of a counted block of bytes, and the FNV of a file,
respectively. The functions whose names have the "Base" suffix respectively. The functions whose names have the "Basis" suffix
take an additional parameter specifying the offset_basis. Note take an additional parameter specifying the offset_basis. Note
that for applications of FNV-32 and of FNV-64 where integers of that for applications of FNV-32 and of FNV-64 where integers of
that size are supported and an integer data type output is that size are supported and an integer data type output is
acceptable, the code is sufficiently simple that, to maximize acceptable, the code is sufficiently simple that, to maximize
performance, the use of open coding or macros may be more performance, the use of open coding or macros may be more
appropriate than calling a subroutine. appropriate than calling a subroutine.
FNVxxxinit, FNVxxxinitBasis: FNVxxxinit, FNVxxxinitBasis:
FNVxxxINTinitBasis: These functions and the next two sets of FNVxxxINTinitBasis: These functions and the next two sets of
skipping to change at line 819 skipping to change at line 819
hash result from an FNVxxxcontext. hash result from an FNVxxxcontext.
8.1.2. Source Files and 64-Bit Support 8.1.2. Source Files and 64-Bit Support
Code optimized for 64-bit integer support -- that is, support of Code optimized for 64-bit integer support -- that is, support of
64-bit integer addition and 32-bit x 32-bit multiplication producing 64-bit integer addition and 32-bit x 32-bit multiplication producing
a 64-bit product -- is provided based on whether or not the a 64-bit product -- is provided based on whether or not the
FNV_64bitIntegers symbol is defined. By default, this is set in FNV_64bitIntegers symbol is defined. By default, this is set in
FNVconfig.h based on the compilation target; however, this can be FNVconfig.h based on the compilation target; however, this can be
overridden by editing that file or by defining certain symbols in, overridden by editing that file or by defining certain symbols in,
for example, a command line invoking compilation. for example, a command line invoking a compilation.
For support of a single FNV size, say "xxx" (e.g., FNV64), in an For support of a single FNV size, say "xxx" (e.g., FNV64), in an
application, the application itself needs to include the appropriate application, the application itself needs to include the appropriate
FNVxxx.h file (which will, in turn, include the FNVconfig.h and FNVxxx.h file (which will, in turn, include the FNVconfig.h and
FNVErrorCodes.h files). To build the particular FNVxxx code itself, FNVErrorCodes.h files). To build the particular FNVxxx code itself,
compile the FNVxxx.c file with FNVconfig.h, fnv-private.h, compile the FNVxxx.c file with FNVconfig.h, fnv-private.h,
FNVErrorCodes.h, and FNVxxx.h (available in Section 8.2). Since the FNVErrorCodes.h, and FNVxxx.h (available to the compiler while
test program provided in Section 8.3 uses all sizes of FNV, all the compiling the FNVxxx.c file; see Section 8.2). Since the test
.c and .h files are needed to compile it. program provided in Section 8.3 uses all sizes of FNV, all the .c and
.h files are needed to compile it.
8.1.3. Command Line Interface 8.1.3. Command Line Interface
The test program provided in Section 8.3 has a command line The test program provided in Section 8.3 has a command line
interface. By default, with no command line arguments, it runs tests interface. By default, with no command line arguments, it runs tests
of all FNV lengths. Command line options are as follows: of all FNV lengths. Command line options are as follows:
FNVhash [-a] [-h] [-t nnn] [-u nnn] [-v] [-f filename] [token ...] FNVhash [-a] [-h] [-t nnn] [-u nnn] [-v] [-f filename] [token ...]
The option letters have the following meanings: The option letters have the following meanings:
skipping to change at line 1095 skipping to change at line 1096
int Computed; /* state */ int Computed; /* state */
uint32_t Hash; uint32_t Hash;
} FNV32context; } FNV32context;
/* Function Prototypes: /* Function Prototypes:
* *
* FNV32string: hash a zero-terminated string not including * FNV32string: hash a zero-terminated string not including
* the terminating zero * the terminating zero
* FNV32stringBasis: also takes an offset_basis parameter * FNV32stringBasis: also takes an offset_basis parameter
* *
* FNV32block: hash a specified length byte vector * FNV32block: hash a byte vector of a specified length
* FNV32blockBasis: also takes an offset_basis parameter * FNV32blockBasis: also takes an offset_basis parameter
* *
* FNV32file: hash the contents of a file * FNV32file: hash the contents of a file
* FNV32fileBasis: also takes an offset_basis parameter * FNV32fileBasis: also takes an offset_basis parameter
* *
* FNV32init: initializes an FNV32 context * FNV32init: initializes an FNV32 context
* FNV32initBasis: initializes an FNV32 context with a * FNV32initBasis: initializes an FNV32 context with a
* provided 4-byte vector basis * provided 4-byte vector basis
* FNV32blockin: hash in a specified length byte vector * FNV32blockin: hash in a byte vector of a specified length
* FNV32stringin: hash in a zero-terminated string not * FNV32stringin: hash in a zero-terminated string not
* including the terminating zero * including the terminating zero
* FNV32filein: hash in the contents of a file * FNV32filein: hash in the contents of a file
* FNV32result: returns the hash value * FNV32result: returns the hash value
* *
* Hash is returned as a 4-byte vector by the functions above, * Hash is returned as a 4-byte vector by the functions above,
* and the following return a 32-bit unsigned integer: * and the following return a 32-bit unsigned integer:
* *
* FNV32INTstring: hash a zero-terminated string not including * FNV32INTstring: hash a zero-terminated string not including
* the terminating zero * the terminating zero
* FNV32INTstringBasis: also takes an offset_basis parameter * FNV32INTstringBasis: also takes an offset_basis parameter
* *
* FNV32INTblock: hash a specified length byte vector * FNV32INTblock: hash a byte vector of a specified length
* FNV32INTblockBasis: also takes an offset_basis parameter * FNV32INTblockBasis: also takes an offset_basis parameter
* *
* FNV32INTfile: hash the contents of a file * FNV32INTfile: hash the contents of a file
* FNV32INTfileBasis: also takes an offset_basis parameter * FNV32INTfileBasis: also takes an offset_basis parameter
* *
* FNV32INTinitBasis: initializes an FNV32 context with a * FNV32INTinitBasis: initializes an FNV32 context with a
* provided 32-bit integer basis * provided 32-bit integer basis
* FNV32INTresult: returns the hash value * FNV32INTresult: returns the hash value
*/ */
skipping to change at line 1211 skipping to change at line 1212
*/ */
#include <stdio.h> #include <stdio.h>
#include "fnv-private.h" #include "fnv-private.h"
#include "FNV32.h" #include "FNV32.h"
/* 32-bit FNV_prime = 2^24 + 2^8 + 0x93 */ /* 32-bit FNV_prime = 2^24 + 2^8 + 0x93 */
#define FNV32prime 0x01000193 #define FNV32prime 0x01000193
/* FNV32 hash a zero-terminated string not including the zero /* FNV32: hash a zero-terminated string not including the zero
*****************************************************************/ *****************************************************************/
int FNV32INTstring ( const char *in, uint32_t * const out ) { int FNV32INTstring ( const char *in, uint32_t * const out ) {
return FNV32INTstringBasis ( in, out, FNV32basis ); return FNV32INTstringBasis ( in, out, FNV32basis );
} /* end FNV32INTstring */ } /* end FNV32INTstring */
/* FNV32 hash a zero-terminated string not including the zero /* FNV32: hash a zero-terminated string not including the zero
* with a non-standard basis * with a non-standard basis
*****************************************************************/ *****************************************************************/
int FNV32INTstringBasis ( const char *in, int FNV32INTstringBasis ( const char *in,
uint32_t * const out, uint32_t * const out,
uint32_t basis ) { uint32_t basis ) {
uint8_t ch; uint8_t ch;
if ( !in || !out ) if ( !in || !out )
return fnvNull; /* Null input pointer */ return fnvNull; /* Null input pointer */
while ( (ch = *in++) ) while ( (ch = *in++) )
basis = FNV32prime * ( basis ^ ch ); basis = FNV32prime * ( basis ^ ch );
*out = basis; *out = basis;
return fnvSuccess; return fnvSuccess;
} /* end FNV32INTstringBasis */ } /* end FNV32INTstringBasis */
/* FNV32 hash a zero-terminated string not including the zero /* FNV32: hash a zero-terminated string not including the zero
*****************************************************************/ *****************************************************************/
int FNV32string ( const char *in, uint8_t out[FNV32size] ) { int FNV32string ( const char *in, uint8_t out[FNV32size] ) {
uint32_t temp; uint32_t temp;
uint8_t ch; uint8_t ch;
if ( !in || !out ) if ( !in || !out )
return fnvNull; /* Null input pointer */ return fnvNull; /* Null input pointer */
temp = FNV32basis; temp = FNV32basis;
while ( (ch = *in++) ) while ( (ch = *in++) )
temp = FNV32prime * ( temp ^ ch ); temp = FNV32prime * ( temp ^ ch );
for ( int i=0; i<FNV32size; ++i ) for ( int i=0; i<FNV32size; ++i )
out[i] = ((uint8_t *)&temp)[i]; out[i] = ((uint8_t *)&temp)[i];
return fnvSuccess; return fnvSuccess;
} /* end FNV32string */ } /* end FNV32string */
/* FNV32 hash a zero-terminated string not including the zero /* FNV32: hash a zero-terminated string not including the zero
* with a non-standard basis * with a non-standard basis
*****************************************************************/ *****************************************************************/
int FNV32stringBasis ( const char *in, int FNV32stringBasis ( const char *in,
uint8_t out[FNV32size], uint8_t out[FNV32size],
const uint8_t basis[FNV32size] ) { const uint8_t basis[FNV32size] ) {
uint32_t temp; uint32_t temp;
int i; int i;
uint8_t ch; uint8_t ch;
if ( !in || !out || !basis ) if ( !in || !out || !basis )
skipping to change at line 1272 skipping to change at line 1273
while ( (ch = *in++) ) while ( (ch = *in++) )
temp = FNV32prime * ( temp ^ ch ); temp = FNV32prime * ( temp ^ ch );
out[0] = temp & 0xFF; out[0] = temp & 0xFF;
for ( i=1; i<FNV32size; ++i ) { for ( i=1; i<FNV32size; ++i ) {
temp >>= 8; temp >>= 8;
out[i] = temp & 0xFF; out[i] = temp & 0xFF;
} }
return fnvSuccess; return fnvSuccess;
} /* end FNV32stringBasis */ } /* end FNV32stringBasis */
/* FNV32 hash a counted block returning an integer /* FNV32: hash a counted block returning an integer
****************************************************************/ ****************************************************************/
int FNV32INTblock ( const void *vin, int FNV32INTblock ( const void *vin,
long int length, long int length,
uint32_t * const out ) { uint32_t * const out ) {
return FNV32INTblockBasis ( vin, length, out, FNV32basis ); return FNV32INTblockBasis ( vin, length, out, FNV32basis );
} /* end FNV32INTblock */ } /* end FNV32INTblock */
/* FNV32 hash a counted block with a non-standard basis /* FNV32: hash a counted block with a non-standard basis
****************************************************************/ ****************************************************************/
int FNV32INTblockBasis ( const void *vin, int FNV32INTblockBasis ( const void *vin,
long int length, long int length,
uint32_t * const out, uint32_t * const out,
uint32_t basis ) { uint32_t basis ) {
const uint8_t *in = (const uint8_t*)vin; const uint8_t *in = (const uint8_t*)vin;
uint32_t temp; uint32_t temp;
if ( !in || !out ) if ( !in || !out )
return fnvNull; /* Null input pointer */ return fnvNull; /* Null input pointer */
if ( length < 0 ) if ( length < 0 )
return fnvBadParam; return fnvBadParam;
for ( temp = basis; length > 0; length-- ) for ( temp = basis; length > 0; length-- )
temp = FNV32prime * ( temp ^ *in++ ); temp = FNV32prime * ( temp ^ *in++ );
*out = temp; *out = temp;
return fnvSuccess; return fnvSuccess;
} /* end FNV32INTblockBasis */ } /* end FNV32INTblockBasis */
/* FNV32 hash a counted block returning a 4-byte vector /* FNV32: hash a counted block returning a 4-byte vector
****************************************************************/ ****************************************************************/
int FNV32block ( const void *vin, int FNV32block ( const void *vin,
long int length, long int length,
uint8_t out[FNV32size] ) { uint8_t out[FNV32size] ) {
const uint8_t *in = (const uint8_t*)vin; const uint8_t *in = (const uint8_t*)vin;
uint32_t temp; uint32_t temp;
if ( !in || !out ) if ( !in || !out )
return fnvNull; /* Null input pointer */ return fnvNull; /* Null input pointer */
if ( length < 0 ) if ( length < 0 )
return fnvBadParam; return fnvBadParam;
for ( temp = FNV32basis; length > 0; length-- ) for ( temp = FNV32basis; length > 0; length-- )
temp = FNV32prime * ( temp ^ *in++ ); temp = FNV32prime * ( temp ^ *in++ );
for ( int i=0; i<FNV32size; ++i ) for ( int i=0; i<FNV32size; ++i )
out[i] = ((uint8_t *)&temp)[i]; out[i] = ((uint8_t *)&temp)[i];
return fnvSuccess; return fnvSuccess;
} /* end FNV32block */ } /* end FNV32block */
/* FNV32 hash a counted block with a non-standard basis /* FNV32: hash a counted block with a non-standard basis
****************************************************************/ ****************************************************************/
int FNV32blockBasis ( const void *vin, int FNV32blockBasis ( const void *vin,
long int length, long int length,
uint8_t out[FNV32size], uint8_t out[FNV32size],
const uint8_t basis[FNV32size] ) { const uint8_t basis[FNV32size] ) {
const uint8_t *in = (const uint8_t*)vin; const uint8_t *in = (const uint8_t*)vin;
uint32_t temp; uint32_t temp;
if ( !in || !out || !basis ) if ( !in || !out || !basis )
return fnvNull; /* Null input pointer */ return fnvNull; /* Null input pointer */
skipping to change at line 1617 skipping to change at line 1618
} FNV64context; } FNV64context;
#endif /* FNV_64bitIntegers */ #endif /* FNV_64bitIntegers */
/* Function Prototypes: /* Function Prototypes:
* *
* FNV64string: hash a zero-terminated string not including * FNV64string: hash a zero-terminated string not including
* the terminating zero * the terminating zero
* FNV64stringBasis: also takes an offset_basis parameter * FNV64stringBasis: also takes an offset_basis parameter
* *
* FNV64block: hash a specified length byte vector * FNV64block: hash a byte vector of a specified length
* FNV64blockBasis: also takes an offset_basis parameter * FNV64blockBasis: also takes an offset_basis parameter
* *
* FNV64file: hash the contents of a file * FNV64file: hash the contents of a file
* FNV128fileBasis: also takes an offset_basis parameter * FNV64fileBasis: also takes an offset_basis parameter
* *
* FNV64init: initializes an FNV64 context * FNV64init: initializes an FNV64 context
* FNV64initBasis: initializes an FNV64 context with a * FNV64initBasis: initializes an FNV64 context with a
* provided 8-byte vector basis * provided 8-byte vector basis
* FNV64blockin: hash in a specified length byte vector * FNV64blockin: hash in a byte vector of a specified length
* FNV64stringin: hash in a zero-terminated string not * FNV64stringin: hash in a zero-terminated string not
* including the terminating zero * including the terminating zero
* FNV128filein: hash in the contents of a file * FNV64filein: hash in the contents of a file
* FNV64result: returns the hash value * FNV64result: returns the hash value
* *
* Hash is returned as an 8-byte vector by the functions above. * Hash is returned as an 8-byte vector by the functions above.
* If 64-bit integers are supported, the following return * If 64-bit integers are supported, the following return
* a 64-bit integer. * a 64-bit integer.
* *
* FNV64INTstring: hash a zero-terminated string not including * FNV64INTstring: hash a zero-terminated string not including
* the terminating zero * the terminating zero
* FNV32INTstringBasis: also takes an offset_basis parameter * FNV64INTstringBasis: also takes an offset_basis parameter
* *
* FNV64INTblock: hash a specified length byte vector * FNV64INTblock: hash a byte vector of a specified length
* FNV32INTblockBasis: also takes an offset_basis parameter * FNV64INTblockBasis: also takes an offset_basis parameter
* *
* FNV64INTfile: hash the contents of a file * FNV64INTfile: hash the contents of a file
* FNV32INTfileBasis: also takes an offset_basis parameter * FNV64INTfileBasis: also takes an offset_basis parameter
* *
* FNV64INTinitBasis: initializes an FNV32 context with a * FNV64INTinitBasis: initializes an FNV64 context with a
* provided 64-bit integer basis * provided 64-bit integer basis
* FNV64INTresult: returns the hash value * FNV64INTresult: returns the hash value
*/ */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* FNV64 */ /* FNV64 */
extern int FNV64string ( const char *in, extern int FNV64string ( const char *in,
skipping to change at line 1819 skipping to change at line 1820
} }
//***************************************************************** //*****************************************************************
// START VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC // START VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC
//***************************************************************** //*****************************************************************
#ifdef FNV_64bitIntegers #ifdef FNV_64bitIntegers
/* 64-bit FNV_prime = 2^40 + 2^8 + 0xb3 */ /* 64-bit FNV_prime = 2^40 + 2^8 + 0xb3 */
#define FNV64prime 0x00000100000001B3 #define FNV64prime 0x00000100000001B3
/* FNV64 hash a zero-terminated string not including the zero /* FNV64: hash a zero-terminated string not including the zero
* to a 64-bit integer (64-bit) * to a 64-bit integer (64-bit)
******************************************************************/ ******************************************************************/
int FNV64INTstring ( const char *in, uint64_t * const out ) { int FNV64INTstring ( const char *in, uint64_t * const out ) {
return FNV64INTstringBasis ( in, out, FNV64basis ); return FNV64INTstringBasis ( in, out, FNV64basis );
} /* end FNV64INTstring */ } /* end FNV64INTstring */
/* FNV64 hash a zero-terminated string not including the zero /* FNV64: hash a zero-terminated string not including the zero
* to a 64-bit integer (64-bit) with a non-standard basis * to a 64-bit integer (64-bit) with a non-standard basis
******************************************************************/ ******************************************************************/
int FNV64INTstringBasis ( const char *in, int FNV64INTstringBasis ( const char *in,
uint64_t * const out, uint64_t * const out,
uint64_t basis ) { uint64_t basis ) {
uint64_t temp; uint64_t temp;
uint8_t ch; uint8_t ch;
if ( !in || !out ) if ( !in || !out )
return fnvNull; /* Null input pointer */ return fnvNull; /* Null input pointer */
temp = basis; temp = basis;
while ( (ch = *in++) ) while ( (ch = *in++) )
temp = FNV64prime * ( temp ^ ch ); temp = FNV64prime * ( temp ^ ch );
*out = temp; *out = temp;
return fnvSuccess; return fnvSuccess;
} /* end FNV64INTstringBasis */ } /* end FNV64INTstringBasis */
/* FNV64 hash a zero-terminated string to a 64-bit integer /* FNV64: hash a zero-terminated string to a 64-bit integer
* to a byte vector (64-bit) * to a byte vector (64-bit)
******************************************************************/ ******************************************************************/
int FNV64string ( const char *in, uint8_t out[FNV64size] ) { int FNV64string ( const char *in, uint8_t out[FNV64size] ) {
uint64_t temp; uint64_t temp;
uint8_t ch; uint8_t ch;
if ( !in || !out ) if ( !in || !out )
return fnvNull; /* Null input pointer */ return fnvNull; /* Null input pointer */
temp = FNV64basis; temp = FNV64basis;
while ( (ch = *in++) ) while ( (ch = *in++) )
temp = FNV64prime * ( temp ^ ch ); temp = FNV64prime * ( temp ^ ch );
for ( int i=0; i<FNV64size; ++i ) for ( int i=0; i<FNV64size; ++i )
out[i] = ((uint8_t *)&temp)[i]; out[i] = ((uint8_t *)&temp)[i];
return fnvSuccess; return fnvSuccess;
} /* end FNV64string */ } /* end FNV64string */
/* FNV64 hash a zero-terminated string to a 64-bit integer /* FNV64: hash a zero-terminated string to a 64-bit integer
* to a byte vector (64-bit) with a non-standard basis * to a byte vector (64-bit) with a non-standard basis
******************************************************************/ ******************************************************************/
int FNV64stringBasis ( const char *in, int FNV64stringBasis ( const char *in,
uint8_t out[FNV64size], uint8_t out[FNV64size],
const uint8_t basis[FNV64size] ) { const uint8_t basis[FNV64size] ) {
uint64_t temp; uint64_t temp;
int i; int i;
uint8_t ch; uint8_t ch;
if ( !in || !out || !basis ) if ( !in || !out || !basis )
skipping to change at line 1883 skipping to change at line 1884
temp = basis[7]; temp = basis[7];
for ( i = FNV64size-2; i>=0; --i ) for ( i = FNV64size-2; i>=0; --i )
temp = (temp<<8) + basis[i]; temp = (temp<<8) + basis[i];
while ( (ch = *in++) ) while ( (ch = *in++) )
temp = FNV64prime * ( temp ^ ch ); temp = FNV64prime * ( temp ^ ch );
for ( i=0; i<FNV64size; ++i ) for ( i=0; i<FNV64size; ++i )
out[i] = ((uint8_t *)&temp)[i]; out[i] = ((uint8_t *)&temp)[i];
return fnvSuccess; return fnvSuccess;
} /* end FNV64stringBasis */ } /* end FNV64stringBasis */
/* FNV64 hash a counted block to a 64-bit integer (64-bit) /* FNV64: hash a counted block to a 64-bit integer (64-bit)
******************************************************************/ ******************************************************************/
int FNV64INTblock ( const void *vin, int FNV64INTblock ( const void *vin,
long int length, long int length,
uint64_t * const out ) { uint64_t * const out ) {
return FNV64INTblockBasis ( vin, length, out, FNV64basis ); return FNV64INTblockBasis ( vin, length, out, FNV64basis );
} /* end FNV64INTblock */ } /* end FNV64INTblock */
/* FNV64 hash a counted block to a 64-bit integer (64-bit) /* FNV64: hash a counted block to a 64-bit integer (64-bit)
* with a non-standard basis * with a non-standard basis
******************************************************************/ ******************************************************************/
int FNV64INTblockBasis ( const void *vin, int FNV64INTblockBasis ( const void *vin,
long int length, long int length,
uint64_t * const out, uint64_t * const out,
uint64_t basis ) { uint64_t basis ) {
const uint8_t *in = (const uint8_t*)vin; const uint8_t *in = (const uint8_t*)vin;
uint64_t temp; uint64_t temp;
if ( !in || !out ) if ( !in || !out )
return fnvNull; /* Null input/out pointer */ return fnvNull;
/* Null input pointer or null output pointer */
if ( length < 0 ) if ( length < 0 )
return fnvBadParam; return fnvBadParam;
for ( temp = basis; length > 0; length-- ) for ( temp = basis; length > 0; length-- )
temp = FNV64prime * ( temp ^ *in++ ); temp = FNV64prime * ( temp ^ *in++ );
*out = temp; *out = temp;
return fnvSuccess; return fnvSuccess;
} /* end FNV64INTblockBasis */ } /* end FNV64INTblockBasis */
/* FNV64 hash a counted block to a byte vector (64-bit) /* FNV64: hash a counted block to a byte vector (64-bit)
******************************************************************/ ******************************************************************/
int FNV64block ( const void *vin, int FNV64block ( const void *vin,
long int length, long int length,
uint8_t out[FNV64size] ) { uint8_t out[FNV64size] ) {
const uint8_t *in = (const uint8_t*)vin; const uint8_t *in = (const uint8_t*)vin;
uint64_t temp; uint64_t temp;
if ( !in || !out ) if ( !in || !out )
return fnvNull; /* Null input/out pointer */ return fnvNull;
/* Null input pointer or null output pointer */
if ( length < 0 ) if ( length < 0 )
return fnvBadParam; return fnvBadParam;
for ( temp = FNV64basis; length > 0; length-- ) for ( temp = FNV64basis; length > 0; length-- )
temp = FNV64prime * ( temp ^ *in++ ); temp = FNV64prime * ( temp ^ *in++ );
for ( int i=0; i<FNV64size; ++i ) for ( int i=0; i<FNV64size; ++i )
out[i] = ((uint8_t *)&temp)[i]; out[i] = ((uint8_t *)&temp)[i];
return fnvSuccess; return fnvSuccess;
} /* end FNV64block */ } /* end FNV64block */
/* FNV64 hash a counted block to a byte vector (64-bit) /* FNV64: hash a counted block to a byte vector (64-bit)
* with a non-standard basis * with a non-standard basis
******************************************************************/ ******************************************************************/
int FNV64blockBasis ( const void *vin, int FNV64blockBasis ( const void *vin,
long int length, long int length,
uint8_t out[FNV64size], uint8_t out[FNV64size],
const uint8_t basis[FNV64size] ) { const uint8_t basis[FNV64size] ) {
const uint8_t *in = (const uint8_t*)vin; const uint8_t *in = (const uint8_t*)vin;
uint64_t temp; uint64_t temp;
int i; int i;
if ( !in || !out || !basis ) if ( !in || !out || !basis )
return fnvNull; /* Null input/out pointer */ return fnvNull;
/* Null input pointer or null output pointer */
if ( length < 0 ) if ( length < 0 )
return fnvBadParam; return fnvBadParam;
temp = basis[7]; temp = basis[7];
for ( i = FNV64size-2; i>=0; --i ) for ( i = FNV64size-2; i>=0; --i )
temp = (temp<<8) + basis[i]; temp = (temp<<8) + basis[i];
for (; length > 0; length-- ) for (; length > 0; length-- )
temp = FNV64prime * ( temp ^ *in++ ); temp = FNV64prime * ( temp ^ *in++ );
for ( i=0; i<FNV64size; ++i ) for ( i=0; i<FNV64size; ++i )
out[i] = ((uint8_t *)&temp)[i]; out[i] = ((uint8_t *)&temp)[i];
return fnvSuccess; return fnvSuccess;
skipping to change at line 2115 skipping to change at line 2119
#else /* FNV_64bitIntegers */ #else /* FNV_64bitIntegers */
//*************************************************************** //***************************************************************
// START VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC // START VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC
//*************************************************************** //***************************************************************
/* 64-bit FNV_prime = 2^40 + 2^8 + 0xb3 */ /* 64-bit FNV_prime = 2^40 + 2^8 + 0xb3 */
/* #define FNV64prime 0x00000100000001B3 */ /* #define FNV64prime 0x00000100000001B3 */
#define FNV64primeX 0x01B3 #define FNV64primeX 0x01B3
#define FNV64shift 8 #define FNV64shift 8
/* FNV64 hash a zero-terminated string not including the zero /* FNV64: hash a zero-terminated string not including the zero
******************************************************************/ ******************************************************************/
int FNV64string ( const char *in, uint8_t out[FNV64size] ) { int FNV64string ( const char *in, uint8_t out[FNV64size] ) {
FNV64context ctx; FNV64context ctx;
int error; int error;
if ( (error = FNV64init (&ctx)) ) if ( (error = FNV64init (&ctx)) )
return error; return error;
if ( (error = FNV64stringin (&ctx, in)) ) if ( (error = FNV64stringin (&ctx, in)) )
return error; return error;
return FNV64result (&ctx, out); return FNV64result (&ctx, out);
} /* end FNV64string */ } /* end FNV64string */
/* FNV64 hash a zero-terminated string not including the zero /* FNV64: hash a zero-terminated string not including the zero
* with a non-standard offset_basis * with a non-standard offset_basis
******************************************************************/ ******************************************************************/
int FNV64stringBasis ( const char *in, int FNV64stringBasis ( const char *in,
uint8_t out[FNV64size], uint8_t out[FNV64size],
const uint8_t basis[FNV64size] ) { const uint8_t basis[FNV64size] ) {
FNV64context ctx; FNV64context ctx;
int error; int error;
if ( (error = FNV64initBasis (&ctx, basis)) ) if ( (error = FNV64initBasis (&ctx, basis)) )
return error; return error;
if ( (error = FNV64stringin (&ctx, in)) ) if ( (error = FNV64stringin (&ctx, in)) )
return error; return error;
return FNV64result (&ctx, out); return FNV64result (&ctx, out);
} /* end FNV64stringBasis */ } /* end FNV64stringBasis */
/* FNV64 hash a counted block /* FNV64: hash a counted block
******************************************************************/ ******************************************************************/
int FNV64block ( const void *vin, int FNV64block ( const void *vin,
long int length, long int length,
uint8_t out[FNV64size] ) { uint8_t out[FNV64size] ) {
FNV64context ctx; FNV64context ctx;
int error; int error;
if ( (error = FNV64init (&ctx)) ) if ( (error = FNV64init (&ctx)) )
return error; return error;
if ( (error = FNV64blockin (&ctx, vin, length)) ) if ( (error = FNV64blockin (&ctx, vin, length)) )
return error; return error;
return FNV64result (&ctx, out); return FNV64result (&ctx, out);
} /* end FNV64block */ } /* end FNV64block */
/* FNV64 hash a counted block with a non-standard offset_basis /* FNV64: hash a counted block with a non-standard offset_basis
******************************************************************/ ******************************************************************/
int FNV64blockBasis ( const void *vin, int FNV64blockBasis ( const void *vin,
long int length, long int length,
uint8_t out[FNV64size], uint8_t out[FNV64size],
const uint8_t basis[FNV64size] ) { const uint8_t basis[FNV64size] ) {
FNV64context ctx; FNV64context ctx;
int error; int error;
if ( (error = FNV64initBasis (&ctx, basis)) ) if ( (error = FNV64initBasis (&ctx, basis)) )
return error; return error;
skipping to change at line 2201 skipping to change at line 2205
} /* end FNV64init */ } /* end FNV64init */
/* initialize context with a non-standard basis (32-bit) /* initialize context with a non-standard basis (32-bit)
******************************************************************/ ******************************************************************/
int FNV64initBasis ( FNV64context * const ctx, int FNV64initBasis ( FNV64context * const ctx,
const uint8_t basis[FNV64size] ) { const uint8_t basis[FNV64size] ) {
if ( !ctx || !basis ) if ( !ctx || !basis )
return fnvNull; return fnvNull;
for ( int i=0; i < FNV64size/2; ++i ) { for ( int i=0; i < FNV64size/2; ++i ) {
uint32_t temp = *basis++; uint32_t temp = *basis++;
ctx->Hash[i] = ( temp<<8 ) + *basis++; ctx->Hash[i] = ( temp<<8 ) + *basis++;
} }
ctx->Computed = FNVinited+FNV64state; ctx->Computed = FNVinited+FNV64state;
return fnvSuccess; return fnvSuccess;
} /* end FNV64initBasis */ } /* end FNV64initBasis */
/* hash in a counted block (32-bit) /* hash in a counted block (32-bit)
******************************************************************/ ******************************************************************/
int FNV64blockin ( FNV64context * const ctx, int FNV64blockin ( FNV64context * const ctx,
const void *vin, const void *vin,
long int length ) { long int length ) {
skipping to change at line 2377 skipping to change at line 2381
} FNV128context; } FNV128context;
#endif /* FNV_64bitIntegers */ #endif /* FNV_64bitIntegers */
/* Function Prototypes: /* Function Prototypes:
* *
* FNV128string: hash a zero-terminated string not including * FNV128string: hash a zero-terminated string not including
* the terminating zero * the terminating zero
* FNV128stringBasis: also takes an offset_basis parameter * FNV128stringBasis: also takes an offset_basis parameter
* *
* FNV128block: hash a specified length byte vector * FNV128block: hash a byte vector of a specified length
* FNV128blockBasis: also takes an offset_basis parameter * FNV128blockBasis: also takes an offset_basis parameter
* *
* FNV128file: hash the contents of a file * FNV128file: hash the contents of a file
* FNV128fileBasis: also takes an offset_basis parameter * FNV128fileBasis: also takes an offset_basis parameter
* *
* FNV128init: initializes an FNV128 context * FNV128init: initializes an FNV128 context
* FNV128initBasis: initializes an FNV128 context with a * FNV128initBasis: initializes an FNV128 context with a
* provided 16-byte vector basis * provided 16-byte vector basis
* FNV128blockin: hash in a specified length byte vector * FNV128blockin: hash in a byte vector of a specified length
* FNV128stringin: hash in a zero-terminated string not * FNV128stringin: hash in a zero-terminated string not
* including the terminating zero * including the terminating zero
* FNV128filein: hash in the contents of a file * FNV128filein: hash in the contents of a file
* FNV128result: returns the hash value * FNV128result: returns the hash value
* *
* Hash is returned as an array of 8-bit unsigned integers * Hash is returned as an array of 8-bit unsigned integers
*/ */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
skipping to change at line 2459 skipping to change at line 2463
#include <stdio.h> #include <stdio.h>
#include "FNVconfig.h" #include "FNVconfig.h"
#include "fnv-private.h" #include "fnv-private.h"
#include "FNV128.h" #include "FNV128.h"
//***************************************************************** //*****************************************************************
// COMMON CODE FOR 64- AND 32-BIT INTEGER MODES // COMMON CODE FOR 64- AND 32-BIT INTEGER MODES
//***************************************************************** //*****************************************************************
/* FNV128 hash a zero-terminated string not including the zero /* FNV128: hash a zero-terminated string not including the zero
******************************************************************/ ******************************************************************/
int FNV128string ( const char *in, uint8_t out[FNV128size] ) { int FNV128string ( const char *in, uint8_t out[FNV128size] ) {
FNV128context ctx; FNV128context ctx;
int error; int error;
if ( (error = FNV128init ( &ctx )) ) if ( (error = FNV128init ( &ctx )) )
return error; return error;
if ( (error = FNV128stringin ( &ctx, in )) ) if ( (error = FNV128stringin ( &ctx, in )) )
return error; return error;
return FNV128result (&ctx, out); return FNV128result (&ctx, out);
} /* end FNV128string */ } /* end FNV128string */
/* FNV128 hash a zero-terminated string not including the zero /* FNV128: hash a zero-terminated string not including the zero
******************************************************************/ ******************************************************************/
int FNV128stringBasis ( const char *in, int FNV128stringBasis ( const char *in,
uint8_t out[FNV128size], uint8_t out[FNV128size],
const uint8_t basis[FNV128size] ) { const uint8_t basis[FNV128size] ) {
FNV128context ctx; FNV128context ctx;
int error; int error;
if ( (error = FNV128initBasis ( &ctx, basis )) ) if ( (error = FNV128initBasis ( &ctx, basis )) )
return error; return error;
if ( (error = FNV128stringin ( &ctx, in )) ) if ( (error = FNV128stringin ( &ctx, in )) )
return error; return error;
return FNV128result ( &ctx, out ); return FNV128result ( &ctx, out );
} /* end FNV128stringBasis */ } /* end FNV128stringBasis */
/* FNV128 hash a counted block (64/32-bit) /* FNV128: hash a counted block (64/32-bit)
******************************************************************/ ******************************************************************/
int FNV128block ( const void *vin, int FNV128block ( const void *vin,
long int length, long int length,
uint8_t out[FNV128size] ) { uint8_t out[FNV128size] ) {
FNV128context ctx; FNV128context ctx;
int error; int error;
if ( (error = FNV128init ( &ctx )) ) if ( (error = FNV128init ( &ctx )) )
return error; return error;
if ( (error = FNV128blockin ( &ctx, vin, length )) ) if ( (error = FNV128blockin ( &ctx, vin, length )) )
return error; return error;
return FNV128result ( &ctx, out ); return FNV128result ( &ctx, out );
} /* end FNV128block */ } /* end FNV128block */
/* FNV128 hash a counted block (64/32-bit) /* FNV128: hash a counted block (64/32-bit)
******************************************************************/ ******************************************************************/
int FNV128blockBasis ( const void *vin, int FNV128blockBasis ( const void *vin,
long int length, long int length,
uint8_t out[FNV128size], uint8_t out[FNV128size],
const uint8_t basis[FNV128size] ) { const uint8_t basis[FNV128size] ) {
FNV128context ctx; FNV128context ctx;
int error; int error;
if ( (error = FNV128initBasis ( &ctx, basis )) ) if ( (error = FNV128initBasis ( &ctx, basis )) )
return error; return error;
skipping to change at line 2777 skipping to change at line 2781
} /* end FNV128init */ } /* end FNV128init */
/* initialize context with a provided 16-byte vector basis (32-bit) /* initialize context with a provided 16-byte vector basis (32-bit)
******************************************************************/ ******************************************************************/
int FNV128initBasis ( FNV128context * const ctx, int FNV128initBasis ( FNV128context * const ctx,
const uint8_t basis[FNV128size] ) { const uint8_t basis[FNV128size] ) {
if ( !ctx || !basis ) if ( !ctx || !basis )
return fnvNull; return fnvNull;
for ( int i=0; i < FNV128size/2; ++i ) { for ( int i=0; i < FNV128size/2; ++i ) {
uint32_t temp = *basis++; uint32_t temp = *basis++;
ctx->Hash[i] = ( temp<<8 ) + *basis++; ctx->Hash[i] = ( temp<<8 ) + *basis++;
} }
ctx->Computed = FNVinited+FNV128state; ctx->Computed = FNVinited+FNV128state;
return fnvSuccess; return fnvSuccess;
} /* end FNV128initBasis */ } /* end FNV128initBasis */
/* hash in a counted block (32-bit) /* hash in a counted block (32-bit)
*****************************************************************/ *****************************************************************/
int FNV128blockin ( FNV128context * const ctx, int FNV128blockin ( FNV128context * const ctx,
const void *vin, const void *vin,
long int length ) { long int length ) {
skipping to change at line 2953 skipping to change at line 2957
} FNV256context; } FNV256context;
#endif /* FNV_64bitIntegers */ #endif /* FNV_64bitIntegers */
/* Function Prototypes: /* Function Prototypes:
* *
* FNV256string: hash a zero-terminated string not including * FNV256string: hash a zero-terminated string not including
* the terminating zero * the terminating zero
* FNV256stringBasis: also takes an offset_basis parameter * FNV256stringBasis: also takes an offset_basis parameter
* *
* FNV256block: hash a specified length byte vector * FNV256block: hash a byte vector of a specified length
* FNV256blockBasis: also takes an offset_basis parameter * FNV256blockBasis: also takes an offset_basis parameter
* *
* FNV256file: hash the contents of a file * FNV256file: hash the contents of a file
* FNV256fileBasis: also takes an offset_basis parameter * FNV256fileBasis: also takes an offset_basis parameter
* *
* FNV256init: initializes an FNV256 context * FNV256init: initializes an FNV256 context
* FNV256initBasis: initializes an FNV256 context with a * FNV256initBasis: initializes an FNV256 context with a
* provided 32-byte vector basis * provided 32-byte vector basis
* FNV256blockin: hash in a specified length byte vector * FNV256blockin: hash in a byte vector of a specified length
* FNV256stringin: hash in a zero-terminated string not * FNV256stringin: hash in a zero-terminated string not
* including the terminating zero * including the terminating zero
* FNV256filein: hash in the contents of a file * FNV256filein: hash in the contents of a file
* FNV256result: returns the hash value * FNV256result: returns the hash value
* *
* Hash is returned as an array of 8-bit unsigned integers * Hash is returned as an array of 8-bit unsigned integers
*/ */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
skipping to change at line 3034 skipping to change at line 3038
#include <stdio.h> #include <stdio.h>
#include "fnv-private.h" #include "fnv-private.h"
#include "FNV256.h" #include "FNV256.h"
//***************************************************************** //*****************************************************************
// COMMON CODE FOR 64- AND 32-BIT INTEGER MODES // COMMON CODE FOR 64- AND 32-BIT INTEGER MODES
//***************************************************************** //*****************************************************************
/* FNV256 hash a zero-terminated string not including the zero /* FNV256: hash a zero-terminated string not including the zero
******************************************************************/ ******************************************************************/
int FNV256string ( const char *in, uint8_t out[FNV256size] ) { int FNV256string ( const char *in, uint8_t out[FNV256size] ) {
FNV256context ctx; FNV256context ctx;
int error; int error;
if ( (error = FNV256init ( &ctx )) ) if ( (error = FNV256init ( &ctx )) )
return error; return error;
if ( (error = FNV256stringin ( &ctx, in )) ) if ( (error = FNV256stringin ( &ctx, in )) )
return error; return error;
return FNV256result ( &ctx, out ); return FNV256result ( &ctx, out );
} /* end FNV256string */ } /* end FNV256string */
/* FNV256 hash a zero-terminated string not including the zero /* FNV256: hash a zero-terminated string not including the zero
* with a non-standard basis * with a non-standard basis
******************************************************************/ ******************************************************************/
int FNV256stringBasis ( const char *in, int FNV256stringBasis ( const char *in,
uint8_t out[FNV256size], uint8_t out[FNV256size],
const uint8_t basis[FNV256size] ) { const uint8_t basis[FNV256size] ) {
FNV256context ctx; FNV256context ctx;
int error; int error;
if ( (error = FNV256initBasis ( &ctx, basis )) ) if ( (error = FNV256initBasis ( &ctx, basis )) )
return error; return error;
if ( (error = FNV256stringin ( &ctx, in )) ) if ( (error = FNV256stringin ( &ctx, in )) )
return error; return error;
return FNV256result ( &ctx, out ); return FNV256result ( &ctx, out );
} /* end FNV256stringBasis */ } /* end FNV256stringBasis */
/* FNV256 hash a counted block (64/32-bit) /* FNV256: hash a counted block (64/32-bit)
******************************************************************/ ******************************************************************/
int FNV256block ( const void *vin, int FNV256block ( const void *vin,
long int length, long int length,
uint8_t out[FNV256size] ) { uint8_t out[FNV256size] ) {
FNV256context ctx; FNV256context ctx;
int error; int error;
if ( (error = FNV256init ( &ctx )) ) if ( (error = FNV256init ( &ctx )) )
return error; return error;
if ( (error = FNV256blockin ( &ctx, vin, length)) ) if ( (error = FNV256blockin ( &ctx, vin, length)) )
return error; return error;
return FNV256result ( &ctx, out ); return FNV256result ( &ctx, out );
} /* end FNV256block */ } /* end FNV256block */
/* FNV256 hash a counted block (64/32-bit) /* FNV256: hash a counted block (64/32-bit)
* with a non-standard basis * with a non-standard basis
******************************************************************/ ******************************************************************/
int FNV256blockBasis ( const void *vin, int FNV256blockBasis ( const void *vin,
long int length, long int length,
uint8_t out[FNV256size], uint8_t out[FNV256size],
const uint8_t basis[FNV256size] ) { const uint8_t basis[FNV256size] ) {
FNV256context ctx; FNV256context ctx;
int error; int error;
if ( (error = FNV256initBasis ( &ctx, basis )) ) if ( (error = FNV256initBasis ( &ctx, basis )) )
skipping to change at line 3324 skipping to change at line 3328
} /* end FNV256result */ } /* end FNV256result */
//**************************************************************** //****************************************************************
// END VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC // END VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC
//**************************************************************** //****************************************************************
#else /* FNV_64bitIntegers */ #else /* FNV_64bitIntegers */
//**************************************************************** //****************************************************************
// START VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC // START VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC
//**************************************************************** //****************************************************************
/* version for when you only have 32-bit arithmetic
*****************************************************************/
/* 256-bit FNV_prime = 2^168 + 2^8 + 0x63 */ /* 256-bit FNV_prime = 2^168 + 2^8 + 0x63 */
/* 0x00000000 00000000 00000100 00000000 /* 0x00000000 00000000 00000100 00000000
00000000 00000000 00000000 00000163 */ 00000000 00000000 00000000 00000163 */
#define FNV256primeX 0x0163 #define FNV256primeX 0x0163
#define FNV256shift 8 #define FNV256shift 8
//**************************************************************** //****************************************************************
// Set of init, input, and output functions below // Set of init, input, and output functions below
// to incrementally compute FNV256 // to incrementally compute FNV256
//**************************************************************** //****************************************************************
skipping to change at line 3361 skipping to change at line 3362
} /* end FNV256init */ } /* end FNV256init */
/* initialize context with a provided 32-byte vector basis (32-bit) /* initialize context with a provided 32-byte vector basis (32-bit)
******************************************************************/ ******************************************************************/
int FNV256initBasis ( FNV256context * const ctx, int FNV256initBasis ( FNV256context * const ctx,
const uint8_t basis[FNV256size] ) { const uint8_t basis[FNV256size] ) {
if ( !ctx || !basis ) if ( !ctx || !basis )
return fnvNull; return fnvNull;
for ( int i=0; i < FNV256size/2; ++i ) { for ( int i=0; i < FNV256size/2; ++i ) {
uint32_t temp = *basis++; uint32_t temp = *basis++;
ctx->Hash[i] = ( temp<<8 ) + (*basis++); ctx->Hash[i] = ( temp<<8 ) + (*basis++);
} }
ctx->Computed = FNVinited+FNV256state; ctx->Computed = FNVinited+FNV256state;
return fnvSuccess; return fnvSuccess;
} /* end FNV256initBasis */ } /* end FNV256initBasis */
/* hash in a counted block (32-bit) /* hash in a counted block (32-bit)
*****************************************************************/ *****************************************************************/
int FNV256blockin ( FNV256context * const ctx, int FNV256blockin ( FNV256context * const ctx,
const void *vin, const void *vin,
long int length ) { long int length ) {
skipping to change at line 3537 skipping to change at line 3538
} FNV512context; } FNV512context;
#endif /* FNV_64bitIntegers */ #endif /* FNV_64bitIntegers */
/* Function Prototypes: /* Function Prototypes:
* *
* FNV512string: hash a zero-terminated string not including * FNV512string: hash a zero-terminated string not including
* the terminating zero * the terminating zero
* FNV512stringBasis: also takes an offset_basis parameter * FNV512stringBasis: also takes an offset_basis parameter
* *
* FNV512block: hash a specified length byte vector * FNV512block: hash a byte vector of a specified length
* FNV512blockBasis: also takes an offset_basis parameter * FNV512blockBasis: also takes an offset_basis parameter
* *
* FNV512file: hash the contents of a file * FNV512file: hash the contents of a file
* FNV512fileBasis: also takes an offset_basis parameter * FNV512fileBasis: also takes an offset_basis parameter
* *
* FNV512init: initializes an FNV1024 context * FNV512init: initializes an FNV512 context
* FNV512initBasis: initializes an FNV1024 context with a * FNV512initBasis: initializes an FNV512 context with a
* provided 128-byte vector basis * provided 64-byte vector basis
* FNV512blockin: hash in a specified length byte vector * FNV512blockin: hash in a byte vector of a specified length
* FNV512stringin: hash in a zero-terminated string not * FNV512stringin: hash in a zero-terminated string not
* including the terminating zero * including the terminating zero
* FNV512filein: hash in the contents of a file * FNV512filein: hash in the contents of a file
* FNV512result: returns the hash value * FNV512result: returns the hash value
* *
* Hash is returned as an array of 8-bit unsigned integers * Hash is returned as an array of 8-bit unsigned integers
*/ */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
skipping to change at line 3618 skipping to change at line 3619
#include <stdio.h> #include <stdio.h>
#include "fnv-private.h" #include "fnv-private.h"
#include "FNV512.h" #include "FNV512.h"
//***************************************************************** //*****************************************************************
// COMMON CODE FOR 64- AND 32-BIT INTEGER MODES // COMMON CODE FOR 64- AND 32-BIT INTEGER MODES
//***************************************************************** //*****************************************************************
/* FNV512 hash a zero-terminated string not including the zero /* FNV512: hash a zero-terminated string not including the zero
******************************************************************/ ******************************************************************/
int FNV512string ( const char *in, uint8_t out[FNV512size] ) { int FNV512string ( const char *in, uint8_t out[FNV512size] ) {
FNV512context ctx; FNV512context ctx;
int error; int error;
if ( (error = FNV512init ( &ctx )) ) if ( (error = FNV512init ( &ctx )) )
return error; return error;
if ( (error = FNV512stringin ( &ctx, in )) ) if ( (error = FNV512stringin ( &ctx, in )) )
return error; return error;
return FNV512result ( &ctx, out ); return FNV512result ( &ctx, out );
} /* end FNV512string */ } /* end FNV512string */
/* FNV512 hash a zero-terminated string not including the zero /* FNV512: hash a zero-terminated string not including the zero
* with a non-standard basis * with a non-standard basis
******************************************************************/ ******************************************************************/
int FNV512stringBasis ( const char *in, int FNV512stringBasis ( const char *in,
uint8_t out[FNV512size], uint8_t out[FNV512size],
const uint8_t basis[FNV512size] ) { const uint8_t basis[FNV512size] ) {
FNV512context ctx; FNV512context ctx;
int error; int error;
if ( (error = FNV512initBasis ( &ctx, basis )) ) if ( (error = FNV512initBasis ( &ctx, basis )) )
return error; return error;
if ( (error = FNV512stringin ( &ctx, in )) ) if ( (error = FNV512stringin ( &ctx, in )) )
return error; return error;
return FNV512result ( &ctx, out ); return FNV512result ( &ctx, out );
} /* end FNV512stringBasis */ } /* end FNV512stringBasis */
/* FNV512 hash a counted block (64/32-bit) /* FNV512: hash a counted block (64/32-bit)
******************************************************************/ ******************************************************************/
int FNV512block ( const void *vin, int FNV512block ( const void *vin,
long int length, long int length,
uint8_t out[FNV512size] ) { uint8_t out[FNV512size] ) {
FNV512context ctx; FNV512context ctx;
int error; int error;
if ( (error = FNV512init ( &ctx )) ) if ( (error = FNV512init ( &ctx )) )
return error; return error;
if ( (error = FNV512blockin ( &ctx, vin, length)) ) if ( (error = FNV512blockin ( &ctx, vin, length)) )
return error; return error;
return FNV512result ( &ctx, out ); return FNV512result ( &ctx, out );
} /* end FNV512block */ } /* end FNV512block */
/* FNV512 hash a counted block (64/32-bit) /* FNV512: hash a counted block (64/32-bit)
* with a non-standard basis * with a non-standard basis
******************************************************************/ ******************************************************************/
int FNV512blockBasis ( const void *vin, int FNV512blockBasis ( const void *vin,
long int length, long int length,
uint8_t out[FNV512size], uint8_t out[FNV512size],
const uint8_t basis[FNV512size] ) { const uint8_t basis[FNV512size] ) {
FNV512context ctx; FNV512context ctx;
int error; int error;
if ( (error = FNV512initBasis ( &ctx, basis )) ) if ( (error = FNV512initBasis ( &ctx, basis )) )
skipping to change at line 3949 skipping to change at line 3950
} /* end FNV512init */ } /* end FNV512init */
/* initialize context with a provided 64-byte vector basis (32-bit) /* initialize context with a provided 64-byte vector basis (32-bit)
******************************************************************/ ******************************************************************/
int FNV512initBasis ( FNV512context * const ctx, int FNV512initBasis ( FNV512context * const ctx,
const uint8_t basis[FNV512size] ) { const uint8_t basis[FNV512size] ) {
if ( !ctx || !basis ) if ( !ctx || !basis )
return fnvNull; return fnvNull;
for ( int i=0; i < FNV512size/2; ++i ) { for ( int i=0; i < FNV512size/2; ++i ) {
uint32_t temp = *basis++; uint32_t temp = *basis++;
ctx->Hash[i] = ( temp<<8 ) + *basis++; ctx->Hash[i] = ( temp<<8 ) + *basis++;
} }
ctx->Computed = FNVinited+FNV512state; ctx->Computed = FNVinited+FNV512state;
return fnvSuccess; return fnvSuccess;
} /* end FNV512initBasis */ } /* end FNV512initBasis */
/* hash in a counted block (32-bit) /* hash in a counted block (32-bit)
******************************************************************/ ******************************************************************/
int FNV512blockin ( FNV512context * const ctx, int FNV512blockin ( FNV512context * const ctx,
const void *vin, const void *vin,
long int length ) { long int length ) {
skipping to change at line 4125 skipping to change at line 4126
} FNV1024context; } FNV1024context;
#endif /* FNV_64bitIntegers */ #endif /* FNV_64bitIntegers */
/* Function Prototypes: /* Function Prototypes:
* *
* FNV1024string: hash a zero-terminated string not including * FNV1024string: hash a zero-terminated string not including
* the terminating zero * the terminating zero
* FNV1024stringBasis: also takes an offset_basis parameter * FNV1024stringBasis: also takes an offset_basis parameter
* *
* FNV1024block: hash a specified length byte vector * FNV1024block: hash a byte vector of a specified length
* FNV1024blockBasis: also takes an offset_basis parameter * FNV1024blockBasis: also takes an offset_basis parameter
* *
* FNV1024file: hash the contents of a file * FNV1024file: hash the contents of a file
* FNV1024fileBasis: also takes an offset_basis parameter * FNV1024fileBasis: also takes an offset_basis parameter
* *
* FNV1024init: initializes an FNV1024 context * FNV1024init: initializes an FNV1024 context
* FNV1024initBasis: initializes an FNV1024 context with a * FNV1024initBasis: initializes an FNV1024 context with a
* provided 128-byte vector basis * provided 128-byte vector basis
* FNV1024blockin: hash in a specified length byte vector * FNV1024blockin: hash in a byte vector of a specified length
* FNV1024stringin: hash in a zero-terminated string not * FNV1024stringin: hash in a zero-terminated string not
* including the terminating zero * including the terminating zero
* FNV1024filein: hash in the contents of a file * FNV1024filein: hash in the contents of a file
* FNV1024result: returns the hash value * FNV1024result: returns the hash value
* *
* Hash is returned as an array of 8-bit unsigned integers * Hash is returned as an array of 8-bit unsigned integers
*/ */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
skipping to change at line 4206 skipping to change at line 4207
#include <stdio.h> #include <stdio.h>
#include "fnv-private.h" #include "fnv-private.h"
#include "FNV1024.h" #include "FNV1024.h"
//***************************************************************** //*****************************************************************
// COMMON CODE FOR 64- AND 32-BIT INTEGER MODES // COMMON CODE FOR 64- AND 32-BIT INTEGER MODES
//***************************************************************** //*****************************************************************
/* FNV1024 hash a zero-terminated string not including the zero /* FNV1024: hash a zero-terminated string not including the zero
******************************************************************/ ******************************************************************/
int FNV1024string ( const char *in, uint8_t out[FNV1024size] ) { int FNV1024string ( const char *in, uint8_t out[FNV1024size] ) {
FNV1024context ctx; FNV1024context ctx;
int error; int error;
if ( (error = FNV1024init ( &ctx )) ) if ( (error = FNV1024init ( &ctx )) )
return error; return error;
if ( (error = FNV1024stringin ( &ctx, in )) ) if ( (error = FNV1024stringin ( &ctx, in )) )
return error; return error;
return FNV1024result ( &ctx, out ); return FNV1024result ( &ctx, out );
} /* end FNV1024string */ } /* end FNV1024string */
/* FNV1024 hash a zero-terminated string not including the zero /* FNV1024: hash a zero-terminated string not including the zero
* with a non-standard basis * with a non-standard basis
******************************************************************/ ******************************************************************/
int FNV1024stringBasis ( const char *in, int FNV1024stringBasis ( const char *in,
uint8_t out[FNV1024size], uint8_t out[FNV1024size],
const uint8_t basis[FNV1024size] ) { const uint8_t basis[FNV1024size] ) {
FNV1024context ctx; FNV1024context ctx;
int error; int error;
if ( (error = FNV1024initBasis ( &ctx, basis )) ) if ( (error = FNV1024initBasis ( &ctx, basis )) )
return error; return error;
if ( (error = FNV1024stringin ( &ctx, in )) ) if ( (error = FNV1024stringin ( &ctx, in )) )
return error; return error;
return FNV1024result ( &ctx, out ); return FNV1024result ( &ctx, out );
} /* end FNV1024stringBasis */ } /* end FNV1024stringBasis */
/* FNV1024 hash a counted block (64/32-bit) /* FNV1024: hash a counted block (64/32-bit)
******************************************************************/ ******************************************************************/
int FNV1024block ( const void *vin, int FNV1024block ( const void *vin,
long int length, long int length,
uint8_t out[FNV1024size] ) { uint8_t out[FNV1024size] ) {
FNV1024context ctx; FNV1024context ctx;
int error; int error;
if ( (error = FNV1024init ( &ctx )) ) if ( (error = FNV1024init ( &ctx )) )
return error; return error;
if ( (error = FNV1024blockin ( &ctx, vin, length)) ) if ( (error = FNV1024blockin ( &ctx, vin, length)) )
return error; return error;
return FNV1024result ( &ctx, out ); return FNV1024result ( &ctx, out );
} /* end FNV1024block */ } /* end FNV1024block */
/* FNV1024 hash a counted block (64/32-bit) /* FNV1024: hash a counted block (64/32-bit)
* with a non-standard basis * with a non-standard basis
******************************************************************/ ******************************************************************/
int FNV1024blockBasis ( const void *vin, int FNV1024blockBasis ( const void *vin,
long int length, long int length,
uint8_t out[FNV1024size], uint8_t out[FNV1024size],
const uint8_t basis[FNV1024size] ) { const uint8_t basis[FNV1024size] ) {
FNV1024context ctx; FNV1024context ctx;
int error; int error;
if ( (error = FNV1024initBasis ( &ctx, basis )) ) if ( (error = FNV1024initBasis ( &ctx, basis )) )
skipping to change at line 4507 skipping to change at line 4508
} /* end FNV1024result */ } /* end FNV1024result */
//****************************************************************// //****************************************************************//
// END VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC // END VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC
//****************************************************************// //****************************************************************//
#else /* FNV_64bitIntegers */ #else /* FNV_64bitIntegers */
//****************************************************************// //****************************************************************//
// START VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC // START VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC
//****************************************************************// //****************************************************************//
/* version for when you only have 32-bit arithmetic
******************************************************************/
/* /*
1024-bit FNV_prime = 2^680 + 2^8 + 0x8d = 1024-bit FNV_prime = 2^680 + 2^8 + 0x8d =
0x00000000 00000000 00000000 00000000 0x00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000100 00000000 00000000 00000000 00000100 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 0000018D */ 00000000 00000000 00000000 0000018D */
skipping to change at line 4557 skipping to change at line 4555
} /* end FNV1024init */ } /* end FNV1024init */
/* initialize context with a provided 128-byte vector basis (32-bit) /* initialize context with a provided 128-byte vector basis (32-bit)
*******************************************************************/ *******************************************************************/
int FNV1024initBasis ( FNV1024context * const ctx, int FNV1024initBasis ( FNV1024context * const ctx,
const uint8_t basis[FNV1024size] ) { const uint8_t basis[FNV1024size] ) {
if ( !ctx || !basis ) if ( !ctx || !basis )
return fnvNull; return fnvNull;
for ( int i=0; i < FNV1024size/2; ++i ) { for ( int i=0; i < FNV1024size/2; ++i ) {
uint32_t temp = *basis++; uint32_t temp = *basis++;
ctx->Hash[i] = ( temp<<8 ) + *basis++; ctx->Hash[i] = ( temp<<8 ) + *basis++;
} }
ctx->Computed = FNVinited+FNV1024state; ctx->Computed = FNVinited+FNV1024state;
return fnvSuccess; return fnvSuccess;
} /* end FNV1024initBasis */ } /* end FNV1024initBasis */
/* hash in a counted block (32-bit) /* hash in a counted block (32-bit)
******************************************************************/ ******************************************************************/
int FNV1024blockin ( FNV1024context * const ctx, int FNV1024blockin ( FNV1024context * const ctx,
const void *vin, const void *vin,
long int length ) { long int length ) {
skipping to change at line 4707 skipping to change at line 4705
#include "FNV64.h" #include "FNV64.h"
#include "FNV128.h" #include "FNV128.h"
#include "FNV256.h" #include "FNV256.h"
#include "FNV512.h" #include "FNV512.h"
#include "FNV1024.h" #include "FNV1024.h"
/* global variables */ /* global variables */
char *funcName = "funcName not set?"; char *funcName = "funcName not set?";
const char *errteststring = "foo"; const char *errteststring = "foo";
int Terr = -1; /* Total errors */ int Terr = -1; /* Total errors */
int verbose = 0; /* verbose flag */ int verbose = 0; /* Verbose flag */
enum { FNV32selected = 0, FNV64selected, FNV128selected, enum { FNV32selected = 0, FNV64selected, FNV128selected,
FNV256selected, FNV512selected, FNV1024selected, FNV256selected, FNV512selected, FNV1024selected,
FNVnone = -1 } selected = FNVnone; FNVnone = -1 } selected = FNVnone;
#define NTestBytes 3 #define NTestBytes 3
const uint8_t errtestbytes[NTestBytes] = { (uint8_t)1, const uint8_t errtestbytes[NTestBytes] = { (uint8_t)1,
(uint8_t)2, (uint8_t)3 }; (uint8_t)2, (uint8_t)3 };
// initial teststring is null, so initial result is offset_basis // initial teststring is null, so initial result is offset_basis
const char *teststring[] = { const char *teststring[] = {
"", "",
"a", "a",
"foobar", "foobar",
"Hello!\x01\xFF\xED" "Hello!\x01\xFF\xED"
}; };
#define NTstrings (sizeof(teststring)/sizeof(char *)) #define NTstrings (sizeof(teststring)/sizeof(char *))
// due to FNV-1 versus FNV1a, xor in final backslash separately // due to FNV-1 versus FNV1a, XOR in final backslash separately
const char BasisString[] = "chongo <Landon Curt Noll> /\\../"; const char BasisString[] = "chongo <Landon Curt Noll> /\\../";
FNV32context e32Context; FNV32context e32Context;
uint32_t eUint32 = 42; uint32_t eUint32 = 42;
#ifdef FNV_64bitIntegers #ifdef FNV_64bitIntegers
uint64_t eUint64 = 42; uint64_t eUint64 = 42;
#endif #endif
FNV64context e64Context; FNV64context e64Context;
FNV128context e128Context; FNV128context e128Context;
FNV256context e256Context; FNV256context e256Context;
FNV512context e512Context; FNV512context e512Context;
skipping to change at line 4814 skipping to change at line 4812
//**************************************************************** //****************************************************************
int main( int argc, const char **argv ) { int main( int argc, const char **argv ) {
int option; // command line option letter int option; // command line option letter
int i; int i;
uint16_t endianness = 5*256 + 11; uint16_t endianness = 5*256 + 11;
mkstemp(tempFileNameTemplate); mkstemp(tempFileNameTemplate);
tempFileName = tempFileNameTemplate; tempFileName = tempFileNameTemplate;
if ( ((uint8_t *)&endianness)[0] != 11 ) if ( ((uint8_t *)&endianness)[0] != 11 )
printf ("Coded for Little Endian but computer seems\n" printf ("Coded for little endian but computer seems\n"
" to be Big Endian! Multi-byte integer results\n" " to be big endian! Multi-byte integer results\n"
" may be incorrect!\n"); " may be incorrect!\n");
for ( i=0; i<FNV1024size; ++i ) {// initialize a couple of arrays for ( i=0; i<FNV1024size; ++i ) {// initialize a couple of arrays
ZeroBasis[i] = 0; ZeroBasis[i] = 0;
FakeBasis[i] = (uint8_t)i; FakeBasis[i] = (uint8_t)i;
} }
if ( argc == 1 ) { // if no arguments if ( argc == 1 ) { // if no arguments
TestAll(); TestAll();
if ( tempFileName ) if ( tempFileName )
unlink(tempFileName); unlink(tempFileName);
exit(0); exit(0);
skipping to change at line 4855 skipping to change at line 4853
if ( funcmap[selected].Filefunc ( optarg, hash )) if ( funcmap[selected].Filefunc ( optarg, hash ))
printf ( "Hashing file '%s' fails: %s.\n", printf ( "Hashing file '%s' fails: %s.\n",
optarg, strerror(errno) ); optarg, strerror(errno) );
else else
HexPrint ( funcmap[selected].length/8, hash ); HexPrint ( funcmap[selected].length/8, hash );
printf ( "\n" ); printf ( "\n" );
break; break;
case 'h': // help case 'h': // help
usage( argv[0] ); usage( argv[0] );
break; break;
case 't': // follow by size of FNV to test, 0->all case 't': // followed by size of FNV to test, 0->all
selected = find_selected(optarg); selected = find_selected(optarg);
if (selected == FNVnone) if (selected == FNVnone)
printf ( "Bad argument to option -t\n" printf ( "Bad argument to option -t\n"
"Valid sizes are 32, 64, 128," "Valid sizes are 32, 64, 128,"
" 256, 512, and 1024\n"); " 256, 512, and 1024\n" );
else else
funcmap[selected].Testfunc(); // invoke test funcmap[selected].Testfunc(); // invoke test
break; break;
case 'u': // follow by size of FNV to use case 'u': // followed by size of FNV to use
selected = find_selected(optarg); selected = find_selected(optarg);
if ( selected == FNVnone ) if ( selected == FNVnone )
printf ( "Bad argument to option -u\n" printf ( "Bad argument to option -u\n"
"Valid sizes are 32, 64, 128," "Valid sizes are 32, 64, 128,"
"256, 512, and 1024\n" ); " 256, 512, and 1024\n" );
break; break;
case 'v': // toggle Verbose flag case 'v': // toggle Verbose flag
if ( (verbose ^= 1) ) { if ( (verbose ^= 1) ) {
printf ( "Verbose on.\n" ); printf ( "Verbose on.\n" );
#ifdef FNV_64bitIntegers #ifdef FNV_64bitIntegers
printf ("Has 64-bit Integers. "); printf ("Has 64-bit integers. ");
#else #else
printf ("Does not have 64-bit integers. "); printf ("Does not have 64-bit integers. ");
#endif #endif
// also tests the TestR function // also tests the TestR function
funcName = "Testing TestR"; funcName = "Testing TestR";
TestR ( "should fail", 1, 2 ); TestR ( "should fail", 1, 2 );
TestR ( "should not have failed", 3, 3 ); TestR ( "should not have failed", 3, 3 );
} }
else else
printf ( "Verbose off.\n" ); printf ( "Verbose off.\n" );
skipping to change at line 4928 skipping to change at line 4926
if ( tempFileName ) if ( tempFileName )
unlink(tempFileName); unlink(tempFileName);
return 0; return 0;
} /* end main */ } /* end main */
/* Write to a temp file /* Write to a temp file
******************************************************************/ ******************************************************************/
const char *WriteTemp( const char *str, long int iLen ) { const char *WriteTemp( const char *str, long int iLen ) {
FILE *fp = fopen( tempFileName, "w" ); FILE *fp = fopen( tempFileName, "w" );
if (!fp) { if (!fp) {
printf( "Cannot open tempfile: %s: %s\n", printf ( "Cannot open tempfile: %s: %s\n",
tempFileName, strerror(errno) ); tempFileName, strerror(errno) );
return 0; return 0;
} }
long int ret = fwrite( str, 1, iLen, fp ); long int ret = fwrite( str, 1, iLen, fp );
fclose(fp); fclose(fp);
if ( ret != iLen ) { if ( ret != iLen ) {
printf( "Cannot write tempfile: %s: %s\n", printf ( "Cannot write tempfile: %s: %s\n",
tempFileName, strerror(errno) ); tempFileName, strerror(errno) );
return 0; return 0;
} }
return tempFileName; return tempFileName;
} }
//**************************************************************** //****************************************************************
// Test status return code // Test status return code
//**************************************************************** //****************************************************************
int TestR ( const char *name, int expect, int actual ) { int TestR ( const char *name, int expect, int actual ) {
if ( expect != actual ) { if ( expect != actual ) {
skipping to change at line 5073 skipping to change at line 5071
TestR ( "blk2b", fnvBadParam, TestR ( "blk2b", fnvBadParam,
funcmap[selected].BlockBasisfunc ( errtestbytes, -1, funcmap[selected].BlockBasisfunc ( errtestbytes, -1,
hash, FakeBasis ) ); hash, FakeBasis ) );
TestR ( "blk3b", fnvNull, TestR ( "blk3b", fnvNull,
funcmap[selected].BlockBasisfunc ( errtestbytes, 1, funcmap[selected].BlockBasisfunc ( errtestbytes, 1,
(uint8_t *)0, FakeBasis ) ); (uint8_t *)0, FakeBasis ) );
TestR ( "blk4b", fnvNull, TestR ( "blk4b", fnvNull,
funcmap[selected].BlockBasisfunc ( errtestbytes, 1, funcmap[selected].BlockBasisfunc ( errtestbytes, 1,
hash, (uint8_t *)0 ) ); hash, (uint8_t *)0 ) );
TestR ( "file1", fnvNull, TestR ( "file1", fnvNull,
funcmap[selected].Filefunc ( (char *)0, hash )); funcmap[selected].Filefunc ( (char *)0, hash ) );
TestR ( "file2", fnvNull, TestR ( "file2", fnvNull,
funcmap[selected].Filefunc ( "foo.txt", (uint8_t *)0 )); funcmap[selected].Filefunc ( "foo.txt", (uint8_t *)0 ) );
TestR ( "file1b", fnvNull, TestR ( "file1b", fnvNull,
funcmap[selected].FileBasisfunc ( (char *)0, hash, funcmap[selected].FileBasisfunc ( (char *)0, hash,
FakeBasis )); FakeBasis ) );
TestR ( "file2b", fnvNull, TestR ( "file2b", fnvNull,
funcmap[selected].FileBasisfunc ( "foo.txt", (uint8_t *)0, funcmap[selected].FileBasisfunc ( "foo.txt", (uint8_t *)0,
FakeBasis )); FakeBasis ) );
TestR ( "file3b", fnvNull, TestR ( "file3b", fnvNull,
funcmap[selected].FileBasisfunc ( "foo.txt", hash, funcmap[selected].FileBasisfunc ( "foo.txt", hash,
(uint8_t *)0 )); (uint8_t *)0 ) );
} /* end CommonTest */ } /* end CommonTest */
//**************************************************************** //****************************************************************
// Print command line help // Print command line help
//**************************************************************** //****************************************************************
void usage( const char *argv0 ) { void usage( const char *argv0 ) {
printf ( printf (
"%s [-a] [-t nnn] [-u nnn] [-v] [-f filename] [token ...]\n" "%s [-a] [-t nnn] [-u nnn] [-v] [-f filename] [token ...]\n"
" -a = run all tests\n" " -a = run all tests\n"
" -f filename = hash file contents\n" " -f filename = hash file contents\n"
skipping to change at line 5108 skipping to change at line 5106
" -v = toggle Verbose flag\n" " -v = toggle Verbose flag\n"
" Each token is hashed.\n", argv0 ); " Each token is hashed.\n", argv0 );
} /* end usage */ } /* end usage */
//**************************************************************** //****************************************************************
// Test Macros // Test Macros
//**************************************************************** //****************************************************************
// test for return values // test for return values
//************************ //************************
#define TestInit(INIT,CTX,CTXT) \ #define TestInit(INIT,CTX,CTXT) \
TestR ( "init1", fnvSuccess, INIT ( &CTX ) ); \ TestR ( "init1", fnvSuccess, INIT ( &CTX ) ); \
TestR ( "init2", fnvNull, INIT ( (CTXT *)0 ) ); TestR ( "init2", fnvNull, INIT ( (CTXT *)0 ) );
#define TestInitBasis(INITB,CTX,CTXT) \ #define TestInitBasis(INITB,CTX,CTXT) \
TestR ( "initB1", fnvSuccess, INITB (&CTX, FakeBasis )); \ TestR ( "initB1", fnvSuccess, INITB (&CTX, FakeBasis ) );
TestR ( "initB2", fnvNull, INITB ( (CTXT *)0, hash ) ); \ TestR ( "initB2", fnvNull, INITB ( (CTXT *)0, hash ) ); \
TestR ( "initB3", fnvNull, INITB ( &CTX, (uint8_t *)0 )); TestR ( "initB3", fnvNull, INITB ( &CTX, (uint8_t *)0 ) );
#define TestBlockin(BLKIN,CTX,CTXT) \ #define TestBlockin(BLKIN,CTX,CTXT) \
TestR ( "blockin1", fnvNull, \ TestR ( "blockin1", fnvNull, \
BLKIN ( (CTXT *)0, errtestbytes, NTestBytes ) ); \ BLKIN ( (CTXT *)0, errtestbytes, NTestBytes ) ); \
TestR ( "blockin2", fnvNull, \ TestR ( "blockin2", fnvNull, \
BLKIN ( &CTX, (uint8_t *)0, NTestBytes ) ); \ BLKIN ( &CTX, (uint8_t *)0, NTestBytes ) ); \
TestR ( "blockin3", fnvBadParam, \ TestR ( "blockin3", fnvBadParam, \
BLKIN ( &CTX, errtestbytes, -1 ) ); \ BLKIN ( &CTX, errtestbytes, -1 ) ); \
TestR ( "blockin4", fnvStateError, \ TestR ( "blockin4", fnvStateError, \
BLKIN ( &CTX, errtestbytes, NTestBytes ) ); BLKIN ( &CTX, errtestbytes, NTestBytes ) );
#define TestStringin(STRIN,CTX,CTXT) \ #define TestStringin(STRIN,CTX,CTXT) \
TestR ( "stringin1", fnvNull, \ TestR ( "stringin1", fnvNull, \
STRIN ( (CTXT *)0, errteststring ) ); \ STRIN ( (CTXT *)0, errteststring ) ); \
TestR ( "stringin2", fnvNull, STRIN ( &CTX, (char *)0 ) ); \ TestR ( "stringin2", fnvNull, STRIN ( &CTX, (char *)0 ) ); \
TestR ( "stringin3", fnvStateError, \ TestR ( "stringin3", fnvStateError, \
STRIN ( &CTX, errteststring ) ); STRIN ( &CTX, errteststring ) );
#define TestFilein(FLIN,CTX,CTXT) \ #define TestFilein(FLIN,CTX,CTXT) \
TestR ( "file1", fnvNull, FLIN ( (CTXT *)0, errteststring ) );\ TestR ( "file1", fnvNull, FLIN ( (CTXT *)0, errteststring ) ); \
TestR ( "file2", fnvNull, FLIN ( &CTX, (char *)0 ) ); \ TestR ( "file2", fnvNull, FLIN ( &CTX, (char *)0 ) ); \
TestR ( "file3", fnvStateError, \ TestR ( "file3", fnvStateError, \
FLIN ( &CTX, errteststring ) ); FLIN ( &CTX, errteststring ) );
#define TestResult(RSLT,CTX,CTXT) \ #define TestResult(RSLT,CTX,CTXT) \
TestR ( "result1", fnvNull, RSLT ( (CTXT *)0, hash ) ); \ TestR ( "result1", fnvNull, RSLT ( (CTXT *)0, hash ) ); \
TestR ( "result2", fnvNull, RSLT ( &CTX, (uint8_t *)0 ) ); \ TestR ( "result2", fnvNull, RSLT ( &CTX, (uint8_t *)0 ) ); \
TestR ( "result3", fnvStateError, \ TestR ( "result3", fnvStateError, \
FNV128result ( &e128Context, hash ) ); FNV128result ( &e128Context, hash ) );
// test return values for INT versions including non-std basis // test return values for INT versions including non-std basis
//************************************************************* //*************************************************************
#define TestINT(STRINT,STRINTB,BLKINT,BLKINTB,INITINTB, \ #define TestINT(STRINT,STRINTB,BLKINT,BLKINTB,INITINTB, \
INTV,INTVT,ctxT) \ INTV,INTVT,ctxT) \
TestR ( "string1i", fnvNull, STRINT ( (char *)0, &INTV ) ); \ TestR ( "string1i", fnvNull, STRINT ( (char *)0, &INTV ) ); \
TestR ( "string2i", fnvNull, \ TestR ( "string2i", fnvNull, \
STRINT ( errteststring, (INTVT *)0 ) ); \ STRINT ( errteststring, (INTVT *)0 ) ); \
TestR ("string3i", fnvNull, STRINTB ((char *)0, &INTV, INTV));\ TestR ( "string3i", fnvNull, STRINTB ((char *)0, &INTV, INTV) );\
TestR ( "string4i", fnvNull, \ TestR ( "string4i", fnvNull, \
STRINTB (errteststring, (INTVT *)0, INTV)); \ STRINTB (errteststring, (INTVT *)0, INTV) ); \
TestR ("block1i", fnvNull, BLKINT ( (uint8_t *)0, 1, &INTV ));\ TestR ( "block1i", fnvNull, BLKINT ( (uint8_t *)0, 1, &INTV ) );\
TestR ( "block2i", fnvBadParam, \ TestR ( "block2i", fnvBadParam, \
BLKINT ( errtestbytes, -1, &INTV ) ); \ BLKINT ( errtestbytes, -1, &INTV ) ); \
TestR ( "block3i", fnvNull, \ TestR ( "block3i", fnvNull, \
BLKINT ( errtestbytes, 1, (INTVT *)0 ) ); \ BLKINT ( errtestbytes, 1, (INTVT *)0 ) ); \
TestR ( "block4i", fnvNull, \ TestR ( "block4i", fnvNull, \
BLKINTB ( (uint8_t *)0, 1, &INTV, INTV ) ); \ BLKINTB ( (uint8_t *)0, 1, &INTV, INTV ) ); \
TestR ( "block5i", fnvBadParam, \ TestR ( "block5i", fnvBadParam, \
BLKINTB ( errtestbytes, -1, &INTV, INTV ) ); \ BLKINTB ( errtestbytes, -1, &INTV, INTV ) ); \
TestR ( "block6i", fnvNull, \ TestR ( "block6i", fnvNull, \
BLKINTB ( errtestbytes, 1, (INTVT *)0, INTV ) ); \ BLKINTB ( errtestbytes, 1, (INTVT *)0, INTV ) ); \
TestR ("initBasis1i", fnvNull, INITINTB ( (ctxT *)0, INTV )); TestR ( "initBasis1i", fnvNull, INITINTB ( (ctxT *)0, INTV ) );
#define TestINTrf(RSLTINT,FILEINT,FILEINTB, \ #define TestINTrf(RSLTINT,FILEINT,FILEINTB, \
ctx,ctxT,INTV,INTVT) \ ctx,ctxT,INTV,INTVT) \
TestR ( "result1i", fnvNull, RSLTINT ( (ctxT *)0, &INTV ) ); \ TestR ( "result1i", fnvNull, RSLTINT ( (ctxT *)0, &INTV ) ); \
TestR ( "result2i", fnvNull, RSLTINT ( &ctx, (INTVT *)0 ) ); \ TestR ( "result2i", fnvNull, RSLTINT ( &ctx, (INTVT *)0 ) ); \
TestR ( "result3i", fnvStateError, RSLTINT ( &ctx, &INTV ) ); \ TestR ( "result3i", fnvStateError, RSLTINT ( &ctx, &INTV ) ); \
TestR ( "file1i", fnvNull, FILEINT ( (char *)0, &INTV )); \ TestR ( "file1i", fnvNull, FILEINT ( (char *)0, &INTV ) ); \
TestR ( "file2i", fnvNull, FILEINT ( "foo.txt", (INTVT *)0 ));\ TestR ( "file2i", fnvNull, FILEINT ( "foo.txt", (INTVT *)0 ) ); \
TestR ("file3i", fnvNull, FILEINTB ( (char *)0, &INTV, INTV));\ TestR ( "file3i", fnvNull, FILEINTB ( (char *)0, &INTV, INTV) );\
TestR ( "file4i", fnvNull, \ TestR ( "file4i", fnvNull, \
FILEINTB ( "foo.txt", (INTVT *)0, INTV )); FILEINTB ( "foo.txt", (INTVT *)0, INTV ) );
// test to calculate standard basis from basis zero FNV-1 // test to calculate standard basis from basis zero FNV-1
// depends on zero basis making the initial multiply a no-op // depends on zero basis making the initial multiply a no-op
//***************************** //*****************************
#define BasisZero(STRING,SIZ,VALUE) \ #define BasisZero(STRING,SIZ,VALUE) \
err = TestR ( "fnv0s", fnvSuccess, \ err = TestR ( "fnv0s", fnvSuccess, \
STRING ( BasisString, hash, ZeroBasis ) ); \ STRING ( BasisString, hash, ZeroBasis ) ); \
if ( err == fnvSuccess ) { \ if ( err == fnvSuccess ) { \
hash[SIZ-1] ^= '\\'; \ hash[SIZ-1] ^= '\\'; \
TestNValue ("fnv0sv", BasisString, SIZ, hash, VALUE[0]); \ TestNValue ( "fnv0sv", BasisString, SIZ, hash, VALUE[0] ); \
} }
#define BasisINTZero(STRINT,SIZ,VALUE,INTV,INTVT) \ #define BasisINTZero(STRINT,SIZ,VALUE,INTV,INTVT) \
err = TestR ( "fnv0s", fnvSuccess, \ err = TestR ( "fnv0s", fnvSuccess, \
STRINT ( BasisString, &INTV, (INTVT) 0 ) ); \ STRINT ( BasisString, &INTV, (INTVT) 0 ) ); \
if ( err == fnvSuccess ) { \ if ( err == fnvSuccess ) { \
INTV ^= '\\'; \ INTV ^= '\\'; \
TestNValue ("fnv0svi", BasisString, SIZ, \ TestNValue ( "fnv0svi", BasisString, SIZ, \
(uint8_t *)&INTV, (uint8_t *)&VALUE[0]); \ (uint8_t *)&INTV, (uint8_t *)&VALUE[0] ); \
} }
// test for return hash values // test for return hash values
//***************************** //*****************************
#define TestSTRBLKHash(STR,BLK,SVAL,BVAL,SZ) \ #define TestSTRBLKHash(STR,BLK,SVAL,BVAL,SZ) \
if ( TestR ( "stringa", fnvSuccess, \ if ( TestR ( "stringa", fnvSuccess, \
STR ( teststring[i], hash ) ) ) \ STR ( teststring[i], hash ) ) ) \
printf ( " Index = %i\n", i ); \ printf ( " Index = %i\n", i ); \
else \ else \
TestNValue ( "stringb", teststring[i], SZ, \ TestNValue ( "stringb", teststring[i], SZ, \
hash, (uint8_t *)&SVAL[i] ); \ hash, (uint8_t *)&SVAL[i] ); \
if ( TestR ( "blocka", fnvSuccess, BLK ( teststring[i], \ if ( TestR ( "blocka", fnvSuccess, BLK ( teststring[i], \
(long int)(strlen(teststring[i])+1), hash ) ) ) \ (long int)(strlen(teststring[i])+1), hash ) ) ) \
printf ( " Index = %i\n", i ); \ printf ( " Index = %i\n", i ); \
else \ else \
TestNValue ( "blockb", teststring[i], SZ, \ TestNValue ( "blockb", teststring[i], SZ, \
hash, (uint8_t *)&BVAL[i] ); hash, (uint8_t *)&BVAL[i] );
// Test incremental functions // Test incremental functions
//**************************** //****************************
#define IncrHash(INIT,CTX,BLK,RSLT,INITB,STR,SZ,SVAL) \ #define IncrHash(INIT,CTX,BLK,RSLT,INITB,STR,SZ,SVAL) \
err = TestR ( "inita", fnvSuccess, INIT ( &CTX ) ); \ err = TestR ( "inita", fnvSuccess, INIT ( &CTX ) ); \
if ( err ) break; \ if ( err ) break; \
iLen = strlen ( teststring[i] ); \ iLen = strlen ( teststring[i] ); \
err = TestR ("blockina", fnvSuccess, \ err = TestR ( "blockina", fnvSuccess, \
BLK ( &CTX, (uint8_t *)teststring[i], iLen/2 )); \ BLK ( &CTX, (uint8_t *)teststring[i], iLen/2 ) ); \
if ( err ) break; \ if ( err ) break; \
if ( i & 1 ) { \ if ( i & 1 ) { \
err = TestR ("basisra", fnvSuccess, RSLT ( &CTX, hash )); \ err = TestR ( "basisra", fnvSuccess, RSLT ( &CTX, hash ) ); \
if ( err ) break; \ if ( err ) break; \
err = TestR ("basisia", fnvSuccess, INITB ( &CTX, hash ));\ err = TestR ( "basisia", fnvSuccess, INITB ( &CTX, hash ) );\
if ( err ) break; \ if ( err ) break; \
} \ } \
err = TestR ( "stringina", fnvSuccess, STR ( &CTX, \ err = TestR ( "stringina", fnvSuccess, STR ( &CTX, \
teststring[i] + iLen/2 ) ); \ teststring[i] + iLen/2 ) ); \
if ( err ) break; \ if ( err ) break; \
err = TestR ( "resulta", fnvSuccess, RSLT ( &CTX, hash ) ); \ err = TestR ( "resulta", fnvSuccess, RSLT ( &CTX, hash ) ); \
if ( err ) break; \ if ( err ) break; \
TestNValue ( "incrementala", teststring[i], SZ, \ TestNValue ( "incrementala", teststring[i], SZ, \
hash, (uint8_t *)&SVAL[i] ); hash, (uint8_t *)&SVAL[i] );
// test file hash // test file hash
//***************************** //*****************************
#define TestFILEHash(FILE,BVAL,SZ) \ #define TestFILEHash(FILE,BVAL,SZ) \
err = TestR ( "fileafh", fnvSuccess, \ err = TestR ( "fileafh", fnvSuccess, \
FILE ( WriteTemp(teststring[i], iLen), \ FILE ( WriteTemp(teststring[i], iLen), \
hash ) ); \ hash ) ); \
if ( err ) break; \ if ( err ) break; \
TestNValue ( "filebfh", teststring[i], SZ, hash, \ TestNValue ( "filebfh", teststring[i], SZ, hash, \
(uint8_t *)&BVAL[i] ); (uint8_t *)&BVAL[i] );
//**************************************************************** //****************************************************************
// FNV32 Test // FNV32 Test
//**************************************************************** //****************************************************************
void Test32 ( void ) { void Test32 ( void ) {
long int iLen; long int iLen;
uint32_t FNV32svalues[NTstrings] = { uint32_t FNV32svalues[NTstrings] = {
0x811c9dc5, 0xe40c292c, 0xbf9cf968, 0xfd9d3881 }; 0x811c9dc5, 0xe40c292c, 0xbf9cf968, 0xfd9d3881 };
uint32_t FNV32bvalues[NTstrings] = { uint32_t FNV32bvalues[NTstrings] = {
skipping to change at line 5280 skipping to change at line 5278
e32Context.Computed = FNVclobber+FNV32state; e32Context.Computed = FNVclobber+FNV32state;
TestBlockin (FNV32blockin, e32Context, FNV32context) TestBlockin (FNV32blockin, e32Context, FNV32context)
TestStringin (FNV32stringin, e32Context, FNV32context) TestStringin (FNV32stringin, e32Context, FNV32context)
TestFilein (FNV32filein, e32Context, FNV32context) TestFilein (FNV32filein, e32Context, FNV32context)
TestResult (FNV32result, e32Context, FNV32context) TestResult (FNV32result, e32Context, FNV32context)
TestINTrf(FNV32INTresult,FNV32INTfile,FNV32INTfileBasis, TestINTrf(FNV32INTresult,FNV32INTfile,FNV32INTfileBasis,
e32Context,FNV32context,eUint32,uint32_t) e32Context,FNV32context,eUint32,uint32_t)
ErrTestReport (); ErrTestReport ();
Terr = 0; Terr = 0;
err = TestR ( "fnv0s", fnvSuccess, err = TestR ( "fnv0s", fnvSuccess,
FNV32stringBasis ( BasisString, hash, ZeroBasis )); FNV32stringBasis ( BasisString, hash, ZeroBasis ) );
if ( err == fnvSuccess ) { if ( err == fnvSuccess ) {
hash[0] ^= '\\'; hash[0] ^= '\\';
TestNValue ( "fnv0sv32", BasisString, FNV32size, TestNValue ( "fnv0sv32", BasisString, FNV32size,
hash, (uint8_t *)&FNV32svalues[0]); hash, (uint8_t *)&FNV32svalues[0]);
} }
BasisINTZero (FNV32INTstringBasis,FNV32size,FNV32svalues, \ BasisINTZero (FNV32INTstringBasis,FNV32size,FNV32svalues, \
eUint32,uint32_t) eUint32,uint32_t)
for ( i = 0; i < NTstrings; ++i ) { for ( i = 0; i < NTstrings; ++i ) {
/* test actual results int */ /* test actual results int */
err = TestR ( "stringai", fnvSuccess, err = TestR ( "stringai", fnvSuccess,
skipping to change at line 5352 skipping to change at line 5350
FNV32stringin ( &e32Context, FNV32stringin ( &e32Context,
teststring[i] + iLen/2 ) ); teststring[i] + iLen/2 ) );
if ( err ) break; if ( err ) break;
err = TestR ( "resultab", fnvSuccess, err = TestR ( "resultab", fnvSuccess,
FNV32result ( &e32Context, hash ) ); FNV32result ( &e32Context, hash ) );
if ( err ) break; if ( err ) break;
TestNValue ( "incrementala", teststring[i], FNV32size, TestNValue ( "incrementala", teststring[i], FNV32size,
hash, (uint8_t *)&FNV32svalues[i] ); hash, (uint8_t *)&FNV32svalues[i] );
/* now try testing file hash int */ /* now try testing file hash int */
err = TestR ( "fileafi", fnvSuccess, err = TestR ( "fileafi", fnvSuccess,
FNV32INTfile ( FNV32INTfile ( WriteTemp(teststring[i], iLen),
WriteTemp(teststring[i], iLen), &eUint32 ) );
&eUint32 )
);
if ( err ) break; if ( err ) break;
TestNValue ( "filebfi", teststring[i], FNV32size, TestNValue ( "filebfi", teststring[i], FNV32size,
(uint8_t *)&eUint32, (uint8_t *)&eUint32,
(uint8_t *)&FNV32svalues[i] ); (uint8_t *)&FNV32svalues[i] );
/* now try testing file hash byte */ /* now try testing file hash byte */
TestFILEHash ( FNV32file, FNV32svalues, FNV32size ) TestFILEHash ( FNV32file, FNV32svalues, FNV32size )
} // end for i } // end for i
ValueTestReport (); ValueTestReport ();
} /* end Test32 */ } /* end Test32 */
skipping to change at line 5403 skipping to change at line 5399
TestBlockin (FNV64blockin, e64Context, FNV64context) TestBlockin (FNV64blockin, e64Context, FNV64context)
TestStringin (FNV64stringin, e64Context, FNV64context) TestStringin (FNV64stringin, e64Context, FNV64context)
TestFilein (FNV64filein, e64Context, FNV64context) TestFilein (FNV64filein, e64Context, FNV64context)
TestResult (FNV64result, e64Context, FNV64context) TestResult (FNV64result, e64Context, FNV64context)
TestINTrf(FNV64INTresult,FNV64INTfile,FNV64INTfileBasis, TestINTrf(FNV64INTresult,FNV64INTfile,FNV64INTfileBasis,
e64Context,FNV64context,eUint64,uint64_t) e64Context,FNV64context,eUint64,uint64_t)
ErrTestReport (); ErrTestReport ();
/* test actual results int */ /* test actual results int */
Terr = 0; Terr = 0;
err = TestR ( "fnv0s", fnvSuccess, err = TestR ( "fnv0s", fnvSuccess,
FNV64stringBasis ( BasisString, hash, ZeroBasis )); FNV64stringBasis ( BasisString, hash, ZeroBasis ) );
if ( err == fnvSuccess ) { if ( err == fnvSuccess ) {
hash[0] ^= '\\'; hash[0] ^= '\\';
TestNValue ( "fnv0sv64", BasisString, FNV64size, TestNValue ( "fnv0sv64", BasisString, FNV64size,
hash, (uint8_t *)&FNV64svalues[0]); hash, (uint8_t *)&FNV64svalues[0]);
} }
BasisINTZero (FNV64INTstringBasis,FNV64size,FNV64svalues, \ BasisINTZero (FNV64INTstringBasis,FNV64size,FNV64svalues, \
eUint64,uint64_t) eUint64,uint64_t)
for ( i = 0; i < NTstrings; ++i ) { for ( i = 0; i < NTstrings; ++i ) {
/* test actual results int */ /* test actual results int */
err = TestR ( "stringai", fnvSuccess, err = TestR ( "stringai", fnvSuccess,
skipping to change at line 5475 skipping to change at line 5471
FNV64stringin ( &e64Context, FNV64stringin ( &e64Context,
teststring[i] + iLen/2 ) ); teststring[i] + iLen/2 ) );
if ( err ) break; if ( err ) break;
err = TestR ( "resultab", fnvSuccess, err = TestR ( "resultab", fnvSuccess,
FNV64result ( &e64Context, hash ) ); FNV64result ( &e64Context, hash ) );
if ( err ) break; if ( err ) break;
TestNValue ( "incrementala", teststring[i], FNV64size, TestNValue ( "incrementala", teststring[i], FNV64size,
hash, (uint8_t *)&FNV64svalues[i] ); hash, (uint8_t *)&FNV64svalues[i] );
/* now try testing file int */ /* now try testing file int */
err = TestR ( "fileafi", fnvSuccess, err = TestR ( "fileafi", fnvSuccess,
FNV64INTfile ( FNV64INTfile ( WriteTemp(teststring[i], iLen),
WriteTemp(teststring[i], iLen), &eUint64 ) );
&eUint64 )
);
if ( err ) break; if ( err ) break;
TestNValue ( "filebfi", teststring[i], FNV64size, TestNValue ( "filebfi", teststring[i], FNV64size,
(uint8_t *)&eUint64, (uint8_t *)&eUint64,
(uint8_t *)&FNV64svalues[i] ); (uint8_t *)&FNV64svalues[i] );
/* now try testing file hash */ /* now try testing file hash */
TestFILEHash(FNV64file,FNV64svalues,FNV64size) TestFILEHash(FNV64file,FNV64svalues,FNV64size)
} }
ValueTestReport (); ValueTestReport ();
} /* end Test64 */ } /* end Test64 */
skipping to change at line 5948 skipping to change at line 5942
# Makefile for fnv # Makefile for fnv
# If you extract this file from RFC 9923, the five-character sequence # If you extract this file from RFC 9923, the five-character sequence
# <TAB> below must be replaced with a tab (0x09) character. # <TAB> below must be replaced with a tab (0x09) character.
explanation: explanation:
<TAB>@echo Choose one of the following make targets: <TAB>@echo Choose one of the following make targets:
<TAB>@echo make FNVhash -- test program <TAB>@echo make FNVhash -- test program
<TAB>@echo make libfnv.a -- library you can use <TAB>@echo make libfnv.a -- library you can use
<TAB>@echo make clean -- removes all of the built targets <TAB>@echo make clean -- removes all of the built targets
SRC=FNV1024.c FNV128.c FNV256.c FNV32.c FNV512.c FNV64.c SRC=FNV32.c FNV64.c FNV128.c FNV256.c FNV512.c FNV1024.c
HDR=FNV32.h FNV64.h FNV128.h FNV256.h FNV512.h FNV1024.h \ HDR=FNV32.h FNV64.h FNV128.h FNV256.h FNV512.h FNV1024.h \
<TAB>FNVErrorCodes.h FNVconfig.h fnv-private.h <TAB>FNVconfig.h FNVErrorCodes.h fnv-private.h
OBJ=$(SRC:.c=.o) OBJ=$(SRC:.c=.o)
CFLAGS=-Wall CFLAGS=-Wall
AR=ar AR=ar
ARFLAGS= rcs ARFLAGS= rcs
FNVhash: libfnv.a main.c FNVhash: libfnv.a main.c
<TAB>$(CC) $(CFLAGS) -o FNVhash main.c libfnv.a <TAB>$(CC) $(CFLAGS) -o FNVhash main.c libfnv.a
libfnv.a: $(SRC) $(HDR) libfnv.a: $(SRC) $(HDR)
<TAB>rm -f libfnv.a *.o <TAB>rm -f libfnv.a *.o
skipping to change at line 5999 skipping to change at line 5993
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/info/rfc8174>. May 2017, <https://www.rfc-editor.org/info/rfc8174>.
10.2. Informative References 10.2. Informative References
[BASIC] Diamond, W., "FNV32 PowerBASIC inline x86 assembler", [BASIC] Diamond, W., "FNV32 PowerBASIC inline x86 assembler",
<http://www.isthe.com/chongo/tech/comp/fnv/ <http://www.isthe.com/chongo/tech/comp/fnv/
index.html#PowerBASIC>. index.html#PowerBASIC>.
[BFDseq] Jethanandani, M., Agarwal, S., Mishra, A., Saxena, A., and
A. DeKok, "Secure BFD Sequence Numbers", Work in Progress,
Internet-Draft, draft-ietf-bfd-secure-sequence-numbers-09,
29 March 2022, <https://datatracker.ietf.org/doc/html/
draft-ietf-bfd-secure-sequence-numbers-09>.
[calc] Bell, D. and L. Noll, "Calc - C-style arbitrary precision [calc] Bell, D. and L. Noll, "Calc - C-style arbitrary precision
calculator", calculator",
<http://www.isthe.com/chongo/tech/comp/calc/index.html>. <http://www.isthe.com/chongo/tech/comp/calc/index.html>.
[Cohesia] Cohesia, "Cohesia website", <http://www.cohesia.com/>. [Cohesia] Cohesia, "Cohesia website", <http://www.cohesia.com/>.
[deliantra] [deliantra]
The Deliantra Team, "Deliantra MMORPG", 2016, The Deliantra Team, "Deliantra MMORPG", 16 October 2022,
<http://www.deliantra.net/>. <http://www.deliantra.net/>.
[fasmlab] Fasmlab, "Integrated Development Environments", [fasmlab] Fasmlab, "Integrated Development Environments",
<https://sourceforge.net/projects/fasmlab/>. <https://sourceforge.net/projects/fasmlab/>.
[FIPS202] NIST, "SHA-3 Standard: Permutation-Based Hash and [FIPS202] NIST, "SHA-3 Standard: Permutation-Based Hash and
Extendable-Output Functions", FIPS PUB 202, Extendable-Output Functions", FIPS PUB 202,
DOI 10.6028/NIST.FIPS.202, August 2015, DOI 10.6028/NIST.FIPS.202, August 2015,
<https://nvlpubs.nist.gov/nistpubs/FIPS/ <https://nvlpubs.nist.gov/nistpubs/FIPS/
NIST.FIPS.202.pdf>. NIST.FIPS.202.pdf>.
[flatassembler] [flatassembler]
Grysztar, T., "flat assembler: Assembly language Grysztar, T., "flat assembler: Assembly language
resources", 2025, <https://flatassembler.net/>. resources", 2025, <https://flatassembler.net/>.
[FNV] Fowler-Noll-Vo, "FNV website", [FNV] Fowler, G., Noll, L., and K. Vo, "FNV (Fowler/Noll/Vo)",
<http://www.isthe.com/chongo/tech/comp/fnv/index.html>. <http://www.isthe.com/chongo/tech/comp/fnv/index.html>.
[Fortran] Fortran Standard Library, "A community driven standard [Fortran] Fortran Standard Library, "A community driven standard
library for (modern) Fortran", library for (modern) Fortran",
<https://stdlib.fortran-lang.org/>. <https://stdlib.fortran-lang.org/>.
[FragCache] [FragCache]
Weaver, E., "Improving Running Components at Twitter", Weaver, E., "Improving Running Components at Twitter",
Slide 31, 2009, <https://www.slideshare.net/slideshow/ Slide 31, 2009, <https://www.slideshare.net/slideshow/
improving-running-components-at-twitter/1141786>. improving-running-components-at-twitter/1141786>.
[FreeBSD] The Free BSD Project, "FreeBSD 4.3 Release Notes", 2025, [FreeBSD] Baio, D. G., "FreeBSD 4.3 Release Notes (Last modified on
21 February 2021)", The Free BSD Project, 2025,
<https://www.freebsd.org/releases/4.3R/notes.html>. <https://www.freebsd.org/releases/4.3R/notes.html>.
[FRET] McCarthy, M., "FRET: helping understand file formats", 19 [FRET] McCarthy, M., "FRET: helping understand file formats", 19
January 2006, <https://fret.sourceforge.net/>. January 2006, <https://fret.sourceforge.net/>.
[GolfHash] Gliim LLC, "Golf Language Hash Tables", 2025,
<https://golf-lang.com/new-hash.html>.
[IEEE] Institute for Electrical and Electronics Engineers, "IEEE [IEEE] Institute for Electrical and Electronics Engineers, "IEEE
website", <https://www.ieee.org/>. website", <https://www.ieee.org/>.
[IEEE8021Qbp] [IEEE8021Q-2022]
"Media Access Control (MAC) Bridges and Virtual Bridged IEEE, "IEEE Standard for Local and Metropolitan Area
Local Area Networks - Equal Cost Multiple Path (ECMP)", Networks--Bridges and Bridged Networks",
IEEE Std 802.1Qbp-2014, 7 April 2014. DOI 10.1109/IEEESTD.2022.10004498, IEEE Std 802.1Q-2022,
December 2022,
<https://ieeexplore.ieee.org/document/10004498>.
[IEN137] Cohen, D., "On Holy Wars and A Plea For Peace", IEN 137, 1 [IEN137] Cohen, D., "On Holy Wars and A Plea For Peace", IEN 137, 1
April 1980, <https://www.rfc-editor.org/ien/ien137.txt>. April 1980, <https://www.rfc-editor.org/ien/ien137.txt>.
[IPv6flow] Anderson, L., Brownlee, N., and B. Carpenter, "Comparing [IPv6flow] Anderson, L., Brownlee, N., and B. E. Carpenter,
Hash Function Algorithms for the IPv6 Flow Label", "Comparing Hash Function Algorithms for the IPv6 Flow
University of Auckland Department of Computer Science Label", University of Auckland Department of Computer
Technical Report 2012-002, ISSN 1173-3500, March 2012, Science Technical Report 2012-002, ISSN 1173-3500, March
<https://researchspace.auckland.ac.nz/bitstream/ 2012,
handle/2292/13240/flowhashRep.pdf>. <https://www.cs.auckland.ac.nz/~brian/flowhashRep.pdf>.
[ISAAC-Auth]
DeKok, A., Jethanandani, M., Agarwal, S., Mishra, A., and
J. Haas, "Meticulous Keyed ISAAC for BFD Optimized
Authentication", Work in Progress, Internet-Draft, draft-
ietf-bfd-secure-sequence-numbers-27, 16 October 2025,
<https://datatracker.ietf.org/doc/html/draft-ietf-bfd-
secure-sequence-numbers-27>.
[LCN2] Noll, L. and C. Ferguson, "lcn2 / fnv", commit 953444c, 19 [LCN2] Noll, L. and C. Ferguson, "lcn2 / fnv", commit 953444c, 19
November 2025, <https://github.com/lcn2/fnv>. November 2025, <https://github.com/lcn2/fnv>.
[Leprechaun] [Leprechaun]
Sanmayce project, "Sanmayce project 'Underdog Way'", Sanmayce project, "Sanmayce project 'Underdog Way'",
<http://www.sanmayce.com/Downloads/>. <http://www.sanmayce.com/Downloads/>.
[libketama]
Jones, R., "libketama: Consistent Hashing library for
memcached clients", 10 April 2007,
<https://www.metabrew.com/article/libketama-consistent-
hashing-algo-memcached-clients>.
[libsir] Lederman, R. and J. Johnson, "libsir logging library", [libsir] Lederman, R. and J. Johnson, "libsir logging library",
commit 0ae0173, 3 December 2025, commit 0ae0173, 3 December 2025,
<https://github.com/aremmell/libsir>. <https://github.com/aremmell/libsir>.
[memcache] Dovgal, A., Joye, P., Radtke, H., Johansson, M., and T. [memcache] Dovgal, A., Joye, P., Radtke, H., Johansson, M., and T.
Srnka, "PHP memcached extension", 30 April 2023, Srnka, "PHP memcached extension", 30 April 2023,
<https://pecl.php.net/package/memcache>. <https://pecl.php.net/package/memcache>.
[NCHF] Hayes, C. and D. Malone, "Questioning the Criteria for [NCHF] Hayes, C. and D. Malone, "Questioning the Criteria for
Evaluating Non-Cryptographic Hash Functions", Evaluating Non-Cryptographic Hash Functions",
skipping to change at line 6131 skipping to change at line 6129
[RFC7873] Eastlake 3rd, D. and M. Andrews, "Domain Name System (DNS) [RFC7873] Eastlake 3rd, D. and M. Andrews, "Domain Name System (DNS)
Cookies", RFC 7873, DOI 10.17487/RFC7873, May 2016, Cookies", RFC 7873, DOI 10.17487/RFC7873, May 2016,
<https://www.rfc-editor.org/info/rfc7873>. <https://www.rfc-editor.org/info/rfc7873>.
[RFC8200] Deering, S. and R. Hinden, "Internet Protocol, Version 6 [RFC8200] Deering, S. and R. Hinden, "Internet Protocol, Version 6
(IPv6) Specification", STD 86, RFC 8200, (IPv6) Specification", STD 86, RFC 8200,
DOI 10.17487/RFC8200, July 2017, DOI 10.17487/RFC8200, July 2017,
<https://www.rfc-editor.org/info/rfc8200>. <https://www.rfc-editor.org/info/rfc8200>.
[RimStone] Gliim LLC, "Golf Language Hash Tables", 2025,
<https://rimstone-lang.com/>.
[Smash] Emms, S., "Smash - find duplicate files super fast", 8
December 2024, <https://www.linuxlinks.com/smash-find-
duplicate-files-super-fast/>.
[twistylists] [twistylists]
Zethmayr, D., "twistylists: A no-sort namespace engine; Zethmayr, D., "twistylists: A no-sort namespace engine;
developers invited", 6 November 2012, developers invited", 6 November 2012,
<https://twistylists.blogspot.com/>. <https://twistylists.blogspot.com/>.
[Vely] Mijatovic, S., "Vely - general purpose framework", 26
October 2023, <https://www.linuxlinks.com/vely-general-
purpose-framework/>.
[Vortetty] "Raytracing for the gba", commit f8bf009, 26 February
2025, <https://github.com/Vortetty/gba-rtx>.
Appendix A. Work Comparison with SHA-1 and SHA-256 Appendix A. Work Comparison with SHA-1 and SHA-256
This appendix provides a simplistic rough comparison of the level of This appendix provides a simplistic rough comparison of the level of
effort required to compute FNV-1a, SHA-1 [RFC3174], and SHA-256 effort required to compute FNV-1a, SHA-1 [RFC3174], and SHA-256
[RFC6234] for short messages -- that is, those less than around 50 [RFC6234] for short messages -- that is, those less than around 50
bytes. Some CPUs may have special instructions or other hardware to bytes. Some CPUs may have special instructions or other hardware to
accelerate certain cryptographic operations, so if performance is accelerate certain cryptographic operations, so if performance is
particularly important for an application, benchmarking on the target particularly important for an application, benchmarking on the target
platform would be appropriate. platform would be appropriate.
skipping to change at line 6168 skipping to change at line 6166
although almost all computer uses apply them to an integer number of although almost all computer uses apply them to an integer number of
bytes. They both process blocks of 512 bits (64 bytes), and we bytes. They both process blocks of 512 bits (64 bytes), and we
estimate the effort involved in processing a full block. There is estimate the effort involved in processing a full block. There is
some overhead per message to indicate message termination and size. some overhead per message to indicate message termination and size.
Assuming that the message is an even number of bytes, this overhead Assuming that the message is an even number of bytes, this overhead
would be 9 bytes for SHA-1 and 17 bytes for SHA-256. So, assuming would be 9 bytes for SHA-1 and 17 bytes for SHA-256. So, assuming
that the message with that overhead fits into one block, the message that the message with that overhead fits into one block, the message
would be up to 55 bytes for SHA-1 or up to 47 bytes for SHA-256. would be up to 55 bytes for SHA-1 or up to 47 bytes for SHA-256.
SHA-1 is a relatively weak cryptographic hash function producing a SHA-1 is a relatively weak cryptographic hash function producing a
160-bit hash. It has been partially broken [RFC6194]. Ignoring SHA- 160-bit hash. It has been substantially broken [RFC6194]. Ignoring
1's initial setup, transfer of control, and conditional tests, but SHA-1's initial setup, transfer of control, and conditional tests,
counting all logical and arithmetic operations, including counting but counting all logical and arithmetic operations, including
indexing as an addition, SHA-1 requires 1,744 operations per 64-byte counting indexing as an addition, SHA-1 requires 1,744 operations per
block or 31.07 operations per byte for a message of 55 bytes. By 64-byte block or 31.07 operations per byte for a message of 55 bytes.
this rough measure, it is a little over 15.5 times the effort of FNV. By this rough measure, it is a little over 15.5 times the effort of
FNV.
SHA-256 is, at the time of publication, considered to be a stronger SHA-256 is, at the time of publication, considered to be a stronger
cryptographic hash function than SHA-1. Ignoring SHA-256's initial cryptographic hash function than SHA-1. Ignoring SHA-256's initial
setup, transfer of control, and conditional tests, but counting all setup, transfer of control, and conditional tests, but counting all
logical and arithmetic operations, SHA-1 requires 2,058 operations logical and arithmetic operations, SHA-1 requires 2,058 operations
per 64-byte block or 48.79 operations per byte for a message of 47 per 64-byte block or 48.79 operations per byte for a message of 47
bytes. By this rough measure, it is over 24 times the effort of FNV. bytes. By this rough measure, it is over 24 times the effort of FNV.
However, FNV is commonly used for short inputs, so doing a comparison However, FNV is commonly used for short inputs, so doing a comparison
of such inputs is relevant. Using the above comparison method, for of such inputs is relevant. Using the above comparison method, for
 End of changes. 137 change blocks. 
294 lines changed or deleted 293 lines changed or added

This html diff was produced by rfcdiff 1.48.