From: Stephan Bosch Date: Tue, 1 Aug 2023 00:04:13 +0000 (+0200) Subject: lib-json: Add JSON formatting tool X-Git-Tag: 2.4.0~2374 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ac13025b1b9fb8eabbdf02022d295aec7e6c694a;p=thirdparty%2Fdovecot%2Fcore.git lib-json: Add JSON formatting tool --- diff --git a/.gitignore b/.gitignore index 09881d8638..9cc3de80b9 100644 --- a/.gitignore +++ b/.gitignore @@ -143,6 +143,7 @@ src/lib-fts/WordBreakProperty.txt src/lib-fts/word-boundary-data.c src/lib-fts/word-break-data.c src/lib-dict-backend/dict-drivers-register.c +src/lib-json/json-format src/lib-sql/sql-drivers-register.c src/log/log src/lmtp/lmtp diff --git a/src/lib-json/Makefile.am b/src/lib-json/Makefile.am index 9e020d8cb6..2dac5aa022 100644 --- a/src/lib-json/Makefile.am +++ b/src/lib-json/Makefile.am @@ -36,7 +36,15 @@ test_programs = \ test-json-tree \ test-json-tree-io -noinst_PROGRAMS = $(test_programs) +noinst_PROGRAMS = json-format $(test_programs) + +json_format_SOURCE = \ + json-format.c +json_format_LDADD = \ + libjson.la \ + ../lib-charset/libcharset.la \ + ../lib/liblib.la \ + $(MODULE_LIBS) test_libs = \ libjson.la \ diff --git a/src/lib-json/json-format.c b/src/lib-json/json-format.c new file mode 100644 index 0000000000..57e2583940 --- /dev/null +++ b/src/lib-json/json-format.c @@ -0,0 +1,137 @@ +/* Copyright (c) 2023 Dovecot Oy, see the included COPYING file */ + +#include "lib.h" +#include "randgen.h" +#include "str.h" +#include "istream.h" +#include "ostream.h" +#include "iostream-temp.h" + +#include "json-istream.h" +#include "json-ostream.h" + +#include +#include +#include +#include +#include +#include + +static bool debug = FALSE; + +/* + * File I/O + */ + +static void +json_format_file_io_run(struct istream *input, struct ostream *output, + const struct json_format *json_format) +{ + struct json_istream *jinput; + struct json_ostream *joutput; + struct json_node jnode; + struct json_limits json_limits; + const char *error; + int rret, wret; + + i_zero(&json_limits); + json_limits.max_name_size = SIZE_MAX; + json_limits.max_string_size = SIZE_MAX; + json_limits.max_nesting = UINT_MAX; + json_limits.max_list_items = UINT_MAX; + + jinput = json_istream_create(input, 0, &json_limits, 0); + joutput = json_ostream_create(output, 0); + json_ostream_set_format(joutput, json_format); + + rret = 0; wret = 1; + i_zero(&jnode); + for (;;) { + if (wret > 0 && rret == 0) { + rret = json_istream_walk_stream(jinput, + 16 * IO_BLOCK_SIZE, + IO_BLOCK_SIZE, + NULL, &jnode); + if (rret < 0) + break; + } + if (json_node_is_none(&jnode)) + wret = 1; + else + wret = json_ostream_write_node(joutput, &jnode, TRUE); + if (wret == 0) + continue; + if (wret < 0) + break; + i_zero(&jnode); + rret = 0; + } + wret = json_ostream_flush(joutput); + json_ostream_destroy(&joutput); + + if (json_istream_finish(&jinput, &error) < 0) + i_error("Failed to read JSON: %s", error); +} + +static void +json_format_file_io(const char *file, const struct json_format *json_format) +{ + struct istream *input; + struct ostream *output; + int fd_in, fd_out; + + if ((fd_in = open(file, O_RDONLY)) < 0) + i_fatal("Failed to open for reading: %m"); + fd_out = 1; + + input = i_stream_create_fd_autoclose(&fd_in, 1024); + output = o_stream_create_fd_autoclose(&fd_out, 1024); + json_format_file_io_run(input, output, json_format); + i_stream_unref(&input); + o_stream_unref(&output); +} + +int main(int argc, char *argv[]) +{ + struct json_format json_format; + int c; + + lib_init(); + + i_zero(&json_format); + json_format.indent_chars = 2; + json_format.new_line = TRUE; + json_format.whitespace = TRUE; + + while ((c = getopt(argc, argv, "Di:n")) > 0) { + switch (c) { + case 'D': + debug = TRUE; + break; + case 'i': + if (str_to_uint(optarg, + &json_format.indent_chars) < 0) { + i_fatal("Invalid number of indent characters."); + } + break; + case 'n': + json_format.new_line = FALSE; + break; + default: + i_fatal("Usage: %s [-D] [-i ] [-n] " + "", argv[0]); + } + } + argc -= optind; + argv += optind; + + if (argc > 1 ) { + i_fatal("Usage: %s [-D] [-i ] [-n] " + "", argv[0]); + } + + json_format_file_io(argv[0], &json_format); + + lib_deinit(); + return 0; +}