diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c1082b..310be26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -496,6 +496,7 @@ if (NOT JANSSON_WITHOUT_TESTS) test_object test_pack test_simple + test_sprintf test_unpack) # Doing arithmetic on void pointers is not allowed by Microsofts compiler diff --git a/doc/apiref.rst b/doc/apiref.rst index 3ad406d..b429d0b 100644 --- a/doc/apiref.rst +++ b/doc/apiref.rst @@ -399,6 +399,16 @@ length-aware functions if you wish to embed null bytes in strings. .. versionadded:: 2.7 +.. function:: json_t *json_sprintf(const char *format, ...) + json_t *json_vsprintf(const char *format, va_list ap) + + .. refcounting:: new + + Construct a JSON string from a format string and varargs, just like + :func:`printf()`. + + .. versionadded:: 2.11 + Number ====== diff --git a/src/jansson.def b/src/jansson.def index cbebefb..15f35c9 100644 --- a/src/jansson.def +++ b/src/jansson.def @@ -3,6 +3,8 @@ EXPORTS json_true json_false json_null + json_sprintf + json_vsprintf json_string json_stringn json_string_nocheck diff --git a/src/jansson.h b/src/jansson.h index b17e8f4..82709eb 100644 --- a/src/jansson.h +++ b/src/jansson.h @@ -289,6 +289,11 @@ int json_unpack(json_t *root, const char *fmt, ...); int json_unpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, ...); int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, va_list ap); +/* sprintf */ + +json_t *json_sprintf(const char *fmt, ...); +json_t *json_vsprintf(const char *fmt, va_list ap); + /* equality */ diff --git a/src/value.c b/src/value.c index d27bb12..b3b3141 100644 --- a/src/value.c +++ b/src/value.c @@ -787,6 +787,40 @@ static json_t *json_string_copy(const json_t *string) return json_stringn_nocheck(s->value, s->length); } +json_t *json_vsprintf(const char *fmt, va_list ap) { + int length; + char *buf; + va_list aq; + va_copy(aq, ap); + + length = vsnprintf(NULL, 0, fmt, ap); + if (length == 0) + return json_string(""); + + buf = jsonp_malloc(length + 1); + if (!buf) + return NULL; + + vsnprintf(buf, length + 1, fmt, aq); + if (!utf8_check_string(buf, length)) { + jsonp_free(buf); + return NULL; + } + + return jsonp_stringn_nocheck_own(buf, length); +} + +json_t *json_sprintf(const char *fmt, ...) { + json_t *result; + va_list ap; + + va_start(ap, fmt); + result = json_vsprintf(fmt, ap); + va_end(ap); + + return result; +} + /*** integer ***/ diff --git a/test/.gitignore b/test/.gitignore index 58e5e31..9c638ac 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -7,14 +7,15 @@ suites/api/test_dump suites/api/test_dump_callback suites/api/test_equal suites/api/test_load +suites/api/test_load_callback suites/api/test_loadb suites/api/test_memory_funcs suites/api/test_number suites/api/test_object suites/api/test_pack suites/api/test_simple +suites/api/test_sprintf suites/api/test_unpack -suites/api/test_load_callback run-suites.log run-suites.trs test-suite.log diff --git a/test/suites/api/Makefile.am b/test/suites/api/Makefile.am index 1dbdd2b..a1bc4d3 100644 --- a/test/suites/api/Makefile.am +++ b/test/suites/api/Makefile.am @@ -14,6 +14,7 @@ check_PROGRAMS = \ test_object \ test_pack \ test_simple \ + test_sprintf \ test_unpack test_array_SOURCES = test_array.c util.h @@ -27,6 +28,7 @@ test_number_SOURCES = test_number.c util.h test_object_SOURCES = test_object.c util.h test_pack_SOURCES = test_pack.c util.h test_simple_SOURCES = test_simple.c util.h +test_sprintf_SOURCES = test_sprintf.c util.h test_unpack_SOURCES = test_unpack.c util.h AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_srcdir)/src diff --git a/test/suites/api/test_sprintf.c b/test/suites/api/test_sprintf.c new file mode 100644 index 0000000..34908d8 --- /dev/null +++ b/test/suites/api/test_sprintf.c @@ -0,0 +1,22 @@ +#include +#include +#include "util.h" + + +static void test_sprintf() { + json_t *s = json_sprintf("foo bar %d", 42); + if (!s) + fail("json_sprintf returned NULL"); + if (!json_is_string(s)) + fail("json_sprintf didn't return a JSON string"); + if (strcmp(json_string_value(s), "foo bar 42")) + fail("json_sprintf generated an unexpected string"); + + json_decref(s); +} + + +static void run_tests() +{ + test_sprintf(); +}