17 #define MAP_LOAD_FACTOR (90)
37 .size =
sizeof(
void *),
43 .data = &gEmptyBucket,
60 size_t index = hash % map->size;
61 return &map->data[index];
67 size_t index = hash % map->size;
68 return &map->data[index];
73 for (
size_t i = 0; i <
size; i++)
75 buckets[i].
key = NULL;
76 buckets[i].
next = NULL;
99 clear_keys(tmp.data,
size);
122 #define MAP_FOREACH_APPLY(self, item, ...) \
125 for (size_t i = 0; i < self->size; i++) \
127 bucket_t *item = &self->data[i]; \
128 while (item && item->key) \
196 static bool impl_key_equal(
const map_t *map,
const void *lhs,
const void *rhs)
199 return info->
equals(lhs, rhs);
203 static const bucket_t *impl_bucket_get_const(
const map_t *map,
const void *
key)
206 return map_get_bucket_const(map, hash);
213 return map_get_bucket(map, hash);
216 static bool impl_entry_exists(
const map_t *map,
const bucket_t *bucket,
const void *
key)
220 if (impl_key_equal(map, bucket->
key,
key))
223 if (bucket->
next != NULL)
224 return impl_entry_exists(map, bucket->
next,
key);
237 if (previous != NULL)
245 if (bucket->
key == NULL)
255 if (impl_key_equal(map, bucket->
key,
key))
265 static void impl_resize(
map_t *map,
size_t new_size)
268 size_t old_size = map->size;
271 map->size = new_size;
274 clear_keys(map->data, new_size);
276 for (
size_t i = 0; i < old_size; i++)
279 while (entry != NULL)
281 if (entry->
key != NULL)
301 impl_resize(map, map->size * 2);
307 if (impl_insert_into_bucket(map, bucket,
key,
value))
310 if (bucket->
next == NULL)
319 bucket = bucket->
next;
338 const bucket_t *bucket = impl_bucket_get_const(map,
key);
339 while (bucket != NULL)
341 if (bucket->
key != NULL && impl_key_equal(map, bucket->
key,
key))
342 return bucket->
value;
344 bucket = bucket->
next;
356 const bucket_t *bucket = impl_bucket_get_const(map,
key);
357 return impl_entry_exists(map, bucket,
key);
369 while (entry != NULL)
371 if (entry->
key != NULL && impl_key_equal(map, entry->
key,
key))
374 impl_delete_bucket(previous, entry);
391 clear_keys(map->data, map->size);
399 if (entry == NULL || entry->
key == NULL)
404 while (entry->
next != NULL)
408 if (entry->
key != NULL)
427 bucket_t *entry = map_next_in_chain(previous);
435 while (i < map->
size)
437 entry = &map->data[i++];
438 if (entry->
key != NULL)
444 entry = map_next_in_chain(entry);
462 bucket_t *bucket = map_find_next_bucket(map, &index, NULL);
463 bucket_t *
next = map_find_next_bucket(map, &index, bucket);
513 return iter->
bucket != NULL;
CT_LOCAL bool info_ptr_equal(const void *lhs, const void *rhs)
CT_LOCAL ctu_hash_t info_ptr_hash(const void *key)
#define CT_PUREFN
mark a function as pure, always returns the same value for the same arguments
#define CT_HOTFN
mark a function as hot, it is likely to be called often
#define STA_DECL
sal2 annotation on function implementations to copy annotations from the declaration
#define CT_NOALIAS
mark a function as only modifying pointers passed to it the same as CT_CONSTFN but allowed to modify/...
STA_DECL size_t map_count(const map_t *map)
get the number of key-value pairs in a map
STA_DECL CT_HOTFN void * map_get_default(const map_t *map, const void *key, void *other)
get a value from a map or a default value
const map_t kEmptyMap
an empty map
STA_DECL typevec_t * map_entries(map_t *map)
collect all key-value pairs in a map into a vector returns a typevec_t<map_entry_t>
STA_DECL CT_PUREFN bool map_has_next(const map_iter_t *iter)
check if a map iterator has more elements
STA_DECL void map_reset(map_t *map)
clear all key-value pairs from a map
STA_DECL bool map_delete(map_t *map, const void *key)
delete a key-value pair from a map
STA_DECL vector_t * map_values(map_t *map)
collect all the values from a map into a vector
STA_DECL bool map_next_pair(map_iter_t *iter, const void **key, void **value)
get the next key-value pair from a map iterator returns the values via out parameters for ease of use...
STA_DECL map_t map_make(size_t size, hash_info_t info, arena_t *arena)
create a new map on the stack
STA_DECL map_iter_t map_iter(const map_t *map)
create a new map iterator
STA_DECL CT_HOTFN void map_set(map_t *map, const void *key, void *value)
set a key-value pair in a map
STA_DECL map_t * map_new(size_t size, hash_info_t info, arena_t *arena)
create a new map on the heap
STA_DECL bool map_contains(const map_t *map, const void *key)
check if a map contains a key
STA_DECL CT_HOTFN void * map_get(const map_t *map, const void *key)
get a value from a map
STA_DECL CT_NOALIAS map_entry_t map_next(map_iter_t *iter)
get the next key-value pair from a map iterator
#define ARENA_IDENTIFY(ptr, name, parent, arena)
rename and reparent a pointer in a custom allocator
#define ARENA_REPARENT(arena, ptr, parent)
reparent a pointer in a custom allocator
#define ARENA_MALLOC(size, name, parent, arena)
allocate memory from a custom allocator
CT_ARENA_API void arena_free(STA_RELEASE void *ptr, size_t size, arena_t *arena)
release memory from a custom allocator
#define CTASSERT(expr)
assert a condition, prints the condition as a message
CT_STD_API void * typevec_push(typevec_t *vec, const void *src)
push a value onto the vector
CT_NODISCARD CT_STD_API typevec_t * typevec_new(size_t width, size_t len, arena_t *arena)
create a new typed vector on the heap
CT_NODISCARD CT_STD_API vector_t * vector_new(size_t size, arena_t *arena)
create a new vector with an initial capacity
CT_STD_API void vector_push(vector_t **vector, void *value)
push a value onto the end of a vector
STA_DECL void map_init(map_t *map, size_t size, hash_info_t info, arena_t *arena)
#define MAP_FOREACH_APPLY(self, item,...)
struct bucket_t * next
the next bucket in the chain
void * value
any pointer value
information for using a type in a hashset or hashmap
hash_fn_t hash
the hash function for the type
equals_fn_t equals
the equality function for the type
a key-value pair in a map
const void * key
the key of this entry
void * value
the value of this entry
bucket_t * next
the next bucket in the chain
size_t index
current top level bucket index
bucket_t * bucket
the current bucket
const map_t * map
the map being iterated over
arena_t * arena
the arena this map allocates from
hash_info_t info
the hash function for this map
A vector with a fixed type size.
a generic vector of pointers