From fee27e1353cfcd4e69a34a1ba70450f74acf1c64 Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Fri, 7 Feb 2014 15:51:46 -0800 Subject: [PATCH] Add a callback interface for non-closing punctuation --- jsoncat.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- jsonpull.c | 48 ++++++++++++++++++++++++++++++------------------ jsonpull.h | 4 ++++ 3 files changed, 84 insertions(+), 20 deletions(-) diff --git a/jsoncat.c b/jsoncat.c index a545684c..1b182921 100644 --- a/jsoncat.c +++ b/jsoncat.c @@ -12,7 +12,7 @@ static void indent(int depth) { } } -void json_print(json_object *j, int depth) { +void json_print_one(json_object *j, int *depth) { if (j == NULL) { printf("NULL"); } else if (j->type == JSON_STRING) { @@ -39,6 +39,20 @@ void json_print(json_object *j, int depth) { } else if (j->type == JSON_FALSE) { printf("false"); } else if (j->type == JSON_HASH) { + printf("\n"); + (*depth)--; + indent(*depth); + printf("}"); + } else if (j->type == JSON_ARRAY) { + printf("\n"); + (*depth)--; + indent(*depth); + printf("]"); + } +} + +void json_print(json_object *j, int depth) { + if (j->type == JSON_HASH) { printf("{\n"); indent(depth + 1); @@ -71,7 +85,40 @@ void json_print(json_object *j, int depth) { indent(depth); printf("]"); } else { - printf("what type? %d", j->type); + json_print_one(j, &depth); + } +} + +void callback(json_type type, json_pull *jp, void *state) { + int *level = state; + + if (type == JSON_ARRAY) { + printf("[\n"); + (*level)++; + indent(*level); + } else if (type == JSON_HASH) { + printf("{\n"); + (*level)++; + indent(*level); + } else if (type == JSON_COMMA) { + printf(", "); + } else if (type == JSON_COLON) { + printf(": "); + } +} + +void process_callback(FILE *f, char *fname) { + json_pull *jp = json_begin_file(f); + json_object *j; + int level = 0; + + while ((j = json_parse_with_separators(jp, callback, &level)) != NULL) { + json_print_one(j, &level); + json_free(j); + } + + if (jp->error != NULL) { + fprintf(stderr, "%s: %d: %s\n", fname, jp->line, jp->error); } } @@ -82,6 +129,7 @@ void process(FILE *f, char *fname) { while ((j = json_parse(jp)) != NULL) { if (j->parent == NULL) { json_print(j, 0); + json_free(j); printf("\n"); } } diff --git a/jsonpull.c b/jsonpull.c index 80dc4988..70d73f40 100644 --- a/jsonpull.c +++ b/jsonpull.c @@ -5,10 +5,6 @@ #include #include "jsonpull.h" -typedef enum json_expect { - JSON_ITEM, JSON_COMMA, JSON_COLON, JSON_KEY, JSON_VALUE, -} json_expect; - static json_pull *json_init() { json_pull *j = malloc(sizeof(json_pull)); j->error = NULL; @@ -76,16 +72,20 @@ json_pull *json_begin_string(char *s) { #define SIZE_FOR(i) (((i) + 31) & ~31) -static json_object *add_object(json_pull *j, json_type type) { +static json_object *fabricate_object(json_object *parent, json_type type) { json_object *o = malloc(sizeof(struct json_object)); o->type = type; - o->parent = j->container; + o->parent = parent; o->array = NULL; o->keys = NULL; o->values = NULL; o->length = 0; + return o; +} +static json_object *add_object(json_pull *j, json_type type) { json_object *c = j->container; + json_object *o = fabricate_object(c, type); if (c != NULL) { if (c->type == JSON_ARRAY) { @@ -178,7 +178,7 @@ static void string_free(struct string *s) { free(s->buf); } -json_object *json_parse(json_pull *j) { +json_object *json_parse_with_separators(json_pull *j, json_separator_callback cb, void *state) { int c; again: /////////////////////////// Whitespace @@ -203,6 +203,11 @@ again: } j->container = o; j->container->expect = JSON_ITEM; + + if (cb != NULL) { + cb(JSON_ARRAY, j, state); + } + goto again; } else if (c == ']') { if (j->container == NULL) { @@ -236,6 +241,11 @@ again: } j->container = o; j->container->expect = JSON_KEY; + + if (cb != NULL) { + cb(JSON_HASH, j, state); + } + goto again; } else if (c == '}') { if (j->container == NULL) { @@ -312,6 +322,10 @@ again: j->container->expect = JSON_ITEM; } + if (cb != NULL) { + cb(JSON_COMMA, j, state); + } + goto again; } @@ -329,6 +343,11 @@ again: } j->container->expect = JSON_VALUE; + + if (cb != NULL) { + cb(JSON_COLON, j, state); + } + goto again; } @@ -459,15 +478,8 @@ again: return NULL; } -static json_object *fabricate_null(json_object *parent) { - json_object *o = malloc(sizeof(struct json_object)); - o->type = JSON_NULL; - o->parent = parent; - o->array = NULL; - o->keys = NULL; - o->values = NULL; - o->length = 0; - return o; +json_object *json_parse(json_pull *j) { + return json_parse_with_separators(j, NULL, NULL); } void json_free(json_object *o) { @@ -531,11 +543,11 @@ void json_free(json_object *o) { if (o->parent->type == JSON_HASH) { for (i = 0; i < o->parent->length; i++) { if (o->parent->keys[i] == o) { - o->parent->keys[i] = fabricate_null(o->parent); + o->parent->keys[i] = fabricate_object(o->parent, JSON_NULL); break; } if (o->parent->values[i] == o) { - o->parent->values[i] = fabricate_null(o->parent); + o->parent->values[i] = fabricate_object(o->parent, JSON_NULL); break; } } diff --git a/jsonpull.h b/jsonpull.h index b0633a76..e69b201e 100644 --- a/jsonpull.h +++ b/jsonpull.h @@ -1,5 +1,6 @@ typedef enum json_type { JSON_HASH, JSON_ARRAY, JSON_NUMBER, JSON_STRING, JSON_TRUE, JSON_FALSE, JSON_NULL, + JSON_COMMA, JSON_COLON, JSON_ITEM, JSON_KEY, JSON_VALUE, } json_type; typedef struct json_object { @@ -30,9 +31,12 @@ struct json_pull { }; typedef struct json_pull json_pull; +typedef void (*json_separator_callback)(json_type type, json_pull *j, void *state); + json_pull *json_begin_file(FILE *f); json_pull *json_begin_string(char *s); json_object *json_parse(json_pull *j); +json_object *json_parse_with_separators(json_pull *j, json_separator_callback cb, void *state); void json_free(json_object *j); json_object *json_hash_get(json_object *o, char *s);