[PATCH v3 2/3] Adding structured output formatter for JSON.

craven at gmx.net craven at gmx.net
Tue Jul 10 11:56:45 PDT 2012


This formatter prints exactly the same structure as the existing JSON formatter, but uses the newly introduced structured formatting primitives.
---
 structured-output.c |  159 +++++++++++++++++++++++++++++++++++++++++++++++++++
 structured-output.h |   48 ++++++++++++++++
 2 files changed, 207 insertions(+)
 create mode 100644 structured-output.c

diff --git a/structured-output.c b/structured-output.c
new file mode 100644
index 0000000..e10fba4
--- /dev/null
+++ b/structured-output.c
@@ -0,0 +1,159 @@
+/* notmuch - Not much of an email program, (just index and search)
+ *
+ * Copyright © 2009 Carl Worth
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see http://www.gnu.org/licenses/ .
+ *
+ * Author: Carl Worth <cworth at cworth.org>
+ */
+
+#include "structured-output.h"
+
+structure_printer_t *
+unstructured_text_printer = NULL;
+
+structure_printer_t 
+json_structure_printer = {
+    &json_map,
+    &json_list,
+    &json_pop,
+    &json_map_key,
+    &json_number,
+    &json_string,
+    &json_bool,
+    &json_initial_state
+};
+static int
+enter_level(void *st, const char *marker, int type) {
+    json_state_t *state = (json_state_t*)st;
+    FILE *output = state->output;
+    if (state->stack != NULL && state->stack->type == TYPE_JSON_ARRAY && state->stack->first_already_seen) {
+	fputs(",", output);
+	if (state->level == 1)
+	    fputs("\n", output);
+	else
+	    fputs(" ", output);
+    }
+    if (state->stack != NULL) {
+	state->stack->first_already_seen = TRUE;
+    }
+    fputs(marker, output);
+    void *ctx_json_map = talloc_new (0);
+    json_list_t *el = talloc(ctx_json_map, json_list_t);
+    el->type = type;
+    el->first_already_seen = FALSE;
+    el->rest = state->stack;
+    state->stack = el;
+    return state->level++;
+}
+
+int
+json_map(void *st)
+{
+    return enter_level(st, "{", TYPE_JSON_MAP);
+}
+
+int
+json_list(void *st)
+{
+    return enter_level(st, "[", TYPE_JSON_ARRAY);
+}
+
+void
+json_pop(void *st, int level) 
+{
+    int i;
+    json_state_t *state = (json_state_t*)st;
+    FILE *output = state->output;
+    for (i = state->level; i > level; i--) {
+	json_list_t *tos = state->stack;
+	if (tos->type == TYPE_JSON_MAP) {
+	    fputs("}", output);
+	}
+	if (tos->type == TYPE_JSON_ARRAY) {
+	    fputs("]", output);
+	}
+	state->stack = tos->rest;
+	state->level--;
+	talloc_free(tos);
+    }
+    if (state->level == 0)
+	fputs("\n", output);
+}
+
+void
+json_map_key(void *st, const char *key)
+{
+    json_state_t *state = (json_state_t*)st;
+    FILE *output = state->output;
+    if (state->stack != NULL && state->stack->first_already_seen) {
+	fputs(",\n", output);
+    }
+    fputs("\"", output);
+    fputs(key, output);
+    fputs("\": ", output);
+}
+
+void
+json_number(void *st, int val)
+{
+    json_state_t *state = (json_state_t*)st;
+    FILE *output = state->output;
+    if (state->stack != NULL && state->stack->type == TYPE_JSON_ARRAY && state->stack->first_already_seen) {
+	fputs(", ", output);
+    }
+    state->stack->first_already_seen = TRUE;
+    fprintf(output, "%i", val);
+}
+
+void
+json_string(void *st, const char *val)
+{
+    json_state_t *state = (json_state_t*)st;
+    FILE *output = state->output;
+    void *ctx = talloc_new(0);
+    if (state->stack != NULL && state->stack->type == TYPE_JSON_ARRAY && state->stack->first_already_seen) {
+	fputs(",", output);
+	if (state->level == 1)
+	    fputs("\n", output);
+	else
+	    fputs(" ", output);
+    }
+
+    state->stack->first_already_seen = TRUE;
+    fprintf(output, "%s", json_quote_str(ctx, val));
+    talloc_free(ctx);
+}
+
+void
+json_bool(void *st, notmuch_bool_t val)
+{
+    json_state_t *state = (json_state_t*)st;
+    FILE *output = state->output;
+    if (val)
+	fputs("true", output);
+    else
+	fputs("false", output);
+}
+
+void *
+json_initial_state(const struct structure_printer *sp, FILE *output)
+{
+    (void)sp;
+    json_state_t *st = talloc(0, json_state_t);
+    st->level = 0;
+    st->stack = NULL;
+    st->output = output;
+    return st;
+}
diff --git a/structured-output.h b/structured-output.h
index b43afe0..cba3882 100644
--- a/structured-output.h
+++ b/structured-output.h
@@ -62,3 +62,51 @@ typedef struct structure_printer {
 } structure_printer_t;
 
 
+/* JSON structure printer */
+
+/* single linked list implementation for keeping track of the array/map nesting state */
+
+typedef struct json_list {
+    int type;
+    int first_already_seen;
+    struct json_list *rest;
+} json_list_t;
+
+#define TYPE_JSON_MAP 1
+#define TYPE_JSON_ARRAY 2
+
+typedef struct json_state {
+    FILE *output;
+    json_list_t *stack;
+    int level;
+} json_state_t;
+
+int
+json_map(void *state);
+
+int
+json_list(void *state);
+
+void
+json_pop(void *state, int level);
+
+void
+json_map_key(void *state, const char *key);
+
+void
+json_number(void *state, int val);
+
+void
+json_string(void *state, const char *val);
+
+void
+json_bool(void *state, notmuch_bool_t val);
+
+void *
+json_initial_state(const struct structure_printer *sp, FILE *output);
+
+structure_printer_t
+json_structure_printer;
+
+structure_printer_t *
+unstructured_text_printer;
-- 
1.7.10.4



More information about the notmuch mailing list