]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-json: Add API for formating JSON text stored in memory
authorStephan Bosch <stephan.bosch@open-xchange.com>
Sun, 13 Aug 2023 15:03:27 +0000 (17:03 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Sat, 18 Nov 2023 18:58:04 +0000 (18:58 +0000)
src/lib-json/Makefile.am
src/lib-json/json-generator.c
src/lib-json/json-text.c [new file with mode: 0644]
src/lib-json/json-text.h [new file with mode: 0644]

index c18c61ea0af97f442539bbc944ff86ec2275d125..9e020d8cb6964320fb0c1fe5439715c34db384b5 100644 (file)
@@ -12,7 +12,8 @@ libjson_la_SOURCES = \
        json-parser.new.c \
        json-generator.c \
        json-istream.c \
-       json-ostream.c
+       json-ostream.c \
+       json-text.c
 libjson_la_LIBADD = -lm
 
 headers = \
@@ -23,7 +24,8 @@ headers = \
        json-parser.new.h \
        json-generator.h \
        json-istream.h \
-       json-ostream.h
+       json-ostream.h \
+       json-text.h
 
 test_programs = \
        test-json-parser \
index 93c8c8480fa23cb9c9a8d8c9fe4626125a02aec9..c6c1adaf26c9b3e1f53909023e7c39b0ba54511b 100644 (file)
@@ -432,8 +432,6 @@ int json_generator_flush(struct json_generator *generator)
                                return ret;
                }
 
-               // FIXME: add indent
-
                level = array_idx_get_space(&generator->level_stack,
                                            generator->level_stack_written);
                if (level->object) {
diff --git a/src/lib-json/json-text.c b/src/lib-json/json-text.c
new file mode 100644 (file)
index 0000000..3b2a392
--- /dev/null
@@ -0,0 +1,81 @@
+/* Copyright (c) 2017-2023 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "buffer.h"
+#include "istream.h"
+#include "ostream.h"
+
+#include "json-istream.h"
+#include "json-ostream.h"
+#include "json-text.h"
+
+int json_text_format_data(const void *data, size_t size,
+                         enum json_parser_flags parser_flags,
+                         const struct json_limits *limits,
+                         const struct json_format *format,
+                         buffer_t *outbuf, const char **error_r)
+{
+       struct istream *input;
+       struct ostream *output;
+       struct json_istream *jinput;
+       struct json_ostream *joutput;
+       struct json_node jnode;
+       int ret;
+
+       *error_r = NULL;
+
+       parser_flags |= JSON_PARSER_FLAG_NUMBERS_AS_STRING;
+
+       input = i_stream_create_from_data(data, size);
+
+       output = o_stream_create_buffer(outbuf);
+       o_stream_set_no_error_handling(output, TRUE);
+
+       jinput = json_istream_create(input, JSON_ISTREAM_TYPE_NORMAL, limits,
+                                     parser_flags);
+       joutput = json_ostream_create(output, 0);
+       if (format != NULL)
+               json_ostream_set_format(joutput, format);
+
+       i_zero(&jnode);
+       for (;;) {
+               ret = json_istream_walk_stream(jinput, 16 * IO_BLOCK_SIZE,
+                                               IO_BLOCK_SIZE, NULL, &jnode);
+               i_assert(ret != 0);
+               if (ret < 0)
+                       break;
+               json_ostream_nwrite_node(joutput, &jnode);
+       }
+       ret = json_ostream_nfinish(joutput);
+       if (ret < 0)
+               *error_r = json_ostream_get_error(joutput);
+       json_ostream_destroy(&joutput);
+
+       if (ret < 0)
+               json_istream_destroy(&jinput);
+       else
+               ret = json_istream_finish(&jinput, error_r);
+
+       i_stream_destroy(&input);
+       o_stream_destroy(&output);
+       return ret;
+}
+
+int json_text_format_buffer(const buffer_t *buf,
+                           enum json_parser_flags parser_flags,
+                           const struct json_limits *limits,
+                           const struct json_format *format,
+                           buffer_t *outbuf, const char **error_r)
+{
+       return json_text_format_data(buf->data, buf->used, parser_flags,
+                                    limits, format, outbuf, error_r);
+}
+
+int json_text_format_cstr(const char *str, enum json_parser_flags parser_flags,
+                         const struct json_limits *limits,
+                         const struct json_format *format,
+                         buffer_t *outbuf, const char **error_r)
+{
+       return json_text_format_data(str, strlen(str), parser_flags,
+                                    limits, format, outbuf, error_r);
+}
diff --git a/src/lib-json/json-text.h b/src/lib-json/json-text.h
new file mode 100644 (file)
index 0000000..754c595
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef JSON_TEXT_H
+#define JSON_TEXT_H
+
+#include "json-parser.h"
+#include "json-generator.h"
+
+int json_text_format_data(const void *data, size_t size,
+                         enum json_parser_flags parser_flags,
+                         const struct json_limits *limits,
+                         const struct json_format *format,
+                         buffer_t *outbuf, const char **error_r);
+int json_text_format_buffer(const buffer_t *buf,
+                           enum json_parser_flags parser_flags,
+                           const struct json_limits *limits,
+                           const struct json_format *format,
+                           buffer_t *outbuf, const char **error_r);
+int json_text_format_cstr(const char *str, enum json_parser_flags parser_flags,
+                         const struct json_limits *limits,
+                         const struct json_format *format,
+                         buffer_t *outbuf, const char **error_r);
+
+#endif