[PATCH v3 1/3] Add support for structured output formatters.
authorcraven <craven@gmx.net>
Wed, 11 Jul 2012 08:26:33 +0000 (10:26 +0200)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:48:10 +0000 (09:48 -0800)
3d/093c5df081c869aae31ad3d517fc6178a92275 [new file with mode: 0644]

diff --git a/3d/093c5df081c869aae31ad3d517fc6178a92275 b/3d/093c5df081c869aae31ad3d517fc6178a92275
new file mode 100644 (file)
index 0000000..72f4a91
--- /dev/null
@@ -0,0 +1,208 @@
+Return-Path: <craven@gmx.net>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+       by olra.theworths.org (Postfix) with ESMTP id A94E3429E4A\r
+       for <notmuch@notmuchmail.org>; Wed, 11 Jul 2012 01:25:25 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: 0.001\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=0.001 tagged_above=-999 required=5\r
+       tests=[FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001]\r
+       autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+       by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+       with ESMTP id Nkw0IEuP2GIO for <notmuch@notmuchmail.org>;\r
+       Wed, 11 Jul 2012 01:25:22 -0700 (PDT)\r
+Received: from mailout-de.gmx.net (mailout-de.gmx.net [213.165.64.23])\r
+       by olra.theworths.org (Postfix) with SMTP id 137A6429E3C\r
+       for <notmuch@notmuchmail.org>; Wed, 11 Jul 2012 01:25:19 -0700 (PDT)\r
+Received: (qmail invoked by alias); 11 Jul 2012 08:25:14 -0000\r
+Received: from gw.arelion.cust.net.lagis.at (EHLO dodekanex.arelion.at)\r
+       [83.164.197.182]\r
+       by mail.gmx.net (mp037) with SMTP; 11 Jul 2012 10:25:14 +0200\r
+X-Authenticated: #201305\r
+X-Provags-ID: V01U2FsdGVkX1887tYf0eI8tllIWkVJ6Mvejk7/HvwFk7Ruqa/5x2\r
+       jalLZfI1VUHSon\r
+Received: by dodekanex.arelion.at (Postfix, from userid 1000)\r
+       id D4A4030313F; Wed, 11 Jul 2012 10:26:36 +0200 (CEST)\r
+From: <craven@gmx.net>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH v3 1/3] Add support for structured output formatters.\r
+Date: Wed, 11 Jul 2012 10:26:33 +0200\r
+Message-Id: <1341995195-2497-2-git-send-email-craven@gmx.net>\r
+X-Mailer: git-send-email 1.7.11.1\r
+In-Reply-To: <1341995195-2497-1-git-send-email-craven@gmx.net>\r
+References: <20120710191331.GE7332@mit.edu>\r
+       <1341995195-2497-1-git-send-email-craven@gmx.net>\r
+MIME-Version: 1.0\r
+Content-Type: text/plain; charset=UTF-8\r
+Content-Transfer-Encoding: 8bit\r
+X-Y-GMX-Trusted: 0\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+       <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Wed, 11 Jul 2012 08:25:26 -0000\r
+\r
+This patch adds a new type structure_printer, which is used for\r
+structured formatting, e.g. JSON or S-Expressions.\r
+\r
+The structure contains the following function pointers:\r
+\r
+- initial_state: is called to create a state object, that is passed to\r
+  all invocations. This should be used to keep track of the output file\r
+  and everything else necessary to correctly format output.\r
+- map: is called when a new map (associative array, dictionary) is\r
+  started. map_key and the primitives (string, number, bool) are used\r
+  alternatingly to add key/value pairs. pop is used to close the map\r
+  (see there). This function must return a nesting level identifier that\r
+  can be used to close all nested structures (maps and lists), backing\r
+  out to the returned nesting level.\r
+- list: is called when a new list (array, vector) is started. the\r
+  primitives (string, number, bool) are used consecutively to add values\r
+  to the list. pop is used to close the list. This function must return\r
+  a nesting level identifier that can be used to close all nested\r
+  structures (maps and lists), backing out to the returned nesting\r
+  level.\r
+- map_key: is called to write the key of a key/value pair.\r
+- pop: is called to return to a given nesting level. All lists and maps\r
+  with a deeper nesting level must be closed.\r
+- number, string, bool: output one element of the specific type.\r
+\r
+All functions should use state to insert delimiters etc. automatically\r
+when appropriate. State is a user-defined object/data that can contain\r
+arbitrary information. Initial state is constructed by a call to\r
+initial_state.\r
+\r
+Example:\r
+int top, one;\r
+top = map(state);\r
+map_key(state, "foo");\r
+one = list(state);\r
+number(state, 1);\r
+number(state, 2);\r
+number(state, 3);\r
+pop(state, one);\r
+map_key(state, "bar");\r
+map(state);\r
+map_key(state, "baaz");\r
+string(state, "hello world");\r
+pop(state, top);\r
+\r
+would output JSON as follows:\r
+\r
+{"foo": [1, 2, 3], "bar": { "baaz": "hello world"}}\r
+---\r
+ structured-output.h | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+ 1 file changed, 90 insertions(+)\r
+ create mode 100644 structured-output.h\r
+\r
+diff --git a/structured-output.h b/structured-output.h\r
+new file mode 100644\r
+index 0000000..73029f1\r
+--- /dev/null\r
++++ b/structured-output.h\r
+@@ -0,0 +1,90 @@\r
++/* notmuch - Not much of an email program, (just index and search)\r
++ *\r
++ * Copyright © 2009 Carl Worth\r
++ *\r
++ * This program is free software: you can redistribute it and/or modify\r
++ * it under the terms of the GNU General Public License as published by\r
++ * the Free Software Foundation, either version 3 of the License, or\r
++ * (at your option) any later version.\r
++ *\r
++ * This program is distributed in the hope that it will be useful,\r
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
++ * GNU General Public License for more details.\r
++ *\r
++ * You should have received a copy of the GNU General Public License\r
++ * along with this program.  If not, see http://www.gnu.org/licenses/ .\r
++ *\r
++ * Author: Carl Worth <cworth@cworth.org>\r
++ */\r
++\r
++#include "notmuch-client.h"\r
++\r
++/* structured formatting, useful for JSON, S-Expressions, ...\r
++ *\r
++ * All functions should use state to insert delimiters\r
++ * etc. automatically when appropriate. State is a user-defined\r
++ * object/data that can contain arbitrary information. Initial state is\r
++ * constructed by a call to initial_state.\r
++ *\r
++ * Example:\r
++ * int top, one;\r
++ * top = map(state);\r
++ * map_key(state, "foo");\r
++ * one = list(state);\r
++ * number(state, 1);\r
++ * number(state, 2);\r
++ * number(state, 3);\r
++ * pop(state, one);\r
++ * map_key(state, "bar");\r
++ * map(state);\r
++ * map_key(state, "baaz");\r
++ * string(state, "hello world");\r
++ * pop(state, top);\r
++ *\r
++ * would output JSON as follows:\r
++ *\r
++ * {"foo": [1, 2, 3], "bar": { "baaz": "hello world"}}\r
++ */\r
++typedef struct structure_printer {\r
++    /* map: is called when a new map (associative array, dictionary) is\r
++     * started. map_key and the primitives (string, number, bool) are\r
++     * used alternatingly to add key/value pairs. pop is used to close\r
++     * the map (see there). This function must return a nesting level\r
++     * identifier number that can be used to close all nested structures\r
++     * (maps and lists), backing out to the returned nesting level.\r
++     */\r
++    int (*map) (void *state);\r
++\r
++    /* list: is called when a new list (array, vector) is started. the\r
++     * primitives (string, number, bool) are used consecutively to add\r
++     * values to the list. pop is used to close the list. This function\r
++     * must return a nesting level identifier number that can be used to\r
++     * close all nested structures (maps and lists), backing out to the\r
++     * returned nesting level.\r
++     */\r
++    int (*list) (void *state);\r
++\r
++    /* pop: is called to return to a given nesting level. All lists and\r
++     * maps with a deeper nesting level must be closed.\r
++     */\r
++    void (*pop) (void *state, int level);\r
++\r
++    /* map_key: is called to write the key of a key/value pair.\r
++     */\r
++    void (*map_key) (void *state, const char *key);\r
++\r
++    /* number, string, bool: output one element of the specific type. */\r
++    void (*number) (void *state, int val);\r
++    void (*string) (void *state, const char *val);\r
++    void (*bool) (void *state, notmuch_bool_t val);\r
++\r
++    /* initial_state: is called to create a state object, that is passed\r
++     * to all invocations. This should be used to keep track of the\r
++     * output file and everything else necessary to correctly format\r
++     * output.\r
++     */\r
++    void *(*initial_state) (const struct structure_printer *sp,\r
++                          FILE *output);\r
++\r
++} structure_printer_t;\r
+-- \r
+1.7.11.1\r
+\r