]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveadm: Add JSON formatter support
authorAki Tuomi <aki.tuomi@dovecot.net>
Thu, 21 Jan 2016 17:49:12 +0000 (19:49 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 1 Feb 2016 11:52:01 +0000 (13:52 +0200)
src/doveadm/Makefile.am
src/doveadm/doveadm-print-json.c [new file with mode: 0644]
src/doveadm/doveadm-print-private.h
src/doveadm/doveadm-print.h
src/doveadm/doveadm.c
src/doveadm/main.c

index 0e0b2307d9815fb1f298418d8e7dc373c897b51e..ac1196af872b3180aa10c0d7064de9ba014e71ca 100644 (file)
@@ -127,12 +127,14 @@ doveadm_SOURCES = \
        doveadm-print-pager.c \
        doveadm-print-tab.c \
        doveadm-print-table.c \
+       doveadm-print-json.c \
        doveadm-pw.c
 
 doveadm_server_SOURCES = \
        $(common) \
        client-connection.c \
        doveadm-print-server.c \
+       doveadm-print-json.c \
        main.c
 
 pkginc_libdir = $(pkgincludedir)
diff --git a/src/doveadm/doveadm-print-json.c b/src/doveadm/doveadm-print-json.c
new file mode 100644 (file)
index 0000000..d5ac28d
--- /dev/null
@@ -0,0 +1,152 @@
+#include "lib.h"
+#include "array.h"
+#include "str.h"
+#include "strescape.h"
+#include "ostream.h"
+#include "json-parser.h"
+#include "client-connection.h"
+#include "doveadm-server.h"
+#include "doveadm-print.h"
+#include "doveadm-print-private.h"
+
+struct doveadm_print_json_context {
+       unsigned int header_idx, header_count;
+       bool first_row;
+       ARRAY(struct doveadm_print_header) headers;
+       pool_t pool;
+       string_t *str;
+};
+
+static struct doveadm_print_json_context ctx;
+
+static void doveadm_print_json_flush_internal(void);
+
+static void doveadm_print_json_init(void)
+{
+       ctx.pool = pool_alloconly_create("doveadm json print", 1024);
+       ctx.str = str_new(ctx.pool, 256);
+       p_array_init(&ctx.headers, ctx.pool, 1);
+       ctx.first_row = TRUE;
+}
+
+static void
+doveadm_print_json_header(const struct doveadm_print_header *hdr)
+{
+       struct doveadm_print_header *lhdr;
+       lhdr = array_append_space(&ctx.headers);
+       lhdr->key = p_strdup(ctx.pool, hdr->key);
+       lhdr->flags = hdr->flags;
+       ctx.header_count++;
+}
+
+static void
+doveadm_print_json_value_header(const struct doveadm_print_header *hdr)
+{
+       // get header name
+       if (ctx.header_idx == 0) {
+               if (ctx.first_row == TRUE) {
+                       ctx.first_row = FALSE;
+                       str_append_c(ctx.str, '[');
+               } else {
+                       str_append_c(ctx.str, ',');
+               }
+               str_append_c(ctx.str, '{');
+       } else {
+               str_append_c(ctx.str, ',');
+       }
+
+       str_append_c(ctx.str, '"');
+       json_append_escaped(ctx.str, hdr->key);
+       str_append_c(ctx.str, '"');
+       str_append_c(ctx.str, ':');
+}
+
+static void
+doveadm_print_json_value_footer(void) {
+       if (++ctx.header_idx == ctx.header_count) {
+               ctx.header_idx = 0;
+               str_append_c(ctx.str, '}');
+               doveadm_print_json_flush_internal();
+       }
+}
+
+static void doveadm_print_json_print(const char *value)
+{
+       const struct doveadm_print_header *hdr = array_idx(&ctx.headers, ctx.header_idx);
+
+       doveadm_print_json_value_header(hdr);
+
+       if (value == NULL) {
+               str_append(ctx.str, "null");
+       } else if ((hdr->flags & DOVEADM_PRINT_HEADER_FLAG_NUMBER) != 0) {
+               i_assert(str_is_float(value, '\0'));
+               str_append(ctx.str, value);
+       } else {
+               str_append_c(ctx.str, '"');
+               json_append_escaped(ctx.str, value);
+               str_append_c(ctx.str, '"');
+       }
+
+       doveadm_print_json_value_footer();
+}
+
+static void
+doveadm_print_json_print_stream(const unsigned char *value, size_t size)
+{
+       if (size == 0) {
+               doveadm_print_json_print("");
+               return;
+       }
+
+       const struct doveadm_print_header *hdr = array_idx(&ctx.headers, ctx.header_idx);
+
+       doveadm_print_json_value_header(hdr);
+
+       if ((hdr->flags & DOVEADM_PRINT_HEADER_FLAG_NUMBER) != 0) {
+               i_assert(str_is_float((const char*)value, (char)value[size]));
+               str_append_data(ctx.str, value, size);
+       } else {
+               str_append_c(ctx.str, '"');
+               json_append_escaped_data(ctx.str, value, size);
+               str_append_c(ctx.str, '"');
+       }
+
+       doveadm_print_json_value_footer();
+
+       if (str_len(ctx.str) >= IO_BLOCK_SIZE)
+               doveadm_print_json_flush_internal();
+}
+
+static void doveadm_print_json_flush_internal(void)
+{
+       o_stream_nsend(doveadm_print_ostream, str_data(ctx.str), str_len(ctx.str));
+       str_truncate(ctx.str, 0);
+}
+
+static void doveadm_print_json_flush(void)
+{
+       if (ctx.first_row == FALSE)
+               str_append_c(ctx.str,']');
+       else {
+               str_append_c(ctx.str,'[');
+               str_append_c(ctx.str,']');
+       }
+       doveadm_print_json_flush_internal();
+}
+
+static void doveadm_print_json_deinit(void)
+{
+       pool_unref(&ctx.pool);
+}
+
+struct doveadm_print_vfuncs doveadm_print_json_vfuncs = {
+       "json",
+
+       doveadm_print_json_init,
+       doveadm_print_json_deinit,
+       doveadm_print_json_header,
+       doveadm_print_json_print,
+       doveadm_print_json_print_stream,
+       doveadm_print_json_flush
+};
+
index 854bfc70e74622560eb0af3f7ce9545e069398ee..f504727fbbf7e3a257c747ddd266149c2b48855f 100644 (file)
@@ -25,5 +25,6 @@ extern struct doveadm_print_vfuncs doveadm_print_flow_vfuncs;
 extern struct doveadm_print_vfuncs doveadm_print_tab_vfuncs;
 extern struct doveadm_print_vfuncs doveadm_print_table_vfuncs;
 extern struct doveadm_print_vfuncs doveadm_print_pager_vfuncs;
+extern struct doveadm_print_vfuncs doveadm_print_json_vfuncs;
 
 #endif
index 233a020fa89d702be191d6c9da8d4c6bab6ab4a7..647d32051d6e22803169a2d8bfa84a58a0f9e78b 100644 (file)
@@ -5,6 +5,7 @@
 #define DOVEADM_PRINT_TYPE_FLOW "flow"
 #define DOVEADM_PRINT_TYPE_TABLE "table"
 #define DOVEADM_PRINT_TYPE_SERVER "server"
+#define DOVEADM_PRINT_TYPE_JSON "json"
 
 enum doveadm_print_header_flags {
        DOVEADM_PRINT_HEADER_FLAG_RIGHT_JUSTIFY         = 0x01,
index 7a85a310f909f012c7b9dbddeebe4c7509f1ccba..67a595be67af90d3617cd1a24f069c4a912e3fdd 100644 (file)
@@ -24,6 +24,7 @@ const struct doveadm_print_vfuncs *doveadm_print_vfuncs_all[] = {
        &doveadm_print_tab_vfuncs,
        &doveadm_print_table_vfuncs,
        &doveadm_print_pager_vfuncs,
+       &doveadm_print_json_vfuncs,
        NULL
 };
 
index 1b6c468afbae853eddc767e3016eb7f1f911c953..f9314f16b9e5c774f4e985a6e0466d815a351636 100644 (file)
@@ -62,6 +62,7 @@ static void main_init(void)
        doveadm_mail_init();
        doveadm_load_modules();
        doveadm_print_init(DOVEADM_PRINT_TYPE_SERVER);
+        doveadm_print_init(DOVEADM_PRINT_TYPE_JSON);
 }
 
 static void main_deinit(void)