Implemented booleans, swapped to YACJS_NAME macro.
authorethereal <ethereal@ethv.net>
Mon, 27 Jan 2014 20:59:21 +0000 (13:59 -0700)
committerethereal <ethereal@ethv.net>
Mon, 27 Jan 2014 20:59:21 +0000 (13:59 -0700)
It is now easy to change the naming prefix, just change yacjs_name.h.

src/main.c
src/yacjs.c
src/yacjs.h
src/yacjs_dict.c
src/yacjs_dict.h
src/yacjs_name.h [new file with mode: 0644]
src/yacjs_u8s.h

index 100e03b..8c2e723 100644 (file)
@@ -6,15 +6,23 @@ int main() {
     struct yacjs_node *root = yacjs_parse("{\"foo\": \"bar\", \"baz\": [\"a\", \"b\", \"c\"]}");
 
     FILE *fp = fopen("test/test1.json", "r");
-    char buffer[8192];
-    int ret = fread(buffer, 1, 8192, fp);
+    char buffer[32768];
+    int ret = fread(buffer, 1, 32768, fp);
     buffer[ret] = 0;
+    printf("bytes read: %i\n", ret);
     fclose(fp);
 
     root = yacjs_parse(buffer);
     printf("root: %p\n", root);
 
-    //printf("%f\n", yacjs_node_float(yacjs_node_array_elem(root, 2)));
+    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));
+
+    node = yacjs_node_array_elem(node, 1);
+    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")));
 
     return 0;
 }
index 7697a2d..a55455b 100644 (file)
@@ -1,24 +1,26 @@
 #include <stdbool.h>
 #include <stdio.h> // for debugging
 #include <stdlib.h>
+#include <string.h>
 #include <ctype.h>
 
 #include "yacjs.h"
 #include "yacjs_dict.h"
 #include "yacjs_u8s.h"
 
-struct yacjs_node {
-    enum yacjs_node_type type;
+struct YACJS_NAME(node) {
+    enum YACJS_NAME(node_type) type;
     union {
         const char *string;
         int64_t number;
         double fp;
         struct {
-            struct yacjs_node *entries;
+            struct YACJS_NAME(node) *entries;
             int entries_count;
             int entries_size;
         } array;
-        struct yacjs_dict *dict;
+        struct YACJS_NAME(dict) *dict;
+        bool boolean;
     } data;
 };
 
@@ -27,6 +29,9 @@ enum token_type {
     TOKEN_NUMBER,
     TOKEN_FLOAT,
     TOKEN_FPNUMBER,
+    TOKEN_TRUE,
+    TOKEN_FALSE,
+    TOKEN_NULL,
     TOKEN_OPENDICT,
     TOKEN_CLOSEDICT,
     TOKEN_OPENARRAY,
@@ -38,60 +43,70 @@ enum token_type {
     TOKEN_TYPES
 };
 
-static enum yacjs_error last_error = YACJS_ERROR_NONE;
+static enum YACJS_NAME(error) last_error = YACJS_ERROR_NONE;
 
-static void destroy_helper(struct yacjs_node *node);
+static void destroy_helper(struct YACJS_NAME(node) *node);
 static void skip_whitespace(const char ** const ptr);
 static const char *next_token(const char ** const ptr, int *length,
     enum token_type *type);
 static const char *peek_token(const char ** const ptr, int *length,
     enum token_type *type);
-static struct yacjs_node *parse_any(const char **string);
-static struct yacjs_node *parse_dict_contents(const char **string);
-static struct yacjs_node *parse_array_contents(const char **string);
+static struct YACJS_NAME(node) *parse_any(const char **string);
+static struct YACJS_NAME(node) *parse_dict_contents(const char **string);
+static struct YACJS_NAME(node) *parse_array_contents(const char **string);
 
-enum yacjs_error yacjs_last_error() {
-    enum yacjs_error err = last_error;
+enum YACJS_NAME(error) YACJS_NAME(last_error)() {
+    enum YACJS_NAME(error) err = last_error;
     last_error = YACJS_ERROR_NONE;
     return err;
 }
 
-struct yacjs_node *yacjs_parse(const char *string) {
-    struct yacjs_node *ret = parse_any(&string);
+struct YACJS_NAME(node) *YACJS_NAME(parse)(const char *string) {
+    struct YACJS_NAME(node) *ret = parse_any(&string);
     // ensure there's nothing afterwards.
     skip_whitespace(&string);
     if(string[0] != 0) {
-        yacjs_destroy(ret);
+        YACJS_NAME(destroy)(ret);
         last_error = YACJS_ERROR_PARSE;
         return NULL;
     }
     return ret;
 }
 
-void yacjs_destroy(struct yacjs_node *node) {
+void YACJS_NAME(destroy)(struct YACJS_NAME(node) *node) {
     if(!node) return;
     destroy_helper(node);
     free(node);
 }
 
-static void destroy_helper(struct yacjs_node *node) {
+static void destroy_helper(struct YACJS_NAME(node) *node) {
     if(node->type == YACJS_NODE_ARRAY) {
         for(int i = 0; i < node->data.array.entries_count; i ++) {
-            yacjs_destroy(node->data.array.entries + i);
+            YACJS_NAME(destroy)(node->data.array.entries + i);
         }
         free(node->data.array.entries);
     }
     else if(node->type == YACJS_NODE_DICT) {
-        yacjs_dict_destroy(node->data.dict,
-            (yacjs_dict_visitor)destroy_helper);
+        YACJS_NAME(dict_destroy)(node->data.dict,
+            (YACJS_NAME(dict_visitor))destroy_helper);
     }
 }
 
-enum yacjs_node_type yacjs_node_type(struct yacjs_node *node) {
+enum YACJS_NAME(node_type) YACJS_NAME(node_type)(
+    struct YACJS_NAME(node) *node) {
+
     return node->type;
 }
 
-const char *yacjs_node_str(struct yacjs_node *node) {
+bool YACJS_NAME(node_bool)(struct YACJS_NAME(node) *node) {
+    if(node->type != YACJS_NODE_BOOLEAN) {
+        last_error = YACJS_ERROR_TYPE;
+        return NULL;
+    }
+    return node->data.boolean;
+}
+
+const char *YACJS_NAME(node_str)(struct YACJS_NAME(node) *node) {
     if(node->type != YACJS_NODE_STRING) {
         last_error = YACJS_ERROR_TYPE;
         return NULL;
@@ -99,7 +114,7 @@ const char *yacjs_node_str(struct yacjs_node *node) {
     return node->data.string;
 }
 
-int64_t yacjs_node_num(struct yacjs_node *node) {
+int64_t YACJS_NAME(node_num)(struct YACJS_NAME(node) *node) {
     if(node->type != YACJS_NODE_NUMBER) {
         last_error = YACJS_ERROR_TYPE;
         return -1;
@@ -107,7 +122,7 @@ int64_t yacjs_node_num(struct yacjs_node *node) {
     return node->data.number;
 }
 
-double yacjs_node_float(struct yacjs_node *node) {
+double YACJS_NAME(node_float)(struct YACJS_NAME(node) *node) {
     if(node->type != YACJS_NODE_FLOAT) {
         last_error = YACJS_ERROR_TYPE;
         return 1/0.0; // NaN
@@ -115,7 +130,7 @@ double yacjs_node_float(struct yacjs_node *node) {
     return node->data.fp;
 }
 
-int yacjs_node_array_size(struct yacjs_node *node) {
+int YACJS_NAME(node_array_size)(struct YACJS_NAME(node) *node) {
     if(node->type != YACJS_NODE_ARRAY) {
         last_error = YACJS_ERROR_TYPE;
         return -1;
@@ -123,7 +138,9 @@ int yacjs_node_array_size(struct yacjs_node *node) {
     return node->data.array.entries_count;
 }
 
-struct yacjs_node *yacjs_node_array_elem(struct yacjs_node *node, int index) {
+struct YACJS_NAME(node) *YACJS_NAME(node_array_elem)(
+    struct YACJS_NAME(node) *node, int index) {
+
     if(node->type != YACJS_NODE_ARRAY) {
         last_error = YACJS_ERROR_TYPE;
         return NULL;
@@ -136,20 +153,20 @@ struct yacjs_node *yacjs_node_array_elem(struct yacjs_node *node, int index) {
     return node->data.array.entries + index;
 }
 
-struct yacjs_node *yacjs_node_dict_get(struct yacjs_node *node,
-    const char *key) {
+struct YACJS_NAME(node) *YACJS_NAME(node_dict_get)(
+    struct YACJS_NAME(node) *node, const char *key) {
 
     if(node->type != YACJS_NODE_DICT) {
         last_error = YACJS_ERROR_TYPE;
         return NULL;
     }
 
-    return yacjs_dict_get(node->data.dict, key);
+    return YACJS_NAME(dict_get)(node->data.dict, key);
 }
 
 static void skip_whitespace(const char ** const ptr) {
     while((**ptr == ' ' || **ptr == '\t' || **ptr == '\n') && **ptr != 0) {
-        *ptr = yacjs_u8s_next(*ptr);
+        *ptr = YACJS_NAME(u8s_next)(*ptr);
     }
 }
 
@@ -178,12 +195,13 @@ static const char *next_token(const char ** const ptr, int *length,
         *type = TOKEN_STRING;
         return start;
     }
-    else if(isdigit(**ptr)) {
-        // TODO: support floating-point etc.
+    else if(isdigit(**ptr) || **ptr == '-') {
         const char *start = (*ptr);
         *length = 0;
         bool is_fp = false;
-        while((isdigit(**ptr) || **ptr == '.' || **ptr == 'e') && **ptr != 0) {
+        while((isdigit(**ptr) || **ptr == '.' || **ptr == 'e' || **ptr == '-')
+            && **ptr != 0) {
+
             if(**ptr == '.' || **ptr == 'e') is_fp = true;
             (*ptr) ++, (*length) ++;
         }
@@ -217,8 +235,21 @@ static const char *next_token(const char ** const ptr, int *length,
         *type = TOKEN_COLON;
         return (*ptr)++;
     }
+    else if(!strncmp(*ptr, "false", 5)) {
+        *type = TOKEN_FALSE;
+        return (*ptr) += 5;
+    }
+    else if(!strncmp(*ptr, "true", 4)) {
+        *type = TOKEN_TRUE;
+        return (*ptr) += 4;
+    }
+    else if(!strncmp(*ptr, "null", 4)) {
+        *type = TOKEN_NULL;
+        return (*ptr) += 4;
+    }
 
     printf("Don't know what to do with a '%c'\n", **ptr);
+    printf("context: \n\n<\n%s\n>\n\n", *ptr);
 
     *type = TOKEN_ERROR;
 
@@ -233,7 +264,7 @@ static const char *peek_token(const char ** const ptr, int *length,
     return next_token(&s, length, type);
 }
 
-static struct yacjs_node *parse_any(const char **string) {
+static struct YACJS_NAME(node) *parse_any(const char **string) {
     enum token_type type;
     const char *s;
     int len;
@@ -242,19 +273,19 @@ static struct yacjs_node *parse_any(const char **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_node *build = malloc(sizeof(*build));
+        struct YACJS_NAME(node) *build = malloc(sizeof(*build));
         build->type = YACJS_NODE_STRING;
-        build->data.string = yacjs_u8s_strndup(s, len);
+        build->data.string = YACJS_NAME(u8s_strndup)(s, len);
         return build;
     }
     else if(type == TOKEN_NUMBER) {
-        struct yacjs_node *build = malloc(sizeof(*build));
+        struct YACJS_NAME(node) *build = malloc(sizeof(*build));
         build->type = YACJS_NODE_NUMBER;
         build->data.number = strtoll(s, NULL, 0);
         return build;
     }
     else if(type == TOKEN_FLOAT) {
-        struct yacjs_node *build = malloc(sizeof(*build));
+        struct YACJS_NAME(node) *build = malloc(sizeof(*build));
         build->type = YACJS_NODE_FLOAT;
         char *e;
         build->data.fp = strtod(s, &e);
@@ -265,20 +296,31 @@ static struct yacjs_node *parse_any(const char **string) {
         }
         return build;
     }
+    else if(type == TOKEN_FALSE || type == TOKEN_TRUE) {
+        struct YACJS_NAME(node) *build = malloc(sizeof(*build));
+        build->type = YACJS_NODE_BOOLEAN;
+        build->data.boolean = type == TOKEN_TRUE;
+        return build;
+    }
+    else if(type == TOKEN_NULL) {
+        struct YACJS_NAME(node) *build = malloc(sizeof(*build));
+        build->type = YACJS_NODE_NULL;
+        return build;
+    }
 
     printf("Unknown token type %i\n", type);
 
     return NULL;
 }
 
-static struct yacjs_node *parse_dict_contents(const char **string) {
+static struct YACJS_NAME(node) *parse_dict_contents(const char **string) {
     enum token_type type;
     const char *s;
     int len;
 
-    struct yacjs_node *result = malloc(sizeof(*result));
+    struct YACJS_NAME(node) *result = malloc(sizeof(*result));
     result->type = YACJS_NODE_DICT;
-    result->data.dict = yacjs_dict_make();
+    result->data.dict = YACJS_NAME(dict_make)();
 
     while((s = next_token(string, &len, &type))) {
         // closing dictionary token
@@ -288,7 +330,7 @@ static struct yacjs_node *parse_dict_contents(const char **string) {
             return NULL;
         }
 
-        char *ds = yacjs_u8s_strndup(s, len);
+        char *ds = YACJS_NAME(u8s_strndup)(s, len);
 
         // expect a colon after the name
         next_token(string, &len, &type);
@@ -296,14 +338,14 @@ static struct yacjs_node *parse_dict_contents(const char **string) {
             return NULL;
         }
 
-        struct yacjs_node *value = parse_any(string);
+        struct YACJS_NAME(node) *value = parse_any(string);
 
         if(value == NULL) {
             // TODO: leaked memory
             return NULL;
         }
 
-        yacjs_dict_set(result->data.dict, ds, value);
+        YACJS_NAME(dict_set)(result->data.dict, ds, value);
         free(ds);
 
         peek_token(string, &len, &type);
@@ -321,12 +363,12 @@ static struct yacjs_node *parse_dict_contents(const char **string) {
     return result;
 }
 
-static struct yacjs_node *parse_array_contents(const char **string) {
+static struct YACJS_NAME(node) *parse_array_contents(const char **string) {
     enum token_type type;
     const char *s;
     int len;
 
-    struct yacjs_node *result = malloc(sizeof(*result));
+    struct YACJS_NAME(node) *result = malloc(sizeof(*result));
     result->type = YACJS_NODE_ARRAY;
     result->data.array.entries = NULL;
     result->data.array.entries_size = 0;
@@ -339,7 +381,7 @@ static struct yacjs_node *parse_array_contents(const char **string) {
             next_token(string, &len, &type);
             break;
         }
-        struct yacjs_node *next = parse_any(string);
+        struct YACJS_NAME(node) *next = parse_any(string);
         if(!next) {
             // TODO: leaked memory
             return NULL;
@@ -349,7 +391,7 @@ static struct yacjs_node *parse_array_contents(const char **string) {
             == result->data.array.entries_count) {
 
             void *nmem = realloc(result->data.array.entries,
-                sizeof(struct yacjs_node)
+                sizeof(struct YACJS_NAME(node))
                     * (result->data.array.entries_size * 2 + 1));
             if(nmem == NULL) {
                 last_error = YACJS_ERROR_MEMORY;
index b3884fb..d441372 100644 (file)
@@ -1,11 +1,16 @@
 #ifndef YACJS_H
 #define YACJS_H
 
+#include <stdbool.h>
 #include <stdint.h>
 
-struct yacjs_node;
+#include "yacjs_name.h"
 
-enum yacjs_node_type {
+struct YACJS_NAME(node);
+
+enum YACJS_NAME(node_type) {
+    YACJS_NODE_NULL,
+    YACJS_NODE_BOOLEAN,
     YACJS_NODE_STRING,
     YACJS_NODE_NUMBER,
     YACJS_NODE_FLOAT,
@@ -14,7 +19,7 @@ enum yacjs_node_type {
     YACJS_NODE_TYPES
 };
 
-enum yacjs_error {
+enum YACJS_NAME(error) {
     YACJS_ERROR_NONE,
     YACJS_ERROR_PARSE,
     YACJS_ERROR_MEMORY,
@@ -23,18 +28,20 @@ enum yacjs_error {
     YACJS_ERROR_TYPES
 };
 
-enum yacjs_error yacjs_last_error();
-
-struct yacjs_node *yacjs_parse(const char *string);
-void yacjs_destroy(struct yacjs_node *node);
-
-enum yacjs_node_type yacjs_node_type(struct yacjs_node *node);
-const char *yacjs_node_str(struct yacjs_node *node);
-int64_t yacjs_node_num(struct yacjs_node *node);
-double yacjs_node_float(struct yacjs_node *node);
-int yacjs_node_array_size(struct yacjs_node *node);
-struct yacjs_node *yacjs_node_array_elem(struct yacjs_node *node, int index);
-struct yacjs_node *yacjs_node_dict_get(struct yacjs_node *node,
-    const char *key);
+enum YACJS_NAME(error) YACJS_NAME(last_error)();
+
+struct YACJS_NAME(node) *YACJS_NAME(parse)(const char *string);
+void YACJS_NAME(destroy)(struct YACJS_NAME(node) *node);
+
+enum YACJS_NAME(node_type) YACJS_NAME(node_type)(struct YACJS_NAME(node) *node);
+bool YACJS_NAME(node_bool)(struct YACJS_NAME(node) *node);
+const char *YACJS_NAME(node_str)(struct YACJS_NAME(node) *node);
+int64_t YACJS_NAME(node_num)(struct YACJS_NAME(node) *node);
+double YACJS_NAME(node_float)(struct YACJS_NAME(node) *node);
+int YACJS_NAME(node_array_size)(struct YACJS_NAME(node) *node);
+struct YACJS_NAME(node) *YACJS_NAME(node_array_elem)(
+    struct YACJS_NAME(node) *node, int index);
+struct YACJS_NAME(node) *YACJS_NAME(node_dict_get)(
+    struct YACJS_NAME(node) *node, const char *key);
 
 #endif
index d3d87db..c59a40a 100644 (file)
@@ -4,26 +4,26 @@
 
 #include "yacjs_dict.h"
 
-struct yacjs_dict_entry {
+struct YACJS_NAME(dict_entry) {
     char *key;
     void *value;
     uint64_t key_hash;
 };
 
-struct yacjs_dict {
-    struct yacjs_dict_entry *entries;
+struct YACJS_NAME(dict) {
+    struct YACJS_NAME(dict_entry) *entries;
     int entries_size;
     int entries_count;
 };
 
 static char *ystrdup(const char *string);
 static uint64_t string_hash(const char *string);
-static void resize(struct yacjs_dict *dict, int newsize);
-static void insert_helper(struct yacjs_dict *dict, uint64_t hash,
+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);
 
-struct yacjs_dict *yacjs_dict_make() {
-    struct yacjs_dict *result = malloc(sizeof(*result));
+struct YACJS_NAME(dict) *YACJS_NAME(dict_make)() {
+    struct YACJS_NAME(dict) *result = malloc(sizeof(*result));
 
     result->entries = NULL;
     result->entries_size = 0;
@@ -32,7 +32,9 @@ struct yacjs_dict *yacjs_dict_make() {
     return result;
 }
 
-void yacjs_dict_destroy(struct yacjs_dict *dict, yacjs_dict_visitor visitor) {
+void YACJS_NAME(dict_destroy)(struct YACJS_NAME(dict) *dict,
+    YACJS_NAME(dict_visitor) visitor) {
+
     if(visitor) {
         for(int i = 0; i < dict->entries_size; i ++) {
             if(dict->entries[i].key) {
@@ -45,7 +47,7 @@ void yacjs_dict_destroy(struct yacjs_dict *dict, yacjs_dict_visitor visitor) {
     free(dict);
 }
 
-void yacjs_dict_set(struct yacjs_dict *dict, const char *key,
+void YACJS_NAME(dict_set)(struct YACJS_NAME(dict) *dict, const char *key,
     void *value) {
 
     if(dict->entries_size == dict->entries_count) {
@@ -56,7 +58,7 @@ void yacjs_dict_set(struct yacjs_dict *dict, const char *key,
     insert_helper(dict, hash, ystrdup(key), value);
 }
 
-void *yacjs_dict_get(struct yacjs_dict *dict, const char *key) {
+void *YACJS_NAME(dict_get)(struct YACJS_NAME(dict) *dict, const char *key) {
     uint64_t hash = string_hash(key);
     for(int i = 0; i < dict->entries_size; i ++) {
         int in = (i+hash) % dict->entries_size;
@@ -82,8 +84,8 @@ static uint64_t string_hash(const char *string) {
     return result;
 }
 
-static void resize(struct yacjs_dict *dict, int newsize) {
-    struct yacjs_dict_entry *oentries = dict->entries;
+static void resize(struct YACJS_NAME(dict) *dict, int newsize) {
+    struct YACJS_NAME(dict_entry) *oentries = dict->entries;
     int osize = dict->entries_size;
     dict->entries_size = newsize;
     dict->entries_count = 0;
@@ -96,7 +98,7 @@ static void resize(struct yacjs_dict *dict, int newsize) {
     }
 }
 
-static void insert_helper(struct yacjs_dict *dict, uint64_t hash,
+static void insert_helper(struct YACJS_NAME(dict) *dict, uint64_t hash,
     const char *key, void *value) {
     for(int i = 0; i < dict->entries_size; i ++) {
         int in = (i+hash) % dict->entries_size;
index 2cf3fca..c3f1ea2 100644 (file)
@@ -1,15 +1,18 @@
 #ifndef YACJS_DICT_H
 #define YACJS_DICT_H
 
-struct yacjs_dict;
+#include "yacjs_name.h"
 
-typedef void (*yacjs_dict_visitor)(void *value);
+struct YACJS_NAME(dict);
 
-struct yacjs_dict *yacjs_dict_make();
-void yacjs_dict_destroy(struct yacjs_dict *dict, yacjs_dict_visitor visitor);
+typedef void (*YACJS_NAME(dict_visitor))(void *value);
 
-void yacjs_dict_set(struct yacjs_dict *dict, const char *key,
+struct YACJS_NAME(dict) *YACJS_NAME(dict_make)();
+void YACJS_NAME(dict_destroy)(struct YACJS_NAME(dict) *dict,
+    YACJS_NAME(dict_visitor) visitor);
+
+void YACJS_NAME(dict_set)(struct YACJS_NAME(dict) *dict, const char *key,
     void *value);
-void *yacjs_dict_get(struct yacjs_dict *dict, const char *key);
+void *YACJS_NAME(dict_get)(struct YACJS_NAME(dict) *dict, const char *key);
 
 #endif
diff --git a/src/yacjs_name.h b/src/yacjs_name.h
new file mode 100644 (file)
index 0000000..8096f7f
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef YACJS_NAME_H
+#define YACJS_NAME_H
+
+#define YACJS_NAME(n) yacjs_ ## n
+
+#endif
index 6414f43..01c0977 100644 (file)
@@ -3,7 +3,9 @@
 
 #include <stddef.h>
 
-#define U8S_NAME(n) yacjs_u8s_ ## n
+#include "yacjs_name.h"
+
+#define U8S_NAME(n) YACJS_NAME(u8s_ ## n)
 
 typedef char * U8S_NAME(ptr);
 typedef const char * U8S_NAME(cptr);