2 * Copyright (c) 2015 Mohamed Aslan <maslan@sce.carleton.ca>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 #define KV_USED (1 << 0)
37 pjw_hash(void *key
, size_t size
)
40 uint8_t *ptr
= (uint8_t *) key
;
43 for (i
= 0; i
< size
; i
++) {
44 h
= (h
<< 4) + ptr
[i
];
45 if ((hi
= h
& 0xf0000000))
53 alloc(struct hashtab
*ht
, void *key
, size_t size
, size_t *idx
)
58 h
= ht
->hash(key
, size
) % ht
->size
;
59 while (i
++ < ht
->size
) {
60 if (!(ht
->kv
[h
].flags
& KV_USED
)) { /* 1. empty slot */
64 if (ht
->kv
[h
].key_size
== size
) { /* 2. used by the same
66 if (!(memcmp(ht
->kv
[h
].key
, key
, size
))) {
71 h
= (h
+ 1) % ht
->size
; /* 3. used by a different key */
77 lookup(struct hashtab
*ht
, void *key
, size_t size
, size_t *idx
)
82 h
= ht
->hash(key
, size
) % ht
->size
;
83 while (i
++ < ht
->size
) {
84 if (ht
->kv
[h
].key_size
== size
) {
85 if (!(memcmp(ht
->kv
[h
].key
, key
, size
))) {
90 h
= (h
+ 1) % ht
->size
;
96 put(struct hashtab
*ht
, size_t idx
, void *key
, size_t ksize
, void *val
,
99 ht
->kv
[idx
].key
= malloc(ksize
);
100 ht
->kv
[idx
].key_size
= ksize
;
101 ht
->kv
[idx
].val
= malloc(vsize
);
102 ht
->kv
[idx
].val_size
= vsize
;
103 memcpy(ht
->kv
[idx
].key
, key
, ksize
);
104 memcpy(ht
->kv
[idx
].val
, val
, vsize
);
105 ht
->kv
[idx
].flags
|= KV_USED
;
109 get(struct hashtab
*ht
, size_t idx
, void **val
, size_t *size
)
111 *val
= ht
->kv
[idx
].val
;
112 *size
= ht
->kv
[idx
].val_size
;
116 del(struct hashtab
*ht
, size_t idx
)
118 free(ht
->kv
[idx
].key
);
119 free(ht
->kv
[idx
].val
);
120 memset(&ht
->kv
[idx
], 0, sizeof(struct hashtab_kv
));
124 hashtab_init(struct hashtab
*ht
, uint8_t size
, struct hashtab_options
*opts
)
128 if (size
< HTMIN
|| size
> HTMAX
)
130 ht
->size
= 1UL << size
;
131 ht
->kv
= (struct hashtab_kv
*) calloc(ht
->size
,
132 sizeof(struct hashtab_kv
));
138 hashtab_first(struct hashtab
*ht
, size_t *iter
)
140 if (ht
== NULL
|| iter
== NULL
)
142 for (*iter
= 0; *iter
< ht
->size
; (*iter
)++) {
143 if (!(ht
->kv
[*iter
].flags
& KV_USED
))
151 hashtab_next(struct hashtab
*ht
, size_t *iter
)
153 if (ht
== NULL
|| iter
== NULL
)
155 for ((*iter
)++; *iter
< ht
->size
; (*iter
)++) {
156 if (!(ht
->kv
[*iter
].flags
& KV_USED
))
164 hashtab_at(struct hashtab
*ht
, size_t iter
, void **key
, size_t *ksize
,
165 void **val
, size_t *vsize
)
167 if (ht
== NULL
|| key
== NULL
|| ksize
== NULL
|| val
== NULL
||
170 if (iter
>= ht
->size
)
172 if (!(ht
->kv
[iter
].flags
& KV_USED
))
174 *key
= ht
->kv
[iter
].key
;
175 *ksize
= ht
->kv
[iter
].key_size
;
176 *val
= ht
->kv
[iter
].val
;
177 *vsize
= ht
->kv
[iter
].val_size
;
182 hashtab_put(struct hashtab
*ht
, void *key
, size_t ksize
, void *val
,
189 if (!alloc(ht
, key
, ksize
, &idx
))
191 put(ht
, idx
, key
, ksize
, val
, vsize
);
196 hashtab_get(struct hashtab
*ht
, void *key
, size_t ksize
, void **val
,
201 if (ht
== NULL
|| val
== NULL
|| vsize
== NULL
)
203 if (!lookup(ht
, key
, ksize
, &idx
))
205 get(ht
, idx
, val
, vsize
);
210 hashtab_del(struct hashtab
*ht
, void *key
, size_t size
)
216 if (!lookup(ht
, key
, size
, &idx
))