Go to the documentation of this file. 1 #ifndef CSNIP_LPHASH_TABLE
2 #define CSNIP_LPHASH_TABLE
32 #define CSNIP_LPHASH_TABLE_DEF_TYPE(struct_tbltype, \
34 struct struct_tbltype { \
48 #define CSNIP_LPHASH_TABLE_DECL_FUNCS(scope, \
54 scope tbltype* prefix##make(int* err); \
55 scope void prefix##free(tbltype* tbl); \
58 scope int prefix##insert( \
62 scope int prefix##insert_or_assign( \
66 entrytype* ret_old); \
67 scope entrytype* prefix##find_or_insert( \
71 scope _Bool prefix##remove( \
75 scope entrytype* prefix##find( \
80 scope size_t prefix##size(const tbltype* tbl); \
81 scope size_t prefix##capacity(const tbltype* tbl); \
84 scope size_t prefix##findslot( \
87 scope _Bool prefix##isslotoccupied( \
90 scope entrytype* prefix##getslotentryaddress( \
93 scope size_t prefix##getslotfromentryaddress( \
95 entrytype const * entry); \
96 scope size_t prefix##removeatslot( \
100 scope size_t prefix##firstoccupiedslot( \
101 const tbltype* tbl); \
102 scope size_t prefix##nextoccupiedslot( \
103 const tbltype* tbl, \
202 #define CSNIP_LPHASH_TABLE_DEF_FUNCS(scope, \
214 CSNIP_LPHASH_TABLE_DECL_FUNCS(scope, prefix, keytype, entrytype, \
218 static size_t prefix##_internal_findloc( \
226 csnip_lphash_Find(T->cap, keytype, k1, u, \
229 (e = T->entry[u], k2 = (get_key), (is_match)), \
230 (e = T->entry[u], (get_key)), \
237 static void prefix##_internal_deleteloc(tbltype* T, \
241 csnip_lphash_Delete(T->cap, keytype, k1, u, v, \
244 (e = T->entry[u], (get_key)), \
245 (T->entry[v] = T->entry[u], T->occ[v] = T->occ[u]), \
250 static _Bool prefix##_internal_grow(tbltype* T, \
254 if (min_size * 3 <= T->cap * 2) { \
260 size_t newcap = (T->cap ? T->cap : 8); \
261 while (min_size * 3 > newcap * 2) { \
268 unsigned char* newocc; \
269 csnip_mem_Alloc(newcap, newarr, *err); \
270 if (err && *err) return 0; \
271 csnip_mem_Alloc(newcap, newocc, *err); \
272 if (err && *err) return 0; \
279 for (size_t i = 0; i < newcap; ++i) { \
284 for (size_t i = 0; i < T->cap; ++i) { \
288 entrytype e = T->entry[i]; \
289 l = prefix##_internal_findloc(&N, \
292 newarr[l] = T->entry[i]; \
298 if (T->entry) csnip_mem_Free(T->entry); \
299 if (T->occ) csnip_mem_Free(T->occ); \
306 scope tbltype* prefix##make(int* err) \
311 csnip_mem_Alloc(1, T, *err); \
321 scope void prefix##free(tbltype* T) \
323 if (T->entry) csnip_mem_Free(T->entry); \
324 if (T->occ) csnip_mem_Free(T->occ); \
334 scope int prefix##insert(tbltype* T, int* err, entrytype e) \
339 prefix##_internal_grow(T, err, T->size + 1); \
345 keytype key = (get_key); \
346 size_t loc = prefix##_internal_findloc(T, key, &r); \
361 scope int prefix##insert_or_assign(tbltype* T, \
369 prefix##_internal_grow(T, err, T->size + 1); \
375 keytype key = (get_key); \
376 size_t loc = prefix##_internal_findloc(T, key, &r); \
379 if (old) *old = T->entry[loc]; \
388 scope entrytype* prefix##find_or_insert(tbltype* T, \
395 entrytype e = entry; \
396 size_t loc = prefix##_internal_findloc(T, (get_key), &r); \
399 if (prefix##_internal_grow(T, err, T->size + 1)) { \
403 loc = prefix##_internal_findloc(T, \
411 T->entry[loc] = entry; \
415 return &T->entry[loc]; \
418 scope _Bool prefix##remove(tbltype* T, int* err, keytype key) \
421 const size_t loc = prefix##_internal_findloc(T, key, &r); \
423 prefix##_internal_deleteloc(T, loc); \
429 scope entrytype* prefix##find(const tbltype* T, keytype key) \
432 const size_t loc = prefix##_internal_findloc(T, key, &r); \
434 return &T->entry[loc]; \
439 scope size_t prefix##size(const tbltype* T) \
444 scope size_t prefix##capacity(const tbltype* T) \
450 scope size_t prefix##findslot(const tbltype* T, keytype key) \
453 const size_t loc = prefix##_internal_findloc(T, key, &r); \
459 scope _Bool prefix##isslotoccupied(const tbltype* T, size_t i) \
461 assert(0 <= i && i < T->cap); \
465 scope entrytype* prefix##getslotentryaddress( \
469 return &T->entry[i]; \
472 scope size_t prefix##getslotfromentryaddress( \
474 entrytype const* entry) \
476 return (size_t)(entry - T->entry); \
479 scope size_t prefix##removeatslot(tbltype* T, int* err, size_t i) \
484 prefix##_internal_deleteloc(T, i); \
489 return prefix##nextoccupiedslot(T, i); \
492 scope size_t prefix##firstoccupiedslot(const tbltype* T) \
495 for (r = 0; r < T->cap; ++r) \
496 if (T->occ[r]) break; \
500 scope size_t prefix##nextoccupiedslot( \
504 for (++r; r < T->cap; ++r) \
505 if (T->occ[r]) break; \