]> git.kaiwu.me - klib.git/commitdiff
added JSON query
authorHeng Li <lh3@me.com>
Sat, 29 Nov 2014 23:20:35 +0000 (18:20 -0500)
committerHeng Li <lh3@me.com>
Sat, 29 Nov 2014 23:20:35 +0000 (18:20 -0500)
kson.c
kson.h

diff --git a/kson.c b/kson.c
index a962ba7d2e2b0228a4b95b164ba1d0d6c5c4eaa9..311780d5c514ab75f6fbffa56a883acda31b53cd 100644 (file)
--- a/kson.c
+++ b/kson.c
@@ -1,5 +1,6 @@
 #include <string.h>
 #include <stdlib.h>
+#include <stdarg.h>
 #include <ctype.h>
 #include <stdio.h>
 #include "kson.h"
@@ -118,7 +119,7 @@ kson_t *kson_parse(const char *json, int *error)
        return kson;
 }
 
-void kson_print_recur(kson_node_t *nodes, kson_node_t *p)
+void kson_print_recur(const kson_node_t *nodes, const kson_node_t *p)
 {
        if (p->key) {
                printf("\"%s\"", p->key);
@@ -141,11 +142,45 @@ void kson_print_recur(kson_node_t *nodes, kson_node_t *p)
        }
 }
 
-void kson_print(kson_t *kson)
+void kson_print(const kson_t *kson)
 {
        kson_print_recur(kson->nodes, kson->nodes);
 }
 
+const kson_node_t *kson_vquery(const kson_node_t *nodes, const kson_node_t *root, int depth, va_list ap)
+{
+       const kson_node_t *p = root;
+       while (p && depth > 0) {
+               if (p->type == KSON_TYPE_BRACE) {
+                       long i;
+                       const char *q = va_arg(ap, const char*);
+                       for (i = 0; i < (long)p->n; ++i) {
+                               const kson_node_t *r = &nodes[i];
+                               if (r->key && strcmp(r->key, q) == 0) {
+                                       p = r;
+                                       break;
+                               }
+                       }
+                       if (i == (long)p->n) p = 0;
+               } else if (p->type == KSON_TYPE_BRACKET) {
+                       long i = va_arg(ap, long);
+                       p = i < (long)p->n? &nodes[p->v.child[i]] : 0;
+               } else break;
+               --depth;
+       }
+       return p;
+}
+
+const kson_node_t *kson_query(const kson_t *kson, int depth, ...)
+{
+       const kson_node_t *p;
+       va_list ap;
+       va_start(ap, depth);
+       p = kson_vquery(kson->nodes, kson->nodes, depth, ap);
+       va_end(ap);
+       return p;
+}
+
 #ifdef KSON_MAIN
 int main(int argc, char *argv[])
 {
@@ -153,6 +188,8 @@ int main(int argc, char *argv[])
        int error;
        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);
+               printf("*** %s\n", p->v.str);
                kson_print(kson);
                putchar('\n');
        } else {
diff --git a/kson.h b/kson.h
index 8b0a1e2592f51566d024745d5c707b172dd1d635..9a44fbccbfade2fac94e99b71b05594dcc3efa18 100644 (file)
--- a/kson.h
+++ b/kson.h
@@ -28,27 +28,29 @@ typedef struct {
        kson_node_t *nodes;
 } kson_t;
 
+#define kson_is_internal(p) ((p)->type == KSON_TYPE_BRACKET || (p)->type == KSON_TYPE_BRACE)
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
        /**
-        * Parse a JSON string into nodes
+        * Parse a JSON string
         *
-        * @param json        JSON string
-        * @param n_nodes     number of nodes
-        * @param error       0 if no error; or set to one of KSON_ERR_* values
-        * @param parsed_len  if not NULL, equal to the parsed length
+        * @param json    JSON string
+        * @param error   error code
         *
-        * @return An array of size $n_nodes keeping parsed nodes
+        * @return a pointer to kson_t if *error==0; or NULL otherwise
         */
-       kson_node_t *kson_parse_core(const char *json, long *n_nodes, int *error, long *parsed_len);
-
-       // Equivalent to: { kson->nodes = kson_parse_core(json, &kson->n_nodes, &error, 0); return *error? 0 : kson; } 
        kson_t *kson_parse(const char *json, int *error);
 
+       /** Destroy a kson_t object */
        void kson_destroy(kson_t *kson);
-       void kson_print(kson_t *kson);
+
+       const kson_node_t *kson_query(const kson_t *kson, int max_depth, ...);
+
+       void kson_print(const kson_t *kson);
+       kson_node_t *kson_parse_core(const char *json, long *n_nodes, int *error, long *parsed_len);
 
 #ifdef __cplusplus
 }