aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2016-07-30 23:28:36 +0200
committerKatharina Fey <kookie@spacekookie.de>2016-07-30 23:28:36 +0200
commit58045e8a341b066a1957cc2472cb91b0d39b28ef (patch)
tree2b5370b30745cad72896bc02eea0371c5a95b33a
parent6715214825f7c4b555227cc48e65c8af860f4010 (diff)
Changing the APi slightly and adding better comments for the api functions.
- Also adding the ability to store custom pointers in a node
-rw-r--r--include/dtree/dyn_tree.h125
-rw-r--r--lib/dyn_tree.c55
2 files changed, 164 insertions, 16 deletions
diff --git a/include/dtree/dyn_tree.h b/include/dtree/dyn_tree.h
index e1db1d6..cfd7239 100644
--- a/include/dtree/dyn_tree.h
+++ b/include/dtree/dyn_tree.h
@@ -30,8 +30,9 @@
extern "C" {
#endif
+/* Type that determines what data is stored inside a tree-node */
typedef enum {
- UNSET, LITERAL, NUMERAL, RECURSIVE, PAIR
+ UNSET, LITERAL, NUMERAL, RECURSIVE, PAIR, POINTER
} dt_uni_t;
typedef struct dtree {
@@ -40,35 +41,139 @@ typedef struct dtree {
union {
char *literal;
int numeral;
- struct dtree *(*recursive);
+ struct dtree *(*recursive);
+ void *pointer;
} payload;
} dtree;
-/** Malloc a new dtree object */
+
+/**
+ * Malloc a new dtree object
+ *
+ * @param data Reference pointer to dtree element
+ * @return
+ */
dt_err dtree_malloc(dtree *(*data));
+
+/**
+ * Reset the type of a node and free child data
+ *
+ * @param data
+ * @return
+ */
dt_err dtree_resettype(dtree *data);
-/** Set the data element to a literal and save it's length */
+
+/**
+ * Set the data element to a literal and save it's length
+ *
+ * @param data Reference to a dtree object
+ * @param literal String to store
+ * @param length TRUE string length to use.
+ * @return
+ */
dt_err dtree_addliteral(dtree *data, const char *literal, size_t length);
-/** Set the data element to a numeral */
+
+/**
+ * Set the data element to a numeral
+ *
+ * @param data Reference to a dtree object
+ * @param numeral Number to store
+ * @return
+ */
dt_err dtree_addnumeral(dtree *data, int numeral);
-/** Add two new elements as a PAIR node under an existing node */
+
+/**
+ * Add two new elements as a PAIR node under an existing node
+ *
+ * @param data dtree node to become the sub-root
+ * @param key Reference pointer to the key node
+ * @param value Reference pointer to the value node
+ * @return
+ */
dt_err dtree_addpair(dtree *data, dtree *(*key), dtree *(*value));
-/** Add a new data element to the resursive data store */
+
+/**
+ * Add a new data element to the resursive data store
+ *
+ * @param data Root reference
+ * @param new_data Reference pointer to a new dtree node
+ * @return
+ */
dt_err dtree_addrecursive(dtree *data, dtree *(*new_data));
+
+/**
+ * This function enables you to store your own structures in a node. It however
+ * also requires you to do some of your own memory management.
+ *
+ * WARNING: Can leak memory if pointer is previously set!
+ *
+ * To make sure that this function CAN NOT leak memory you should run
+ * "dtree_resettype" on the root element to remove the pointer.
+ *
+ * Also make sure that no other part of your application will use the
+ * pointer at a later date!
+ *
+ * @param data Root reference
+ * @param ptr A pointer to store in this node
+ * @return
+ */
+dt_err dtree_addpointer(dtree *data, void *ptr);
+
+
+/**
+ * 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.
+ *
+ * @param data Node reference to access
+ * @param val Reference pointer to write into
+ * @return
+ */
dt_err dtree_get(dtree *data, void *(*val));
-const char *dtree_dtype(dt_uni_t type);
-/** Prints*/
+/**
+ * Return the type of a node as plain text
+ *
+ * @param data
+ * @return
+ */
+const char *dtree_dtype(dtree *data);
+
+
+/**
+ * Prints the data dtree object and all of its children
+ *
+ * @param data
+ */
void dtree_print(dtree *data);
-/** Will free all memory allocated by this element and it's children */
+/**
+ * Will free the data reference and all of it's children. It will however NOT
+ * touch pointers to objects that weren't allocated by libdyntree!
+ *
+ * @param data
+ * @return
+ */
+dt_err dtree_free_shallow(dtree *data);
+
+/**
+ * Like #{dtree_free_shallow} but will also remove structs that
+ * weren't allocated by libdyntree
+ *
+ * @param data
+ * @return
+ */
dt_err dtree_free(dtree *data);
#ifdef __cplusplus
diff --git a/lib/dyn_tree.c b/lib/dyn_tree.c
index 4665332..095d379 100644
--- a/lib/dyn_tree.c
+++ b/lib/dyn_tree.c
@@ -74,6 +74,21 @@ dt_err dtree_addliteral(dtree *data, const char *literal, size_t length)
return SUCCESS;
}
+
+dt_err dtree_addpointer(dtree *data, void *ptr)
+{
+ if(data->type != UNSET)
+ if(data->type != POINTER) return INVALID_PAYLOAD;
+
+ data->payload.pointer = ptr;
+ data->type = POINTER;
+ data->size = sizeof(ptr);
+ data->used = sizeof(*ptr);
+
+ return SUCCESS;
+}
+
+
dt_err dtree_addnumeral(dtree *data, int numeral)
{
/* Make sure we are a literal or unset data object */
@@ -130,6 +145,7 @@ dt_err dtree_addrecursive(dtree *data, dtree *(*new_data))
return SUCCESS;
}
+
dt_err dtree_addpair(dtree *data, dtree *(*key), dtree *(*value))
{
/* Make sure we are a literal or unset data object */
@@ -265,6 +281,7 @@ dt_err dtree_free(dtree *data)
if(data->type == LITERAL) {
if(data->payload.literal) free(data->payload.literal);
+
} else if(data->type == RECURSIVE || data->type == PAIR) {
int i;
dt_err err;
@@ -274,19 +291,45 @@ dt_err dtree_free(dtree *data)
}
free(data->payload.recursive);
+
+ } else if(data->type == POINTER) {
+ if(data->payload.pointer) free(data->payload.pointer);
}
free(data);
return SUCCESS;
}
-const char *dtree_dtype(dt_uni_t type)
+dt_err dtree_free_shallow(dtree *data)
{
- switch(type) {
- case LITERAL: return "Literal";
- case NUMERAL: return "Numeral";
- case RECURSIVE: return "Recursive";
- default: return "Unknown";
+ if(data == NULL) return SUCCESS;
+
+ if(data->type == LITERAL) {
+ if(data->payload.literal) free(data->payload.literal);
+ } else if(data->type == RECURSIVE || data->type == PAIR) {
+ int i;
+ dt_err err;
+ for(i = 0; i < data->size; i++) {
+ err = dtree_free(data->payload.recursive[i]);
+ if(err) return err;
+ }
+
+ free(data->payload.recursive);
+ }
+
+ free(data);
+ return SUCCESS;
+}
+
+const char *dtree_dtype(dtree *data)
+{
+ switch(data->type) {
+ case LITERAL: return "Literal";
+ case NUMERAL: return "Numeral";
+ case RECURSIVE: return "Recursive";
+ case PAIR: return "Pair";
+ case POINTER: return "Pointer";
+ default: return "Unknown";
}
}