pool.h (1899B)
1 #ifndef KIT_POOL_H 2 #define KIT_POOL_H 3 4 #include "core/arena.h" 5 #include "core/core.h" 6 #include "core/heap.h" 7 #include "core/slice.h" 8 9 typedef struct PoolEntry { 10 const char* data; 11 u32 len; 12 u32 hash; 13 } PoolEntry; 14 15 /* Direct-mapped accelerator cache for pool_intern_slice. Keyed on a cheap fold 16 * of (len + the leading bytes), NOT full FNV. A hit byte-verifies via the 17 * interned bytes, so it is a pure accelerator that can never return a wrong 18 * Sym and never affects Sym numbering (a first occurrence still goes through 19 * the normal hash+probe+insert). sym == 0 marks an empty slot. We store only 20 * {keyhash, sym} — never a borrowed input pointer (those aim into transient 21 * lexer buffers). Power-of-two size; mask is POOL_ICACHE_SIZE - 1. */ 22 #define POOL_ICACHE_SIZE 1024u 23 typedef struct PoolICacheSlot { 24 u32 keyhash; 25 Sym sym; 26 } PoolICacheSlot; 27 28 struct Pool { 29 Heap* heap; 30 Arena arena; /* string storage */ 31 32 /* Hash table: 0 means empty. Otherwise it's a Sym id (1-based). */ 33 Sym* table; 34 u32 cap; /* always a power of two */ 35 u32 used; 36 u32 grow_threshold; /* precomputed cap*LOAD_NUM/LOAD_DEN; grow when used>= it */ 37 38 /* Sym → string mapping. Index 0 reserved as Sym = 0 ("none"). */ 39 PoolEntry* entries; 40 u32 nentries; 41 u32 entries_cap; 42 43 /* Direct-mapped intern accelerator (zero-init = all empty). */ 44 PoolICacheSlot* icache; 45 }; 46 47 void pool_init(Pool*, Heap*); 48 void pool_fini(Pool*); 49 50 /* Interning. Returns the canonical id; equal byte sequences → equal ids 51 * (Sym 0 for the empty slice). pool_slice returns the interned bytes as a 52 * slice (SLICE_NULL for Sym 0); its pointer is NUL-terminated as a boundary 53 * convenience, with the NUL excluded from len. */ 54 Sym pool_intern_slice(Pool*, Slice); 55 /* Convenience: intern a NUL-terminated C string (interns Sym 0 for NULL). */ 56 Sym pool_intern_cstr(Pool*, const char*); 57 Slice pool_slice(Pool*, Sym); 58 59 #endif