Refactor error reporting

This commit is contained in:
Petri Lehtinen 2009-05-13 22:25:34 +03:00
parent 6e160c146c
commit fdcf28b667
2 changed files with 42 additions and 36 deletions

View File

@ -80,11 +80,16 @@ double json_number_value(const json_t *json);
/* loading, printing */ /* loading, printing */
const char *json_get_error(void); #define JSON_ERROR_TEXT_LENGTH 160
json_t *json_load(const char *path); typedef struct {
json_t *json_loads(const char *input); char text[JSON_ERROR_TEXT_LENGTH];
json_t *json_loadf(FILE *input); int line;
} json_error_t;
json_t *json_load(const char *path, json_error_t *error);
json_t *json_loads(const char *input, json_error_t *error);
json_t *json_loadf(FILE *input, json_error_t *error);
#define JSON_INDENT(n) (n & 0xFF) #define JSON_INDENT(n) (n & 0xFF)
#define JSON_SORT_KEYS 0x100 #define JSON_SORT_KEYS 0x100

View File

@ -30,23 +30,24 @@ typedef struct {
/*** error reporting ***/ /*** error reporting ***/
static __thread char *json_error_msg = NULL; static void json_set_error(json_error_t *error, const json_lex *lex,
const char *msg)
static void json_set_error(const json_lex *lex, const char *msg)
{ {
free(json_error_msg); if(!error)
return;
if(*lex->start) if(*lex->start)
asprintf(&json_error_msg, "%s near '%.*s' on line %d", msg,
(int)(lex->input - lex->start), lex->start, lex->line);
else
asprintf(&json_error_msg, "%s near end of file", msg);
}
const char *json_get_error(void)
{ {
if(!json_error_msg) int n = (int)(lex->input - lex->start);
json_error_msg = strdup("success"); error->line = lex->line;
return json_error_msg; snprintf(error->text, JSON_ERROR_TEXT_LENGTH,
"%s near '%.*s'", msg, n, lex->start);
}
else
{
snprintf(error->text, JSON_ERROR_TEXT_LENGTH,
"%s near end of file", msg);
}
} }
@ -265,9 +266,9 @@ static void json_lex_close(json_lex *lex)
/*** parser ***/ /*** parser ***/
static json_t *json_parse(json_lex *lex); static json_t *json_parse(json_lex *lex, json_error_t *error);
static json_t *json_parse_object(json_lex *lex) static json_t *json_parse_object(json_lex *lex, json_error_t *error)
{ {
json_t *object = json_object(); json_t *object = json_object();
if(!object) if(!object)
@ -282,7 +283,7 @@ static json_t *json_parse_object(json_lex *lex)
json_t *value; json_t *value;
if(lex->token != JSON_TOKEN_STRING) { if(lex->token != JSON_TOKEN_STRING) {
json_set_error(lex, "string expected"); json_set_error(error, lex, "string expected");
goto error; goto error;
} }
@ -292,13 +293,13 @@ static json_t *json_parse_object(json_lex *lex)
json_lex_scan(lex); json_lex_scan(lex);
if(lex->token != ':') { if(lex->token != ':') {
json_set_error(lex, "':' expected"); json_set_error(error, lex, "':' expected");
goto error; goto error;
} }
json_lex_scan(lex); json_lex_scan(lex);
value = json_parse(lex); value = json_parse(lex, error);
if(!value) if(!value)
goto error; goto error;
@ -317,7 +318,7 @@ static json_t *json_parse_object(json_lex *lex)
} }
if(lex->token != '}') { if(lex->token != '}') {
json_set_error(lex, "'}' expected"); json_set_error(error, lex, "'}' expected");
goto error; goto error;
} }
@ -328,7 +329,7 @@ error:
return NULL; return NULL;
} }
static json_t *json_parse_array(json_lex *lex) static json_t *json_parse_array(json_lex *lex, json_error_t *error)
{ {
json_t *array = json_array(); json_t *array = json_array();
if(!array) if(!array)
@ -337,7 +338,7 @@ static json_t *json_parse_array(json_lex *lex)
json_lex_scan(lex); json_lex_scan(lex);
if(lex->token != ']') { if(lex->token != ']') {
while(1) { while(1) {
json_t *elem = json_parse(lex); json_t *elem = json_parse(lex, error);
if(!elem) if(!elem)
goto error; goto error;
@ -355,7 +356,7 @@ static json_t *json_parse_array(json_lex *lex)
} }
if(lex->token != ']') { if(lex->token != ']') {
json_set_error(lex, "']' expected"); json_set_error(error, lex, "']' expected");
goto error; goto error;
} }
@ -366,7 +367,7 @@ error:
return NULL; return NULL;
} }
static json_t *json_parse(json_lex *lex) static json_t *json_parse(json_lex *lex, json_error_t *error)
{ {
json_t *json; json_t *json;
@ -394,19 +395,19 @@ static json_t *json_parse(json_lex *lex)
break; break;
case '{': case '{':
json = json_parse_object(lex); json = json_parse_object(lex, error);
break; break;
case '[': case '[':
json = json_parse_array(lex); json = json_parse_array(lex, error);
break; break;
case JSON_TOKEN_INVALID: case JSON_TOKEN_INVALID:
json_set_error(lex, "invalid token"); json_set_error(error, lex, "invalid token");
return NULL; return NULL;
default: default:
json_set_error(lex, "unexpected token"); json_set_error(error, lex, "unexpected token");
return NULL; return NULL;
} }
@ -417,7 +418,7 @@ static json_t *json_parse(json_lex *lex)
return json; return json;
} }
json_t *json_loads(const char *string) json_t *json_loads(const char *string, json_error_t *error)
{ {
json_lex lex; json_lex lex;
json_t *result = NULL; json_t *result = NULL;
@ -426,16 +427,16 @@ json_t *json_loads(const char *string)
return NULL; return NULL;
if(lex.token != '[' && lex.token != '{') { if(lex.token != '[' && lex.token != '{') {
json_set_error(&lex, "'[' or '{' expected"); json_set_error(error, &lex, "'[' or '{' expected");
goto out; goto out;
} }
result = json_parse(&lex); result = json_parse(&lex, error);
if(!result) if(!result)
goto out; goto out;
if(lex.token != JSON_TOKEN_EOF) { if(lex.token != JSON_TOKEN_EOF) {
json_set_error(&lex, "end of file expected"); json_set_error(error, &lex, "end of file expected");
json_decref(result); json_decref(result);
result = NULL; result = NULL;
} }