json-syntax.c \
json-types.c \
json-tree.new.c \
+ json-tree-io.c \
json-parser.new.c \
json-generator.c \
json-istream.c \
json-syntax.h \
json-types.h \
json-tree.new.h \
+ json-tree-io.h \
json-parser.new.h \
json-generator.h \
json-istream.h \
--- /dev/null
+/* 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);
+}
--- /dev/null
+#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
#include "json-istream.h"
#include "json-ostream.h"
+#include "json-tree-io.h"
#include <unistd.h>
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;
int c;
static void (*test_functions[])(void) = {
+ test_json_tree_io,
test_json_tree_stream_io,
NULL
};