1#include "include/pw.h"
2#include "src/types/string/string_internal.h"
3
4/*
5 * Implementation of hash methods.
6 *
7 * Calculate hash of codepoints regardless of char size.
8 */
9
10#define HASH_IMPL(type_name) \
11{ \
12 type_name* ptr = (type_name*) self_ptr; \
13 while (length--) { \
14 union { \
15 struct { \
16 char32_t a; \
17 char32_t b; \
18 }; \
19 uint64_t i64; \
20 } data; \
21 \
22 data.a = *ptr++; \
23 \
24 if (0 == length--) { \
25 data.b = 0; \
26 _pw_hash_uint64(ctx, data.i64); \
27 break; \
28 } \
29 data.b = *ptr++; \
30 _pw_hash_uint64(ctx, data.i64); \
31 } \
32}
33
34static void strhash_1(uint8_t* self_ptr, unsigned length, PwHashContext* ctx) HASH_IMPL(uint8_t)
35static void strhash_2(uint8_t* self_ptr, unsigned length, PwHashContext* ctx) HASH_IMPL(uint16_t)
36static void strhash_4(uint8_t* self_ptr, unsigned length, PwHashContext* ctx) HASH_IMPL(uint32_t)
37
38static void strhash_3(uint8_t* self_ptr, unsigned length, PwHashContext* ctx)
39{
40 while (length--) {
41 union {
42 struct {
43 char32_t a;
44 char32_t b;
45 };
46 uint64_t i64;
47 } data;
48
49 data.a = *self_ptr++;
50 data.a |= (*self_ptr++) << 8;
51 data.a |= (*self_ptr++) << 16;
52 if (0 == length--) {
53 data.b = 0;
54 _pw_hash_uint64(ctx, data.i64);
55 break;
56 }
57 data.b = *self_ptr++;
58 data.b |= (*self_ptr++) << 8;
59 data.b |= (*self_ptr++) << 16;
60 _pw_hash_uint64(ctx, data.i64);
61 }
62}
63
64StrHash _pw_strhash_variants[5] = {
65 nullptr,
66 strhash_1,
67 strhash_2,
68 strhash_3,
69 strhash_4
70};