NAME
HashMap
—
A simple hash map
implementation.
SYNOPSIS
#include
<HashMap.h>
HashMap *
HashMapCreate
(void);
void
HashMapFree
(HashMap
*);
void
HashMapLoadSet
(HashMap
*, float);
void
HashMapFunctionSet
(HashMap
*, unsigned long (*)
(const char *));
void *
HashMapSet
(HashMap
*, char *,
void *);
void *
HashMapGet
(HashMap
*, char *);
void *
HashMapDelete
(HashMap
*, char *);
int
HashMapIterate
(HashMap
*, char **,
void **);
DESCRIPTION
This is the public interface for Telodendria's hash map implementation. This hash map is designed to be simple, well documented, and generally readable and understandable, yet also performant enough to be useful, because it is used extensively in Telodendria.
Fundamentally, this is an entirely generic map implementation. It
can be used for many general purposes, but it is designed to only implement
the features that Telodendria needs to function well. One example of a
Telodendria-specific feature is that keys are NULL
-terminated
strings, not any arbitrary data.
These functions operate on an opaque
HashMap
structure, which the caller has no knowledge
about.
HashMapCreate
()
creates a new hash map that is ready to be used with the rest of the hash
map functions.
HashMapFree
()
frees this hash map, such that it becomes invalid and any future use with
the functions in this API results in undefined behavior. Note that it does
not free the keys or values stored in the hash map, since this
implementation has no way of knowing what is actually stored in it, and
where it is located. You should use HashMapIterate
()
to free the values appropriately.
HashMapMaxLoadSet
()
controls the maximum load of the hash map before it is expanded. When the
hash map reaches the given capacity, it is grown. You don't want to only
grow hash maps when they are full, because that makes them perform very
poorly. The maximum load value is a percentage of how full the hash map is,
and it should be between 0 and 1, where 0 means that no elements will cause
the map to be expanded, and 1 means that the hash map must be completely
full before it is expanded. The default maximum load on a new
HashMap
object is 0.75, which should be good enough
for most purposes, but if you need finer tuning, feel free to play with the
max load with this function. The changes take effect on the next insert.
HashMapFunctionSet
()
allows the given hash map to use a custom hashing function. New hash maps
have a sane hashing function that should work okay for most use cases, but
if you have a better hash function, it can be specified with this function.
Do not change the hash function after keys have been added; doing so results
in undefined behavior. Only set the hash function immediately after
constructing a new hash map.
HashMapSet
()
sets the given string key to the given value. Note neither the key nor the
value is copied into the hash map's own memory space; only pointers are
stored. It is the caller's job to ensure that the key and value memory
remains valid for the life of the HashMap, and are freed when they are no
longer needed.
HashMapGet
()
retrieves the value for the given key and .Fn HashMapDelete removes a value
from a given key.
HashMapIterate
()
iterates over all the keys and values of a hash map. This function works
very similarly to
getopt(3), where calls are repeatedly made in a
while
loop until there are no more items to go over.
The difference is that this function does not rely on globals; it takes
pointer pointers, and stores all necessary state inside the hash map
structure itself. Note that this does not make this function thread-safe;
two threads cannot be iterating over any given hash map at the same time,
though they can be iterating over different hash maps at the same time.
This function can be tricky to use in some scenarios, as it continues where it left off on each call, until there are no more elements to go through in the hash map. If you are not iterating over the entire map in one go, and happen to break the loop, then the next time you attempt to iterate the hash map, you'll start somewhere in the middle. Thus, it's recommended to always iterate over the entire hash map if you're going to use this function. Also note that the behavior of this function is undefined if insertions or deletions occur during the iteration. It may work fine; it may not. That functionality has not been tested.
HashMapIterate
()
takes a pointer to a string ponter, and a pointer to a value pointer. When
iterating over the keys and values of the hash map, it sets these pointers
to the current position in the map so that the caller can use them for his
own purposes.
RETURN VALUES
HashMapCreate
() may return
NULL
if memory could not be allocated on the heap.
Otherwise, it returns a valid pointer to a HashMap
structure which can be used with the other functions in this API.
HashMapSet
() returns the previous value at
the passed key, or NULL
if no such value exists. All
keys must have values; you can't set a key to NULL
.
To delete a key, use the HashMapDelete
()
function.
HashMapDelete
() returns the value that was
deleted from the hash map at the given key, or NULL
if no such value exists.
HashMapIterate
() returns 1 if there are
still elements left in the current iteration of the hash map, or 0 if no
valid hash map was provided, or there are no more elements in it for the
current iteration. Note that as soon as this function returns 0 on a hash
map, subsequent iterations will start from the beginning.