aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Harvey-Macaulay <alteous@outlook.com>2016-02-22 21:32:20 +0000
committerDavid Harvey-Macaulay <alteous@outlook.com>2016-02-23 19:28:56 +0000
commit107cfe94991190d20dd8d7a91e3078167ad62a6f (patch)
treef1df72056e8a410ba38ad266b5442b067cc04e18
parente08101704c46e7577f17942ce11990990131ff20 (diff)
downloadjansson-107cfe94991190d20dd8d7a91e3078167ad62a6f.zip
jansson-107cfe94991190d20dd8d7a91e3078167ad62a6f.tar.gz
jansson-107cfe94991190d20dd8d7a91e3078167ad62a6f.tar.bz2
Implemented json_pack() format specifiers 's?', 'o?', and 'O?'.
-rw-r--r--src/pack_unpack.c72
-rw-r--r--test/suites/api/test_pack.c48
2 files changed, 103 insertions, 17 deletions
diff --git a/src/pack_unpack.c b/src/pack_unpack.c
index 9b1ef9e..f6c700c 100644
--- a/src/pack_unpack.c
+++ b/src/pack_unpack.c
@@ -48,7 +48,6 @@ static const char * const type_names[] = {
static const char unpack_value_starters[] = "{[siIbfFOon";
-
static void scanner_init(scanner_t *s, json_error_t *error,
size_t flags, const char *fmt)
{
@@ -291,6 +290,28 @@ error:
return NULL;
}
+static json_t *pack_string(scanner_t *s, va_list *ap)
+{
+ char *str;
+ size_t len;
+ int ours;
+ int nullable;
+
+ next_token(s);
+ nullable = token(s) == '?';
+ if (!nullable)
+ prev_token(s);
+
+ str = read_string(s, ap, "string", &len, &ours);
+ if (!str) {
+ return nullable ? json_null() : NULL;
+ } else if (ours) {
+ return jsonp_stringn_nocheck_own(str, len);
+ } else {
+ return json_stringn_nocheck(str, len);
+ }
+}
+
static json_t *pack(scanner_t *s, va_list *ap)
{
switch(token(s)) {
@@ -301,20 +322,7 @@ static json_t *pack(scanner_t *s, va_list *ap)
return pack_array(s, ap);
case 's': /* string */
- {
- char *str;
- size_t len;
- int ours;
-
- str = read_string(s, ap, "string", &len, &ours);
- if(!str)
- return NULL;
-
- if (ours)
- return jsonp_stringn_nocheck_own(str, len);
- else
- return json_stringn_nocheck(str, len);
- }
+ return pack_string(s, ap);
case 'n': /* null */
return json_null();
@@ -332,10 +340,40 @@ static json_t *pack(scanner_t *s, va_list *ap)
return json_real(va_arg(*ap, double));
case 'O': /* a json_t object; increments refcount */
- return json_incref(va_arg(*ap, json_t *));
+ {
+ int nullable;
+ json_t *json;
+
+ next_token(s);
+ nullable = token(s) == '?';
+ if (!nullable)
+ prev_token(s);
+
+ json = va_arg(*ap, json_t *);
+ if (!json && nullable) {
+ return json_null();
+ } else {
+ return json_incref(json);
+ }
+ }
case 'o': /* a json_t object; doesn't increment refcount */
- return va_arg(*ap, json_t *);
+ {
+ int nullable;
+ json_t *json;
+
+ next_token(s);
+ nullable = token(s) == '?';
+ if (!nullable)
+ prev_token(s);
+
+ json = va_arg(*ap, json_t *);
+ if (!json && nullable) {
+ return json_null();
+ } else {
+ return json;
+ }
+ }
default:
set_error(s, "<format>", "Unexpected format character '%c'",
diff --git a/test/suites/api/test_pack.c b/test/suites/api/test_pack.c
index 9a8a62c..24c49a4 100644
--- a/test/suites/api/test_pack.c
+++ b/test/suites/api/test_pack.c
@@ -83,6 +83,22 @@ static void run_tests()
fail("json_pack string refcount failed");
json_decref(value);
+ /* nullable string (defined case) */
+ value = json_pack("s?", "test");
+ if(!json_is_string(value) || strcmp("test", json_string_value(value)))
+ fail("json_pack nullable string (defined case) failed");
+ if(value->refcount != (size_t)1)
+ fail("json_pack nullable string (defined case) refcount failed");
+ json_decref(value);
+
+ /* nullable string (NULL case) */
+ value = json_pack("s?", NULL);
+ if(!json_is_null(value))
+ fail("json_pack nullable string (NULL case) failed");
+ if(value->refcount != (size_t)-1)
+ fail("json_pack nullable string (NULL case) refcount failed");
+ json_decref(value);
+
/* string and length (int) */
value = json_pack("s#", "test asdf", 4);
if(!json_is_string(value) || strcmp("test", json_string_value(value)))
@@ -163,6 +179,22 @@ static void run_tests()
fail("json_pack integer refcount failed");
json_decref(value);
+ /* non-incref'd nullable object (defined case) */
+ value = json_pack("o?", json_integer(1));
+ if(!json_is_integer(value) || json_integer_value(value) != 1)
+ fail("json_pack nullable object (defined case) failed");
+ if(value->refcount != (size_t)1)
+ fail("json_pack nullable object (defined case) refcount failed");
+ json_decref(value);
+
+ /* non-incref'd nullable object (NULL case) */
+ value = json_pack("o?", NULL);
+ if(!json_is_null(value))
+ fail("json_pack nullable object (NULL case) failed");
+ if(value->refcount != (size_t)-1)
+ fail("json_pack nullable object (NULL case) refcount failed");
+ json_decref(value);
+
/* incref'd object */
value = json_pack("O", json_integer(1));
if(!json_is_integer(value) || json_integer_value(value) != 1)
@@ -172,6 +204,22 @@ static void run_tests()
json_decref(value);
json_decref(value);
+ /* incref'd nullable object (defined case) */
+ value = json_pack("O?", json_integer(1));
+ if(!json_is_integer(value) || json_integer_value(value) != 1)
+ fail("json_pack incref'd nullable object (defined case) failed");
+ if(value->refcount != (size_t)2)
+ fail("json_pack incref'd nullable object (defined case) refcount failed");
+ json_decref(value);
+ json_decref(value);
+
+ /* incref'd nullable object (NULL case) */
+ value = json_pack("O?", NULL);
+ if(!json_is_null(value))
+ fail("json_pack incref'd nullable object (NULL case) failed");
+ if(value->refcount != (size_t)-1)
+ fail("json_pack incref'd nullable object (NULL case) refcount failed");
+
/* simple object */
value = json_pack("{s:[]}", "foo");
if(!json_is_object(value) || json_object_size(value) != 1)