Skip to content

Commit

Permalink
Create JSON_RAW type, implement helpers and test coverage.
Browse files Browse the repository at this point in the history
Related to issue akheron#10
  • Loading branch information
coreyfarrell committed Nov 9, 2018
1 parent 4ba5c7c commit 887c7ba
Show file tree
Hide file tree
Showing 12 changed files with 344 additions and 22 deletions.
3 changes: 3 additions & 0 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@ static int do_dump(const json_t *json, size_t flags, int depth,
case JSON_STRING:
return dump_string(json_string_value(json), json_string_length(json), dump, data, flags);

case JSON_RAW:
return dump(json_raw_value(json), json_raw_length(json), data);

case JSON_ARRAY:
{
size_t n;
Expand Down
10 changes: 10 additions & 0 deletions src/jansson.def
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ EXPORTS
json_string_setn
json_string_set_nocheck
json_string_setn_nocheck
json_raw
json_raw_length
json_rawn
json_rawn_nocheck
json_raw_nocheck
json_raw_set
json_raw_setn
json_raw_setn_nocheck
json_raw_set_nocheck
json_raw_value
json_integer
json_integer_value
json_integer_set
Expand Down
15 changes: 14 additions & 1 deletion src/jansson.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ typedef enum {
JSON_REAL,
JSON_TRUE,
JSON_FALSE,
JSON_NULL
JSON_NULL,
JSON_RAW
} json_type;

typedef struct json_t {
Expand Down Expand Up @@ -89,6 +90,7 @@ typedef long json_int_t;
#define json_boolean_value json_is_true
#define json_is_boolean(json) (json_is_true(json) || json_is_false(json))
#define json_is_null(json) ((json) && json_typeof(json) == JSON_NULL)
#define json_is_raw(json) ((json) && json_typeof(json) == JSON_RAW)

/* construction, destruction, reference counting */

Expand All @@ -104,6 +106,10 @@ json_t *json_true(void);
json_t *json_false(void);
#define json_boolean(val) ((val) ? json_true() : json_false())
json_t *json_null(void);
json_t *json_raw(const char *value);
json_t *json_rawn(const char *value, size_t len);
json_t *json_raw_nocheck(const char *value);
json_t *json_rawn_nocheck(const char *value, size_t len);

/* do not call JSON_INTERNAL_INCREF or JSON_INTERNAL_DECREF directly */
#if JSON_HAVE_ATOMIC_BUILTINS
Expand Down Expand Up @@ -282,6 +288,13 @@ int json_string_setn_nocheck(json_t *string, const char *value, size_t len);
int json_integer_set(json_t *integer, json_int_t value);
int json_real_set(json_t *real, double value);

const char *json_raw_value(const json_t *raw);
size_t json_raw_length(const json_t *raw);
int json_raw_set(json_t *raw, const char *value);
int json_raw_setn(json_t *raw, const char *value, size_t len);
int json_raw_set_nocheck(json_t *raw, const char *value);
int json_raw_setn_nocheck(json_t *raw, const char *value, size_t len);

/* pack, unpack */

json_t *json_pack(const char *fmt, ...) JANSSON_ATTRS(warn_unused_result);
Expand Down
1 change: 1 addition & 0 deletions src/jansson_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ typedef struct {
#define json_to_string(json_) container_of(json_, json_string_t, json)
#define json_to_real(json_) container_of(json_, json_real_t, json)
#define json_to_integer(json_) container_of(json_, json_integer_t, json)
#define json_to_raw(json_) container_of(json_, json_string_t, json)

/* Create a string by taking ownership of an existing buffer */
json_t *jsonp_stringn_nocheck_own(const char *value, size_t len);
Expand Down
4 changes: 2 additions & 2 deletions src/pack_unpack.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ static char *read_string(scanner_t *s, va_list *ap,

length = strlen(str);

if(!utf8_check_string(str, length)) {
if(!utf8_check_string(str, length, 0)) {
set_error(s, "<args>", json_error_invalid_utf8, "Invalid UTF-8 %s", purpose);
s->has_error = 1;
return NULL;
Expand Down Expand Up @@ -213,7 +213,7 @@ static char *read_string(scanner_t *s, va_list *ap,
return NULL;
}

if(!utf8_check_string(strbuff.value, strbuff.length)) {
if(!utf8_check_string(strbuff.value, strbuff.length, 0)) {
set_error(s, "<args>", json_error_invalid_utf8, "Invalid UTF-8 %s", purpose);
strbuffer_close(&strbuff);
s->has_error = 1;
Expand Down
4 changes: 3 additions & 1 deletion src/utf.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ const char *utf8_iterate(const char *buffer, size_t bufsize, int32_t *codepoint)
return buffer + count;
}

int utf8_check_string(const char *string, size_t length)
int utf8_check_string(const char *string, size_t length, int no_null)
{
size_t i;

Expand All @@ -180,6 +180,8 @@ int utf8_check_string(const char *string, size_t length)
return 0;

i += count - 1;
} else if (no_null && string[i] == '\0') {
return 0;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/utf.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ size_t utf8_check_first(char byte);
size_t utf8_check_full(const char *buffer, size_t size, int32_t *codepoint);
const char *utf8_iterate(const char *buffer, size_t size, int32_t *codepoint);

int utf8_check_string(const char *string, size_t length);
int utf8_check_string(const char *string, size_t length, int no_null);

#endif
133 changes: 124 additions & 9 deletions src/value.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ int json_object_set_new_nocheck(json_t *json, const char *key, json_t *value)

int json_object_set_new(json_t *json, const char *key, json_t *value)
{
if(!key || !utf8_check_string(key, strlen(key)))
if(!key || !utf8_check_string(key, strlen(key), 0))
{
json_decref(value);
return -1;
Expand Down Expand Up @@ -634,8 +634,9 @@ static json_t *json_array_deep_copy(const json_t *array)

/*** string ***/

static json_t *string_create(const char *value, size_t len, int own)
static json_t *string_create(const char *value, size_t len, int own, json_type type)
{
/* This function is used for JSON_STRING and JSON_RAW. */
char *v;
json_string_t *string;

Expand All @@ -655,7 +656,7 @@ static json_t *string_create(const char *value, size_t len, int own)
jsonp_free(v);
return NULL;
}
json_init(&string->json, JSON_STRING);
json_init(&string->json, type);
string->value = v;
string->length = len;

Expand All @@ -667,18 +668,18 @@ json_t *json_string_nocheck(const char *value)
if(!value)
return NULL;

return string_create(value, strlen(value), 0);
return string_create(value, strlen(value), 0, JSON_STRING);
}

json_t *json_stringn_nocheck(const char *value, size_t len)
{
return string_create(value, len, 0);
return string_create(value, len, 0, JSON_STRING);
}

/* this is private; "steal" is not a public API concept */
json_t *jsonp_stringn_nocheck_own(const char *value, size_t len)
{
return string_create(value, len, 1);
return string_create(value, len, 1, JSON_STRING);
}

json_t *json_string(const char *value)
Expand All @@ -691,7 +692,7 @@ json_t *json_string(const char *value)

json_t *json_stringn(const char *value, size_t len)
{
if(!value || !utf8_check_string(value, len))
if(!value || !utf8_check_string(value, len, 0))
return NULL;

return json_stringn_nocheck(value, len);
Expand Down Expand Up @@ -751,7 +752,7 @@ int json_string_set(json_t *json, const char *value)

int json_string_setn(json_t *json, const char *value, size_t len)
{
if(!value || !utf8_check_string(value, len))
if(!value || !utf8_check_string(value, len, 0))
return -1;

return json_string_setn_nocheck(json, value, len);
Expand All @@ -765,6 +766,7 @@ static void json_delete_string(json_string_t *string)

static int json_string_equal(const json_t *string1, const json_t *string2)
{
/* This function is used for JSON_STRING and JSON_RAW. */
json_string_t *s1, *s2;

s1 = json_to_string(string1);
Expand Down Expand Up @@ -798,7 +800,7 @@ json_t *json_vsprintf(const char *fmt, va_list ap) {
goto out;

vsnprintf(buf, length + 1, fmt, aq);
if (!utf8_check_string(buf, length)) {
if (!utf8_check_string(buf, length, 0)) {
jsonp_free(buf);
goto out;
}
Expand Down Expand Up @@ -957,6 +959,110 @@ json_t *json_null(void)
}


/*** raw ***/
json_t *json_raw_nocheck(const char *value)
{
if(!value)
return NULL;

return string_create(value, strlen(value), 0, JSON_RAW);
}

json_t *json_rawn_nocheck(const char *value, size_t len)
{
return string_create(value, len, 0, JSON_RAW);
}

json_t *json_raw(const char *value)
{
if(!value)
return NULL;

return json_rawn(value, strlen(value));
}

json_t *json_rawn(const char *value, size_t len)
{
if(!value || !utf8_check_string(value, len, 1))
return NULL;

return json_rawn_nocheck(value, len);
}

const char *json_raw_value(const json_t *json)
{
if(!json_is_raw(json))
return NULL;

return json_to_raw(json)->value;
}

size_t json_raw_length(const json_t *json)
{
if(!json_is_raw(json))
return 0;

return json_to_raw(json)->length;
}

int json_raw_set_nocheck(json_t *json, const char *value)
{
if(!value)
return -1;

return json_raw_setn_nocheck(json, value, strlen(value));
}

int json_raw_setn_nocheck(json_t *json, const char *value, size_t len)
{
char *dup;
json_string_t *raw;

if(!json_is_raw(json) || !value)
return -1;

dup = jsonp_strndup(value, len);
if(!dup)
return -1;

raw = json_to_raw(json);
jsonp_free(raw->value);
raw->value = dup;
raw->length = len;

return 0;
}

int json_raw_set(json_t *json, const char *value)
{
if(!value)
return -1;

return json_raw_setn(json, value, strlen(value));
}

int json_raw_setn(json_t *json, const char *value, size_t len)
{
if(!value || !utf8_check_string(value, len, 1))
return -1;

return json_raw_setn_nocheck(json, value, len);
}

static void json_delete_raw(json_string_t *raw)
{
jsonp_free(raw->value);
jsonp_free(raw);
}

static json_t *json_raw_copy(const json_t *raw)
{
json_string_t *s;

s = json_to_raw(raw);
return json_rawn_nocheck(s->value, s->length);
}

/*** deletion ***/

void json_delete(json_t *json)
Expand All @@ -980,6 +1086,9 @@ void json_delete(json_t *json)
case JSON_REAL:
json_delete_real(json_to_real(json));
break;
case JSON_RAW:
json_delete_raw(json_to_raw(json));
break;
default:
return;
}
Expand Down Expand Up @@ -1013,6 +1122,8 @@ int json_equal(const json_t *json1, const json_t *json2)
return json_integer_equal(json1, json2);
case JSON_REAL:
return json_real_equal(json1, json2);
case JSON_RAW:
return json_string_equal(json1, json2);
default:
return 0;
}
Expand Down Expand Up @@ -1041,6 +1152,8 @@ json_t *json_copy(json_t *json)
case JSON_FALSE:
case JSON_NULL:
return json;
case JSON_RAW:
return json_raw_copy(json);
default:
return NULL;
}
Expand Down Expand Up @@ -1068,6 +1181,8 @@ json_t *json_deep_copy(const json_t *json)
case JSON_FALSE:
case JSON_NULL:
return (json_t *)json;
case JSON_RAW:
return json_raw_copy(json);
default:
return NULL;
}
Expand Down
2 changes: 2 additions & 0 deletions test/suites/api/test_chaos.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ static void test_chaos()
json_t *arr1 = json_array();
json_t *arr2 = json_array();
json_t *txt = json_string("test");
json_t *raw = json_raw("{}");
json_t *intnum = json_integer(1);
json_t *dblnum = json_real(0.5);
char *dumptxt = NULL;
Expand Down Expand Up @@ -160,6 +161,7 @@ static void test_chaos()

chaos_loop(json_array_extend(arr1, arr2),,);
chaos_loop(json_string_set_nocheck(txt, "test"),,);
chaos_loop(json_raw_set_nocheck(raw, "[]"),,);

json_set_alloc_funcs(orig_malloc, orig_free);
json_decref(obj);
Expand Down
Loading

0 comments on commit 887c7ba

Please sign in to comment.