Add support for string values with embedded '\0' characters (#137)

* Add support for strings with \0 chars

* address feedback

* Increments minor version, adds comments, changes license year

Co-authored-by: Krzysztof Gabis <kgabis@gmail.com>
This commit is contained in:
reuben olinsky 2020-04-16 12:55:56 -07:00 committed by GitHub
parent 8d8850d9d5
commit 102a4467e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 164 additions and 47 deletions

3
.gitignore vendored
View File

@ -1,3 +1,6 @@
.DS_Store
test
*.o
testcpp
tests/test_2_serialized.txt
tests/test_2_serialized_pretty.txt

View File

@ -3,7 +3,7 @@ project(parson C)
include (GNUInstallDirs)
set(PARSON_VERSION 1.0.2)
set(PARSON_VERSION 1.1.0)
add_library(parson parson.c)
target_include_directories(parson PUBLIC $<INSTALL_INTERFACE:include>)

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2012 - 2019 Krzysztof Gabis
Copyright (c) 2012 - 2020 Krzysztof Gabis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
{
"name": "parson",
"version": "1.0.2",
"version": "1.1.0",
"repo": "kgabis/parson",
"description": "Small json parser and reader",
"keywords": [ "json", "parser" ],

175
parson.c
View File

@ -1,8 +1,8 @@
/*
SPDX-License-Identifier: MIT
Parson 1.0.2 ( http://kgabis.github.com/parson/ )
Copyright (c) 2012 - 2019 Krzysztof Gabis
Parson 1.1.0 ( http://kgabis.github.com/parson/ )
Copyright (c) 2012 - 2020 Krzysztof Gabis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -68,9 +68,14 @@ static int parson_escape_slashes = 1;
#define IS_CONT(b) (((unsigned char)(b) & 0xC0) == 0x80) /* is utf-8 continuation byte */
typedef struct json_string {
char *chars;
size_t length;
} JSON_String;
/* Type definitions */
typedef union json_value_value {
char *string;
JSON_String string;
double number;
JSON_Object *object;
JSON_Array *array;
@ -128,13 +133,14 @@ static JSON_Status json_array_resize(JSON_Array *array, size_t new_capacity);
static void json_array_free(JSON_Array *array);
/* JSON Value */
static JSON_Value * json_value_init_string_no_copy(char *string);
static JSON_Value * json_value_init_string_no_copy(char *string, size_t length);
static const JSON_String * json_value_get_string_desc(const JSON_Value *value);
/* Parser */
static JSON_Status skip_quotes(const char **string);
static int parse_utf16(const char **unprocessed, char **processed);
static char * process_string(const char *input, size_t len);
static char * get_quoted_string(const char **string);
static char * process_string(const char *input, size_t input_len, size_t *output_len);
static char * get_quoted_string(const char **string, size_t *output_string_len);
static JSON_Value * parse_object_value(const char **string, size_t nesting);
static JSON_Value * parse_array_value(const char **string, size_t nesting);
static JSON_Value * parse_string_value(const char **string);
@ -145,12 +151,13 @@ static JSON_Value * parse_value(const char **string, size_t nesting);
/* Serialization */
static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf);
static int json_serialize_string(const char *string, char *buf);
static int json_serialize_string(const char *string, size_t len, char *buf);
static int append_indent(char *buf, int level);
static int append_string(char *buf, const char *string);
/* Various */
static char * parson_strndup(const char *string, size_t n) {
/* We expect the caller has validated that 'n' fits within the input buffer. */
char *output_string = (char*)parson_malloc(n + 1);
if (!output_string) {
return NULL;
@ -536,14 +543,15 @@ static void json_array_free(JSON_Array *array) {
}
/* JSON Value */
static JSON_Value * json_value_init_string_no_copy(char *string) {
static JSON_Value * json_value_init_string_no_copy(char *string, size_t length) {
JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
if (!new_value) {
return NULL;
}
new_value->parent = NULL;
new_value->type = JSONString;
new_value->value.string = string;
new_value->value.string.chars = string;
new_value->value.string.length = length;
return new_value;
}
@ -617,9 +625,9 @@ static int parse_utf16(const char **unprocessed, char **processed) {
/* Copies and processes passed string up to supplied length.
Example: "\u006Corem ipsum" -> lorem ipsum */
static char* process_string(const char *input, size_t len) {
static char* process_string(const char *input, size_t input_len, size_t *output_len) {
const char *input_ptr = input;
size_t initial_size = (len + 1) * sizeof(char);
size_t initial_size = (input_len + 1) * sizeof(char);
size_t final_size = 0;
char *output = NULL, *output_ptr = NULL, *resized_output = NULL;
output = (char*)parson_malloc(initial_size);
@ -627,7 +635,7 @@ static char* process_string(const char *input, size_t len) {
goto error;
}
output_ptr = output;
while ((*input_ptr != '\0') && (size_t)(input_ptr - input) < len) {
while ((*input_ptr != '\0') && (size_t)(input_ptr - input) < input_len) {
if (*input_ptr == '\\') {
input_ptr++;
switch (*input_ptr) {
@ -664,6 +672,7 @@ static char* process_string(const char *input, size_t len) {
goto error;
}
memcpy(resized_output, output, final_size);
*output_len = final_size - 1;
parson_free(output);
return resized_output;
error:
@ -673,15 +682,15 @@ error:
/* Return processed contents of a string between quotes and
skips passed argument to a matching quote. */
static char * get_quoted_string(const char **string) {
static char * get_quoted_string(const char **string, size_t *output_string_len) {
const char *string_start = *string;
size_t string_len = 0;
size_t input_string_len = 0;
JSON_Status status = skip_quotes(string);
if (status != JSONSuccess) {
return NULL;
}
string_len = *string - string_start - 2; /* length without quotes */
return process_string(string_start + 1, string_len);
input_string_len = *string - string_start - 2; /* length without quotes */
return process_string(string_start + 1, input_string_len, output_string_len);
}
static JSON_Value * parse_value(const char **string, size_t nesting) {
@ -729,8 +738,10 @@ static JSON_Value * parse_object_value(const char **string, size_t nesting) {
return output_value;
}
while (**string != '\0') {
new_key = get_quoted_string(string);
if (new_key == NULL) {
size_t key_len = 0;
new_key = get_quoted_string(string, &key_len);
/* We do not support key names with embedded \0 chars */
if (new_key == NULL || key_len != strlen(new_key)) {
json_value_free(output_value);
return NULL;
}
@ -819,11 +830,12 @@ static JSON_Value * parse_array_value(const char **string, size_t nesting) {
static JSON_Value * parse_string_value(const char **string) {
JSON_Value *value = NULL;
char *new_string = get_quoted_string(string);
size_t new_string_len = 0;
char *new_string = get_quoted_string(string, &new_string_len);
if (new_string == NULL) {
return NULL;
}
value = json_value_init_string_no_copy(new_string);
value = json_value_init_string_no_copy(new_string, new_string_len);
if (value == NULL) {
parson_free(new_string);
return NULL;
@ -885,6 +897,7 @@ static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int le
size_t i = 0, count = 0;
double num = 0.0;
int written = -1, written_total = 0;
size_t len = 0;
switch (json_value_get_type(value)) {
case JSONArray:
@ -934,7 +947,8 @@ static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int le
if (is_pretty) {
APPEND_INDENT(level+1);
}
written = json_serialize_string(key, buf);
/* We do not support key names with embedded \0 chars */
written = json_serialize_string(key, strlen(key), buf);
if (written < 0) {
return -1;
}
@ -972,7 +986,8 @@ static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int le
if (string == NULL) {
return -1;
}
written = json_serialize_string(string, buf);
len = json_value_get_string_len(value);
written = json_serialize_string(string, len, buf);
if (written < 0) {
return -1;
}
@ -1012,8 +1027,8 @@ static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int le
}
}
static int json_serialize_string(const char *string, char *buf) {
size_t i = 0, len = strlen(string);
static int json_serialize_string(const char *string, size_t len, char *buf) {
size_t i = 0;
char c = '\0';
int written = -1, written_total = 0;
APPEND_STRING("\"");
@ -1159,6 +1174,10 @@ const char * json_object_get_string(const JSON_Object *object, const char *name)
return json_value_get_string(json_object_get_value(object, name));
}
size_t json_object_get_string_len(const JSON_Object *object, const char *name) {
return json_value_get_string_len(json_object_get_value(object, name));
}
double json_object_get_number(const JSON_Object *object, const char *name) {
return json_value_get_number(json_object_get_value(object, name));
}
@ -1188,6 +1207,10 @@ const char * json_object_dotget_string(const JSON_Object *object, const char *na
return json_value_get_string(json_object_dotget_value(object, name));
}
size_t json_object_dotget_string_len(const JSON_Object *object, const char *name) {
return json_value_get_string_len(json_object_dotget_value(object, name));
}
double json_object_dotget_number(const JSON_Object *object, const char *name) {
return json_value_get_number(json_object_dotget_value(object, name));
}
@ -1256,6 +1279,10 @@ const char * json_array_get_string(const JSON_Array *array, size_t index) {
return json_value_get_string(json_array_get_value(array, index));
}
size_t json_array_get_string_len(const JSON_Array *array, size_t index) {
return json_value_get_string_len(json_array_get_value(array, index));
}
double json_array_get_number(const JSON_Array *array, size_t index) {
return json_value_get_number(json_array_get_value(array, index));
}
@ -1293,8 +1320,18 @@ JSON_Array * json_value_get_array(const JSON_Value *value) {
return json_value_get_type(value) == JSONArray ? value->value.array : NULL;
}
static const JSON_String * json_value_get_string_desc(const JSON_Value *value) {
return json_value_get_type(value) == JSONString ? &value->value.string : NULL;
}
const char * json_value_get_string(const JSON_Value *value) {
return json_value_get_type(value) == JSONString ? value->value.string : NULL;
const JSON_String *str = json_value_get_string_desc(value);
return str ? str->chars : NULL;
}
size_t json_value_get_string_len(const JSON_Value *value) {
const JSON_String *str = json_value_get_string_desc(value);
return str ? str->length : 0;
}
double json_value_get_number(const JSON_Value *value) {
@ -1315,7 +1352,7 @@ void json_value_free(JSON_Value *value) {
json_object_free(value->value.object);
break;
case JSONString:
parson_free(value->value.string);
parson_free(value->value.string.chars);
break;
case JSONArray:
json_array_free(value->value.array);
@ -1357,21 +1394,26 @@ JSON_Value * json_value_init_array(void) {
}
JSON_Value * json_value_init_string(const char *string) {
char *copy = NULL;
JSON_Value *value;
size_t string_len = 0;
if (string == NULL) {
return NULL;
}
string_len = strlen(string);
if (!is_valid_utf8(string, string_len)) {
return json_value_init_string_with_len(string, strlen(string));
}
JSON_Value * json_value_init_string_with_len(const char *string, size_t length) {
char *copy = NULL;
JSON_Value *value;
if (string == NULL) {
return NULL;
}
copy = parson_strndup(string, string_len);
if (!is_valid_utf8(string, length)) {
return NULL;
}
copy = parson_strndup(string, length);
if (copy == NULL) {
return NULL;
}
value = json_value_init_string_no_copy(copy);
value = json_value_init_string_no_copy(copy, length);
if (value == NULL) {
parson_free(copy);
}
@ -1417,7 +1459,8 @@ JSON_Value * json_value_init_null(void) {
JSON_Value * json_value_deep_copy(const JSON_Value *value) {
size_t i = 0;
JSON_Value *return_value = NULL, *temp_value_copy = NULL, *temp_value = NULL;
const char *temp_string = NULL, *temp_key = NULL;
const JSON_String *temp_string = NULL;
const char *temp_key = NULL;
char *temp_string_copy = NULL;
JSON_Array *temp_array = NULL, *temp_array_copy = NULL;
JSON_Object *temp_object = NULL, *temp_object_copy = NULL;
@ -1471,15 +1514,15 @@ JSON_Value * json_value_deep_copy(const JSON_Value *value) {
case JSONNumber:
return json_value_init_number(json_value_get_number(value));
case JSONString:
temp_string = json_value_get_string(value);
temp_string = json_value_get_string_desc(value);
if (temp_string == NULL) {
return NULL;
}
temp_string_copy = parson_strdup(temp_string);
temp_string_copy = parson_strndup(temp_string->chars, temp_string->length);
if (temp_string_copy == NULL) {
return NULL;
}
return_value = json_value_init_string_no_copy(temp_string_copy);
return_value = json_value_init_string_no_copy(temp_string_copy, temp_string->length);
if (return_value == NULL) {
parson_free(temp_string_copy);
}
@ -1651,6 +1694,18 @@ JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* s
return JSONSuccess;
}
JSON_Status json_array_replace_string_with_len(JSON_Array *array, size_t i, const char *string, size_t len) {
JSON_Value *value = json_value_init_string_with_len(string, len);
if (value == NULL) {
return JSONFailure;
}
if (json_array_replace_value(array, i, value) == JSONFailure) {
json_value_free(value);
return JSONFailure;
}
return JSONSuccess;
}
JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number) {
JSON_Value *value = json_value_init_number(number);
if (value == NULL) {
@ -1718,6 +1773,18 @@ JSON_Status json_array_append_string(JSON_Array *array, const char *string) {
return JSONSuccess;
}
JSON_Status json_array_append_string_with_len(JSON_Array *array, const char *string, size_t len) {
JSON_Value *value = json_value_init_string_with_len(string, len);
if (value == NULL) {
return JSONFailure;
}
if (json_array_append_value(array, value) == JSONFailure) {
json_value_free(value);
return JSONFailure;
}
return JSONSuccess;
}
JSON_Status json_array_append_number(JSON_Array *array, double number) {
JSON_Value *value = json_value_init_number(number);
if (value == NULL) {
@ -1784,6 +1851,15 @@ JSON_Status json_object_set_string(JSON_Object *object, const char *name, const
return status;
}
JSON_Status json_object_set_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len) {
JSON_Value *value = json_value_init_string_with_len(string, len);
JSON_Status status = json_object_set_value(object, name, value);
if (status == JSONFailure) {
json_value_free(value);
}
return status;
}
JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number) {
JSON_Value *value = json_value_init_number(number);
JSON_Status status = json_object_set_value(object, name, value);
@ -1865,6 +1941,18 @@ JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, con
return JSONSuccess;
}
JSON_Status json_object_dotset_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len) {
JSON_Value *value = json_value_init_string_with_len(string, len);
if (value == NULL) {
return JSONFailure;
}
if (json_object_dotset_value(object, name, value) == JSONFailure) {
json_value_free(value);
return JSONFailure;
}
return JSONSuccess;
}
JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number) {
JSON_Value *value = json_value_init_number(number);
if (value == NULL) {
@ -1985,7 +2073,7 @@ JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value) {
int json_value_equals(const JSON_Value *a, const JSON_Value *b) {
JSON_Object *a_object = NULL, *b_object = NULL;
JSON_Array *a_array = NULL, *b_array = NULL;
const char *a_string = NULL, *b_string = NULL;
const JSON_String *a_string = NULL, *b_string = NULL;
const char *key = NULL;
size_t a_count = 0, b_count = 0, i = 0;
JSON_Value_Type a_type, b_type;
@ -2027,12 +2115,13 @@ int json_value_equals(const JSON_Value *a, const JSON_Value *b) {
}
return 1;
case JSONString:
a_string = json_value_get_string(a);
b_string = json_value_get_string(b);
a_string = json_value_get_string_desc(a);
b_string = json_value_get_string_desc(b);
if (a_string == NULL || b_string == NULL) {
return 0; /* shouldn't happen */
}
return strcmp(a_string, b_string) == 0;
return a_string->length == b_string->length &&
memcmp(a_string->chars, b_string->chars, a_string->length) == 0;
case JSONBoolean:
return json_value_get_boolean(a) == json_value_get_boolean(b);
case JSONNumber:
@ -2062,6 +2151,10 @@ const char * json_string (const JSON_Value *value) {
return json_value_get_string(value);
}
size_t json_string_len(const JSON_Value *value) {
return json_value_get_string_len(value);
}
double json_number (const JSON_Value *value) {
return json_value_get_number(value);
}

View File

@ -1,8 +1,8 @@
/*
SPDX-License-Identifier: MIT
Parson 1.0.2 ( http://kgabis.github.com/parson/ )
Copyright (c) 2012 - 2019 Krzysztof Gabis
Parson 1.1.0 ( http://kgabis.github.com/parson/ )
Copyright (c) 2012 - 2020 Krzysztof Gabis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -114,6 +114,7 @@ JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value);
*/
JSON_Value * json_object_get_value (const JSON_Object *object, const char *name);
const char * json_object_get_string (const JSON_Object *object, const char *name);
size_t json_object_get_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */
JSON_Object * json_object_get_object (const JSON_Object *object, const char *name);
JSON_Array * json_object_get_array (const JSON_Object *object, const char *name);
double json_object_get_number (const JSON_Object *object, const char *name); /* returns 0 on fail */
@ -125,6 +126,7 @@ int json_object_get_boolean(const JSON_Object *object, const char *nam
this way. */
JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name);
const char * json_object_dotget_string (const JSON_Object *object, const char *name);
size_t json_object_dotget_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */
JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name);
JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name);
double json_object_dotget_number (const JSON_Object *object, const char *name); /* returns 0 on fail */
@ -148,6 +150,7 @@ int json_object_dothas_value_of_type(const JSON_Object *object, const char *name
* json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */
JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value);
JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string);
JSON_Status json_object_set_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len); /* length shouldn't include last null character */
JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number);
JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean);
JSON_Status json_object_set_null(JSON_Object *object, const char *name);
@ -156,6 +159,7 @@ JSON_Status json_object_set_null(JSON_Object *object, const char *name);
* json_object_dotset_value does not copy passed value so it shouldn't be freed afterwards. */
JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value);
JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string);
JSON_Status json_object_dotset_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len); /* length shouldn't include last null character */
JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number);
JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean);
JSON_Status json_object_dotset_null(JSON_Object *object, const char *name);
@ -174,6 +178,7 @@ JSON_Status json_object_clear(JSON_Object *object);
*/
JSON_Value * json_array_get_value (const JSON_Array *array, size_t index);
const char * json_array_get_string (const JSON_Array *array, size_t index);
size_t json_array_get_string_len(const JSON_Array *array, size_t index); /* doesn't account for last null character */
JSON_Object * json_array_get_object (const JSON_Array *array, size_t index);
JSON_Array * json_array_get_array (const JSON_Array *array, size_t index);
double json_array_get_number (const JSON_Array *array, size_t index); /* returns 0 on fail */
@ -190,6 +195,7 @@ JSON_Status json_array_remove(JSON_Array *array, size_t i);
* json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */
JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value);
JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string);
JSON_Status json_array_replace_string_with_len(JSON_Array *array, size_t i, const char *string, size_t len); /* length shouldn't include last null character */
JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number);
JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean);
JSON_Status json_array_replace_null(JSON_Array *array, size_t i);
@ -201,6 +207,7 @@ JSON_Status json_array_clear(JSON_Array *array);
* json_array_append_value does not copy passed value so it shouldn't be freed afterwards. */
JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value);
JSON_Status json_array_append_string(JSON_Array *array, const char *string);
JSON_Status json_array_append_string_with_len(JSON_Array *array, const char *string, size_t len); /* length shouldn't include last null character */
JSON_Status json_array_append_number(JSON_Array *array, double number);
JSON_Status json_array_append_boolean(JSON_Array *array, int boolean);
JSON_Status json_array_append_null(JSON_Array *array);
@ -211,6 +218,7 @@ JSON_Status json_array_append_null(JSON_Array *array);
JSON_Value * json_value_init_object (void);
JSON_Value * json_value_init_array (void);
JSON_Value * json_value_init_string (const char *string); /* copies passed string */
JSON_Value * json_value_init_string_with_len(const char *string, size_t length); /* copies passed string, length shouldn't include last null character */
JSON_Value * json_value_init_number (double number);
JSON_Value * json_value_init_boolean(int boolean);
JSON_Value * json_value_init_null (void);
@ -221,6 +229,7 @@ JSON_Value_Type json_value_get_type (const JSON_Value *value);
JSON_Object * json_value_get_object (const JSON_Value *value);
JSON_Array * json_value_get_array (const JSON_Value *value);
const char * json_value_get_string (const JSON_Value *value);
size_t json_value_get_string_len(const JSON_Value *value); /* doesn't account for last null character */
double json_value_get_number (const JSON_Value *value);
int json_value_get_boolean(const JSON_Value *value);
JSON_Value * json_value_get_parent (const JSON_Value *value);
@ -230,6 +239,7 @@ JSON_Value_Type json_type (const JSON_Value *value);
JSON_Object * json_object (const JSON_Value *value);
JSON_Array * json_array (const JSON_Value *value);
const char * json_string (const JSON_Value *value);
size_t json_string_len(const JSON_Value *value); /* doesn't account for last null character */
double json_number (const JSON_Value *value);
int json_boolean(const JSON_Value *value);

View File

@ -2,7 +2,7 @@
SPDX-License-Identifier: MIT
Parson ( http://kgabis.github.com/parson/ )
Copyright (c) 2012 - 2019 Krzysztof Gabis
Copyright (c) 2012 - 2020 Krzysztof Gabis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -136,6 +136,7 @@ void test_suite_2(JSON_Value *root_value) {
JSON_Object *root_object;
JSON_Array *array;
JSON_Value *array_value;
size_t len;
size_t i;
TEST(root_value);
TEST(json_value_get_type(root_value) == JSONObject);
@ -176,6 +177,10 @@ void test_suite_2(JSON_Value *root_value) {
TEST(STREQ(json_object_get_string(root_object, "utf-8 string"), "あいうえお"));
TEST(STREQ(json_object_get_string(root_object, "surrogate string"), "lorem𝄞ipsum𝍧lorem"));
len = json_object_get_string_len(root_object, "string with null");
TEST(len == 7);
TEST(memcmp(json_object_get_string(root_object, "string with null"), "abc\0def", len) == 0);
TEST(json_object_get_number(root_object, "positive one") == 1.0);
TEST(json_object_get_number(root_object, "negative one") == -1.0);
TEST(fabs(json_object_get_number(root_object, "hard to parse number") - (-0.000314)) < EPSILON);
@ -370,6 +375,7 @@ void test_suite_5(void) {
TEST(json_object_set_string(obj, "utf string", "lorem ipsum") == JSONSuccess);
TEST(json_object_set_string(obj, "utf-8 string", "あいうえお") == JSONSuccess);
TEST(json_object_set_string(obj, "surrogate string", "lorem𝄞ipsum𝍧lorem") == JSONSuccess);
TEST(json_object_set_string_with_len(obj, "string with null", "abc\0def", 7) == JSONSuccess);
TEST(json_object_set_string(obj, "windows path", "C:\\Windows\\Path") == JSONSuccess);
TEST(json_value_equals(val_from_file, val));

View File

@ -26,6 +26,7 @@
"digit": "0123456789",
"0123456789": "digit",
"special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
"nullchar": "abc\u0000def",
"hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
"true": true,
"false": false,

View File

@ -3,6 +3,7 @@
"utf string" : "\u006corem\u0020ipsum",
"utf-8 string": "あいうえお",
"surrogate string": "lorem\uD834\uDD1Eipsum\uD834\uDF67lorem",
"string with null": "abc\u0000def",
"positive one" : 1,
"negative one" : -1,
"pi" : 3.14,

View File

@ -9,6 +9,7 @@
"utf string" : "\u006corem\u0020ipsum", // lorem ipsum //
"utf-8 string": "あいうえお", // /* lorem ipsum */
"surrogate string": "lorem\uD834\uDD1Eipsum\uD834\uDF67lorem",
"string with null": "abc\u0000def",
"positive one" : 1,
"negative one" : -1,
"pi" : 3.14,

View File

@ -3,6 +3,7 @@
"utf string": "lorem ipsum",
"utf-8 string": "あいうえお",
"surrogate string": "lorem𝄞ipsum𝍧lorem",
"string with null": "abc\u0000def",
"positive one": 1,
"negative one": -1,
"pi": 3.1400000000000001,

View File

@ -11,5 +11,6 @@
"utf string" : "\u006corem\u0020ipsum",
"utf-8 string": "あいうえお",
"surrogate string": "lorem\uD834\uDD1Eipsum\uD834\uDF67lorem",
"string with null": "abc\u0000def",
"windows path": "C:\\Windows\\Path"
}