-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathxht.h
156 lines (127 loc) · 3.89 KB
/
xht.h
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// (c) 2020 shdown
// This code is licensed under MIT license (see LICENSE.MIT for details)
#pragma once
#include "common.h"
typedef union {
void *p;
uintptr_t u;
} xHt_Value;
typedef struct {
char *key;
size_t nkey;
xHt_Value value;
uint32_t next;
uint32_t hash;
} xHt_Item;
typedef struct {
xHt_Item *items;
uint32_t *buckets;
uint32_t nbuckets;
uint32_t items_size;
uint32_t items_capacity;
} xHt;
xHt_Value xht_remove(
xHt *ht,
const char *key,
size_t nkey,
uint32_t hash,
xHt_Value if_absent);
#define xht_remove_ptr(ht, key, nkey, hash, if_absent) \
(xht_remove(ht, key, nkey, hash, (xHt_Value) {.p = (if_absent)}).p)
#define xht_remove_int(ht, key, nkey, hash, if_absent) \
(xht_remove(ht, key, nkey, hash, (xHt_Value) {.u = (if_absent)}).u)
xHt_Value *xht_insert_new_unchecked(
xHt *ht,
const char *key,
size_t nkey,
uint32_t hash,
xHt_Value value);
#define xht_insert_new_unchecked_ptr(ht, key, nkey, hash, value) \
(&xht_insert_new_unchecked(ht, key, nkey, hash, (xHt_Value) {.p = (value)})->p)
#define xht_insert_new_unchecked_int(ht, key, nkey, hash, value) \
(&xht_insert_new_unchecked(ht, key, nkey, hash, (xHt_Value) {.u = (value)})->u)
uint32_t xht_indexed_first(
xHt *ht,
uint32_t start_bucket);
uint32_t xht_indexed_next(
xHt *ht,
const char *key,
size_t nkey,
uint32_t hash);
UU_INHEADER xHt xht_new(int8_t rank)
{
uint32_t nbuckets = ((uint32_t) 1) << rank;
uint32_t *buckets = uu_xmalloc(nbuckets, sizeof(uint32_t));
memset(buckets, '\xFF', sizeof(uint32_t) * (size_t) nbuckets);
return (xHt) {
.items = NULL,
.buckets = buckets,
.nbuckets = nbuckets,
.items_size = 0,
.items_capacity = 0,
};
}
UU_INHEADER uint32_t xht_size(xHt *ht)
{
return ht->items_size;
}
UU_INHEADER xHt_Value xht_get(
xHt *ht,
const char *key,
size_t nkey,
uint32_t hash,
xHt_Value if_absent)
{
uint32_t bucket = hash & (ht->nbuckets - 1);
uint32_t i = ht->buckets[bucket];
while (i != (uint32_t) -1) {
xHt_Item item = ht->items[i];
if (item.nkey == nkey && (nkey == 0 || memcmp(key, item.key, nkey) == 0))
return item.value;
i = item.next;
}
return if_absent;
}
#define xht_get_ptr(ht, key, nkey, hash, if_absent) \
(xht_get(ht, key, nkey, hash, (xHt_Value) {.p = (if_absent)}).p)
#define xht_get_int(ht, key, nkey, hash, if_absent) \
(xht_get(ht, key, nkey, hash, (xHt_Value) {.u = (if_absent)}).u)
UU_INHEADER xHt_Value *xht_put(
xHt *ht,
const char *key,
size_t nkey,
uint32_t hash,
xHt_Value value)
{
uint32_t bucket = hash & (ht->nbuckets - 1);
uint32_t i = ht->buckets[bucket];
while (i != (uint32_t) -1) {
xHt_Item item = ht->items[i];
if (item.nkey == nkey && (nkey == 0 || memcmp(key, item.key, nkey) == 0))
return &ht->items[i].value;
i = item.next;
}
return xht_insert_new_unchecked(ht, key, nkey, hash, value);
}
#define xht_put_ptr(ht, key, nkey, hash, value) \
(&xht_put(ht, key, nkey, hash, (xHt_Value) {.p = (value)})->p)
#define xht_put_int(ht, key, nkey, hash, value) \
(&xht_put(ht, key, nkey, hash, (xHt_Value) {.u = (value)})->u)
UU_INHEADER const char *xht_indexed_key(xHt *ht, uint32_t idx, size_t *len)
{
xHt_Item *pitem = &ht->items[idx];
*len = pitem->nkey;
return pitem->key;
}
UU_INHEADER void xht_destroy(xHt *ht)
{
free(ht->buckets);
xHt_Item *items = ht->items;
uint32_t nitems = ht->items_size;
for (uint32_t i = 0; i < nitems; ++i) {
free(items[i].key);
}
free(items);
}
#define xht_foreach(ht, item, item_end) \
for (xHt_Item *item = (ht)->items, *item_end = (ht)->items + (ht)->items_size; item != item_end; ++item)