aboutsummaryrefslogtreecommitdiff
path: root/data.c
diff options
context:
space:
mode:
Diffstat (limited to 'data.c')
-rw-r--r--data.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/data.c b/data.c
new file mode 100644
index 0000000..9077d9b
--- /dev/null
+++ b/data.c
@@ -0,0 +1,81 @@
+#include "bowl.h"
+
+#include <stdlib.h>
+#include <memory.h>
+#include <stdbool.h>
+#include <stdarg.h>
+
+/// Allocate memory for a new data node
+err_t data_malloc(struct bowl **self, data_t type, ...)
+{
+ err_t e;
+ va_list args;
+
+ struct data *d = calloc(sizeof(struct data), 1);
+ CHECK(d, MALLOC_FAILED)
+ d->type = type;
+
+ va_start(args, type);
+ switch(type) {
+ case LITERAL: {
+ char *lit = va_arg(args, char *);
+ size_t len = REAL_STRLEN(lit);
+
+ d->_pl.literal = calloc(sizeof(char), len);
+ if(!d->_pl.literal) {
+ e = MALLOC_FAILED;
+ goto fail;
+ }
+
+ strcpy(d->_pl.literal, lit);
+ break;
+ };
+ case INTEGER: {
+ int i = va_arg(args, long);
+ d->_pl.integer = i;
+ break;
+ }
+ case REAL: {
+ int r = va_arg(args, double);
+ d->_pl.real = r;
+ break;
+ }
+ case BOOLEAN: {
+ int b = va_arg(args, int);
+ d->_pl.boolean = (bool) b;
+ break;
+ }
+ case RAW: {
+ void *raw = va_arg(args, void *);
+ d->_pl.raw = raw;
+ break;
+ }
+ default: e = INVALID_PARAMS; goto fail;
+ }
+ va_end(args);
+
+ e = bowl_malloc(self, LEAF);
+ if(e) goto fail;
+
+ (*self)->_pl.data = d;
+ return OK;
+
+fail:
+ if(d->type == LITERAL && d->_pl.literal) free(d->_pl.literal);
+ if(*self) bowl_free(*self);
+ if(d) free(d);
+ return e;
+}
+
+/// Free all data node memory
+err_t data_free(struct data *self)
+{
+ CHECK(self, INVALID_PARAMS)
+ switch(self->type) {
+ case LITERAL: free(self->_pl.literal); break;
+ default: break;
+ }
+
+ free(self);
+ return OK;
+}