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};