diff options
Diffstat (limited to 'src/doveadm/doveadm-print-formatted.c')
-rw-r--r-- | src/doveadm/doveadm-print-formatted.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/doveadm/doveadm-print-formatted.c b/src/doveadm/doveadm-print-formatted.c new file mode 100644 index 0000000..d0518b0 --- /dev/null +++ b/src/doveadm/doveadm-print-formatted.c @@ -0,0 +1,92 @@ +/* Copyright (c) 2016-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "ostream.h" +#include "doveadm.h" +#include "doveadm-server.h" +#include "doveadm-print.h" +#include "doveadm-print-private.h" +#include "client-connection.h" +#include "var-expand.h" + +struct doveadm_print_formatted_context { + pool_t pool; + const char *format; + ARRAY(struct var_expand_table) headers; + string_t *buf; + string_t *vbuf; + unsigned int idx; +}; + +static struct doveadm_print_formatted_context ctx; + +void doveadm_print_formatted_set_format(const char *format) +{ + ctx.format = format; +} + +static void doveadm_print_formatted_init(void) +{ + i_zero(&ctx); + ctx.pool = pool_alloconly_create("doveadm formatted print", 1024); + ctx.buf = str_new(ctx.pool, 256); + p_array_init(&ctx.headers, ctx.pool, 8); + ctx.idx = 0; +} + +static void +doveadm_print_formatted_header(const struct doveadm_print_header *hdr) +{ + struct var_expand_table entry; + i_zero(&entry); + entry.key = '\0'; + entry.long_key = p_strdup(ctx.pool, hdr->key); + entry.value = NULL; + array_push_back(&ctx.headers, &entry); +} + + +static void doveadm_print_formatted_flush(void) +{ + o_stream_nsend(doveadm_print_ostream, str_data(ctx.buf), str_len(ctx.buf)); + str_truncate(ctx.buf, 0); +} + +static void doveadm_print_formatted_print(const char *value) +{ + if (ctx.format == NULL) { + i_fatal("formatted formatter cannot be used without a format."); + } + const char *error; + struct var_expand_table *entry = array_idx_modifiable(&ctx.headers, ctx.idx++); + entry->value = value; + + if (ctx.idx >= array_count(&ctx.headers)) { + if (var_expand(ctx.buf, ctx.format, array_front(&ctx.headers), &error) <= 0) { + i_error("Failed to expand print format '%s': %s", + ctx.format, error); + } + doveadm_print_formatted_flush(); + ctx.idx = 0; + } + +} + +static void doveadm_print_formatted_deinit(void) +{ + pool_unref(&ctx.pool); +} + +struct doveadm_print_vfuncs doveadm_print_formatted_vfuncs = { + "formatted", + + doveadm_print_formatted_init, + doveadm_print_formatted_deinit, + doveadm_print_formatted_header, + doveadm_print_formatted_print, + NULL, + doveadm_print_formatted_flush +}; + |