Implemented json_pack() format specifiers 's?', 'o?', and 'O?'.

This commit is contained in:
David Harvey-Macaulay 2016-02-22 21:32:20 +00:00
parent e08101704c
commit 811965b475
2 changed files with 99 additions and 17 deletions

View File

@ -48,7 +48,6 @@ static const char * const type_names[] = {
static const char unpack_value_starters[] = "{[siIbfFOon"; static const char unpack_value_starters[] = "{[siIbfFOon";
static void scanner_init(scanner_t *s, json_error_t *error, static void scanner_init(scanner_t *s, json_error_t *error,
size_t flags, const char *fmt) size_t flags, const char *fmt)
{ {
@ -291,6 +290,26 @@ error:
return NULL; 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) static json_t *pack(scanner_t *s, va_list *ap)
{ {
switch(token(s)) { switch(token(s)) {
@ -301,20 +320,7 @@ static json_t *pack(scanner_t *s, va_list *ap)
return pack_array(s, ap); return pack_array(s, ap);
case 's': /* string */ case 's': /* string */
{ return pack_string(s, ap);
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);
}
case 'n': /* null */ case 'n': /* null */
return json_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)); return json_real(va_arg(*ap, double));
case 'O': /* a json_t object; increments refcount */ 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 */ 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: default:
set_error(s, "<format>", "Unexpected format character '%c'", set_error(s, "<format>", "Unexpected format character '%c'",

View File

@ -83,6 +83,22 @@ static void run_tests()
fail("json_pack string refcount failed"); fail("json_pack string refcount failed");
json_decref(value); 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) */ /* string and length (int) */
value = json_pack("s#", "test asdf", 4); value = json_pack("s#", "test asdf", 4);
if(!json_is_string(value) || strcmp("test", json_string_value(value))) 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"); fail("json_pack integer refcount failed");
json_decref(value); 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 */ /* incref'd object */
value = json_pack("O", json_integer(1)); value = json_pack("O", json_integer(1));
if(!json_is_integer(value) || json_integer_value(value) != 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);
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 */ /* simple object */
value = json_pack("{s:[]}", "foo"); value = json_pack("{s:[]}", "foo");
if(!json_is_object(value) || json_object_size(value) != 1) if(!json_is_object(value) || json_object_size(value) != 1)