From 2684eeb3601b3f0fa2ee22d6c1875ba61bb2f05a Mon Sep 17 00:00:00 2001 From: Krzysztof Gabis Date: Wed, 24 Oct 2012 10:41:05 +0200 Subject: [PATCH] Not parsing hex and octal values, refractoring, code cleanup, new tests. Also changed parson_strndup and parson_strdup to be static. --- README.md | 3 --- parson.c | 75 ++++++++++++++++++++++++++++++++++--------------------- tests.c | 10 ++++++++ 3 files changed, 56 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index ee2ff05..6b9fb8c 100644 --- a/README.md +++ b/README.md @@ -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 [The MIT License (MIT)](http://opensource.org/licenses/mit-license.php) \ No newline at end of file diff --git a/parson.c b/parson.c index b921b26..db77d22 100644 --- a/parson.c +++ b/parson.c @@ -81,20 +81,21 @@ static JSON_Value * json_value_init_boolean(int boolean); static JSON_Value * json_value_init_null(void); /* Parser */ -char * parson_strndup(const char *string, size_t n); -char * parson_strdup(const char *string); +static char * parson_strndup(const char *string, size_t n); +static char * parson_strdup(const char *string); static const char * skip_string(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 * get_string(const char **string); -static JSON_Value * parse_object_value(const char **string, size_t depth); -static JSON_Value * parse_array_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 nesting); static JSON_Value * parse_string_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_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 */ 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) { size_t i; - for (i = 0; i < array->count; i++) { - json_value_free(array->items[i]); - } + for (i = 0; i < array->count; i++) { json_value_free(array->items[i]); } parson_free(array->items); parson_free(array); } @@ -226,7 +225,7 @@ static JSON_Value * json_value_init_null(void) { } /* 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); if (!output_string) { return NULL; } output_string[n] = '\0'; @@ -234,7 +233,7 @@ char * parson_strndup(const char *string, size_t n) { return output_string; } -char * parson_strdup(const char *string) { +static char * parson_strdup(const char *string) { return parson_strndup(string, strlen(string)); } @@ -280,10 +279,18 @@ static char * copy_and_remove_whitespaces(const char *string) { return output_string; } -static int is_utf_string(const char *string) { - int i; - if (strlen(string) < 4) { return 0; } - for (i = 0; i < 4; i++) { if (!isxdigit(string[i])) { return 0; } } +static int is_utf(const char *string) { + if (!isxdigit(string[0])) { return 0; } + if (!isxdigit(string[1])) { 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; } @@ -308,7 +315,7 @@ static const char * parse_escaped_characters(const char *string) { case 't': current_char = '\t'; break; case 'u': string_ptr++; - if (!is_utf_string(string_ptr) || + if (!is_utf(string_ptr) || sscanf(string_ptr, "%4x", &utf_val) == EOF) { parson_free(output_string); return NULL; } @@ -357,21 +364,20 @@ static const char * get_string(const char **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; - if (*string == NULL || depth > MAX_NESTING) { return NULL; } + if (*string == NULL || nesting > MAX_NESTING) { return NULL; } switch ((*string)[0]) { case '{': - output_value = parse_object_value(string, depth + 1); + output_value = parse_object_value(string, nesting + 1); break; case '[': - output_value = parse_array_value(string, depth + 1); + output_value = parse_array_value(string, nesting + 1); break; case '\"': output_value = parse_string_value(string); break; - case 'f': - case 't': + case 'f': case 't': output_value = parse_boolean_value(string); break; case '-': @@ -388,7 +394,7 @@ static JSON_Value * parse_value(const char **string, size_t depth) { 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(); const char *new_key = NULL; JSON_Value *new_value = NULL; @@ -402,7 +408,7 @@ static JSON_Value * parse_object_value(const char **string, size_t depth) { return NULL; } (*string)++; - new_value = parse_value(string, depth); + new_value = parse_value(string, nesting); if (!new_value) { parson_free((void*)new_key); json_value_free(output_value); @@ -423,7 +429,7 @@ static JSON_Value * parse_object_value(const char **string, size_t depth) { 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 *new_array_value = 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; } while (**string != '\0') { - new_array_value = parse_value(string, depth); + new_array_value = parse_value(string, nesting); if (!new_array_value) { json_value_free(output_value); return NULL; @@ -474,7 +480,19 @@ static JSON_Value * parse_boolean_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) { @@ -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) { - return array != NULL ? array->count : 0; + return array ? array->count : 0; } /* 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) { return json_value_get_type(value) == JSONArray ? value->value.array : NULL; - } const char * json_value_get_string(const JSON_Value *value) { diff --git a/tests.c b/tests.c index 449884a..4625a3c 100644 --- a/tests.c +++ b/tests.c @@ -144,6 +144,8 @@ void test_suite_3(void) { TEST(json_parse_string("{:\"no name\"}") == NULL); TEST(json_parse_string("[,\"no first value\"]") == NULL); 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("[\"\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("[\"\r\"]") == NULL); /* control character */ 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) {