Skip to content

Instantly share code, notes, and snippets.

@epicabsol
Created June 2, 2021 09:47
Show Gist options
  • Save epicabsol/4f041928eec0cae8b9ff0ebc326a1d79 to your computer and use it in GitHub Desktop.
Save epicabsol/4f041928eec0cae8b9ff0ebc326a1d79 to your computer and use it in GitHub Desktop.
64-bit FNV1a Hash (Run-Time and Compile-Time)
/**
* @file Hash.h
* @author Ben Garcia (ben@bendoescode.com)
* @brief Provides run-time and compile-time 64-bit FNV1a hashing for strings and data.
* @version 1.0
* @date 2021-06-02
*/
#pragma once
#include <cstdint>
#include <string>
typedef uint64_t hash64_t;
// FNV1a initialization parameters
constexpr hash64_t HashInitialValue = 0xCBF29CE484222325;
constexpr hash64_t HashPrime = 0x100000001B3;
/**
* @brief Computes the 64-bit FNV1a hash of the bytes at the given pointer.
*
* @param data A pointer to the data to compute the hash for.
* @param len The number of bytes from `data` to hash.
* @return The 64-bit FNV1a hash of the bytes.
*/
inline hash64_t HashData(const void* data, const uint32_t len) {
const char* bytes = (char*)data;
hash64_t hash = HashInitialValue;
for (uint32_t i = 0; i < len; ++i) {
uint8_t value = bytes[i];
hash = hash ^ value;
hash *= HashPrime;
}
return hash;
}
/**
* @brief Computes the 64-bit FNV1a hash of the bytes of the given string.
*
* @param text The string to compute the hash for.
* @return The 64-bit FNV1a hash of the string.
*/
inline hash64_t HashString(const std::string& text) {
return HashData(text.c_str(), (uint32_t)text.length());
}
/**
* @brief Computes the 64-bit FNV1a hash of the given null-terminated string literal at compile time.
*
* @param str The null-terminated string literal to compute the hash for.
* @param value For internal use.
* @param iter For internal use.
* @return The 64-bit FNV1a hash of the string.
*
* @note Source: https://notes.underscorediscovery.com/constexpr-fnv1a/
*/
inline constexpr hash64_t HashDataConst(const char* const str, const hash64_t value = HashInitialValue, const int iter = 0) noexcept {
return (str[0] == '\0') ? value : HashDataConst(&str[1], (value ^ hash64_t(str[0])) * HashPrime, iter + 1);
}
/**
* @brief Computes the 64-bit FNV1a hash of the given null-terminated string literal at compile time, leaving no trace of the original string.
*
* @param str The null-terminated string literal to compute the hash for.
*/
#define STRINGHASH(str) std::integral_constant<hash64_t, HashDataConst(str, HashInitialValue, 0)>::value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment