Skip to content

Commit

Permalink
doveadm: Add JSON formatter support
Browse files Browse the repository at this point in the history
  • Loading branch information
Aki Tuomi authored and sirainen committed Feb 1, 2016
1 parent fe5fcad commit 3cd674e
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/doveadm/Makefile.am
Expand Up @@ -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)
Expand Down
152 changes: 152 additions & 0 deletions src/doveadm/doveadm-print-json.c
@@ -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
};

1 change: 1 addition & 0 deletions src/doveadm/doveadm-print-private.h
Expand Up @@ -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
1 change: 1 addition & 0 deletions src/doveadm/doveadm-print.h
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions src/doveadm/doveadm.c
Expand Up @@ -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
};

Expand Down
1 change: 1 addition & 0 deletions src/doveadm/main.c
Expand Up @@ -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)
Expand Down

0 comments on commit 3cd674e

Please sign in to comment.