blob: 5db544ce8bceea1464efa6133ee37aa82ec22ab0 [file] [log] [blame]
Zane Shelley72b755f2022-01-18 17:06:22 -06001#pragma once
2
3#include <assert.h>
4
5#include <hei_types.hpp>
6
7#include <limits>
8#include <string>
9
10namespace libhei
11{
12
13//------------------------------------------------------------------------------
14
15/**
16 * @brief The string hashing algorithm used for register and isolation node
17 * names.
18 */
19inline uint64_t hash(unsigned int i_bytes, const std::string& i_str)
20{
21 // This hash is a simple "n*s[0] + (n-1)*s[1] + ... + s[n-1]" algorithm,
22 // where s[i] is a chunk from the input string the length of i_bytes.
23
24 // Currently only supporting 1-8 byte hashes.
25 assert(1 <= i_bytes && i_bytes <= sizeof(uint64_t));
26
27 // Start hashing each chunk.
28 uint64_t sumA = 0;
29 uint64_t sumB = 0;
30
31 // Iterate one chunk at a time.
32 for (unsigned int i = 0; i < i_str.size(); i += i_bytes)
33 {
34 // Combine each chunk into a single integer value. If we reach the end
35 // of the string, pad with null characters.
36 uint64_t chunk = 0;
37 for (unsigned int j = 0; j < i_bytes; j++)
38 {
39 chunk <<= 8;
40 chunk |= (i + j < i_str.size()) ? i_str[i + j] : '\0';
41 }
42
43 // Apply the simple hash.
44 sumA += chunk;
45 sumB += sumA;
46 }
47
48 // Mask off everything except the target number of bytes.
49 auto mask = std::numeric_limits<uint64_t>::max();
50 sumB &= mask >> ((sizeof(uint64_t) - i_bytes) * 8);
51
52 return sumB;
53}
54
55template <class T>
56inline T hash(const std::string& i_str)
57{
58 return static_cast<T>(hash(sizeof(T), i_str));
59}
60
61// Specialization for RegisterId_t because they are only a 3-byte field.
62template <>
63inline RegisterId_t hash<RegisterId_t>(const std::string& i_str)
64{
65 return static_cast<RegisterId_t>(hash(3, i_str));
66}
67
68//------------------------------------------------------------------------------
69
70} // namespace libhei