[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