aboutsummaryrefslogtreecommitdiff
path: root/bowl.c
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2019-06-09 09:07:48 +0200
committerKatharina Fey <kookie@spacekookie.de>2019-06-09 09:12:52 +0200
commitd0cca976be6fb90f3724911c8a124bce56b3c5f9 (patch)
tree96c92dc695f81b39227fb5f52e4c2ac469fea06b /bowl.c
parent7df71001ef1a9ea271ae3c409a367d6c2dd628b7 (diff)
Restructuring the main API and project
This commit rewrites pretty much the entire library. It is now much smaller and more maintainable (split over multiple files). It will now also support more features (that aren't implemented yet). Adding two examples to show how to use the new API. Also changing the name of the library everywhere.
Diffstat (limited to 'bowl.c')
-rw-r--r--bowl.c828
1 files changed, 68 insertions, 760 deletions
diff --git a/bowl.c b/bowl.c
index 0f43db2..4eeeb59 100644
--- a/bowl.c
+++ b/bowl.c
@@ -1,815 +1,123 @@
-// Include our header file
#include "bowl.h"
+#include "array.h"
-// Runtime includes
#include <stdlib.h>
-#include <stdio.h>
#include <memory.h>
#include <stdbool.h>
-#define RDB_REC_DEF_SIZE 2
-#define RDB_REC_MULTIPLY 2
+#define ARRAY_START_SIZE 2
+#define HASH_START_SIZE 24
-#define ORIGINAL (short) 0
-#define SHALLOW (short) 1
-#define DEEP (short) 2
-
-/*** Forward declared functions ***/
-
-int list_search(struct bowl**, struct bowl*, struct bowl*);
-
-void list_print(struct bowl *data, const char *offset);
-
-/******/
-
-dt_err bowl_malloc(struct bowl *(*data))
-{
- (*data) = (struct bowl*) malloc(sizeof(struct bowl));
- if(*data == NULL) {
- printf("Creating bowl object FAILED");
- return MALLOC_FAILED;
- }
-
- memset(*data, 0, sizeof(struct bowl));
-
- (*data)->type = UNSET;
- return SUCCESS;
-}
-
-dt_err bowl_resettype(struct bowl *data)
-{
- if(data->type == LITERAL) {
- if(data->payload.literal) free(data->payload.literal);
-
- } else if(data->type == LIST || data->type == PAIR) {
-
- /* Iterate over all children and clear them */
- int i;
- dt_err err;
- for(i = 0; i < data->size; i++) {
- err = bowl_free(data->payload.list[i]);
- if(err) return err;
- }
- }
-
- /* Set the data type to unset */
- data->type = UNSET;
- data->encset = 0;
- data->size = 0;
- data->used = 0;
-
- /* Forcibly clean union memory to avoid bleeding data */
- memset(&data->payload, 0, sizeof(data->payload));
-
- return SUCCESS;
-}
-
-dt_err bowl_addliteral(struct bowl *data, const char *literal)
-{
- /* Make sure we are a literal or unset data object */
- if(data->type != UNSET)
- if(data->type != LITERAL) return INVALID_PAYLOAD;
-
- size_t length = REAL_STRLEN(literal);
-
- /* Get rid of previous data */
- if(data->payload.literal) free(data->payload.literal);
-
- /* Allocate space for the data */
- char *tmp = (char *) malloc(sizeof(char) * length);
- if(tmp == NULL) {
- printf("Allocating space for literal data FAILED");
- return MALLOC_FAILED;
- }
-
- /* Copy the string over and store it in the union */
- strcpy(tmp, literal);
- data->payload.literal = tmp;
- data->type = LITERAL;
- data->size = length;
- data->used = length;
-
- return SUCCESS;
-}
-
-
-dt_err bowl_addpointer(struct bowl *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 bowl_addnumeral(struct bowl *data, long numeral)
-{
- /* Make sure we are a literal or unset data object */
- if(data->type != UNSET)
- if(data->type != NUMERIC) return INVALID_PAYLOAD;
-
- data->payload.numeral = numeral;
- data->type = NUMERIC;
- data->size = sizeof(int);
- data->used = sizeof(int);
- return SUCCESS;
-}
-
-
-dt_err bowl_addboolean(struct bowl *data, bool b)
-{
- /* Make sure we are a literal or unset data object */
- if(data->type != UNSET)
- if(data->type != BOOLEAN) return INVALID_PAYLOAD;
-
- data->payload.boolean = b;
- data->type = BOOLEAN;
- data->size = sizeof(bool);
- data->used = sizeof(bool);
- return SUCCESS;
-}
-
-
-dt_err bowl_addlist(struct bowl *data, struct bowl *(*new_data))
-{
- /* Make sure we are a literal or unset data object */
- if(data->type != UNSET)
- if(data->type != LIST) return INVALID_PAYLOAD;
-
- dt_err err;
-
- /* This means elements already exist */
- if(data->size > 0) {
-
- /* Used should never > size */
- if(data->used >= data->size) {
- data->size += RDB_REC_MULTIPLY;
-
- // TODO Use Realloc
- struct bowl **tmp = (struct bowl**) malloc(sizeof(struct bowl*) * data->size);
- memcpy(tmp, data->payload.list, sizeof(struct bowl*) * data->used);
-
- /* Free the list WITHOUT the children! */
- free(data->payload.list);
- data->payload.list = tmp;
- }
-
- /* This means the data object is new */
- } else {
- struct bowl **tmp = (struct bowl**) malloc(sizeof(struct bowl*) * RDB_REC_DEF_SIZE);
- data->payload.list = tmp;
- data->type = LIST;
- data->used = 0;
- data->size = RDB_REC_DEF_SIZE;
- }
-
- err = bowl_malloc(new_data);
- if(err) return err;
-
- /* Reference the slot, assign it, then move our ctr */
- data->payload.list[data->used++] = *new_data;
-
- return SUCCESS;
-}
-
-
-dt_err bowl_addpair(struct bowl *data, struct bowl *(*key), struct bowl *(*value))
-{
- /* Make sure we are a literal or unset data object */
- if(data->type != UNSET) return INVALID_PAYLOAD;
-
- dt_err err;
-
- /* Malloc two nodes */
- err = bowl_malloc(key);
- if(err) goto cleanup;
-
- err = bowl_malloc(value);
- if(err) goto cleanup;
-
- /** Malloc space for PAIR */
- data->size = 2;
- struct bowl **tmp = (struct bowl**) malloc(sizeof(struct bowl*) * data->size);
- if(!tmp) goto cleanup;
-
- data->payload.list = tmp;
-
- { /* Assign data to new array */
- data->payload.list[data->used] = *key;
- data->used++;
- data->payload.list[data->used] = *value;
- data->used++;
- }
-
- /* Assign our new type and return */
- data->type = PAIR;
- return SUCCESS;
-
- /* Code we run when we can't allocate structs anymore */
- cleanup:
- free(*key);
- free(*value);
- free(tmp);
- return MALLOC_FAILED;
-}
-
-
-dt_err bowl_split_trees(struct bowl *data, struct bowl *sp)
-{
- /* Make sure we are a literal or unset data object */
- if(data->type == UNSET) return INVALID_PAYLOAD;
-
- /* Check that sp is really a child of data */
- struct bowl *dp;
- int ret = list_search(&dp, data, sp);
- if(ret != 0) return DATA_NOT_RELATED;
- if(dp == NULL) return NODE_NOT_FOUND;
-
- /* Find the exact list reference and remove it */
- int i;
- for(i = 0; i < dp->used; i++) {
- if(dp->payload.list[i] == NULL) continue;
-
- /* Manually remove the entry */
- if(dp->payload.list[i] == sp) {
- dp->used--;
- dp->payload.list[i] = NULL;
- }
- }
-
- return SUCCESS;
-}
-
-
-dt_err bowl_merge_trees(struct bowl *data, struct bowl *merge)
-{
- /* REALLY make sure the type is correct */
- if(data->type == UNSET) return INVALID_PARAMS;
- if(!(data->type == LIST || data->type == PAIR))
- return INVALID_PAYLOAD;
-
- /* This means elements already exist */
- if(data->size > 0) {
-
- /* Used should never > size */
- if(data->used >= data->size) {
- data->size += RDB_REC_MULTIPLY;
-
- struct bowl **tmp = (struct bowl**) malloc(sizeof(struct bowl*) * data->size);
- memcpy(tmp, data->payload.list, sizeof(struct bowl*) * data->used);
-
- /* Free the list WITHOUT the children! */
- free(data->payload.list);
- data->payload.list = tmp;
- }
-
- /* This means the data object is new */
- } else {
- struct bowl **tmp = (struct bowl**) malloc(sizeof(struct bowl*) * data->size);
- data->payload.list = tmp;
- data->type = LIST;
- data->used = 0;
- data->size = RDB_REC_DEF_SIZE;
- }
-
- /* Reference the slot, assign it, then move our ctr */
- data->payload.list[data->used] = merge;
- data->used++;
-
- return SUCCESS;
-}
-
-
-dt_err bowl_copy_deep(struct bowl *data, struct bowl *(*copy))
-{
- if(data == NULL) return INVALID_PARAMS;
- dt_err err = SUCCESS;
-
- int it_type = -1;
- bowl_t type = data->type;
-
- /* Check if we're the first call */
- if((*copy) == NULL) bowl_malloc(copy);
- (*copy)->copy = DEEP;
-
- switch(type) {
- case LITERAL:
- bowl_addliteral(*copy, data->payload.literal);
- break;
-
- case NUMERIC:
- bowl_addnumeral(*copy, data->payload.numeral);
- break;
-
- case BOOLEAN:
- bowl_addboolean(*copy, data->payload.boolean);
- break;
-
- case LIST:
- {
- int i;
- int num = (int) data->used;
-
- for(i = 0; i < num; i++) {
- struct bowl *node = data->payload.list[i];
-
- struct bowl *new;
- bowl_addlist(*copy, &new);
- bowl_copy_deep(node, &new);
- }
-
- break;
- }
-
- case PAIR:
- {
- struct bowl *key, *val;
- bowl_addpair(*copy, &key, &val);
-
- struct bowl *orig_key = data->payload.list[0];
- struct bowl *orig_val = data->payload.list[1];
-
- bowl_copy_deep(orig_key, &key);
- bowl_copy_deep(orig_val, &val);
-
- break;
- }
-
- case POINTER:
- bowl_addpointer(*copy, data->payload.pointer);
- break;
-
- default:
- err = INVALID_PAYLOAD;
- break;
- }
-
- return err;
-}
-
-
-dt_err bowl_parent(struct bowl *root, struct bowl *data, struct bowl **parent)
+void *_get_data(struct bowl *ptr)
{
- if(root == NULL || data == NULL) return INVALID_PARAMS;
-
- /* Blank the search pointer for easy error checking */
- (*parent) = NULL;
-
- switch(root->type) {
-
- /* Dead-end data stores automatically return @{NODE_NOT_FOUND} */
- case POINTER:
- case LITERAL:
- case BOOLEAN:
- case NUMERIC:
- return NODE_NOT_FOUND;
-
- case PAIR:
- case LIST:
- {
- int i;
- for(i = 0; i < root->used; i++) {
-
- /* Check if the node we're looking at is what we're searching for */
- if(root->payload.list[i] == data) {
- (*parent) = root;
- return SUCCESS;
- }
-
- dt_err err = bowl_parent(root->payload.list[i], data, parent);
- if(err == SUCCESS) return SUCCESS;
- }
- }
- break;
-
- default:
- return INVALID_PAYLOAD;
+ switch(ptr->type) {
+ case ARRAY | HASH: return ptr->_pl.array;
+ case LINKED: return ptr->_pl.linked;
+ case LEAF: return ptr->_pl.data;
+ default: return NULL;
}
-
- return NODE_NOT_FOUND;
}
-
-dt_err bowl_copy(struct bowl *data, struct bowl *(*copy))
+err_t bowl_malloc(struct bowl **ptr, bowl_t type)
{
- if(data == NULL) return INVALID_PARAMS;
- dt_err err = SUCCESS;
-
- /* Allocate a new node */
- err = bowl_malloc(copy);
- if(err) goto exit;
-
- /* Mark as shallow copy */
- (*copy)->copy = SHALLOW;
-
- /* Find out how to handle specific payloads */
- switch(data->type) {
- case LITERAL:
- err = bowl_addliteral(*copy, data->payload.literal);
- break;
+ CHECK((type != 0), INVALID_PARAMS)
- case NUMERIC:
- err = bowl_addnumeral(*copy, data->payload.numeral);
- break;
+ (*ptr) = malloc(sizeof(struct bowl));
+ CHECK(*ptr, MALLOC_FAILED)
- case BOOLEAN:
- err = bowl_addboolean(*copy, data->payload.boolean);
- break;
+ memset(*ptr, 0, sizeof(struct bowl));
+ (*ptr)->type = type;
- case LIST:
- (*copy)->type = LIST;
- (*copy)->payload.list = (struct bowl**) malloc(sizeof(struct bowl*) * data->size);
- memcpy((*copy)->payload.list, data->payload.list, sizeof(struct bowl*) * data->used);
- break;
-
- case PAIR:
- (*copy)->type = PAIR;
- (*copy)->payload.list = (struct bowl**) malloc(sizeof(struct bowl*) * data->size);
- memcpy((*copy)->payload.list, data->payload.list, sizeof(struct bowl*) * data->used);
- break;
-
- case POINTER:
- (*copy)->type = POINTER;
- memcpy((*copy)->payload.pointer, data->payload.pointer, sizeof(void*));
- break;
-
- default:
- return INVALID_PAYLOAD;
+ switch((*ptr)->type) {
+ case LEAF: return OK; // No further allocation needed
+ case ARRAY: return array_malloc(*ptr, ARRAY_START_SIZE);
+ default: return INVALID_STATE;
}
- exit:
- return err;
+ return OK;
}
-
-dt_err bowl_search_payload(struct bowl *data, struct bowl *(*found), void *payload, bowl_t type)
+err_t bowl_insert(struct bowl *self, struct bowl *new)
{
- if(data == NULL) return INVALID_PARAMS;
-
- /* Make sure our pointer is clean */
- *found = NULL;
-
- if(data->type == LIST|| data->type == PAIR) {
-
- int i;
- for(i = 0; i < data->used; i++) {
- dt_err err = bowl_search_payload(data->payload.list[i], found, payload, type);
- if(err == SUCCESS) return SUCCESS;
- }
-
- } else {
-
- /* Check the type aligns */
- if(data->type != type) return NODE_NOT_FOUND;
-
- switch(type) {
- case LITERAL:
- if(strcmp(data->payload.literal, (char*) payload) == 0)
- *found = data;
- break;
-
- case NUMERIC:
- if(data->payload.numeral == (long) payload)
- *found = data;
- break;
-
- case BOOLEAN:
- if(data->payload.boolean == (bool) payload)
- *found = data;
- break;
-
- case POINTER:
- if(data->payload.pointer == payload)
- *found = data;
- break;
-
- default: return NODE_NOT_FOUND;
- }
-
- }
-
- return (*found == NULL) ? NODE_NOT_FOUND : SUCCESS;
-}
-
-// FIXME: This is horrible. Do via context?
-static int reached = 0;
-dt_err bowl_search_keypayload(struct bowl *data, struct bowl *(*found), void *payload, bowl_t type, int depth)
-{
- if(data == NULL) return INVALID_PARAMS;
- if(reached++ >= depth) return QUERY_TOO_DEEP;
-
- /* Make sure our pointer is clean */
- *found = NULL;
-
- /* We can only search LISTed values or PAIRs */
- if(data->type == PAIR) {
- struct bowl *key = data->payload.list[0];
-
- bowl_t tt;
- int hit = -1;
-
- if(strcmp(key->payload.literal, (char*) payload) == 0) {
- tt = LITERAL;
- hit = 0;
- }
-
- if(key->payload.numeral == (long) payload) {
- tt = NUMERIC;
- hit = 0;
- }
-
- if(key->payload.boolean == (bool) payload) {
- tt = BOOLEAN;
- hit = 0;
- }
-
- if(hit == 0) *found = data->payload.list[1];
-
- } else if(data->type == LIST) {
-
- int i;
- for(i = 0; i < data->used; i++) {
- bowl_search_keypayload(data->payload.list[i], found, payload, type, depth);
- }
-
- } else {
-
-
- }
-
- if(data->type == LIST|| data->type == PAIR) {
-
- int i;
- for(i = 0; i < data->used; i++) {
- dt_err err = bowl_search_payload(data->payload.list[i], found, payload, type);
- if(err == SUCCESS) return SUCCESS;
- }
-
- } else {
-
- /* Check the type aligns */
- if(data->type != type) return NODE_NOT_FOUND;
-
- switch(type) {
- case LITERAL:
- if(strcmp(data->payload.literal, (char*) payload) == 0)
- *found = data;
- break;
-
- case NUMERIC:
- if(data->payload.numeral == (long) payload)
- *found = data;
- break;
+ CHECK(self, INVALID_PARAMS)
+ CHECK(new, INVALID_PARAMS)
- case BOOLEAN:
- if(data->payload.boolean == (bool) payload)
- *found = data;
-
- case POINTER:
- if(data->payload.pointer == payload)
- *found = data;
- break;
-
- default: return NODE_NOT_FOUND;
- }
+ switch(self->type) {
+ case LEAF: return INVALID_PARAMS;
+ case ARRAY: return array_insert(self, new);
+ default: return INVALID_STATE;
}
- return (*found == NULL) ? NODE_NOT_FOUND : SUCCESS;
+ return OK;
}
-
-void list_print(struct bowl *data, const char *offset)
+err_t bowl_insert_key(struct bowl *self, size_t idx, struct bowl *child)
{
- bowl_t type = data->type;
-
- switch(type) {
- 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 BOOLEAN:
- printf("%s['%s']\n", offset, (data->payload.boolean) ? "TRUE" : "FALSE");
- break;
-
- case PAIR:
- {
- bowl_t k_type = data->payload.list[0]->type;
- bowl_t v_type = data->payload.list[1]->type;
-
- if(k_type == LITERAL) printf("%s['%s']", offset, data->payload.list[0]->payload.literal);
- if(k_type == NUMERIC) printf("%s[%lu]", offset, data->payload.list[0]->payload.numeral);
- if(k_type == BOOLEAN) printf("%s[%s]", offset, (data->payload.list[0]->payload.boolean) ? "TRUE" : "FALSE");
-
- char new_offset[REAL_STRLEN(offset) + 2];
- strcpy(new_offset, offset);
- strcat(new_offset, " ");
-
- if(k_type == LIST || k_type == PAIR) list_print(data->payload.list[0], new_offset);
-
- /* Print the value now */
- if(v_type == LITERAL) printf(" => ['%s']\n", data->payload.list[1]->payload.literal);
- if(v_type== NUMERIC) printf(" => [%lu]\n", data->payload.list[1]->payload.numeral);
- if(v_type == BOOLEAN) printf(" => [%s]\n", (data->payload.list[1]->payload.boolean) ? "TRUE" : "FALSE");
-
- if(v_type == LIST || k_type == PAIR) list_print(data->payload.list[1], new_offset);
-
- break;
- }
-
- case LIST:
- {
- int i;
- printf("%s[LIST]\n", offset);
- for(i = 0; i < data->used; i++) {
- bowl_t t = data->payload.list[i]->type;
-
- /* Calculate the new offset */
- char new_offset[REAL_STRLEN(offset) + 2];
- strcpy(new_offset, offset);
- strcat(new_offset, " ");
-
- switch(t) {
- case LITERAL:
- case BOOLEAN:
- case NUMERIC:
- list_print(data->payload.list[i], new_offset);
- continue;
-
- case LIST:
- list_print(data->payload.list[i], new_offset);
- continue;
-
- case PAIR:
- printf("%s[PAIR] <==> ", new_offset);
- list_print(data->payload.list[i], new_offset);
- continue;
-
- default:
- break;
- }
- }
- break;
- }
+ CHECK(self, INVALID_PARAMS)
+ CHECK(child, INVALID_PARAMS)
+ CHECK((idx >= 0), INVALID_PARAMS)
- default:
- break;
+ switch(self->type) {
+ case LEAF: return INVALID_PARAMS;
+ case ARRAY: return array_insert_key(self, idx, child);
+ default: return INVALID_STATE;
}
}
-
-void bowl_print(struct bowl *data)
+err_t bowl_swap_key(struct bowl *self, size_t idx, struct bowl *child, struct bowl **prev)
{
- list_print(data, "");
-}
+ CHECK(self, INVALID_PARAMS)
+ CHECK(child, INVALID_PARAMS)
+ CHECK((idx >= 0), INVALID_PARAMS)
-dt_err bowl_get(struct bowl *data, void *(*val))
-{
- if(data->type == LITERAL) *val = data->payload.literal;
- if(data->type == NUMERIC) *val = &data->payload.numeral;
- if(data->type == BOOLEAN) *val = &data->payload.boolean;
- if(data->type == LIST || data->type == PAIR) *val = (struct bowl*) data->payload.list;
- return SUCCESS;
-}
-
-
-dt_err bowl_free(struct bowl *data)
-{
- if(data == NULL) return SUCCESS;
- if(data->copy == SHALLOW) return NODE_NOT_ORIGINAL;
+ switch(self->type) {
+ case LEAF: return INVALID_PARAMS;
+ case ARRAY: return array_swap_key(self, idx, child, prev);
- if(data->type == LITERAL) {
- if(data->payload.literal) free(data->payload.literal);
-
- } else if(data->type == LIST || data->type == PAIR) {
- int i;
- dt_err err;
- for(i = 0; i < data->used; i++) {
-
- err = bowl_free(data->payload.list[i]);
- if(err) return err;
- }
-
- free(data->payload.list);
-
- } else if(data->type == POINTER) {
- if(data->copy != SHALLOW && data->payload.pointer)
- free(data->payload.pointer);
+ default: return INVALID_STATE;
}
-
- free(data);
- return SUCCESS;
}
-
-dt_err bowl_free_shallow(struct bowl *data)
+err_t bowl_remove(struct bowl *self, struct bowl *child)
{
- if(data == NULL) return SUCCESS;
+ CHECK(self, INVALID_PARAMS)
+ CHECK(child, INVALID_PARAMS)
- if(data->type == LITERAL) {
- if(data->payload.literal) free(data->payload.literal);
- } else if(data->type == LIST || data->type == PAIR) {
- int i;
- dt_err err;
- for(i = 0; i < data->size; i++) {
- err = bowl_free(data->payload.list[i]);
- if(err) return err;
- }
+ switch(self->type) {
+ case LEAF: return INVALID_PARAMS;
+ case ARRAY: return array_remove(self, child);
- free(data->payload.list);
+ default: return INVALID_STATE;
}
-
- free(data);
- return SUCCESS;
}
-
-const char *bowl_dtype(struct bowl *data)
+err_t bowl_remove_key(struct bowl *self, size_t idx, struct bowl **prev)
{
- switch(data->type) {
- case LITERAL: return "Literal";
- case NUMERIC: return "Numeric";
- case BOOLEAN: return "Boolean";
- case LIST: return "List";
- case PAIR: return "Pair";
- case POINTER: return "Pointer";
- default: return "Unknown";
- }
-}
+ CHECK(self, INVALID_PARAMS)
+ CHECK((idx >= 0), INVALID_PARAMS)
+ switch(self->type) {
+ case LEAF: return INVALID_PARAMS;
+ case ARRAY: return array_remove_key(self, idx, prev);
-/**************** PRIVATE UTILITY FUNCTIONS ******************/
-
-
-/**
- * Steps down the list hirarchy of a dyntree node to
- * find a sub-child target. Returns 0 if it can be found.
- *
- * @param data
- * @param target
- * @return
- */
-int list_search(struct bowl **direct_parent, struct bowl *data, struct bowl *target)
-{
- /* Check if data is actually valid */
- if(data == NULL) return 1;
-
- /* Compare the pointers :) */
- if(data == target) return 0;
-
- int res = 1;
- if(data->type == LIST || data->type == PAIR) {
- int i;
- for(i = 0; i < data->used; i++) {
- res = list_search(direct_parent, data->payload.list[i], target);
- if(res == 0) {
-
- /* Save the node that contains our child for later */
- (*direct_parent) = data;
- return res;
- }
- }
+ default: return INVALID_STATE;
}
-
- return res;
}
-
-/**
- * Small utility function that checks if a datablock is valid to write into.
- * Potentially releases previously owned memory to prevent memory leaks
- *
- * @param data The bowl object to check
- * @return
- */
-dt_err data_check(struct bowl *data)
+err_t bowl_free(struct bowl *self)
{
- /* Check if the data block has children */
- if(data->type == LIST)
- {
- printf("Won't override heap payload with data!");
- return INVALID_PAYLOAD;
- }
+ CHECK(self, INVALID_PARAMS)
- /* Free the existing string */
- if(data->type == LITERAL)
- {
- if(data->payload.literal) free(data->payload.literal);
+ err_t e;
+ switch(self->type) {
+ case LEAF: e = data_free(self->_pl.data); break;
+ case ARRAY: e = array_free(self); break;
+ default: e = INVALID_STATE; break;
}
+ if(e) return e;
- return SUCCESS;
+ free(self);
+ return OK;
}