From adc29e7ca7d9ed63d65ce167e1d4b5cfab58c589 Mon Sep 17 00:00:00 2001 From: craven Date: Tue, 10 Jul 2012 20:56:45 +0200 Subject: [PATCH] [PATCH v3 2/3] Adding structured output formatter for JSON. --- 9c/8127e59eb94482cd7fb5d476fdb8d7e82a19f1 | 291 ++++++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100644 9c/8127e59eb94482cd7fb5d476fdb8d7e82a19f1 diff --git a/9c/8127e59eb94482cd7fb5d476fdb8d7e82a19f1 b/9c/8127e59eb94482cd7fb5d476fdb8d7e82a19f1 new file mode 100644 index 000000000..3ab5c628b --- /dev/null +++ b/9c/8127e59eb94482cd7fb5d476fdb8d7e82a19f1 @@ -0,0 +1,291 @@ +Return-Path: +X-Original-To: notmuch@notmuchmail.org +Delivered-To: notmuch@notmuchmail.org +Received: from localhost (localhost [127.0.0.1]) + by olra.theworths.org (Postfix) with ESMTP id 69BE2431FC0 + for ; Tue, 10 Jul 2012 11:56:49 -0700 (PDT) +X-Virus-Scanned: Debian amavisd-new at olra.theworths.org +X-Spam-Flag: NO +X-Spam-Score: 0.001 +X-Spam-Level: +X-Spam-Status: No, score=0.001 tagged_above=-999 required=5 + tests=[FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001] + autolearn=disabled +Received: from olra.theworths.org ([127.0.0.1]) + by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id yMOhQ3kgmDbP for ; + Tue, 10 Jul 2012 11:56:48 -0700 (PDT) +Received: from mailout-de.gmx.net (mailout-de.gmx.net [213.165.64.23]) + by olra.theworths.org (Postfix) with SMTP id 61CE1431FBF + for ; Tue, 10 Jul 2012 11:56:48 -0700 (PDT) +Received: (qmail invoked by alias); 10 Jul 2012 18:56:46 -0000 +Received: from www.nexoid.at (EHLO mail.nexoid.at) [178.79.130.240] + by mail.gmx.net (mp041) with SMTP; 10 Jul 2012 20:56:46 +0200 +X-Authenticated: #4563876 +X-Provags-ID: V01U2FsdGVkX18D5ZtgJdoDpVbribBLKxrNVd64ms3Eu0lWmXSckZ + MjfNwa30lEc1cA +Received: from nexoid (localhost [127.0.0.1]) + by mail.nexoid.at (Postfix) with ESMTP id C9C63E00C + for ; Tue, 10 Jul 2012 20:56:45 +0200 (CEST) +From: +To: notmuch@notmuchmail.org +Subject: [PATCH v3 2/3] Adding structured output formatter for JSON. +User-Agent: Notmuch/0.11+77~gad6d0d5 (http://notmuchmail.org) Emacs/24.1.50.2 + (i686-pc-linux-gnu) +Date: Tue, 10 Jul 2012 20:56:45 +0200 +Message-ID: <87zk77tpg2.fsf@nexoid.at> +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: quoted-printable +X-Y-GMX-Trusted: 0 +X-BeenThere: notmuch@notmuchmail.org +X-Mailman-Version: 2.1.13 +Precedence: list +List-Id: "Use and development of the notmuch mail system." + +List-Unsubscribe: , + +List-Archive: +List-Post: +List-Help: +List-Subscribe: , + +X-List-Received-Date: Tue, 10 Jul 2012 18:56:49 -0000 + +This formatter prints exactly the same structure as the existing JSON forma= +tter, 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 =C2=A9 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 ++ */ ++ ++#include "structured-output.h" ++ ++structure_printer_t * ++unstructured_text_printer =3D NULL; ++ ++structure_printer_t=20 ++json_structure_printer =3D { ++ &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 =3D (json_state_t*)st; ++ FILE *output =3D state->output; ++ if (state->stack !=3D NULL && state->stack->type =3D=3D TYPE_JSON_ARRA= +Y && state->stack->first_already_seen) { ++ fputs(",", output); ++ if (state->level =3D=3D 1) ++ fputs("\n", output); ++ else ++ fputs(" ", output); ++ } ++ if (state->stack !=3D NULL) { ++ state->stack->first_already_seen =3D TRUE; ++ } ++ fputs(marker, output); ++ void *ctx_json_map =3D talloc_new (0); ++ json_list_t *el =3D talloc(ctx_json_map, json_list_t); ++ el->type =3D type; ++ el->first_already_seen =3D FALSE; ++ el->rest =3D state->stack; ++ state->stack =3D 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)=20 ++{ ++ int i; ++ json_state_t *state =3D (json_state_t*)st; ++ FILE *output =3D state->output; ++ for (i =3D state->level; i > level; i--) { ++ json_list_t *tos =3D state->stack; ++ if (tos->type =3D=3D TYPE_JSON_MAP) { ++ fputs("}", output); ++ } ++ if (tos->type =3D=3D TYPE_JSON_ARRAY) { ++ fputs("]", output); ++ } ++ state->stack =3D tos->rest; ++ state->level--; ++ talloc_free(tos); ++ } ++ if (state->level =3D=3D 0) ++ fputs("\n", output); ++} ++ ++void ++json_map_key(void *st, const char *key) ++{ ++ json_state_t *state =3D (json_state_t*)st; ++ FILE *output =3D state->output; ++ if (state->stack !=3D 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 =3D (json_state_t*)st; ++ FILE *output =3D state->output; ++ if (state->stack !=3D NULL && state->stack->type =3D=3D TYPE_JSON_ARRA= +Y && state->stack->first_already_seen) { ++ fputs(", ", output); ++ } ++ state->stack->first_already_seen =3D TRUE; ++ fprintf(output, "%i", val); ++} ++ ++void ++json_string(void *st, const char *val) ++{ ++ json_state_t *state =3D (json_state_t*)st; ++ FILE *output =3D state->output; ++ void *ctx =3D talloc_new(0); ++ if (state->stack !=3D NULL && state->stack->type =3D=3D TYPE_JSON_ARRA= +Y && state->stack->first_already_seen) { ++ fputs(",", output); ++ if (state->level =3D=3D 1) ++ fputs("\n", output); ++ else ++ fputs(" ", output); ++ } ++ ++ state->stack->first_already_seen =3D 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 =3D (json_state_t*)st; ++ FILE *output =3D 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 =3D talloc(0, json_state_t); ++ st->level =3D 0; ++ st->stack =3D NULL; ++ st->output =3D 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; +=20 +=20 ++/* JSON structure printer */ ++ ++/* single linked list implementation for keeping track of the array/map ne= +sting 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; +--=20 +1.7.10.4 + -- 2.26.2