]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-json: Add JSON formatting tool
authorStephan Bosch <stephan.bosch@open-xchange.com>
Tue, 1 Aug 2023 00:04:13 +0000 (02:04 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Sat, 18 Nov 2023 18:58:04 +0000 (18:58 +0000)
.gitignore
src/lib-json/Makefile.am
src/lib-json/json-format.c [new file with mode: 0644]

index 09881d8638f4789e0f1593d278862eb1bb6e0450..9cc3de80b998cc565f2f925a9b1d8ef0325a6f76 100644 (file)
@@ -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
index 9e020d8cb6964320fb0c1fe5439715c34db384b5..2dac5aa022051a355f5ff44c2f166a97088454f0 100644 (file)
@@ -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 (file)
index 0000000..57e2583
--- /dev/null
@@ -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 <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+
+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 <indent-chars>] [-n] "
+                               "<json-file>", argv[0]);
+               }
+       }
+       argc -= optind;
+       argv += optind;
+
+       if (argc > 1 ) {
+               i_fatal("Usage: %s [-D] [-i <indent>] [-n] "
+                       "<json-file>", argv[0]);
+       }
+
+       json_format_file_io(argv[0], &json_format);
+
+       lib_deinit();
+       return 0;
+}