int main() {
struct yacjs_node *root = yacjs_parse("{\"foo\": \"bar\", \"baz\": [\"a\", \"b\", \"c\"]}");
+ yacjs_destroy(root);
+ root = NULL;
+
FILE *fp = fopen("test/test1.json", "r");
char buffer[32768];
int ret = fread(buffer, 1, 32768, fp);
root = yacjs_parse(buffer);
printf("root: %p\n", root);
+ printf("error: %i\n", yacjs_last_error());
+
+ /*
struct yacjs_node *node = yacjs_node_array_elem(root, 0);
node = yacjs_node_dict_get(node, "friends");
printf("%i friends\n", yacjs_node_array_size(node));
printf("second friend ID and name: %li, %s\n",
yacjs_node_num(yacjs_node_dict_get(node, "id")),
yacjs_node_str(yacjs_node_dict_get(node, "name")));
+*/
+ yacjs_destroy(root);
return 0;
}
#include "yacjs_dict.h"
#include "yacjs_u8s.h"
+#define zalloc(size) calloc(size, 1)
+
struct YACJS_NAME(node) {
enum YACJS_NAME(node_type) type;
union {
- const char *string;
+ char *string;
int64_t number;
double fp;
struct {
static void destroy_helper(struct YACJS_NAME(node) *node) {
if(node->type == YACJS_NAME_CAP(NODE_ARRAY)) {
for(int i = 0; i < node->data.array.entries_count; i ++) {
- YACJS_NAME(destroy)(node->data.array.entries + i);
+ destroy_helper(node->data.array.entries + i);
}
free(node->data.array.entries);
}
else if(node->type == YACJS_NAME_CAP(NODE_DICT)) {
YACJS_NAME(dict_destroy)(node->data.dict,
- (YACJS_NAME(dict_visitor))destroy_helper);
+ (YACJS_NAME(dict_visitor))YACJS_NAME(destroy));
+ }
+ else if(node->type == YACJS_NAME_CAP(NODE_STRING)) {
+ free(node->data.string);
}
}
if(type == TOKEN_OPENDICT) return parse_dict_contents(string);
else if(type == TOKEN_OPENARRAY) return parse_array_contents(string);
else if(type == TOKEN_STRING) {
- struct YACJS_NAME(node) *build = malloc(sizeof(*build));
+ struct YACJS_NAME(node) *build = zalloc(sizeof(*build));
build->type = YACJS_NAME_CAP(NODE_STRING);
build->data.string = U8S_NAME(strndup)(s, len);
return build;
}
else if(type == TOKEN_NUMBER) {
- struct YACJS_NAME(node) *build = malloc(sizeof(*build));
+ struct YACJS_NAME(node) *build = zalloc(sizeof(*build));
build->type = YACJS_NAME_CAP(NODE_NUMBER);
build->data.number = strtoll(s, NULL, 0);
return build;
}
else if(type == TOKEN_FLOAT) {
- struct YACJS_NAME(node) *build = malloc(sizeof(*build));
+ struct YACJS_NAME(node) *build = zalloc(sizeof(*build));
build->type = YACJS_NAME_CAP(NODE_FLOAT);
char *e;
build->data.fp = strtod(s, &e);
return build;
}
else if(type == TOKEN_FALSE || type == TOKEN_TRUE) {
- struct YACJS_NAME(node) *build = malloc(sizeof(*build));
+ struct YACJS_NAME(node) *build = zalloc(sizeof(*build));
build->type = YACJS_NAME_CAP(NODE_BOOLEAN);
build->data.boolean = type == TOKEN_TRUE;
return build;
}
else if(type == TOKEN_NULL) {
- struct YACJS_NAME(node) *build = malloc(sizeof(*build));
+ struct YACJS_NAME(node) *build = zalloc(sizeof(*build));
build->type = YACJS_NAME_CAP(NODE_NULL);
return build;
}
const char *s;
int len;
- struct YACJS_NAME(node) *result = malloc(sizeof(*result));
+ struct YACJS_NAME(node) *result = zalloc(sizeof(*result));
result->type = YACJS_NAME_CAP(NODE_DICT);
result->data.dict = YACJS_NAME(dict_make)();
if(type == TOKEN_CLOSEDICT) break;
// we expect a string here if it's not a closing dictionary
else if(type != TOKEN_STRING) {
+ YACJS_NAME(destroy)(result);
return NULL;
}
// expect a colon after the name
next_token(string, &len, &type);
if(type != TOKEN_COLON) {
+ YACJS_NAME(destroy)(result);
+ free(ds);
return NULL;
}
struct YACJS_NAME(node) *value = parse_any(string);
if(value == NULL) {
- // TODO: leaked memory
+ YACJS_NAME(destroy)(result);
+ YACJS_NAME(destroy)(value);
+ free(ds);
return NULL;
}
}
}
if(!s) {
- // TODO: leaked memory
+ YACJS_NAME(destroy)(result);
return NULL;
}
const char *s;
int len;
- struct YACJS_NAME(node) *result = malloc(sizeof(*result));
+ struct YACJS_NAME(node) *result = zalloc(sizeof(*result));
result->type = YACJS_NAME_CAP(NODE_ARRAY);
result->data.array.entries = NULL;
result->data.array.entries_size = 0;
}
struct YACJS_NAME(node) *next = parse_any(string);
if(!next) {
- // TODO: leaked memory
+ YACJS_NAME(destroy)(result);
+ YACJS_NAME(destroy)(next);
return NULL;
}
* (result->data.array.entries_size * 2 + 1));
if(nmem == NULL) {
last_error = YACJS_NAME_CAP(ERROR_MEMORY);
+ YACJS_NAME(destroy)(result);
+ YACJS_NAME(destroy)(next);
return NULL;
}
}
}
if(!s) {
- // TODO: leaked memory
+ YACJS_NAME(destroy)(result);
return NULL;
}
static uint64_t string_hash(const char *string);
static void resize(struct YACJS_NAME(dict) *dict, int newsize);
static void insert_helper(struct YACJS_NAME(dict) *dict, uint64_t hash,
- const char *key, void *value);
+ char *key, void *value);
struct YACJS_NAME(dict) *YACJS_NAME(dict_make)() {
struct YACJS_NAME(dict) *result = malloc(sizeof(*result));
}
}
}
+
free(dict->entries);
free(dict);
}
insert_helper(dict, oentries[i].key_hash, oentries[i].key,
oentries[i].value);
}
+ free(oentries);
}
static void insert_helper(struct YACJS_NAME(dict) *dict, uint64_t hash,
- const char *key, void *value) {
+ char *key, void *value) {
for(int i = 0; i < dict->entries_size; i ++) {
int in = (i+hash) % dict->entries_size;
if(dict->entries[in].key) continue;
- dict->entries[in].key = ystrdup(key);
+ dict->entries[in].key = key;
dict->entries[in].key_hash = hash;
dict->entries[in].value = value;
break;