vessel/scripts/hash.c
Arija A. e5b9ea5155
refact: Refactor HMap to use size_t.
Signed-off-by: Arija A. <ari@ari.lt>
2025-05-05 00:27:49 +03:00

120 lines
2.9 KiB
C

#include <stdio.h>
#include <ctype.h>
#include <stdint.h>
#include <string.h>
#ifndef NULL
# define NULL ((void *)0)
#endif /* NULL */
/* xxHash implementation */
#define XXH3_PRIME64_1 0x9E3779B185EBCA87ULL
#define XXH3_PRIME64_2 0xC2B2AE3D27D4EB4FULL
#define XXH3_PRIME64_3 0x165667B19E3779F9ULL
#define XXH3_PRIME64_4 0x85EBCA77C2B2AE63ULL
#define XXH3_PRIME64_5 0x27D4EB2F165667C5ULL
#define xxh3_rotl64(x, r) ((x << r) | (x >> (64 - r)))
#define xxh3_avalanche(h) \
(h) ^= (h) >> 37; \
(h) *= XXH3_PRIME64_3; \
(h) ^= (h) >> 32
#define xxh3_mix16B(input, seed) \
(*(const uint64_t *)(input) + seed) * (*(const uint64_t *)(input + 8) + seed) + XXH3_PRIME64_1
static uint64_t xxhash3(const void *data, const uint64_t data_size, uint64_t seed) {
uint64_t h64, k1;
if (!data || data_size == 0)
return 0;
if (seed == 0)
seed = data_size;
const uint8_t *input = (const uint8_t *)data;
const uint8_t *end = input + data_size;
if (data_size >= 16) {
h64 = seed * XXH3_PRIME64_1;
do {
h64 += xxh3_mix16B(input, seed);
input += 16;
} while (input <= end - 16);
xxh3_avalanche(h64);
} else
h64 = data_size + XXH3_PRIME64_5;
h64 += data_size;
while (input + 8 <= end) {
k1 = *(const uint64_t *)input;
k1 *= XXH3_PRIME64_2;
k1 = xxh3_rotl64(k1, 31);
k1 *= XXH3_PRIME64_1;
h64 ^= k1;
h64 = xxh3_rotl64(h64, 27) * XXH3_PRIME64_1 + XXH3_PRIME64_4;
input += 8;
}
while (input < end) {
h64 ^= (uint64_t)(*input) * (uint64_t)XXH3_PRIME64_5;
h64 = xxh3_rotl64(h64, 11) * XXH3_PRIME64_1;
++input;
}
xxh3_avalanche(h64);
#ifdef __BIG_ENDIAN__
h64 = (h64 >> 56) | ((h64 >> 40) & 0x000000000000FF00ULL) |
((h64 >> 24) & 0x0000000000FF0000ULL) | ((h64 >> 8) & 0x00000000FF000000ULL) |
((h64 << 8) & 0x000000FF00000000ULL) | ((h64 << 24) & 0x0000FF0000000000ULL) |
((h64 << 40) & 0x00FF000000000000ULL) | ((h64 << 56) & 0xFF00000000000000ULL);
#endif /* __BIG_ENDIAN__ */
return h64;
}
static uint64_t fnv1a(const void *src, const uint64_t length) {
const uint8_t *data = (const uint8_t *)src;
uint64_t h = 14695981039346656037ULL;
for (uint64_t idx = 0; idx < length; ++idx) {
h ^= data[idx];
h *= 1099511628211ULL;
}
return h;
}
static char *uppstr(char *src) {
if (!src)
return NULL;
while (*src) {
*src = (char)toupper((unsigned char)*src);
++src;
}
return src;
}
int main(int argc, char *argv[]) {
if (argc < 3) {
fprintf(stderr, "Usage: %s <name> <string>\n", argv[0]);
return 1;
}
uppstr(argv[1]);
printf("#define %s_HASH %luULL /* %s */\n",
argv[1],
xxhash3(argv[2], strlen(argv[2]), fnv1a(argv[2], strlen(argv[2]))),
argv[2]);
return 0;
}