aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathaniel McCallum <npmccallum@redhat.com>2017-01-26 09:46:48 +0100
committerNathaniel McCallum <npmccallum@redhat.com>2017-01-26 16:16:24 +0100
commitb900967f6fbfae098ced9dfeab7b2b51e1a22c0a (patch)
treec58c08d1d918756cfb57b5fd8d20345eeb410fa6
parent746c2c3a996a7f6e80bd19fe3de438637e6363e1 (diff)
downloadjansson-b900967f6fbfae098ced9dfeab7b2b51e1a22c0a.zip
jansson-b900967f6fbfae098ced9dfeab7b2b51e1a22c0a.tar.gz
jansson-b900967f6fbfae098ced9dfeab7b2b51e1a22c0a.tar.bz2
Implement json_dumpb()
This function encodes the json_t object to a pre-allocated buffer. It compliments the already existing json_loadb() function and is useful for parsing JSON-RPC (among other protocols) when sent over datagram sockets. Signed-off-by: Nathaniel McCallum <npmccallum@redhat.com>
-rw-r--r--doc/apiref.rst22
-rw-r--r--src/dump.c27
-rw-r--r--src/jansson.def1
-rw-r--r--src/jansson.h1
-rw-r--r--test/suites/api/test_dump.c26
5 files changed, 77 insertions, 0 deletions
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();
}