From: Stephan Bosch Date: Sat, 22 Feb 2020 16:44:24 +0000 (+0100) Subject: lib-json: Add API for reading and writing JSON tree values from and to memory X-Git-Tag: 2.4.0~2379 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=29d51810a7fe012819459870b244e4146e6a661f;p=thirdparty%2Fdovecot%2Fcore.git lib-json: Add API for reading and writing JSON tree values from and to memory --- diff --git a/src/lib-json/Makefile.am b/src/lib-json/Makefile.am index f694b4a706..c18c61ea0a 100644 --- a/src/lib-json/Makefile.am +++ b/src/lib-json/Makefile.am @@ -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 index 0000000000..00a3f356e6 --- /dev/null +++ b/src/lib-json/json-tree-io.c @@ -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 index 0000000000..a51577adde --- /dev/null +++ b/src/lib-json/json-tree-io.h @@ -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 diff --git a/src/lib-json/test-json-tree-io.c b/src/lib-json/test-json-tree-io.c index 2bb8a5cd79..0b988a8d55 100644 --- a/src/lib-json/test-json-tree-io.c +++ b/src/lib-json/test-json-tree-io.c @@ -8,6 +8,7 @@ #include "json-istream.h" #include "json-ostream.h" +#include "json-tree-io.h" #include @@ -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 };