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