From 811965b4756731dae5c08215ca048cb7af9b8b63 Mon Sep 17 00:00:00 2001 From: David Harvey-Macaulay Date: Mon, 22 Feb 2016 21:32:20 +0000 Subject: [PATCH] Implemented json_pack() format specifiers 's?', 'o?', and 'O?'. --- src/pack_unpack.c | 68 +++++++++++++++++++++++++++---------- test/suites/api/test_pack.c | 48 ++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 17 deletions(-) diff --git a/src/pack_unpack.c b/src/pack_unpack.c index 9b1ef9e..625f4d9 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,26 @@ error: return NULL; } +static json_t *pack_string(scanner_t *s, va_list *ap) { + char *str; + size_t len; + int ours; + int nullable; + + nullable = s->start[1] == '?'; + if (nullable) + next_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 +320,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 +338,38 @@ 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; + + nullable = s->start[1] == '?'; + if (nullable) + next_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; + + nullable = s->start[1] == '?'; + if (nullable) + next_token(s); + + json = va_arg(*ap, json_t *); + if (!json && nullable) { + return json_null(); + } else { + return json; + } + } default: set_error(s, "", "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)