From cb73654ecc93d8efed08ab337812bd0d63170241 Mon Sep 17 00:00:00 2001 From: Katharina Fey Date: Sun, 28 Aug 2016 13:58:50 +0200 Subject: Adding the ability to copy nodes in shallow or deep mode --- include/dtree/dtree.h | 22 ++++++++++++-- lib/dtree.c | 84 +++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 93 insertions(+), 13 deletions(-) diff --git a/include/dtree/dtree.h b/include/dtree/dtree.h index 912030a..e4ced5b 100644 --- a/include/dtree/dtree.h +++ b/include/dtree/dtree.h @@ -200,6 +200,20 @@ dt_err dtree_merge_trees(dtree *data, dtree *merge); dt_err dtree_search_payload(dtree *data, dtree *(*found), void *payload, dt_uni_t type); + +/** + * Much like #{dtree_search_payload} but limiting it's search to keys in a list structure of certain depth. + * This means that in a key-value store structure only top-level items can be searched or the entire + * depth of the tree (or any vaue in between) + * + * @param data + * @param found + * @param payload + * @param type + * @return + */ +dt_err dtree_search_keypayload(dtree *data, dtree *(*found), void *payload, dt_uni_t type, int depth); + /** * Performs a deep copy of a data node hirarchy. Does not copy externally * pointed structures. Does garuantee safety of hirarchy. @@ -225,14 +239,15 @@ dt_err dtree_copy_deep(dtree *data, dtree *(*copy)); */ dt_err dtree_copy(dtree *data, dtree *(*copy)); + /** * A retrieve function to get data back from a node that doesn't require * you to manually access parts of the struct. * * Needs to be provided with a reference to a pointer that can then be * written to. You can make the reference type specific if you know - * what kind of data you're expecting or leave it as a void* to let - * libdyntree do the casting for you. + * what kind of data you're expecting. Please however note that compiler + * errors might occur if you provide a wrong pointer type. * * @param data Node reference to access * @param val Reference pointer to write into @@ -270,7 +285,8 @@ dt_err dtree_free_shallow(dtree *data); /** * Like #{dtree_free_shallow} but will also remove structs that - * weren't allocated by libdyntree + * weren't allocated by libdyntree. Will throw warnings when trying + * to free payloads from shallow copy nodes * * @param data * @return diff --git a/lib/dtree.c b/lib/dtree.c index b2ea03e..30d8c9a 100644 --- a/lib/dtree.c +++ b/lib/dtree.c @@ -18,6 +18,8 @@ int recursive_search(dtree**, dtree *, dtree *); +void recursive_print(dtree *data, const char *offset); + /******/ @@ -96,7 +98,7 @@ dt_err dtree_addpointer(dtree *data, void *ptr) data->payload.pointer = ptr; data->type = POINTER; data->size = sizeof(ptr); - data->used = sizeof(*ptr); + data->used = sizeof(ptr); return SUCCESS; } @@ -270,8 +272,64 @@ dt_err dtree_merge_trees(dtree *data, dtree *merge) dt_err dtree_copy_deep(dtree *data, dtree *(*copy)) { if(data == NULL) return INVALID_PARAMS; + dt_err err = SUCCESS; - return SUCCESS; + int it_type = -1; + dt_uni_t type = data->type; + + /* Check if we're the first call */ + if((*copy) == NULL) dtree_malloc(copy); + (*copy)->copy = DEEP; + + switch(type) { + case LITERAL: + dtree_addliteral((*copy), data->payload.literal); + break; + + case NUMERIC: + dtree_addnumeral((*copy), data->payload.numeral); + break; + + case LIST: + { + int i; + int num = (int) data->used; + + for(i = 0; i < num; i++) { + dtree *node = data->payload.recursive[i]; + + dtree *new; + dtree_addlist((*copy), &new); + dtree_copy_deep(node, &new); + } + + break; + } + + case PAIR: + { + dtree *key, *val; + dtree_addpair((*copy), &key, &val); + + dtree *orig_key = data->payload.recursive[0]; + dtree *orig_val = data->payload.recursive[1]; + + dtree_copy_deep(orig_key, &key); + dtree_copy_deep(orig_val, &val); + + break; + } + + case POINTER: + dtree_addpointer((*copy), data->payload.pointer); + break; + + default: + err = INVALID_PAYLOAD; + break; + } + + return err; } dt_err dtree_copy(dtree *data, dtree *(*copy)) @@ -375,12 +433,15 @@ void recursive_print(dtree *data, const char *offset) case UNSET: printf("[NULL]\n"); break; + case LITERAL: printf("%s['%s']\n", offset, data->payload.literal); break; + case NUMERIC: printf("%s[%lu]\n", offset, data->payload.numeral); break; + case PAIR: { dt_uni_t k_type = data->payload.recursive[0]->type; @@ -452,11 +513,9 @@ void dtree_print(dtree *data) dt_err dtree_get(dtree *data, void *(*val)) { - if(data->type == LITERAL) *val = (char*) data->payload.literal; - if(data->type == NUMERIC) *val = (int*) &data->payload.numeral; - if(data->type == LIST || data->type == PAIR) - *val = (dtree*) data->payload.recursive; - + if(data->type == LITERAL) *val = data->payload.literal; + if(data->type == NUMERIC) *val = &data->payload.numeral; + if(data->type == LIST || data->type == PAIR) *val = (dtree*) data->payload.recursive; return SUCCESS; } @@ -472,6 +531,8 @@ dt_err dtree_free(dtree *data) int i; dt_err err; for(i = 0; i < data->used; i++) { + if(data->copy == SHALLOW) continue; + err = dtree_free(data->payload.recursive[i]); if(err) return err; } @@ -479,7 +540,8 @@ dt_err dtree_free(dtree *data) free(data->payload.recursive); } else if(data->type == POINTER) { - if(data->payload.pointer) free(data->payload.pointer); + if(data->copy != SHALLOW && data->payload.pointer) + free(data->payload.pointer); } free(data); @@ -513,16 +575,18 @@ const char *dtree_dtype(dtree *data) { switch(data->type) { case LITERAL: return "Literal"; - case NUMERIC: return "Numeral"; - case LIST: return "Recursive"; + case NUMERIC: return "Numeric"; + case LIST: return "List"; case PAIR: return "Pair"; case POINTER: return "Pointer"; default: return "Unknown"; } } + /**************** PRIVATE UTILITY FUNCTIONS ******************/ + /** * Steps down the recursive hirarchy of a dyntree node to * find a sub-child target. Returns 0 if it can be found. -- cgit v1.2.3