From cf97068884083c7d1d1bc95fb3099b113d7e8dad Mon Sep 17 00:00:00 2001 From: Katharina Fey Date: Sun, 21 Aug 2016 12:12:59 +0200 Subject: Adding new functions to API - Encode a dyntree object hirarchy into json - Decode a json string to a dyntree object hirarchy - Split a tree in two (no longer related) sub-trees - Merge two non-related subtrees together --- include/dtree/dyn_err.h | 29 ------------- include/dtree/dyn_tree.h | 107 ++++++++++++++++++++++++++++++++++++++++++++++- lib/dyn_tree.c | 2 +- 3 files changed, 107 insertions(+), 31 deletions(-) delete mode 100644 include/dtree/dyn_err.h diff --git a/include/dtree/dyn_err.h b/include/dtree/dyn_err.h deleted file mode 100644 index 23dae0f..0000000 --- a/include/dtree/dyn_err.h +++ /dev/null @@ -1,29 +0,0 @@ - -/* Make sure we're not included multiple times */ -#ifndef _DYN_ERR_H -#define _DYN_ERR_H - -/* Also make sure we're _always_ interpreted as a C file */ -#ifdef __cplusplus -extern "C" { -#endif - -/** Define some generic error codes first that we can propagate **/ -typedef enum dt_err { - - /* General purpose error codes */ - FAILURE = -1, - SUCCESS = 0, - - INVALID_PARAMS, - MALLOC_FAILED, - INVALID_PAYLOAD - -} dt_err; - -const char *rdb_error_getmsg(dt_err *e); - -#ifdef __cplusplus -} -#endif -#endif /* _DYN_ERR_H */ \ No newline at end of file diff --git a/include/dtree/dyn_tree.h b/include/dtree/dyn_tree.h index cfd7239..c91f48b 100644 --- a/include/dtree/dyn_tree.h +++ b/include/dtree/dyn_tree.h @@ -21,20 +21,27 @@ #ifndef _DYNTREE_H_ #define _DYNTREE_H_ -#include "dyn_err.h" #include +/* A helpful macro that can take care of \0 termated strings! */ +#define REAL_STRLEN(str) (strlen(str) + 1) + +#define DYNTREE_ENCODE_NONE 0x0 +#define DYNTREE_JSON_MINIFIED 0xA +#define DYNTREE_JSON_HUMAN 0xB /* Also make sure we're _always_ interpreted as a C file */ #ifdef __cplusplus extern "C" { #endif + /* Type that determines what data is stored inside a tree-node */ typedef enum { UNSET, LITERAL, NUMERAL, RECURSIVE, PAIR, POINTER } dt_uni_t; + typedef struct dtree { dt_uni_t type; size_t size, used; @@ -44,9 +51,24 @@ typedef struct dtree { struct dtree *(*recursive); void *pointer; } payload; + short encset; } dtree; +/** Define some generic error codes first that we can propagate **/ +typedef enum dt_err { + + /* General purpose error codes */ + FAILURE = -1, + SUCCESS = 0, + + INVALID_PARAMS, + MALLOC_FAILED, + INVALID_PAYLOAD + +} dt_err; + + /** * Malloc a new dtree object * @@ -125,6 +147,38 @@ dt_err dtree_addrecursive(dtree *data, dtree *(*new_data)); */ dt_err dtree_addpointer(dtree *data, void *ptr); +/** + * This function takes two nodes as arguments. The nodes MUST be + * related or an error will be thrown. Both nodes will still + * be accessable after this operation but no longer be related to + * each other. + * + * The second node will be removed from the tree of the root node. + * + * + * + * @param data Root reference + * @param sp Subtree node related to root to split off + * @return + */ +dt_err dtree_split_trees(dtree *data, dtree *sp); + +/** + * This function is very simmilar to dt_err "dtree_addrecursive" + * with the difference that it doesn't allocate new memory but instead + * works with existing nodes. + * + * You need to provide a ROOT node which is of type recursive. It will + * procede to add the second (merge) node into the child-list of the + * root data node - essentially making them related. + * + * This allows for very efficient tree merging. + * + * @param data Root reference + * @param merge Second root reference to merge + * @return + */ +dt_err dtree_merge_trees(dtree *data, dtree *merge); /** * A retrieve function to get data back from a node that doesn't require @@ -176,6 +230,57 @@ dt_err dtree_free_shallow(dtree *data); */ dt_err dtree_free(dtree *data); +/************************** + * + * Error handling functions + * + **************************/ + +const char *dtree_err_getmsg(dt_err *e); + +/*************************** + * + * Encoding/ Decoding support hooks + * + ***************************/ + +/** + * This function sets the wanted encoding setting on a + * root node (and assumes for children). Without setting flags via + * this function first the encode will fail. + * + * @param data Root reference + * @param setting Look at DYNTREE_JSON flags for options + * @return + */ +dt_err dtree_encode_set(dtree *data, short setting); + +/** + * A simple recursive node walker that encodes a dyn_tree node hirarchy + * into a json string. Requires the encoding setting to be set on the + * root node in order to successfully encode. + * + * Can throw errors and initialise NULL return string. + * + * @param data + * @param json_data + * @return + */ +dt_err dtree_encode_json(dtree *data, char *(*json_data)); + + +/** + * Decodes a json string into a dyn_tree node hirarchy while providing + * memory safety and error checking. Will gracefully return errors + * if the provided json string is invalid or contains errors. + * + * @param data New root reference + * @param json_data Input json string + * @return + */ +dt_err dtree_decode_json(d_tree *(*data), const char *json_data); + + #ifdef __cplusplus } #endif diff --git a/lib/dyn_tree.c b/lib/dyn_tree.c index 095d379..6cb456b 100644 --- a/lib/dyn_tree.c +++ b/lib/dyn_tree.c @@ -9,7 +9,6 @@ #define RDB_REC_DEF_SIZE 2 #define RDB_REC_MULTIPLY 2 -#define REAL_STRLEN(str) (strlen(str) + 1) dt_err dtree_malloc(dtree *(*data)) { @@ -42,6 +41,7 @@ dt_err dtree_resettype(dtree *data) /* Set the data type to unset */ data->type = UNSET; + data->encset = DYNTREE_ENCODE_NONE; data->size = 0; data->used = 0; -- cgit v1.2.3