Repository navigation
Expand file tree
/
Copy pathhash_string.h
More file actions
118 lines (99 loc) · 3.84 KB
/
Copy pathhash_string.h
File metadata and controls
118 lines (99 loc) · 3.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#ifndef MODULE_HASH_STRING
#define MODULE_HASH_STRING
#include "string.h"
typedef struct Hash_String {
//Same trick as with String_Builder to make working with
// hashed strings as easy as with regular ones.
union {
struct {
const char* data;
isize count;
};
String string;
};
uint64_t hash;
} Hash_String;
EXTERNAL Hash_String hash_string_from_cstring(const char* cstr);
EXTERNAL Hash_String hash_string_make(String string);
EXTERNAL uint64_t hash_string(String string);
EXTERNAL uint64_t hash_string_ptrs(const String* string);
EXTERNAL bool hash_string_is_equal(Hash_String a, Hash_String b); //Compares two hash strings using hash, size and the contents of data.
EXTERNAL bool hash_string_is_equal_approx(Hash_String a, Hash_String b); //Compares two hash strings using only hash and size. Can be forced to compare data by defining DISSABLE_APPROXIMATE_EQUAL
EXTERNAL Hash_String hash_string_allocate(Allocator* alloc, Hash_String hstring);
EXTERNAL void hash_string_deallocate(Allocator* alloc, Hash_String* hstring);
//Makes a hashed string out of string literal, with optimizations evaluating the hash at compile time (except on GCC). Fails for anything but string literals
#define HSTRING(string_literal) SINIT(Hash_String){string_literal "", sizeof(string_literal "") - 1, hash64_fnv_inline(string_literal "", sizeof(string_literal "") - 1)}
#define HSTRING_FMT "[%08llx]:'%.*s'"
#define HSTRING_PRINT(hstring) (hstring).hash, (int) (hstring).count, (hstring).data
#if defined(_MSC_VER)
#define ATTRIBUTE_INLINE_ALWAYS __forceinline
#elif defined(__GNUC__) || defined(__clang__)
#define ATTRIBUTE_INLINE_ALWAYS __attribute__((always_inline)) inline
#else
#define ATTRIBUTE_INLINE_ALWAYS inline
#endif
//@NOTE: We use fnv because of its extreme simplicity making it very likely to be inlined
// and thus for static strings be evaluated at compile time.
// Both MSVC and CLANG evaluate it at compile time, GCC does not.
ATTRIBUTE_INLINE_ALWAYS static uint64_t hash64_fnv_inline(const char* data, isize size)
{
uint64_t hash = 0;
for(int64_t i = 0; i < size; i++)
hash = (hash * 0x100000001b3ULL) ^ (uint8_t) data[i];
return hash;
}
#endif
#if (defined(MODULE_IMPL_ALL) || defined(MODULE_IMPL_HASH_STRING)) && !defined(MODULE_HAS_IMPL_HASH_STRING)
#define MODULE_HAS_IMPL_HASH_STRING
EXTERNAL Hash_String hash_string_make(String string)
{
Hash_String out = {0};
out.string = string;
out.hash = hash_string(string);
return out;
}
EXTERNAL Hash_String hash_string_from_cstring(const char* cstr)
{
return hash_string_make(string_of(cstr));
}
EXTERNAL uint64_t hash_string(String string)
{
return hash64_fnv_inline(string.data, string.count);
}
EXTERNAL uint64_t hash_string_ptrs(const String* string)
{
return hash64_fnv_inline(string->data, string->count);
}
EXTERNAL bool hash_string_is_equal(Hash_String a, Hash_String b)
{
if(a.hash != b.hash || a.count != b.count)
return false;
return memcmp(a.data, b.data, a.count) == 0;
}
EXTERNAL bool hash_string_is_equal_approx(Hash_String a, Hash_String b)
{
#ifndef DISSABLE_APPROXIMATE_EQUAL
return hash_string_is_equal(a, b);
#else
return a.hash == b.hash && a.count == b.count;
#endif
}
EXTERNAL int hash_string_compare(Hash_String a, Hash_String b)
{
if(a.hash < b.hash) return -1;
if(a.hash > b.hash) return 1;
else return string_compare(a.string, b.string);
}
EXTERNAL Hash_String hash_string_allocate(Allocator* alloc, Hash_String hstring)
{
Hash_String out = {0};
out.string = string_allocate(alloc, hstring.string);
out.hash = hstring.hash;
return out;
}
EXTERNAL void hash_string_deallocate(Allocator* alloc, Hash_String* hstring)
{
string_deallocate(alloc, &hstring->string);
hstring->hash = 0;
}
#endif