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:
Krzysztof Gabis 2012-10-24 10:41:05 +02:00
parent a3bb4c7390
commit 2684eeb360
3 changed files with 56 additions and 32 deletions

View File

@ -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)

View File

@ -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
View File

@ -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) {