From: Heng Li Date: Sat, 29 Nov 2014 23:20:35 +0000 (-0500) Subject: added JSON query X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=d4827d96c44a8c950115b6d23fac1b7037c7fb8b;p=klib.git added JSON query --- diff --git a/kson.c b/kson.c index a962ba7..311780d 100644 --- a/kson.c +++ b/kson.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #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 8b0a1e2..9a44fbc 100644 --- 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 }