From: craven Date: Wed, 11 Jul 2012 08:26:33 +0000 (+0200) Subject: [PATCH v3 1/3] Add support for structured output formatters. X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=55173009c7b13099070c46a6ae0407e32212435d;p=notmuch-archives.git [PATCH v3 1/3] Add support for structured output formatters. --- diff --git a/3d/093c5df081c869aae31ad3d517fc6178a92275 b/3d/093c5df081c869aae31ad3d517fc6178a92275 new file mode 100644 index 000000000..72f4a91d5 --- /dev/null +++ b/3d/093c5df081c869aae31ad3d517fc6178a92275 @@ -0,0 +1,208 @@ +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 A94E3429E4A + for ; Wed, 11 Jul 2012 01:25:25 -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 Nkw0IEuP2GIO for ; + Wed, 11 Jul 2012 01:25:22 -0700 (PDT) +Received: from mailout-de.gmx.net (mailout-de.gmx.net [213.165.64.23]) + by olra.theworths.org (Postfix) with SMTP id 137A6429E3C + for ; Wed, 11 Jul 2012 01:25:19 -0700 (PDT) +Received: (qmail invoked by alias); 11 Jul 2012 08:25:14 -0000 +Received: from gw.arelion.cust.net.lagis.at (EHLO dodekanex.arelion.at) + [83.164.197.182] + by mail.gmx.net (mp037) with SMTP; 11 Jul 2012 10:25:14 +0200 +X-Authenticated: #201305 +X-Provags-ID: V01U2FsdGVkX1887tYf0eI8tllIWkVJ6Mvejk7/HvwFk7Ruqa/5x2 + jalLZfI1VUHSon +Received: by dodekanex.arelion.at (Postfix, from userid 1000) + id D4A4030313F; Wed, 11 Jul 2012 10:26:36 +0200 (CEST) +From: +To: notmuch@notmuchmail.org +Subject: [PATCH v3 1/3] Add support for structured output formatters. +Date: Wed, 11 Jul 2012 10:26:33 +0200 +Message-Id: <1341995195-2497-2-git-send-email-craven@gmx.net> +X-Mailer: git-send-email 1.7.11.1 +In-Reply-To: <1341995195-2497-1-git-send-email-craven@gmx.net> +References: <20120710191331.GE7332@mit.edu> + <1341995195-2497-1-git-send-email-craven@gmx.net> +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +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: Wed, 11 Jul 2012 08:25:26 -0000 + +This patch adds a new type structure_printer, which is used for +structured formatting, e.g. JSON or S-Expressions. + +The structure contains the following function pointers: + +- initial_state: is called to create a state object, that is passed to + all invocations. This should be used to keep track of the output file + and everything else necessary to correctly format output. +- map: is called when a new map (associative array, dictionary) is + started. map_key and the primitives (string, number, bool) are used + alternatingly to add key/value pairs. pop is used to close the map + (see there). This function must return a nesting level identifier that + can be used to close all nested structures (maps and lists), backing + out to the returned nesting level. +- list: is called when a new list (array, vector) is started. the + primitives (string, number, bool) are used consecutively to add values + to the list. pop is used to close the list. This function must return + a nesting level identifier that can be used to close all nested + structures (maps and lists), backing out to the returned nesting + level. +- map_key: is called to write the key of a key/value pair. +- pop: is called to return to a given nesting level. All lists and maps + with a deeper nesting level must be closed. +- number, string, bool: output one element of the specific type. + +All functions should use state to insert delimiters etc. automatically +when appropriate. State is a user-defined object/data that can contain +arbitrary information. Initial state is constructed by a call to +initial_state. + +Example: +int top, one; +top = map(state); +map_key(state, "foo"); +one = list(state); +number(state, 1); +number(state, 2); +number(state, 3); +pop(state, one); +map_key(state, "bar"); +map(state); +map_key(state, "baaz"); +string(state, "hello world"); +pop(state, top); + +would output JSON as follows: + +{"foo": [1, 2, 3], "bar": { "baaz": "hello world"}} +--- + structured-output.h | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 90 insertions(+) + create mode 100644 structured-output.h + +diff --git a/structured-output.h b/structured-output.h +new file mode 100644 +index 0000000..73029f1 +--- /dev/null ++++ b/structured-output.h +@@ -0,0 +1,90 @@ ++/* 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 ++ */ ++ ++#include "notmuch-client.h" ++ ++/* structured formatting, useful for JSON, S-Expressions, ... ++ * ++ * All functions should use state to insert delimiters ++ * etc. automatically when appropriate. State is a user-defined ++ * object/data that can contain arbitrary information. Initial state is ++ * constructed by a call to initial_state. ++ * ++ * Example: ++ * int top, one; ++ * top = map(state); ++ * map_key(state, "foo"); ++ * one = list(state); ++ * number(state, 1); ++ * number(state, 2); ++ * number(state, 3); ++ * pop(state, one); ++ * map_key(state, "bar"); ++ * map(state); ++ * map_key(state, "baaz"); ++ * string(state, "hello world"); ++ * pop(state, top); ++ * ++ * would output JSON as follows: ++ * ++ * {"foo": [1, 2, 3], "bar": { "baaz": "hello world"}} ++ */ ++typedef struct structure_printer { ++ /* map: is called when a new map (associative array, dictionary) is ++ * started. map_key and the primitives (string, number, bool) are ++ * used alternatingly to add key/value pairs. pop is used to close ++ * the map (see there). This function must return a nesting level ++ * identifier number that can be used to close all nested structures ++ * (maps and lists), backing out to the returned nesting level. ++ */ ++ int (*map) (void *state); ++ ++ /* list: is called when a new list (array, vector) is started. the ++ * primitives (string, number, bool) are used consecutively to add ++ * values to the list. pop is used to close the list. This function ++ * must return a nesting level identifier number that can be used to ++ * close all nested structures (maps and lists), backing out to the ++ * returned nesting level. ++ */ ++ int (*list) (void *state); ++ ++ /* pop: is called to return to a given nesting level. All lists and ++ * maps with a deeper nesting level must be closed. ++ */ ++ void (*pop) (void *state, int level); ++ ++ /* map_key: is called to write the key of a key/value pair. ++ */ ++ void (*map_key) (void *state, const char *key); ++ ++ /* number, string, bool: output one element of the specific type. */ ++ void (*number) (void *state, int val); ++ void (*string) (void *state, const char *val); ++ void (*bool) (void *state, notmuch_bool_t val); ++ ++ /* initial_state: is called to create a state object, that is passed ++ * to all invocations. This should be used to keep track of the ++ * output file and everything else necessary to correctly format ++ * output. ++ */ ++ void *(*initial_state) (const struct structure_printer *sp, ++ FILE *output); ++ ++} structure_printer_t; +-- +1.7.11.1 +