]> git.kaiwu.me - klib.git/commitdiff
simplified API
authorHeng Li <lh3@me.com>
Sun, 30 Nov 2014 00:54:16 +0000 (19:54 -0500)
committerHeng Li <lh3@me.com>
Sun, 30 Nov 2014 00:54:16 +0000 (19:54 -0500)
kson.c
kson.h

diff --git a/kson.c b/kson.c
index 204ecac4cd2a7b937dfe7f6fcd6f2ac8bfa8618b..33d1e6ba492d56f9f5238d8e904e3f6f08689022 100644 (file)
--- a/kson.c
+++ b/kson.c
@@ -11,7 +11,7 @@
 
 kson_node_t *kson_parse_core(const char *json, long *_n, int *error, long *parsed_len)
 {
-       long *stack = 0, top = 0, max = 0, n_a = 0, m_a = 0;
+       long *stack = 0, top = 0, max = 0, n_a = 0, m_a = 0, i, j;
        kson_node_t *a = 0, *u;
        const char *p, *q;
 
@@ -56,9 +56,9 @@ kson_node_t *kson_parse_core(const char *json, long *_n, int *error, long *parse
                        u = &a[stack[start-1]];
                        u->key = u->v.str;
                        u->n = top - 1 - start;
-                       u->v.child = (long*)malloc(u->n * sizeof(long));
+                       u->v.child = (kson_ptr_t*)malloc(u->n * sizeof(kson_ptr_t));
                        for (i = start + 1; i < top; ++i)
-                               u->v.child[i - start - 1] = stack[i];
+                               u->v.child[i - start - 1].i = stack[i];
                        u->type = *p == ']'? KSON_TYPE_BRACKET : KSON_TYPE_BRACE;
                        if ((top = start) == 1) break; // completed one object; remaining characters discarded
                } else if (*p == ':') {
@@ -95,6 +95,12 @@ kson_node_t *kson_parse_core(const char *json, long *_n, int *error, long *parse
        if (parsed_len) *parsed_len = p - json;
        if (top != 1) *error = KSON_ERR_EXTRA_LEFT;
 
+       for (i = 0; i < n_a; ++i) {
+               u = &a[i];
+               for (j = 0; j < (long)u->n; ++j)
+                       u->v.child[j].p = &a[u->v.child[j].i];
+       }
+
        free(stack);
        *_n = n_a;
        return a;
@@ -126,16 +132,15 @@ kson_t *kson_parse(const char *json, int *error)
  *** Query ***
  *************/
 
-const kson_node_t *kson_query(const kson_t *kson, int depth, ...)
+const kson_node_t *kson_query(const kson_node_t *p, int depth, ...)
 {
-       const kson_node_t *p = kson->nodes;
        va_list ap;
        va_start(ap, depth);
        while (p && depth > 0) {
                if (p->type == KSON_TYPE_BRACE) {
-                       p = kson_by_key(kson->nodes, p, va_arg(ap, const char*));
+                       p = kson_by_key(p, va_arg(ap, const char*));
                } else if (p->type == KSON_TYPE_BRACKET) {
-                       p = kson_by_index(kson->nodes, p, va_arg(ap, long));
+                       p = kson_by_index(p, va_arg(ap, long));
                } else break;
                --depth;
        }
@@ -147,7 +152,7 @@ const kson_node_t *kson_query(const kson_t *kson, int depth, ...)
  *** Fromat ***
  **************/
 
-void kson_format_recur(const kson_node_t *nodes, int depth, const kson_node_t *p)
+void kson_format_recur(const kson_node_t *p, int depth)
 {
        long i;
        if (p->key) {
@@ -164,7 +169,7 @@ void kson_format_recur(const kson_node_t *nodes, int depth, const kson_node_t *p
                                        putchar(',');
                                        putchar('\n'); for (i = 0; i <= depth; ++i) fputs("  ", stdout);
                                }
-                               kson_format_recur(nodes, depth + 1, &nodes[p->v.child[i]]);
+                               kson_format_recur(p->v.child[i].p, depth + 1);
                        }
                        putchar('\n'); for (i = 0; i < depth; ++i) fputs("  ", stdout);
                }
@@ -178,9 +183,9 @@ void kson_format_recur(const kson_node_t *nodes, int depth, const kson_node_t *p
        }
 }
 
-void kson_format(const kson_t *kson)
+void kson_format(const kson_node_t *root)
 {
-       kson_format_recur(kson->nodes, 0, kson->nodes);
+       kson_format_recur(root, 0);
        putchar('\n');
 }
 
@@ -220,9 +225,9 @@ int main(int argc, char *argv[])
                                        const kson_node_t *p = kson->nodes;
                                        for (i = 2; i < argc && p; ++i) {
                                                if (p->type == KSON_TYPE_BRACKET)
-                                                       p = kson_by_index(kson->nodes, p, atoi(argv[i]));
+                                                       p = kson_by_index(p, atoi(argv[i]));
                                                else if (p->type == KSON_TYPE_BRACE)
-                                                       p = kson_by_key(kson->nodes, p, argv[i]);
+                                                       p = kson_by_key(p, argv[i]);
                                                else p = 0;
                                        }
                                        if (p) {
@@ -235,7 +240,7 @@ int main(int argc, char *argv[])
        } else {
                kson = kson_parse("{'a' : 1,'b':[0,'isn\\'t',true],'d':[{\n}]}", &error);
                if (error == 0) {
-                       const kson_node_t *p = kson_query(kson, 2, "b", 1);
+                       const kson_node_t *p = kson_query(kson->nodes, 2, "b", 1);
                        if (p) printf("*** %s\n", p->v.str);
                        else printf("!!! not found\n");
                        kson_format(kson);
diff --git a/kson.h b/kson.h
index 25845ada35662a62887a78e5f2b21429864538f0..d8b7e38f7c17d2cdd8cef2fc28c840d343f36b71 100644 (file)
--- a/kson.h
+++ b/kson.h
 #define KSON_ERR_EXTRA_RIGHT 2
 #define KSON_ERR_NO_KEY      3
 
-typedef struct {
+struct kson_node_s;
+
+typedef union {
+       long i; // this is a temporary variable; don't use it!
+       struct kson_node_s *p;
+} kson_ptr_t;
+
+typedef struct kson_node_s {
        uint64_t type:3, n:61;
        char *key;
        union {
-               long *child;
+               kson_ptr_t *child;
                char *str;
        } v;
 } kson_node_t;
 
 typedef struct {
        long n_nodes;
-       kson_node_t *nodes;
+       kson_node_t *nodes; // nodes[0] is the root
 } kson_t;
 
 #define kson_is_internal(p) ((p)->type == KSON_TYPE_BRACKET || (p)->type == KSON_TYPE_BRACE)
@@ -47,28 +54,28 @@ extern "C" {
        /** Destroy a kson_t object */
        void kson_destroy(kson_t *kson);
 
-       const kson_node_t *kson_query(const kson_t *kson, int max_depth, ...);
+       const kson_node_t *kson_query(const kson_node_t *root, int max_depth, ...);
 
-       void kson_format(const kson_t *kson);
+       void kson_format(const kson_node_t *root);
 
 #ifdef __cplusplus
 }
 #endif
 
-static inline const kson_node_t *kson_by_key(const kson_node_t *nodes, const kson_node_t *p, const char *key)
+static inline const kson_node_t *kson_by_key(const kson_node_t *p, const char *key)
 {
        long i;
        for (i = 0; i < (long)p->n; ++i) {
-               const kson_node_t *q = &nodes[p->v.child[i]];
+               const kson_node_t *q = p->v.child[i].p;
                if (q->key && strcmp(q->key, key) == 0)
                        return q;
        }
        return 0;
 }
 
-static inline const kson_node_t *kson_by_index(const kson_node_t *nodes, const kson_node_t *p, long i)
+static inline const kson_node_t *kson_by_index(const kson_node_t *p, long i)
 {
-       return 0 <= i && i < (long)p->n? &nodes[p->v.child[i]] : 0;
+       return 0 <= i && i < (long)p->n? p->v.child[i].p : 0;
 }
 
 #endif