diff options
Diffstat (limited to 'src/libmowgli/container/dictionary.c')
-rw-r--r-- | src/libmowgli/container/dictionary.c | 97 |
1 files changed, 61 insertions, 36 deletions
diff --git a/src/libmowgli/container/dictionary.c b/src/libmowgli/container/dictionary.c index 22445d7..3ffe08e 100644 --- a/src/libmowgli/container/dictionary.c +++ b/src/libmowgli/container/dictionary.c @@ -50,7 +50,8 @@ struct mowgli_dictionary_ * - if services runs out of memory and cannot allocate the object, * the program will abort. */ -mowgli_dictionary_t *mowgli_dictionary_create(mowgli_dictionary_comparator_func_t compare_cb) +mowgli_dictionary_t * +mowgli_dictionary_create(mowgli_dictionary_comparator_func_t compare_cb) { mowgli_dictionary_t *dtree = (mowgli_dictionary_t *) mowgli_alloc(sizeof(mowgli_dictionary_t)); @@ -63,7 +64,7 @@ mowgli_dictionary_t *mowgli_dictionary_create(mowgli_dictionary_comparator_func_ } /* - * mowgli_dictionary_create_named(const char *name, + * mowgli_dictionary_create_named(const char *name, * mowgli_dictionary_comparator_func_t compare_cb) * * Dictionary object factory. @@ -79,8 +80,8 @@ mowgli_dictionary_t *mowgli_dictionary_create(mowgli_dictionary_comparator_func_ * - if services runs out of memory and cannot allocate the object, * the program will abort. */ -mowgli_dictionary_t *mowgli_dictionary_create_named(const char *name, - mowgli_dictionary_comparator_func_t compare_cb) +mowgli_dictionary_t * +mowgli_dictionary_create_named(const char *name, mowgli_dictionary_comparator_func_t compare_cb) { mowgli_dictionary_t *dtree = (mowgli_dictionary_t *) mowgli_alloc(sizeof(mowgli_dictionary_t)); @@ -110,8 +111,8 @@ mowgli_dictionary_t *mowgli_dictionary_create_named(const char *name, * Side Effects: * - the dictionary comparator function is reset. */ -void mowgli_dictionary_set_comparator_func(mowgli_dictionary_t *dict, - mowgli_dictionary_comparator_func_t compare_cb) +void +mowgli_dictionary_set_comparator_func(mowgli_dictionary_t *dict, mowgli_dictionary_comparator_func_t compare_cb) { return_if_fail(dict != NULL); return_if_fail(compare_cb != NULL); @@ -166,11 +167,14 @@ mowgli_dictionary_get_linear_index(mowgli_dictionary_t *dict, const void *key) return_val_if_fail(key != NULL, 0); elem = mowgli_dictionary_find(dict, key); + if (elem == NULL) return -1; if (!dict->dirty) + { return elem->position; + } else { mowgli_dictionary_elem_t *delem; @@ -248,14 +252,14 @@ mowgli_dictionary_retune(mowgli_dictionary_t *dict, const void *key) * we initialize n with known values, since it's on stack * memory. otherwise the dict would become corrupted. * - * n is used for temporary storage while the tree is retuned. + * n is used for temporary storage while the tree is retuned. * -nenolod */ n.left = n.right = NULL; left = right = &n; /* this for(;;) loop is the main workhorse of the rebalancing */ - for (node = dict->root; ; ) + for (node = dict->root;;) { if ((ret = dict->compare_cb(key, node->key)) == 0) break; @@ -333,8 +337,7 @@ mowgli_dictionary_retune(mowgli_dictionary_t *dict, const void *key) * - a node is linked to the dictionary tree */ void -mowgli_dictionary_link(mowgli_dictionary_t *dict, - mowgli_dictionary_elem_t *delem) +mowgli_dictionary_link(mowgli_dictionary_t *dict, mowgli_dictionary_elem_t *delem) { return_if_fail(dict != NULL); return_if_fail(delem != NULL); @@ -420,19 +423,25 @@ mowgli_dictionary_unlink_root(mowgli_dictionary_t *dict) dict->dirty = true; delem = dict->root; + if (delem == NULL) return; if (dict->root->left == NULL) + { dict->root = dict->root->right; + } else if (dict->root->right == NULL) + { dict->root = dict->root->left; + } else { /* Make the node with the next highest key the new root. * This node has a NULL left pointer. */ nextnode = delem->next; soft_assert(nextnode->left == NULL); + if (nextnode == delem->right) { dict->root = nextnode; @@ -441,8 +450,12 @@ mowgli_dictionary_unlink_root(mowgli_dictionary_t *dict) else { parentofnext = delem->right; + while (parentofnext->left != NULL && parentofnext->left != nextnode) + { parentofnext = parentofnext->left; + } + soft_assert(parentofnext->left == nextnode); parentofnext->left = nextnode->right; dict->root = nextnode; @@ -489,9 +502,8 @@ mowgli_dictionary_unlink_root(mowgli_dictionary_t *dict) * - if this is called without a callback, the objects bound to the * DTree will not be destroyed. */ -void mowgli_dictionary_destroy(mowgli_dictionary_t *dtree, - void (*destroy_cb)(mowgli_dictionary_elem_t *delem, void *privdata), - void *privdata) +void +mowgli_dictionary_destroy(mowgli_dictionary_t *dtree, void (*destroy_cb)(mowgli_dictionary_elem_t *delem, void *privdata), void *privdata) { mowgli_dictionary_elem_t *n, *tn; @@ -526,9 +538,8 @@ void mowgli_dictionary_destroy(mowgli_dictionary_t *dtree, * Side Effects: * - on success, a dtree is iterated */ -void mowgli_dictionary_foreach(mowgli_dictionary_t *dtree, - int (*foreach_cb)(mowgli_dictionary_elem_t *delem, void *privdata), - void *privdata) +void +mowgli_dictionary_foreach(mowgli_dictionary_t *dtree, int (*foreach_cb)(mowgli_dictionary_elem_t *delem, void *privdata), void *privdata) { mowgli_dictionary_elem_t *n, *tn; @@ -563,9 +574,8 @@ void mowgli_dictionary_foreach(mowgli_dictionary_t *dtree, * Side Effects: * - a dtree is iterated until the requested conditions are met */ -void *mowgli_dictionary_search(mowgli_dictionary_t *dtree, - void *(*foreach_cb)(mowgli_dictionary_elem_t *delem, void *privdata), - void *privdata) +void * +mowgli_dictionary_search(mowgli_dictionary_t *dtree, void *(*foreach_cb)(mowgli_dictionary_elem_t * delem, void *privdata), void *privdata) { mowgli_dictionary_elem_t *n, *tn; void *ret = NULL; @@ -603,8 +613,8 @@ void *mowgli_dictionary_search(mowgli_dictionary_t *dtree, * Side Effects: * - the static iterator, &state, is initialized. */ -void mowgli_dictionary_foreach_start(mowgli_dictionary_t *dtree, - mowgli_dictionary_iteration_state_t *state) +void +mowgli_dictionary_foreach_start(mowgli_dictionary_t *dtree, mowgli_dictionary_iteration_state_t *state) { return_if_fail(dtree != NULL); return_if_fail(state != NULL); @@ -641,8 +651,8 @@ void mowgli_dictionary_foreach_start(mowgli_dictionary_t *dtree, * Side Effects: * - none */ -void *mowgli_dictionary_foreach_cur(mowgli_dictionary_t *dtree, - mowgli_dictionary_iteration_state_t *state) +void * +mowgli_dictionary_foreach_cur(mowgli_dictionary_t *dtree, mowgli_dictionary_iteration_state_t *state) { return_val_if_fail(dtree != NULL, NULL); return_val_if_fail(state != NULL, NULL); @@ -666,15 +676,15 @@ void *mowgli_dictionary_foreach_cur(mowgli_dictionary_t *dtree, * Side Effects: * - the static iterator, &state, is advanced to a new DTree node. */ -void mowgli_dictionary_foreach_next(mowgli_dictionary_t *dtree, - mowgli_dictionary_iteration_state_t *state) +void +mowgli_dictionary_foreach_next(mowgli_dictionary_t *dtree, mowgli_dictionary_iteration_state_t *state) { return_if_fail(dtree != NULL); return_if_fail(state != NULL); if (state->cur == NULL) { - mowgli_log("mowgli_dictionary_foreach_next(): called again after iteration finished on dtree<%p>", dtree); + mowgli_log("mowgli_dictionary_foreach_next(): called again after iteration finished on dtree<%p>", (void *) dtree); return; } @@ -702,7 +712,8 @@ void mowgli_dictionary_foreach_next(mowgli_dictionary_t *dtree, * Side Effects: * - none */ -mowgli_dictionary_elem_t *mowgli_dictionary_find(mowgli_dictionary_t *dict, const void *key) +mowgli_dictionary_elem_t * +mowgli_dictionary_find(mowgli_dictionary_t *dict, const void *key) { return_val_if_fail(dict != NULL, NULL); return_val_if_fail(key != NULL, NULL); @@ -733,7 +744,8 @@ mowgli_dictionary_elem_t *mowgli_dictionary_find(mowgli_dictionary_t *dict, cons * Side Effects: * - data is inserted into the DTree. */ -mowgli_dictionary_elem_t *mowgli_dictionary_add(mowgli_dictionary_t *dict, const void *key, void *data) +mowgli_dictionary_elem_t * +mowgli_dictionary_add(mowgli_dictionary_t *dict, const void *key, void *data) { mowgli_dictionary_elem_t *delem; @@ -748,7 +760,7 @@ mowgli_dictionary_elem_t *mowgli_dictionary_add(mowgli_dictionary_t *dict, const if (delem->key == NULL) { - mowgli_log("major WTF: delem->key is NULL, not adding node.", key); + mowgli_log("major WTF: delem->key<%p> is NULL, not adding node.", (void *) key); mowgli_heap_free(elem_heap, delem); return NULL; } @@ -777,7 +789,8 @@ mowgli_dictionary_elem_t *mowgli_dictionary_add(mowgli_dictionary_t *dict, const * Notes: * - the returned data needs to be mowgli_freed/released manually! */ -void *mowgli_dictionary_delete(mowgli_dictionary_t *dtree, const void *key) +void * +mowgli_dictionary_delete(mowgli_dictionary_t *dtree, const void *key) { mowgli_dictionary_elem_t *delem = mowgli_dictionary_find(dtree, key); void *data; @@ -788,7 +801,7 @@ void *mowgli_dictionary_delete(mowgli_dictionary_t *dtree, const void *key) data = delem->data; mowgli_dictionary_unlink_root(dtree); - mowgli_heap_free(elem_heap, delem); + mowgli_heap_free(elem_heap, delem); return data; } @@ -809,7 +822,8 @@ void *mowgli_dictionary_delete(mowgli_dictionary_t *dtree, const void *key) * Side Effects: * - none */ -void *mowgli_dictionary_retrieve(mowgli_dictionary_t *dtree, const void *key) +void * +mowgli_dictionary_retrieve(mowgli_dictionary_t *dtree, const void *key) { mowgli_dictionary_elem_t *delem = mowgli_dictionary_find(dtree, key); @@ -833,7 +847,8 @@ void *mowgli_dictionary_retrieve(mowgli_dictionary_t *dtree, const void *key) * Side Effects: * - none */ -unsigned int mowgli_dictionary_size(mowgli_dictionary_t *dict) +unsigned int +mowgli_dictionary_size(mowgli_dictionary_t *dict) { return_val_if_fail(dict != NULL, 0); @@ -848,11 +863,15 @@ stats_recurse(mowgli_dictionary_elem_t *delem, int depth, int *pmaxdepth) if (depth > *pmaxdepth) *pmaxdepth = depth; + result = depth; + if (delem->left) result += stats_recurse(delem->left, depth + 1, pmaxdepth); + if (delem->right) result += stats_recurse(delem->right, depth + 1, pmaxdepth); + return result; } @@ -872,7 +891,8 @@ stats_recurse(mowgli_dictionary_elem_t *delem, int depth, int *pmaxdepth) * Side Effects: * - callback called with stats text */ -void mowgli_dictionary_stats(mowgli_dictionary_t *dict, void (*cb)(const char *line, void *privdata), void *privdata) +void +mowgli_dictionary_stats(mowgli_dictionary_t *dict, void (*cb)(const char *line, void *privdata), void *privdata) { char str[256]; int sum, maxdepth; @@ -881,19 +901,24 @@ void mowgli_dictionary_stats(mowgli_dictionary_t *dict, void (*cb)(const char *l if (dict->id != NULL) snprintf(str, sizeof str, "Dictionary stats for %s (%d)", - dict->id, dict->count); + dict->id, dict->count); else snprintf(str, sizeof str, "Dictionary stats for <%p> (%d)", - dict, dict->count); + (void *) dict, dict->count); + cb(str, privdata); maxdepth = 0; + if (dict->root != NULL) { sum = stats_recurse(dict->root, 0, &maxdepth); snprintf(str, sizeof str, "Depth sum %d Avg depth %d Max depth %d", sum, sum / dict->count, maxdepth); } else + { snprintf(str, sizeof str, "Depth sum 0 Avg depth 0 Max depth 0"); + } + cb(str, privdata); return; } |