aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2016-08-28 13:58:50 +0200
committerKatharina Fey <kookie@spacekookie.de>2019-06-04 20:21:03 +0200
commitcb73654ecc93d8efed08ab337812bd0d63170241 (patch)
tree5c281b61ce4a97470267c76494098eaa27df9b20
parentdf049ef1715c2b16667f9a26d8a9fd26be24977a (diff)
Adding the ability to copy nodes in shallow or deep mode
-rw-r--r--include/dtree/dtree.h22
-rw-r--r--lib/dtree.c84
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.