mirror of
https://github.com/kgabis/parson.git
synced 2025-05-09 19:32:07 +00:00
Not parsing hex and octal values, refractoring, code cleanup, new tests.
Also changed parson_strndup and parson_strdup to be static.
This commit is contained in:
parent
a3bb4c7390
commit
2684eeb360
@ -72,8 +72,5 @@ Date SHA Author
|
|||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
##Important
|
|
||||||
Parson currently supports hexadecimal and octal numbers, but they're not a part of JSON standard, so you shouldn't use them.
|
|
||||||
|
|
||||||
##License
|
##License
|
||||||
[The MIT License (MIT)](http://opensource.org/licenses/mit-license.php)
|
[The MIT License (MIT)](http://opensource.org/licenses/mit-license.php)
|
75
parson.c
75
parson.c
@ -81,20 +81,21 @@ static JSON_Value * json_value_init_boolean(int boolean);
|
|||||||
static JSON_Value * json_value_init_null(void);
|
static JSON_Value * json_value_init_null(void);
|
||||||
|
|
||||||
/* Parser */
|
/* Parser */
|
||||||
char * parson_strndup(const char *string, size_t n);
|
static char * parson_strndup(const char *string, size_t n);
|
||||||
char * parson_strdup(const char *string);
|
static char * parson_strdup(const char *string);
|
||||||
static const char * skip_string(const char *string);
|
static const char * skip_string(const char *string);
|
||||||
static char * copy_and_remove_whitespaces(const char *string);
|
static char * copy_and_remove_whitespaces(const char *string);
|
||||||
static int is_utf_string(const char *string);
|
static int is_utf(const char *string);
|
||||||
|
static int is_decimal(const char *string, size_t length);
|
||||||
static const char * parse_escaped_characters(const char *string);
|
static const char * parse_escaped_characters(const char *string);
|
||||||
static const char * get_string(const char **string);
|
static const char * get_string(const char **string);
|
||||||
static JSON_Value * parse_object_value(const char **string, size_t depth);
|
static JSON_Value * parse_object_value(const char **string, size_t nesting);
|
||||||
static JSON_Value * parse_array_value(const char **string, size_t depth);
|
static JSON_Value * parse_array_value(const char **string, size_t nesting);
|
||||||
static JSON_Value * parse_string_value(const char **string);
|
static JSON_Value * parse_string_value(const char **string);
|
||||||
static JSON_Value * parse_boolean_value(const char **string);
|
static JSON_Value * parse_boolean_value(const char **string);
|
||||||
static JSON_Value * parse_number_value(const char **string);
|
static JSON_Value * parse_number_value(const char **string);
|
||||||
static JSON_Value * parse_null_value(const char **string);
|
static JSON_Value * parse_null_value(const char **string);
|
||||||
static JSON_Value * parse_value(const char **string, size_t depth);
|
static JSON_Value * parse_value(const char **string, size_t nesting);
|
||||||
|
|
||||||
/* JSON Object */
|
/* JSON Object */
|
||||||
static JSON_Object * json_object_init(void) {
|
static JSON_Object * json_object_init(void) {
|
||||||
@ -168,9 +169,7 @@ static int json_array_add(JSON_Array *array, JSON_Value *value) {
|
|||||||
|
|
||||||
static void json_array_free(JSON_Array *array) {
|
static void json_array_free(JSON_Array *array) {
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < array->count; i++) {
|
for (i = 0; i < array->count; i++) { json_value_free(array->items[i]); }
|
||||||
json_value_free(array->items[i]);
|
|
||||||
}
|
|
||||||
parson_free(array->items);
|
parson_free(array->items);
|
||||||
parson_free(array);
|
parson_free(array);
|
||||||
}
|
}
|
||||||
@ -226,7 +225,7 @@ static JSON_Value * json_value_init_null(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parser */
|
/* Parser */
|
||||||
char * parson_strndup(const char *string, size_t n) {
|
static char * parson_strndup(const char *string, size_t n) {
|
||||||
char *output_string = (char*)parson_malloc(n + 1);
|
char *output_string = (char*)parson_malloc(n + 1);
|
||||||
if (!output_string) { return NULL; }
|
if (!output_string) { return NULL; }
|
||||||
output_string[n] = '\0';
|
output_string[n] = '\0';
|
||||||
@ -234,7 +233,7 @@ char * parson_strndup(const char *string, size_t n) {
|
|||||||
return output_string;
|
return output_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
char * parson_strdup(const char *string) {
|
static char * parson_strdup(const char *string) {
|
||||||
return parson_strndup(string, strlen(string));
|
return parson_strndup(string, strlen(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,10 +279,18 @@ static char * copy_and_remove_whitespaces(const char *string) {
|
|||||||
return output_string;
|
return output_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_utf_string(const char *string) {
|
static int is_utf(const char *string) {
|
||||||
int i;
|
if (!isxdigit(string[0])) { return 0; }
|
||||||
if (strlen(string) < 4) { return 0; }
|
if (!isxdigit(string[1])) { return 0; }
|
||||||
for (i = 0; i < 4; i++) { if (!isxdigit(string[i])) { return 0; } }
|
if (!isxdigit(string[2])) { return 0; }
|
||||||
|
if (!isxdigit(string[3])) { return 0; }
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_decimal(const char *string, size_t length) {
|
||||||
|
if (strchr(string, 'x') || strchr(string, 'X')) { return 0; }
|
||||||
|
if (length > 1 && string[0] == '0' && string[1] != '.') { return 0; }
|
||||||
|
if (length > 2 && !strncmp(string, "-0", 2) && string[2] != '.') { return 0; }
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,7 +315,7 @@ static const char * parse_escaped_characters(const char *string) {
|
|||||||
case 't': current_char = '\t'; break;
|
case 't': current_char = '\t'; break;
|
||||||
case 'u':
|
case 'u':
|
||||||
string_ptr++;
|
string_ptr++;
|
||||||
if (!is_utf_string(string_ptr) ||
|
if (!is_utf(string_ptr) ||
|
||||||
sscanf(string_ptr, "%4x", &utf_val) == EOF) {
|
sscanf(string_ptr, "%4x", &utf_val) == EOF) {
|
||||||
parson_free(output_string); return NULL;
|
parson_free(output_string); return NULL;
|
||||||
}
|
}
|
||||||
@ -357,21 +364,20 @@ static const char * get_string(const char **string) {
|
|||||||
return (const char*)parsed_string;
|
return (const char*)parsed_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSON_Value * parse_value(const char **string, size_t depth) {
|
static JSON_Value * parse_value(const char **string, size_t nesting) {
|
||||||
JSON_Value *output_value = NULL;
|
JSON_Value *output_value = NULL;
|
||||||
if (*string == NULL || depth > MAX_NESTING) { return NULL; }
|
if (*string == NULL || nesting > MAX_NESTING) { return NULL; }
|
||||||
switch ((*string)[0]) {
|
switch ((*string)[0]) {
|
||||||
case '{':
|
case '{':
|
||||||
output_value = parse_object_value(string, depth + 1);
|
output_value = parse_object_value(string, nesting + 1);
|
||||||
break;
|
break;
|
||||||
case '[':
|
case '[':
|
||||||
output_value = parse_array_value(string, depth + 1);
|
output_value = parse_array_value(string, nesting + 1);
|
||||||
break;
|
break;
|
||||||
case '\"':
|
case '\"':
|
||||||
output_value = parse_string_value(string);
|
output_value = parse_string_value(string);
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f': case 't':
|
||||||
case 't':
|
|
||||||
output_value = parse_boolean_value(string);
|
output_value = parse_boolean_value(string);
|
||||||
break;
|
break;
|
||||||
case '-':
|
case '-':
|
||||||
@ -388,7 +394,7 @@ static JSON_Value * parse_value(const char **string, size_t depth) {
|
|||||||
return output_value;
|
return output_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSON_Value * parse_object_value(const char **string, size_t depth) {
|
static JSON_Value * parse_object_value(const char **string, size_t nesting) {
|
||||||
JSON_Value *output_value = json_value_init_object();
|
JSON_Value *output_value = json_value_init_object();
|
||||||
const char *new_key = NULL;
|
const char *new_key = NULL;
|
||||||
JSON_Value *new_value = NULL;
|
JSON_Value *new_value = NULL;
|
||||||
@ -402,7 +408,7 @@ static JSON_Value * parse_object_value(const char **string, size_t depth) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
(*string)++;
|
(*string)++;
|
||||||
new_value = parse_value(string, depth);
|
new_value = parse_value(string, nesting);
|
||||||
if (!new_value) {
|
if (!new_value) {
|
||||||
parson_free((void*)new_key);
|
parson_free((void*)new_key);
|
||||||
json_value_free(output_value);
|
json_value_free(output_value);
|
||||||
@ -423,7 +429,7 @@ static JSON_Value * parse_object_value(const char **string, size_t depth) {
|
|||||||
return output_value;
|
return output_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSON_Value * parse_array_value(const char **string, size_t depth) {
|
static JSON_Value * parse_array_value(const char **string, size_t nesting) {
|
||||||
JSON_Value *output_value = json_value_init_array();
|
JSON_Value *output_value = json_value_init_array();
|
||||||
JSON_Value *new_array_value = NULL;
|
JSON_Value *new_array_value = NULL;
|
||||||
if (!output_value) { return NULL; }
|
if (!output_value) { return NULL; }
|
||||||
@ -433,7 +439,7 @@ static JSON_Value * parse_array_value(const char **string, size_t depth) {
|
|||||||
return output_value;
|
return output_value;
|
||||||
}
|
}
|
||||||
while (**string != '\0') {
|
while (**string != '\0') {
|
||||||
new_array_value = parse_value(string, depth);
|
new_array_value = parse_value(string, nesting);
|
||||||
if (!new_array_value) {
|
if (!new_array_value) {
|
||||||
json_value_free(output_value);
|
json_value_free(output_value);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -474,7 +480,19 @@ static JSON_Value * parse_boolean_value(const char **string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static JSON_Value * parse_number_value(const char **string) {
|
static JSON_Value * parse_number_value(const char **string) {
|
||||||
return json_value_init_number(strtod(*string, (char**)string));
|
const char *number_string;
|
||||||
|
char *end;
|
||||||
|
double number = strtod(*string, &end);
|
||||||
|
JSON_Value *output_value;
|
||||||
|
number_string = parson_strndup(*string, end - *string);
|
||||||
|
if (is_decimal(number_string, end - *string)) {
|
||||||
|
*string = end;
|
||||||
|
output_value = json_value_init_number(number);
|
||||||
|
} else {
|
||||||
|
output_value = NULL;
|
||||||
|
}
|
||||||
|
free((void*)number_string);
|
||||||
|
return output_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSON_Value * parse_null_value(const char **string) {
|
static JSON_Value * parse_null_value(const char **string) {
|
||||||
@ -606,7 +624,7 @@ int json_array_get_boolean(const JSON_Array *array, size_t index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t json_array_get_count(const JSON_Array *array) {
|
size_t json_array_get_count(const JSON_Array *array) {
|
||||||
return array != NULL ? array->count : 0;
|
return array ? array->count : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* JSON Value API */
|
/* JSON Value API */
|
||||||
@ -620,7 +638,6 @@ JSON_Object * json_value_get_object(const JSON_Value *value) {
|
|||||||
|
|
||||||
JSON_Array * json_value_get_array(const JSON_Value *value) {
|
JSON_Array * json_value_get_array(const JSON_Value *value) {
|
||||||
return json_value_get_type(value) == JSONArray ? value->value.array : NULL;
|
return json_value_get_type(value) == JSONArray ? value->value.array : NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * json_value_get_string(const JSON_Value *value) {
|
const char * json_value_get_string(const JSON_Value *value) {
|
||||||
|
10
tests.c
10
tests.c
@ -144,6 +144,8 @@ void test_suite_3(void) {
|
|||||||
TEST(json_parse_string("{:\"no name\"}") == NULL);
|
TEST(json_parse_string("{:\"no name\"}") == NULL);
|
||||||
TEST(json_parse_string("[,\"no first value\"]") == NULL);
|
TEST(json_parse_string("[,\"no first value\"]") == NULL);
|
||||||
TEST(json_parse_string("[\"\\u00zz\"]") == NULL); /* invalid utf value */
|
TEST(json_parse_string("[\"\\u00zz\"]") == NULL); /* invalid utf value */
|
||||||
|
TEST(json_parse_string("[\"\\u00\"]") == NULL); /* invalid utf value */
|
||||||
|
TEST(json_parse_string("[\"\\u\"]") == NULL); /* invalid utf value */
|
||||||
TEST(json_parse_string("[\"\\\"]") == NULL); /* control character */
|
TEST(json_parse_string("[\"\\\"]") == NULL); /* control character */
|
||||||
TEST(json_parse_string("[\"\"\"]") == NULL); /* control character */
|
TEST(json_parse_string("[\"\"\"]") == NULL); /* control character */
|
||||||
TEST(json_parse_string("[\"\0\"]") == NULL); /* control character */
|
TEST(json_parse_string("[\"\0\"]") == NULL); /* control character */
|
||||||
@ -154,6 +156,14 @@ void test_suite_3(void) {
|
|||||||
TEST(json_parse_string("[\"\f\"]") == NULL); /* control character */
|
TEST(json_parse_string("[\"\f\"]") == NULL); /* control character */
|
||||||
TEST(json_parse_string("[\"\r\"]") == NULL); /* control character */
|
TEST(json_parse_string("[\"\r\"]") == NULL); /* control character */
|
||||||
TEST(json_parse_string(nested_20x) == NULL); /* too deep */
|
TEST(json_parse_string(nested_20x) == NULL); /* too deep */
|
||||||
|
TEST(json_parse_string("[0x2]") == NULL); /* hex */
|
||||||
|
TEST(json_parse_string("[0X2]") == NULL); /* HEX */
|
||||||
|
TEST(json_parse_string("[07]") == NULL); /* octals */
|
||||||
|
TEST(json_parse_string("[0070]") == NULL);
|
||||||
|
TEST(json_parse_string("[07.0]") == NULL);
|
||||||
|
TEST(json_parse_string("[-07]") == NULL);
|
||||||
|
TEST(json_parse_string("[-007]") == NULL);
|
||||||
|
TEST(json_parse_string("[-07.0]") == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_commits_info(const char *username, const char *repo) {
|
void print_commits_info(const char *username, const char *repo) {
|
||||||
|
Loading…
Reference in New Issue
Block a user