]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-json: Add API for reading and writing JSON tree values from and to memory
authorStephan Bosch <stephan.bosch@open-xchange.com>
Sat, 22 Feb 2020 16:44:24 +0000 (17:44 +0100)
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-tree-io.c [new file with mode: 0644]
src/lib-json/json-tree-io.h [new file with mode: 0644]
src/lib-json/test-json-tree-io.c

index f694b4a70699b27ca5cc33bcbe178108f011e7ac..c18c61ea0af97f442539bbc944ff86ec2275d125 100644 (file)
@@ -8,6 +8,7 @@ libjson_la_SOURCES = \
        json-syntax.c \
        json-types.c \
        json-tree.new.c \
+       json-tree-io.c \
        json-parser.new.c \
        json-generator.c \
        json-istream.c \
@@ -18,6 +19,7 @@ headers = \
        json-syntax.h \
        json-types.h \
        json-tree.new.h \
+       json-tree-io.h \
        json-parser.new.h \
        json-generator.h \
        json-istream.h \
diff --git a/src/lib-json/json-tree-io.c b/src/lib-json/json-tree-io.c
new file mode 100644 (file)
index 0000000..00a3f35
--- /dev/null
@@ -0,0 +1,87 @@
+/* Copyright (c) 2017-2023 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "str.h"
+#include "buffer.h"
+#include "istream.h"
+#include "ostream.h"
+
+#include "json-istream.h"
+#include "json-ostream.h"
+
+#include "json-tree-io.h"
+
+/*
+ * Input
+ */
+
+int json_tree_read_data(const void *data, size_t size,
+                       enum json_parser_flags parser_flags,
+                       struct json_tree **jtree_r, const char **error_r)
+{
+       struct istream *input = i_stream_create_from_data(data, size);
+       struct json_istream *jinput;
+       int ret;
+
+       *jtree_r = NULL;
+
+       jinput = json_istream_create(input, JSON_ISTREAM_TYPE_NORMAL, NULL,
+                                    parser_flags);
+       ret = json_istream_read_tree(jinput, jtree_r);
+       i_assert(ret != 0);
+       ret = json_istream_finish(&jinput, error_r);
+       i_assert(ret != 0);
+
+       if (ret < 0)
+               json_tree_unref(jtree_r);
+
+       i_stream_unref(&input);
+       return (ret > 0 ? 0 : -1);
+}
+
+int json_tree_read_buffer(const buffer_t *buf,
+                         enum json_parser_flags parser_flags,
+                         struct json_tree **jtree_r, const char **error_r)
+{
+       return json_tree_read_data(buf->data, buf->used, parser_flags,
+                                  jtree_r, error_r);
+}
+
+int json_tree_read_cstr(const char *str, enum json_parser_flags parser_flags,
+                       struct json_tree **jtree_r, const char **error_r)
+{
+       return json_tree_read_data(str, strlen(str), parser_flags,
+                                  jtree_r, error_r);
+}
+
+/*
+ * Output
+ */
+
+void json_tree_write_buffer(const struct json_tree *jtree, buffer_t *buf,
+                           enum json_generator_flags gen_flags)
+{
+       struct json_ostream *joutput;
+
+       joutput = json_ostream_create_str(buf, gen_flags);
+       json_ostream_nwrite_tree(joutput, NULL, jtree);
+       json_ostream_nfinish_destroy(&joutput);
+}
+
+const char *
+json_tree_to_text(const struct json_tree *jtree,
+                 enum json_generator_flags gen_flags)
+{
+       string_t *str = t_str_new(1024);
+
+       json_tree_write_buffer(jtree, str, gen_flags);
+       return str_c(str);
+}
+
+const char *json_tree_to_text_line(const struct json_tree *jtree)
+{
+       string_t *str = t_str_new(1024);
+
+       json_tree_write_buffer(jtree, str, 0);
+       return str_c(str);
+}
diff --git a/src/lib-json/json-tree-io.h b/src/lib-json/json-tree-io.h
new file mode 100644 (file)
index 0000000..a51577a
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef JSON_TREE_IO_H
+#define JSON_TREE_IO_H
+
+#include "json-tree.new.h"
+#include "json-parser.new.h"
+#include "json-generator.h"
+
+/*
+ * Input
+ */
+
+int json_tree_read_data(const void *data, size_t size,
+                       enum json_parser_flags parser_flags,
+                       struct json_tree **jtree_r, const char **error_r);
+
+int json_tree_read_buffer(const buffer_t *buf,
+                         enum json_parser_flags parser_flags,
+                         struct json_tree **jtree_r, const char **error_r);
+int json_tree_read_cstr(const char *str, enum json_parser_flags parser_flags,
+                       struct json_tree **jtree_r, const char **error_r);
+
+/*
+ * Output
+ */
+
+void json_tree_write_buffer(const struct json_tree *jtree, buffer_t *buf,
+                           enum json_generator_flags gen_flags);
+const char *
+json_tree_to_text(const struct json_tree *jtree,
+                 enum json_generator_flags gen_flags);
+const char *json_tree_to_text_line(const struct json_tree *jtree);
+
+#endif
index 2bb8a5cd79495193483828d0cabfcc9cf4e9e64e..0b988a8d55f1f5a527e478396e3617c4bbee4c41 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "json-istream.h"
 #include "json-ostream.h"
+#include "json-tree-io.h"
 
 #include <unistd.h>
 
@@ -245,6 +246,55 @@ tests[] = {
 
 static const unsigned tests_count = N_ELEMENTS(tests);
 
+static void test_json_tree_io(void)
+{
+       string_t *outbuf;
+       unsigned int i;
+
+       outbuf = str_new(default_pool, 1024);
+
+       for (i = 0; i < tests_count; i++) T_BEGIN {
+               const struct json_io_test *test;
+               const char *text, *text_out;
+               unsigned int text_len;
+               struct json_tree *jtree = NULL;
+               const char *error = NULL;
+               int ret = 0;
+
+               test = &tests[i];
+               text = test->input;
+               text_out = test->output;
+               if (text_out == NULL)
+                       text_out = test->input;
+               text_len = strlen(text);
+
+               test_begin(t_strdup_printf("json tree io [%d]", i));
+
+               buffer_set_used_size(outbuf, 0);
+
+               ret = json_tree_read_data(text, text_len, 0, &jtree, &error);
+               test_out_reason_quiet("input ok", ret >= 0, error);
+
+               if (jtree != NULL)
+                       json_tree_write_buffer(jtree, outbuf, 0);
+
+               test_out_quiet("io match",
+                              strcmp(text_out, str_c(outbuf)) == 0);
+
+               if (debug) {
+                       i_debug("OUT: >%s<", text_out);
+                       i_debug("OUT: >%s<", str_c(outbuf));
+               }
+
+               json_tree_unref(&jtree);
+
+               test_end();
+
+       } T_END;
+
+       buffer_free(&outbuf);
+}
+
 static void test_json_tree_stream_io(void)
 {
        string_t *outbuf;
@@ -421,6 +471,7 @@ int main(int argc, char *argv[])
        int c;
 
        static void (*test_functions[])(void) = {
+               test_json_tree_io,
                test_json_tree_stream_io,
                NULL
        };