diff options
Diffstat (limited to 'libmisc')
-rw-r--r-- | libmisc/include/libmisc/linkedlist.h | 112 | ||||
-rw-r--r-- | libmisc/include/libmisc/map.h | 86 | ||||
-rw-r--r-- | libmisc/linkedlist.c | 14 | ||||
-rw-r--r-- | libmisc/map.c | 73 |
4 files changed, 176 insertions, 109 deletions
diff --git a/libmisc/include/libmisc/linkedlist.h b/libmisc/include/libmisc/linkedlist.h index 8adef66..e8c65db 100644 --- a/libmisc/include/libmisc/linkedlist.h +++ b/libmisc/include/libmisc/linkedlist.h @@ -7,40 +7,102 @@ #ifndef _LIBMISC_LINKEDLIST_H_ #define _LIBMISC_LINKEDLIST_H_ -#include <libmisc/assert.h> -#include <libmisc/macro.h> +/* low-level (intrusive) singly linked list ***********************************/ -/* singly linked list *********************************************************/ +struct _slist_node { + struct _slist_node *rear; +}; -typedef struct _lm_sll_node { - struct _lm_sll_node *rear; -} lm_sll_node; +struct _slist_root { + struct _slist_node *front, *rear; +}; -typedef struct { - lm_sll_node *front, *rear; -} lm_sll_root; +void _slist_push_to_rear(struct _slist_root *root, struct _slist_node *node); +void _slist_pop_from_front(struct _slist_root *root); -#define lm_sll_node_cast(node_typ, node_ptr) \ - LM_CAST_FIELD_TO_STRUCT(node_typ, lm_sll_node, node_ptr) +/* low-level (intrusive) doubly linked list ***********************************/ -void lm_sll_push_to_rear(lm_sll_root *root, lm_sll_node *node); -void lm_sll_pop_from_front(lm_sll_root *root); +struct _dlist_node { + struct _dlist_node *front, *rear; +}; -/* doubly linked list *********************************************************/ +struct _dlist_root { + struct _dlist_node *front, *rear; +}; -typedef struct _lm_dll_node { - struct _lm_dll_node *front, *rear; -} lm_dll_node; +void _dlist_push_to_rear(struct _dlist_root *root, struct _dlist_node *node); +void _dlist_remove(struct _dlist_root *root, struct _dlist_node *node); +void _dlist_pop_from_front(struct _dlist_root *root); -typedef struct { - lm_dll_node *front, *rear; -} lm_dll_root; +/* singly linked list (non-intrusive) *****************************************/ -#define lm_dll_node_cast(node_typ, node_ptr) \ - LM_CAST_FIELD_TO_STRUCT(node_typ, lm_dll_node, node_ptr) +#define SLIST_DECLARE(NAME) \ + struct NAME##_node; \ + struct NAME { \ + struct NAME##_node *front, *rear; \ + struct NAME *_slist_root_typ[0]; \ + } -void lm_dll_push_to_rear(lm_dll_root *root, lm_dll_node *node); -void lm_dll_remove(lm_dll_root *root, lm_dll_node *node); -void lm_dll_pop_from_front(lm_dll_root *root); +#define SLIST_DECLARE_NODE(NAME, VAL_T) \ + struct NAME##_node { \ + struct NAME##_node *rear; \ + VAL_T val; \ + } + +#define slist_push_to_rear(ROOT, NODE) { \ + /* These temporary variables are to get the compiler to check \ + * the types. */ \ + typeof(*(ROOT)->_slist_root_typ[0]) *_rootp = ROOT; \ + typeof(*_rootp->front) *_nodep = NODE; \ + _slist_push_to_rear((struct _slist_root *)_rootp, \ + (struct _slist_node *)_nodep); \ +} while(0) + +#define slist_pop_from_front(ROOT) { \ + /* This temporary variables are to get the compiler to check \ + * the type. */ \ + typeof(*(ROOT)->_slist_root_typ[0]) *_rootp = ROOT; \ + _slist_pop_from_front((struct _slist_root *)_rootp); \ +} while(0) + +/* doubly linked list (non-intrusive) *****************************************/ + +#define DLIST_DECLARE(NAME) \ + struct NAME##_node; \ + struct NAME { \ + struct NAME##_node *front, *rear; \ + struct NAME *_dlist_root_typ[0]; \ + } + +#define DLIST_DECLARE_NODE(NAME, VAL_T) \ + struct NAME##_node { \ + struct NAME##_node *front, *rear; \ + VAL_T val; \ + } + +#define dlist_push_to_rear(ROOT, NODE) { \ + /* These temporary variables are to get the compiler to check \ + * the types. */ \ + typeof(*(ROOT)->_dlist_root_typ[0]) *_rootp = ROOT; \ + typeof(*_rootp->front) *_nodep = NODE; \ + _dlist_push_to_rear((struct _dlist_root *)_rootp, \ + (struct _dlist_node *)_nodep); \ +} while(0) + +#define dlist_remove(ROOT, NODE) { \ + /* These temporary variables are to get the compiler to check \ + * the types. */ \ + typeof(*(ROOT)->_dlist_root_typ[0]) *_rootp = ROOT; \ + typeof(*_rootp->front) *_nodep = NODE; \ + _dlist_remove((struct _dlist_root *)_rootp, \ + (struct _dlist_node *)_nodep); \ +} while(0) + +#define dlist_pop_from_front(ROOT) { \ + /* This temporary variables are to get the compiler to check \ + * the type. */ \ + typeof(*(ROOT)->_dlist_root_typ[0]) *_rootp = ROOT; \ + _dlist_pop_from_front((struct _dlist_root *)_rootp); \ +} while(0) #endif /* _LIBMISC_LINKEDLIST_H_ */ diff --git a/libmisc/include/libmisc/map.h b/libmisc/include/libmisc/map.h index f846f57..41ac069 100644 --- a/libmisc/include/libmisc/map.h +++ b/libmisc/include/libmisc/map.h @@ -15,12 +15,14 @@ /* Type ***********************************************************************/ +DLIST_DECLARE(_map_kv_list); + struct _map { - size_t len; - size_t nbuckets; - lm_dll_root *buckets; + size_t len; + size_t nbuckets; + struct _map_kv_list *buckets; - unsigned iterating; + unsigned int iterating; size_t sizeof_kv; size_t offsetof_k, sizeof_k; @@ -30,25 +32,26 @@ struct _map { /** * MAP_DECLARE(MAPNAME, KEY_T, VAL_T) declares `struct MAPNAME`. */ -#define MAP_DECLARE(MAPNAME, KEY_T, VAL_T) \ - struct MAPNAME { \ - struct _map core; \ - struct { \ - lm_dll_node; \ - uint8_t flags; \ - KEY_T key; \ - VAL_T val; \ - } kv_typ[0]; \ +#define MAP_DECLARE(MAPNAME, KEY_T, VAL_T) \ + struct _##MAPNAME##_kv { \ + uint8_t flags; \ + KEY_T key; \ + VAL_T val; \ + }; \ + DLIST_DECLARE_NODE(_##MAPNAME##_kv_list, struct _##MAPNAME##_kv); \ + struct MAPNAME { \ + struct _map core; \ + struct _##MAPNAME##_kv_list_node kv_typ[0]; \ } -#define _map_init(M) do { \ - if (!(M)->core.sizeof_kv) { \ - (M)->core.sizeof_kv = sizeof((M)->kv_typ[0]); \ - (M)->core.sizeof_k = sizeof((M)->kv_typ[0].key); \ - (M)->core.sizeof_v = sizeof((M)->kv_typ[0].val); \ - (M)->core.offsetof_k = offsetof(typeof((M)->kv_typ[0]), key); \ - (M)->core.offsetof_v = offsetof(typeof((M)->kv_typ[0]), val); \ - } \ +#define _map_init(M) do { \ + if (!(M)->core.sizeof_kv) { \ + (M)->core.sizeof_kv = sizeof((M)->kv_typ[0]); \ + (M)->core.sizeof_k = sizeof((M)->kv_typ[0].val.key); \ + (M)->core.sizeof_v = sizeof((M)->kv_typ[0].val.val); \ + (M)->core.offsetof_k = offsetof(typeof((M)->kv_typ[0]), val.key); \ + (M)->core.offsetof_v = offsetof(typeof((M)->kv_typ[0]), val.val); \ + } \ } while(0) /* Methods ********************************************************************/ @@ -64,8 +67,8 @@ struct _map { */ #define map_load(M, K) ({ \ _map_init(M); \ - typeof((M)->kv_typ[0].key) _k = K; \ - (typeof((M)->kv_typ[0].val)*)_map_load(&(M)->core, &_k); \ + typeof((M)->kv_typ[0].val.key) _k = K; \ + (typeof((M)->kv_typ[0].val.val)*)_map_load(&(M)->core, &_k); \ }) void *_map_load(struct _map *m, void *kp); @@ -73,10 +76,10 @@ void *_map_load(struct _map *m, void *kp); * map_del(map, key) ensures that `key` is not present in `map`. * Returns whether `key` was in `map` before the call. */ -#define map_del(M, K) ({ \ - _map_init(M); \ - typeof((M)->kv_typ[0].key) _k = K; \ - _map_del(&(M)->core, &_k); \ +#define map_del(M, K) ({ \ + _map_init(M); \ + typeof((M)->kv_typ[0].val.key) _k = K; \ + _map_del(&(M)->core, &_k); \ }) bool _map_del(struct _map *m, void *kp); @@ -84,11 +87,11 @@ bool _map_del(struct _map *m, void *kp); * map_store(map, key, val) sets a value in the map. Returns a * pointer to the map's copy of `val`. */ -#define map_store(M, K, ...) ({ \ - _map_init(M); \ - typeof((M)->kv_typ[0].key) _k = K; \ - typeof((M)->kv_typ[0].val) _v = __VA_ARGS__; \ - (typeof((M)->kv_typ[0].val)*)_map_store(&(M)->core, &_k, &_v); \ +#define map_store(M, K, ...) ({ \ + _map_init(M); \ + typeof((M)->kv_typ[0].val.key) _k = K; \ + typeof((M)->kv_typ[0].val.val) _v = __VA_ARGS__; \ + (typeof((M)->kv_typ[0].val.val)*)_map_store(&(M)->core, &_k, &_v); \ }) void *_map_store(struct _map *m, void *kp, void *vp); @@ -100,18 +103,13 @@ void _map_free(struct _map *m); /* Iteration ******************************************************************/ -struct _map_kv { - lm_dll_node; - uint8_t flags; -}; - struct _map_iter { - struct _map *m; - void *keyp; - void **valpp; + struct _map *m; + void *keyp; + void **valpp; - size_t i; - struct _map_kv *kv; + size_t i; + struct _map_kv_list_node *kv; }; /** @@ -128,8 +126,8 @@ struct _map_iter { #define MAP_FOREACH(M, KNAME, VNAME) _MAP_FOREACH(__COUNTER__, M, KNAME, VNAME) #define _MAP_FOREACH(CNT, M, KNAME, VNAME) \ for (bool _once_##CNT = true; _once_##CNT;) \ - for (typeof((M)->kv_typ[0].key) KNAME; _once_##CNT;) \ - for (typeof((M)->kv_typ[0].val) *VNAME; _once_##CNT;) \ + for (typeof((M)->kv_typ[0].val.key) KNAME; _once_##CNT;) \ + for (typeof((M)->kv_typ[0].val.val) *VNAME; _once_##CNT;) \ for ( \ struct _map_iter _iter_##CNT = ({ \ _map_init(M); \ diff --git a/libmisc/linkedlist.c b/libmisc/linkedlist.c index 5fe0977..71a0aa9 100644 --- a/libmisc/linkedlist.c +++ b/libmisc/linkedlist.c @@ -6,11 +6,13 @@ #include <stddef.h> /* for NULL */ +#include <libmisc/assert.h> + #include <libmisc/linkedlist.h> /* singly linked list *********************************************************/ -void lm_sll_push_to_rear(lm_sll_root *root, lm_sll_node *node) { +void _slist_push_to_rear(struct _slist_root *root, struct _slist_node *node) { assert(root); node->rear = NULL; if (root->rear) @@ -20,7 +22,7 @@ void lm_sll_push_to_rear(lm_sll_root *root, lm_sll_node *node) { root->rear = node; } -void lm_sll_pop_from_front(lm_sll_root *root) { +void _slist_pop_from_front(struct _slist_root *root) { assert(root); assert(root->front); root->front = root->front->rear; @@ -30,7 +32,7 @@ void lm_sll_pop_from_front(lm_sll_root *root) { /* doubly linked list *********************************************************/ -void lm_dll_push_to_rear(lm_dll_root *root, lm_dll_node *node) { +void _dlist_push_to_rear(struct _dlist_root *root, struct _dlist_node *node) { assert(root); assert(node); node->front = root->rear; @@ -42,7 +44,7 @@ void lm_dll_push_to_rear(lm_dll_root *root, lm_dll_node *node) { root->rear = node; } -void lm_dll_remove(lm_dll_root *root, lm_dll_node *node) { +void _dlist_remove(struct _dlist_root *root, struct _dlist_node *node) { assert(root); assert(node); if (node->front) @@ -55,8 +57,8 @@ void lm_dll_remove(lm_dll_root *root, lm_dll_node *node) { root->rear = node->front; } -void lm_dll_pop_from_front(lm_dll_root *root) { +void _dlist_pop_from_front(struct _dlist_root *root) { assert(root); assert(root->front); - lm_dll_remove(root, root->front); + _dlist_remove(root, root->front); } diff --git a/libmisc/map.c b/libmisc/map.c index bb8a2d2..7629c8c 100644 --- a/libmisc/map.c +++ b/libmisc/map.c @@ -16,14 +16,19 @@ /* Internal utilities *********************************************************/ -#define cast(n) lm_dll_node_cast(struct _map_kv, n) - -static inline void *_map_kv_keyp(struct _map *m, struct _map_kv *kv) { +struct _map_kv { + uint8_t flags; + /* opaque key; */ + /* opaque val; */ +}; +DLIST_DECLARE_NODE(_map_kv_list, struct _map_kv); + +static inline void *_map_kv_keyp(struct _map *m, struct _map_kv_list_node *kv) { assert(m); assert(kv); return ((void*)kv)+m->offsetof_k; } -static inline void *_map_kv_valp(struct _map *m, struct _map_kv *kv) { +static inline void *_map_kv_valp(struct _map *m, struct _map_kv_list_node *kv) { assert(m); assert(kv); return ((void*)kv)+m->offsetof_v; @@ -31,8 +36,8 @@ static inline void *_map_kv_valp(struct _map *m, struct _map_kv *kv) { static inline void _map_lookup(struct _map *m, void *keyp, hash_t *ret_hash, - lm_dll_root **ret_bucket, - struct _map_kv **ret_kv) { + struct _map_kv_list **ret_bucket, + struct _map_kv_list_node **ret_kv) { assert(m); assert(keyp); assert(ret_hash); @@ -45,8 +50,8 @@ static inline void _map_lookup(struct _map *m, void *keyp, return; } *ret_bucket = &m->buckets[*ret_hash % m->nbuckets]; - for (struct _map_kv *kv = cast((*ret_bucket)->front); kv; kv = cast(kv->rear)) { - if (!(kv->flags & FLAG_DEL) && + for (struct _map_kv_list_node *kv = (*ret_bucket)->front; kv; kv = kv->rear) { + if (!(kv->val.flags & FLAG_DEL) && memcmp(_map_kv_keyp(m, kv), keyp, m->sizeof_k) == 0) { *ret_kv = kv; return; @@ -58,13 +63,13 @@ static inline void _map_lookup(struct _map *m, void *keyp, static inline void _map_resize(struct _map *m, size_t new_nbuckets) { assert(m); assert(new_nbuckets); - lm_dll_root *new_buckets = calloc(new_nbuckets, sizeof(lm_dll_root)); + struct _map_kv_list *new_buckets = calloc(new_nbuckets, sizeof(struct _map_kv_list)); for (size_t i = 0; i < m->nbuckets; i++) { while (m->buckets[i].front) { - struct _map_kv *kv = cast(m->buckets[i].front); - lm_dll_pop_from_front(&m->buckets[i]); + struct _map_kv_list_node *kv = m->buckets[i].front; + dlist_pop_from_front(&m->buckets[i]); hash_t h = hash(_map_kv_keyp(m, kv), m->sizeof_k); - lm_dll_push_to_rear(&new_buckets[h % new_nbuckets], kv); + dlist_push_to_rear(&new_buckets[h % new_nbuckets], kv); } } m->nbuckets = new_nbuckets; @@ -91,8 +96,8 @@ void *_map_load(struct _map *m, void *keyp) { assert(keyp); hash_t h; - lm_dll_root *bucket; - struct _map_kv *kv; + struct _map_kv_list *bucket; + struct _map_kv_list_node *kv; _map_lookup(m, keyp, &h, &bucket, &kv); if (!kv) @@ -105,16 +110,16 @@ bool _map_del(struct _map *m, void *keyp) { assert(keyp); hash_t h; - lm_dll_root *bucket; - struct _map_kv *kv; + struct _map_kv_list *bucket; + struct _map_kv_list_node *kv; _map_lookup(m, keyp, &h, &bucket, &kv); if (!kv) return false; - if (kv->flags & FLAG_ITER) { - kv->flags |= FLAG_DEL; + if (kv->val.flags & FLAG_ITER) { + kv->val.flags |= FLAG_DEL; } else { - lm_dll_remove(bucket, kv); + dlist_remove(bucket, kv); free(kv); } m->len--; @@ -127,12 +132,12 @@ void *_map_store(struct _map *m, void *keyp, void *valp) { assert(valp); hash_t h; - lm_dll_root *bucket; - struct _map_kv *old; + struct _map_kv_list *bucket; + struct _map_kv_list_node *old; _map_lookup(m, keyp, &h, &bucket, &old); if (old) { - lm_dll_remove(bucket, old); + dlist_remove(bucket, old); free(old); m->len--; } @@ -141,10 +146,10 @@ void *_map_store(struct _map *m, void *keyp, void *valp) { h = hash(keyp, m->sizeof_k); bucket = &m->buckets[h % m->nbuckets]; } - struct _map_kv *kv = calloc(1, m->sizeof_kv); + struct _map_kv_list_node *kv = calloc(1, m->sizeof_kv); memcpy(_map_kv_keyp(m, kv), keyp, m->sizeof_k); memcpy(_map_kv_valp(m, kv), valp, m->sizeof_v); - lm_dll_push_to_rear(bucket, kv); + dlist_push_to_rear(bucket, kv); return _map_kv_valp(m, kv); } @@ -153,8 +158,8 @@ void _map_free(struct _map *m) { for (size_t i = 0; i < m->nbuckets; i++) { while (m->buckets[i].front) { - struct _map_kv *kv = cast(m->buckets[i].front); - lm_dll_pop_from_front(&m->buckets[i]); + struct _map_kv_list_node *kv = m->buckets[i].front; + dlist_pop_from_front(&m->buckets[i]); free(kv); } } @@ -199,14 +204,14 @@ bool _map_iter_next(struct _map_iter *state) { return false; while (!state->m->buckets[state->i].front) state->i++; - state->kv = cast(state->m->buckets[state->i].front); + state->kv = state->m->buckets[state->i].front; } else { - struct _map_kv *old_kv = state->kv; - state->kv = cast(old_kv->rear); + struct _map_kv_list_node *old_kv = state->kv; + state->kv = old_kv->rear; - old_kv->flags &= ~FLAG_ITER; - if (old_kv->flags & FLAG_DEL) { - lm_dll_remove(&state->m->buckets[state->i], old_kv); + old_kv->val.flags &= ~FLAG_ITER; + if (old_kv->val.flags & FLAG_DEL) { + dlist_remove(&state->m->buckets[state->i], old_kv); free(old_kv); } @@ -214,10 +219,10 @@ bool _map_iter_next(struct _map_iter *state) { state->i++; if (state->i == state->m->nbuckets) return false; - state->kv = cast(state->m->buckets[state->i].front); + state->kv = state->m->buckets[state->i].front; } } - state->kv->flags |= FLAG_ITER; + state->kv->val.flags |= FLAG_ITER; memcpy(state->keyp, _map_kv_keyp(state->m, state->kv), state->m->sizeof_k); *(state->valpp) = _map_kv_valp(state->m, state->kv); return true; |