diff --git a/doc/apiref.rst b/doc/apiref.rst index ca38bbf..839bb68 100644 --- a/doc/apiref.rst +++ b/doc/apiref.rst @@ -948,6 +948,28 @@ These functions output UTF-8: error. *flags* is described above. The return value must be freed by the caller using :func:`free()`. +.. function:: size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags) + + Writes the JSON representation of *json* to the *buffer* of + *size* bytes. Returns the number of bytes that would be written + or 0 on error. *flags* is described above. *buffer* is not + null-terminated. + + This function never writes more than *size* bytes. If the return + value is greater than *size*, the contents of the *buffer* are + undefined. This behavior enables you to specify a NULL *buffer* + to determine the length of the encoding. For example:: + + size_t size = json_dumpb(json, NULL, 0, 0); + if (size == 0) + return -1; + + char *buf = alloca(size); + + size = json_dumpb(json, buf, size, 0); + + .. versionadded:: 2.10 + .. function:: int json_dumpf(const json_t *json, FILE *output, size_t flags) Write the JSON representation of *json* to the stream *output*. diff --git a/src/dump.c b/src/dump.c index 6b1aabd..4d97a6a 100644 --- a/src/dump.c +++ b/src/dump.c @@ -25,11 +25,28 @@ #define FLAGS_TO_INDENT(f) ((f) & 0x1F) #define FLAGS_TO_PRECISION(f) (((f) >> 11) & 0x1F) +struct buffer { + const size_t size; + size_t used; + char *data; +}; + static int dump_to_strbuffer(const char *buffer, size_t size, void *data) { return strbuffer_append_bytes((strbuffer_t *)data, buffer, size); } +static int dump_to_buffer(const char *buffer, size_t size, void *data) +{ + struct buffer *buf = (struct buffer *)data; + + if(buf->used + size <= buf->size) + memcpy(&buf->data[buf->used], buffer, size); + + buf->used += size; + return 0; +} + static int dump_to_file(const char *buffer, size_t size, void *data) { FILE *dest = (FILE *)data; @@ -416,6 +433,16 @@ char *json_dumps(const json_t *json, size_t flags) return result; } +size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags) +{ + struct buffer buf = { size, 0, buffer }; + + if(json_dump_callback(json, dump_to_buffer, (void *)&buf, flags)) + return 0; + + return buf.used; +} + int json_dumpf(const json_t *json, FILE *output, size_t flags) { return json_dump_callback(json, dump_to_file, (void *)output, flags); diff --git a/src/jansson.def b/src/jansson.def index c43eb07..55cb117 100644 --- a/src/jansson.def +++ b/src/jansson.def @@ -48,6 +48,7 @@ EXPORTS json_object_key_to_iter json_object_seed json_dumps + json_dumpb json_dumpf json_dump_file json_dump_callback diff --git a/src/jansson.h b/src/jansson.h index 591f2a9..74f11a0 100644 --- a/src/jansson.h +++ b/src/jansson.h @@ -292,6 +292,7 @@ json_t *json_load_callback(json_load_callback_t callback, void *data, size_t fla typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data); char *json_dumps(const json_t *json, size_t flags); +size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags); int json_dumpf(const json_t *json, FILE *output, size_t flags); int json_dump_file(const json_t *json, const char *path, size_t flags); int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags); diff --git a/test/suites/api/test_dump.c b/test/suites/api/test_dump.c index 3591fa5..e528031 100644 --- a/test/suites/api/test_dump.c +++ b/test/suites/api/test_dump.c @@ -22,6 +22,9 @@ static void encode_null() if(json_dumps(NULL, JSON_ENCODE_ANY) != NULL) fail("json_dumps didn't fail for NULL"); + if(json_dumpb(NULL, NULL, 0, JSON_ENCODE_ANY) != 0) + fail("json_dumps didn't fail for NULL"); + if(json_dumpf(NULL, stderr, JSON_ENCODE_ANY) != -1) fail("json_dumpf didn't fail for NULL"); @@ -212,6 +215,28 @@ static void dump_file() remove("json_dump_file.json"); } +static void dumpb() +{ + char buf[2]; + json_t *obj; + size_t size; + + obj = json_object(); + + size = json_dumpb(obj, buf, sizeof(buf), 0); + if(size != 2 || strncmp(buf, "{}", 2)) + fail("json_dumpb failed"); + + json_decref(obj); + obj = json_pack("{s:s}", "foo", "bar"); + + size = json_dumpb(obj, buf, sizeof(buf), JSON_COMPACT); + if(size != 13) + fail("json_dumpb size check failed"); + + json_decref(obj); +} + static void run_tests() { encode_null(); @@ -221,4 +246,5 @@ static void run_tests() escape_slashes(); encode_nul_byte(); dump_file(); + dumpb(); }