- sort: add cpp #ifdef to remove restrict from declaration - tests for guf_dict with GUF_DICT_64_BIT_IDX (and also hash32/hash64); maybe pass kv_type to insert to avoid copy - dict elems shrink to fit; allow to pass GUF_DBUF_USE_GROWTH_FAC_ONE_POINT_FIVE - guf_stack, guf_queue, guf_dqueue, guf_prio_queue (using a heap), guf_ringbuf - guf_dict: maybe put key_hash into kv_elem; maybe change order of key and val in kv_elem depending on size of key and val. - track allocs for test (implement alloc tracker): - each thread needs its own alloc and alloc_ctx; don't track granular, give each allocator it's unique id maybe? - potential idea for alloc: instead of using a pointer (8 or 4 bytes), use a 2 byte id to save space (and avoid dangling pointers): typedef guf_allocator_id uint16_t; // allows for up to (UINT16_MAX - 1) allocators (and 0 for NULL) guf_allocator_dbuf guf_global_allocators; // cf. https://github.com/erincatto/box2d/blob/main/src/id_pool.c typedef struct guf_allocator_id_pool { // Implement generically with macro "templates" guf_allocator_id_dbuf free_ids; guf_allocator_id next_free_id; } guf_allocator_id_pool; guf_allocator_id_pool guf_global_allocator_id_pool; guf_allocator_id guf_register_allocator(guf_allocator allocator) { guf_allocator_id id = get_free_id(&guf_global_allocator_id_pool); if (!id) { return 0; } guf_global_allocators[id] = allocator; } guf_allocator *guf_get_allocator(guf_allocator_id id) { return (id == 0 || id >= UINT16_MAX) ? NULL : (guf_global_allocators + id); } - no guf_init.h - unicode normalisation - handle right-to-left text properly