From 932849a0629221f741883fe750cf75fddbec5ba2 Mon Sep 17 00:00:00 2001 From: Gregory Lirent Date: Fri, 26 Aug 2022 17:54:27 +0300 Subject: [PATCH] Add callback support on value update (#61) --- include/dict.h | 18 +++----- include/list.h | 24 +++++------ include/map.h | 20 ++++----- src/dict/modify.c | 107 ++++++++-------------------------------------- src/list/modify.c | 16 ++++--- src/map/modify.c | 13 ++++-- 6 files changed, 66 insertions(+), 132 deletions(-) diff --git a/include/dict.h b/include/dict.h index 1be89a3..80b705b 100644 --- a/include/dict.h +++ b/include/dict.h @@ -19,10 +19,8 @@ inline void dict_init(vtype_dict* x) { x->nodes = (void*)(x->capacity = x->size #define dict_pop(x, key, data, callback) libcdsb_dict_find (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), data, callback, 1) #define dict_get(x, key, data, callback) libcdsb_dict_find (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), data, callback, 0) -#define dict_update(x, key, value) libcdsb_dict_update (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value)) -#define dict_inject(x, key, value) libcdsb_dict_inject (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value)) -#define dict_inject_key(x, key, value) libcdsb_dict_inject_key (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value)) -#define dict_inject_value(x, key, value) libcdsb_dict_inject_value(x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value)) +#define dict_update(x, key, value) libcdsb_dict_update (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), 0, 0) +#define dict_inject(x, key, value) libcdsb_dict_inject (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), 0, 0) #define dict_foreach(x, data, callback) libcdsb_dict_foreach (x, data, callback, 0) #define dict_remove(x, key) dict_pop (x, key, 0, 0) @@ -30,12 +28,10 @@ inline void dict_init(vtype_dict* x) { x->nodes = (void*)(x->capacity = x->size /*#####################################################################################################################*/ -extern bool libcdsb_dict_update (vtype_dict* x, const void* key, vtype key_type, const void* value, vtype value_type) Nonnull__(1); -extern bool libcdsb_dict_inject (vtype_dict* x, const void* key, vtype key_type, const void* value, vtype value_type) Nonnull__(1); -extern bool libcdsb_dict_inject_key (vtype_dict* x, const void* key, vtype key_type, const void* value, vtype value_type) Nonnull__(1); -extern bool libcdsb_dict_inject_value (vtype_dict* x, const void* key, vtype key_type, const void* value, vtype value_type) Nonnull__(1); -extern int libcdsb_dict_find (vtype_dict* x, const void* key, vtype key_type, void* data, dict_access_callback, bool cut) Nonnull__(1); -extern int libcdsb_dict_foreach (vtype_dict* x, void* data, dict_access_callback, bool flush) Nonnull__(1,3); -extern bool libcdsb_dict_shrink_to_fit(vtype_dict* x) Nonnull__(1); +extern bool libcdsb_dict_update (vtype_dict* x, const void* key, vtype key_type, const void* value, vtype value_type, void* data, dict_access_callback) Nonnull__(1); +extern bool libcdsb_dict_inject (vtype_dict* x, const void* key, vtype key_type, const void* value, vtype value_type, void* data, dict_access_callback) Nonnull__(1); +extern int libcdsb_dict_find (vtype_dict* x, const void* key, vtype key_type, void* data, dict_access_callback, bool cut) Nonnull__(1); +extern int libcdsb_dict_foreach (vtype_dict* x, void* data, dict_access_callback, bool flush) Nonnull__(1,3); +extern bool libcdsb_dict_shrink_to_fit(vtype_dict* x) Nonnull__(1); #endif /* LIBCDSB_DICT_H */ diff --git a/include/list.h b/include/list.h index 0ebbf47..01fe796 100644 --- a/include/list.h +++ b/include/list.h @@ -28,12 +28,12 @@ inline void list_init (vtype_list* x) { x->first = x->last = 0; } #define list_find(x, value, data, callback) libcdsb_list_find (x, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), data, callback, 0, 0) #define list_rfind(x, value, data, callback) libcdsb_list_find (x, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), data, callback, 1, 0) #define list_countof(x, value) libcdsb_list_count (x, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value)) -#define list_insert(x, index, value) libcdsb_list_insert (x, index, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), -1) -#define list_replace(x, index, value) libcdsb_list_insert (x, index, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), 0) -#define list_push_back(x, value) libcdsb_list_insert (x, -1, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), 1) -#define list_push_front(x, value) libcdsb_list_insert (x, 0, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), -1) -#define list_attach_back(x, value) libcdsb_list_attach (x, -1, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), 1) -#define list_attach_front(x, value) libcdsb_list_attach (x, 0, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), -1) +#define list_insert(x, index, value) libcdsb_list_insert (x, index, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), -1, 0, 0) +#define list_replace(x, index, value) libcdsb_list_insert (x, index, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), 0, 0, 0) +#define list_push_back(x, value) libcdsb_list_insert (x, -1, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), 1, 0, 0) +#define list_push_front(x, value) libcdsb_list_insert (x, 0, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), -1, 0, 0) +#define list_attach_back(x, value) libcdsb_list_attach (x, -1, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), 1, 0, 0) +#define list_attach_front(x, value) libcdsb_list_attach (x, 0, _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), -1, 0, 0) #define list_foreach(x, data, callback) libcdsb_list_foreach(x, data, callback, 0) #define list_remove(x, value) list_pop (x, value, 0, 0) #define list_remove_by_index(x, index) list_pop_by_index (x, index, 0, 0) @@ -42,12 +42,12 @@ inline void list_init (vtype_list* x) { x->first = x->last = 0; } /*#####################################################################################################################*/ -extern bool libcdsb_list_insert (vtype_list* x, ssize_t index, const void* value, vtype type, int ins_direction) Nonnull__(1); -extern bool libcdsb_list_attach (vtype_list* x, ssize_t index, const void* value, vtype type, int ins_direction) Nonnull__(1); -extern int libcdsb_list_find (vtype_list* x, const void* value, vtype type, void* data, list_access_callback, bool reverse, bool cut) Nonnull__(1); -extern int libcdsb_list_get (vtype_list* x, ssize_t index, void* data, list_access_callback, bool cut) Nonnull__(1); -extern int libcdsb_list_foreach (vtype_list* x, void* data, list_access_callback, bool flush) Nonnull__(1,3); +extern bool libcdsb_list_insert (vtype_list* x, ssize_t index, const void* value, vtype type, int ins_direction, void* data, list_access_callback) Nonnull__(1); +extern bool libcdsb_list_attach (vtype_list* x, ssize_t index, const void* value, vtype type, int ins_direction, void* data, list_access_callback) Nonnull__(1); +extern int libcdsb_list_find (vtype_list* x, const void* value, vtype type, void* data, list_access_callback, bool reverse, bool cut) Nonnull__(1); +extern int libcdsb_list_get (vtype_list* x, ssize_t index, void* data, list_access_callback, bool cut) Nonnull__(1); +extern int libcdsb_list_foreach (vtype_list* x, void* data, list_access_callback, bool flush) Nonnull__(1,3); -extern size_t libcdsb_list_count(const vtype_list* s, const void* value, vtype type) Pure__ Warn_unused_result__ Nonnull__(1); +extern size_t libcdsb_list_count(const vtype_list* s, const void* value, vtype type) Pure__ Warn_unused_result__ Nonnull__(1); #endif /* LIBCDSB_LIST_H */ diff --git a/include/map.h b/include/map.h index a3264be..f5ed144 100644 --- a/include/map.h +++ b/include/map.h @@ -16,20 +16,20 @@ extern void map_init(vtype_map* x, vtype key_type) Nonnull__(1); /*#####################################################################################################################*/ -#define map_pop(x, key, data, callback) libcdsb_map_find (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), data, callback, 1) -#define map_get(x, key, data, callback) libcdsb_map_find (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), data, callback, 0) -#define map_update(x, key, value) libcdsb_map_update (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value)) -#define map_inject(x, key, value) libcdsb_map_inject (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value)) -#define map_foreach(x, data, callback) libcdsb_map_foreach (x, data, callback, RBFOREACH_UNSPECIFIED, 0) -#define map_remove(x, key) map_pop (x, key, 0, 0) +#define map_pop(x, key, data, callback) libcdsb_map_find (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), data, callback, 1) +#define map_get(x, key, data, callback) libcdsb_map_find (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), data, callback, 0) +#define map_update(x, key, value) libcdsb_map_update (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), 0, 0) +#define map_inject(x, key, value) libcdsb_map_inject (x, _LIBCDSB_value_pointer(key), _LIBCDSB_vtypeof(key), _LIBCDSB_value_pointer(value), _LIBCDSB_vtypeof(value), 0, 0) +#define map_foreach(x, data, callback) libcdsb_map_foreach(x, data, callback, RBFOREACH_UNSPECIFIED, 0) +#define map_remove(x, key) map_pop (x, key, 0, 0) #define in_map(x, key) (map_get(x, key, 0, 0) == 0) /*#####################################################################################################################*/ -extern bool libcdsb_map_update (vtype_map* x, const void* key, vtype key_type, const void* value, vtype value_type) Nonnull__(1); -extern bool libcdsb_map_inject (vtype_map* x, const void* key, vtype key_type, const void* value, vtype value_type) Nonnull__(1); -extern int libcdsb_map_find (vtype_map* x, const void* key, vtype key_type, void* data, map_access_callback, bool cut) Nonnull__(1); -extern int libcdsb_map_foreach(vtype_map* x, void* data, map_access_callback, rbforeach_t, bool flush) Nonnull__(1,3); +extern bool libcdsb_map_update (vtype_map* x, const void* key, vtype key_type, const void* value, vtype value_type, void* data, map_access_callback) Nonnull__(1); +extern bool libcdsb_map_inject (vtype_map* x, const void* key, vtype key_type, const void* value, vtype value_type, void* data, map_access_callback) Nonnull__(1); +extern int libcdsb_map_find (vtype_map* x, const void* key, vtype key_type, void* data, map_access_callback, bool cut) Nonnull__(1); +extern int libcdsb_map_foreach(vtype_map* x, void* data, map_access_callback, rbforeach_t, bool flush) Nonnull__(1,3); #endif /* LIBCDSB_MAP_H */ diff --git a/src/dict/modify.c b/src/dict/modify.c index 7f34591..5720b10 100644 --- a/src/dict/modify.c +++ b/src/dict/modify.c @@ -50,7 +50,7 @@ bool libcdsb_dict_shrink_to_fit(dict_t* s) { } -bool libcdsb_dict_update(dict_t* x, const void* k, vtype kt, const void* v, vtype vt) { +bool libcdsb_dict_update(dict_t* x, const void* k, vtype kt, const void* v, vtype vt, void* dt, dict_access_callback callback) { dnode_t *c, **p; if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX) @@ -60,10 +60,12 @@ bool libcdsb_dict_update(dict_t* x, const void* k, vtype kt, const void* v, vtyp while (!is_null(c)) { if (vtype_compare(k, kt, vnode_peek(&c->key, c->key_type), c->key_type) == 0) { + if (!callback) callback(vnode_peek(&c->key, c->key_type), c->key_type, + vnode_peek(&c->value, c->value_type), c->value_type, dt); + vnode_free(&c->value, c->value_type); - c->value = vnode_create(v, vt); - c->value_type = vt; + c->value = vnode_create(v, c->value_type = vt); return true; } else c = c->prev; @@ -71,11 +73,9 @@ bool libcdsb_dict_update(dict_t* x, const void* k, vtype kt, const void* v, vtyp c = malloc(sizeof(*c)); - c->prev = *p; - c->key = vnode_create(k, kt); - c->value = vnode_create(v, vt); - c->key_type = kt; - c->value_type = vt; + c->prev = *p; + c->key = vnode_create(k, c->key_type = kt); + c->value = vnode_create(v, c->value_type = vt); *p = c; ++x->size; @@ -84,7 +84,7 @@ bool libcdsb_dict_update(dict_t* x, const void* k, vtype kt, const void* v, vtyp } -bool libcdsb_dict_inject(dict_t* x, const void* k, vtype kt, const void* v, vtype vt) { +bool libcdsb_dict_inject(dict_t* x, const void* k, vtype kt, const void* v, vtype vt, void* dt, dict_access_callback callback) { dnode_t *c, **p; if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX) @@ -94,93 +94,22 @@ bool libcdsb_dict_inject(dict_t* x, const void* k, vtype kt, const void* v, vtyp while (!is_null(c)) { if (vtype_compare(k, kt, vnode_peek(&c->key, c->key_type), c->key_type) == 0) { + if (!callback) callback(vnode_peek(&c->key, c->key_type), c->key_type, + vnode_peek(&c->value, c->value_type), c->value_type, dt); + + vnode_free(&c->key, c->key_type); vnode_free(&c->value, c->value_type); - c->value = vnode_create(v, vt); - c->value_type = vt; + vnode_attach(&c->key, k, c->key_type = kt); + vnode_attach(&c->value, v, c->value_type = vt); return true; } else c = c->prev; } - c = malloc(sizeof(*c)); - - c->prev = *p; - c->key_type = kt; - c->value_type = vt; - - vnode_attach(&c->key, k, kt); - vnode_attach(&c->value, v, vt); - - *p = c; - ++x->size; - - return false; -} - - -bool libcdsb_dict_inject_key(dict_t* x, const void* k, vtype kt, const void* v, vtype vt) { - dnode_t *c, **p; - - if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX) - libcdsb_builtin_rehash(x, x->capacity + CAPACITY_BLOCK); - - c = *(p = x->nodes + (vtype_hash(k, kt) % x->capacity)); - - while (!is_null(c)) { - if (vtype_compare(k, kt, vnode_peek(&c->key, c->key_type), c->key_type) == 0) { - vnode_free(&c->value, c->value_type); - - c->value = vnode_create(v, vt); - c->value_type = vt; - - return true; - } else c = c->prev; - } - - c = malloc(sizeof(*c)); - - c->prev = *p; - c->value = vnode_create(v, vt); - c->key_type = kt; - c->value_type = vt; - - vnode_attach(&c->key, k, kt); - - *p = c; - ++x->size; - - return false; -} - - -bool libcdsb_dict_inject_value(dict_t* x, const void* k, vtype kt, const void* v, vtype vt) { - dnode_t *c, **p; - - if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX) - libcdsb_builtin_rehash(x, x->capacity + CAPACITY_BLOCK); - - c = *(p = x->nodes + (vtype_hash(k, kt) % x->capacity)); - - while (!is_null(c)) { - if (vtype_compare(k, kt, vnode_peek(&c->key, c->key_type), c->key_type) == 0) { - vnode_free(&c->value, c->value_type); - - c->value = vnode_create(v, vt); - c->value_type = vt; - - return true; - } else c = c->prev; - } - - c = malloc(sizeof(*c)); - - c->prev = *p; - c->key = vnode_create(k, kt); - c->key_type = kt; - c->value_type = vt; - - vnode_attach(&c->value, v, vt); + (c = malloc(sizeof(*c)))->prev = *p; + vnode_attach(&c->key, k, c->key_type = kt); + vnode_attach(&c->value, v, c->value_type = vt); *p = c; ++x->size; diff --git a/src/list/modify.c b/src/list/modify.c index 5e1a604..c9265ea 100644 --- a/src/list/modify.c +++ b/src/list/modify.c @@ -3,7 +3,7 @@ #include "include.h" -bool libcdsb_list_insert(list_t* x, ssize_t i, const void* v, vtype t, int ins) { +bool libcdsb_list_insert(list_t* x, ssize_t i, const void* v, vtype t, int ins, void* dt, list_access_callback callback) { ldir_t dir; lnode_t* c; @@ -41,8 +41,10 @@ bool libcdsb_list_insert(list_t* x, ssize_t i, const void* v, vtype t, int ins) } else ldir_inv((lnode_t*)x, dir) = c; ldir_dir(ldir_inv(c, dir), dir) = c; - - } else vnode_free(&c->node, c->type); + } else { + if (callback) callback(vnode_peek(&c->node, c->type), -1, c->type, dt); + vnode_free(&c->node, c->type); + } c->node = vnode_create(v, t); c->type = t; @@ -51,7 +53,7 @@ bool libcdsb_list_insert(list_t* x, ssize_t i, const void* v, vtype t, int ins) } -bool libcdsb_list_attach(list_t* x, ssize_t i, const void* v, vtype t, int ins) { +bool libcdsb_list_attach(list_t* x, ssize_t i, const void* v, vtype t, int ins, void* dt, list_access_callback callback) { ldir_t dir; lnode_t* c; @@ -89,8 +91,10 @@ bool libcdsb_list_attach(list_t* x, ssize_t i, const void* v, vtype t, int ins) } else ldir_inv((lnode_t*)x, dir) = c; ldir_dir(ldir_inv(c, dir), dir) = c; - - } else vnode_free(&c->node, c->type); + } else { + if (callback) callback(vnode_peek(&c->node, c->type), -1, c->type, dt); + vnode_free(&c->node, c->type); + } vnode_attach(&c->node, v, c->type = t); diff --git a/src/map/modify.c b/src/map/modify.c index 400fa6a..32c5461 100644 --- a/src/map/modify.c +++ b/src/map/modify.c @@ -3,7 +3,7 @@ #include "include.h" -bool libcdsb_map_update(map_t* x, const void* k, vtype kt, const void* v, vtype vt) { +bool libcdsb_map_update(map_t* x, const void* k, vtype kt, const void* v, vtype vt, void* dt, map_access_callback callback) { int cmp; mnode_t* n; mnode_t* p; @@ -14,10 +14,12 @@ bool libcdsb_map_update(map_t* x, const void* k, vtype kt, const void* v, vtype cmp = vtype_compare(k, kt, vnode_peek(&n->key, kt), kt); if (cmp == 0) { + if (callback) callback(vnode_peek(&n->key, x->type), x->type, + vnode_peek(&n->value, n->type), n->type, dt); + vnode_free(&n->value, n->type); - n->value = vnode_create(v, vt); - n->type = vt; + n->value = vnode_create(v, n->type = vt); return true; } @@ -43,7 +45,7 @@ bool libcdsb_map_update(map_t* x, const void* k, vtype kt, const void* v, vtype } -bool libcdsb_map_inject(map_t* x, const void* k, vtype kt, const void* v, vtype vt) { +bool libcdsb_map_inject(map_t* x, const void* k, vtype kt, const void* v, vtype vt, void* dt, map_access_callback callback) { int cmp; mnode_t* n; mnode_t* p; @@ -60,6 +62,9 @@ bool libcdsb_map_inject(map_t* x, const void* k, vtype kt, const void* v, vtype cmp = vtype_compare(k, kt, vnode_peek(&n->key, kt), kt); if (cmp == 0) { + if (callback) callback(vnode_peek(&n->key, x->type), x->type, + vnode_peek(&n->value, n->type), n->type, dt); + vnode_free(&n->key, x->type); vnode_free(&n->value, n->type);