aboutsummaryrefslogtreecommitdiff
path: root/data.c
blob: 9077d9b25082c0fdc0da7969161812bceffe9fd2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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;
}