Exception handling

This commit is contained in:
Ekaitz Zarraga 2020-05-22 00:22:50 +02:00
parent bb1fdbb719
commit 0e01716827

View file

@ -11,7 +11,7 @@ static int digit_value (int c) {
sexp parse_json (sexp ctx, sexp self, sexp str, const char* s, int* i, const int len); sexp parse_json (sexp ctx, sexp self, sexp str, const char* s, int* i, const int len);
sexp sexp_json_exception (sexp ctx, sexp self, const char* msg, sexp str, const int pos) { sexp sexp_json_parse_exception (sexp ctx, sexp self, const char* msg, sexp str, const int pos) {
sexp_gc_var2(res, tmp); sexp_gc_var2(res, tmp);
sexp_gc_preserve2(ctx, res, tmp); sexp_gc_preserve2(ctx, res, tmp);
tmp = sexp_list2(ctx, str, sexp_make_fixnum(pos)); tmp = sexp_list2(ctx, str, sexp_make_fixnum(pos));
@ -20,6 +20,15 @@ sexp sexp_json_exception (sexp ctx, sexp self, const char* msg, sexp str, const
return res; return res;
} }
sexp sexp_json_unparse_exception (sexp ctx, sexp self, const char* msg, sexp obj) {
sexp_gc_var2(res, tmp);
sexp_gc_preserve2(ctx, res, tmp);
tmp = sexp_list1(ctx, obj);
res = sexp_user_exception(ctx, self, msg, tmp);
sexp_gc_release2(ctx);
return res;
}
sexp parse_json_number (sexp ctx, sexp self, sexp str, const char* s, int* i, const int len) { sexp parse_json_number (sexp ctx, sexp self, sexp str, const char* s, int* i, const int len) {
double res = 0, scale = 1; double res = 0, scale = 1;
int j = *i, sign = 1, inexactp = 0, scale_sign = 1; int j = *i, sign = 1, inexactp = 0, scale_sign = 1;
@ -62,7 +71,7 @@ sexp parse_json_literal (sexp ctx, sexp self, sexp str, const char* s, int* i, c
res = value; res = value;
*i += namelen; *i += namelen;
} else { } else {
res = sexp_json_exception(ctx, self, "unexpected character in json at", str, *i); res = sexp_json_parse_exception(ctx, self, "unexpected character in json at", str, *i);
} }
return res; return res;
} }
@ -87,7 +96,7 @@ sexp parse_json_string (sexp ctx, sexp self, sexp str, const char* s, int* i, co
res = SEXP_NULL; res = SEXP_NULL;
for ( ; s[to] != '"' && !sexp_exceptionp(res); ++to) { for ( ; s[to] != '"' && !sexp_exceptionp(res); ++to) {
if (to+1 >= len) { if (to+1 >= len) {
res = sexp_json_exception(ctx, self, "unterminated string in json started at", str, *i); res = sexp_json_parse_exception(ctx, self, "unterminated string in json started at", str, *i);
break; break;
} }
if (s[to] == '\\') { if (s[to] == '\\') {
@ -117,7 +126,7 @@ sexp parse_json_string (sexp ctx, sexp self, sexp str, const char* s, int* i, co
} }
} }
if (utfchar < 0) { if (utfchar < 0) {
res = sexp_json_exception(ctx, self, "invalid \\u sequence at", str, to - USEQ_LEN); res = sexp_json_parse_exception(ctx, self, "invalid \\u sequence at", str, to - USEQ_LEN);
} else { } else {
tmp = sexp_make_string(ctx, sexp_make_fixnum(1), sexp_make_character(utfchar)); tmp = sexp_make_string(ctx, sexp_make_fixnum(1), sexp_make_character(utfchar));
res = sexp_cons(ctx, tmp, res); res = sexp_cons(ctx, tmp, res);
@ -153,11 +162,11 @@ sexp parse_json_array (sexp ctx, sexp self, sexp str, const char* s, int* i, con
res = SEXP_NULL; res = SEXP_NULL;
while (1) { while (1) {
if (j >= len) { if (j >= len) {
res = sexp_json_exception(ctx, self, "unterminated array in json started at", str, *i); res = sexp_json_parse_exception(ctx, self, "unterminated array in json started at", str, *i);
break; break;
} else if (s[j] == ']') { } else if (s[j] == ']') {
if (comma && res != SEXP_NULL) { if (comma && res != SEXP_NULL) {
res = sexp_json_exception(ctx, self, "missing value after comma in json array at", str, j); res = sexp_json_parse_exception(ctx, self, "missing value after comma in json array at", str, j);
} else { } else {
res = sexp_nreverse(ctx, res); res = sexp_nreverse(ctx, res);
res = sexp_list_to_vector(ctx, res); res = sexp_list_to_vector(ctx, res);
@ -165,7 +174,7 @@ sexp parse_json_array (sexp ctx, sexp self, sexp str, const char* s, int* i, con
++j; ++j;
break; break;
} else if (s[j] == ',' && comma) { } else if (s[j] == ',' && comma) {
res = sexp_json_exception(ctx, self, "unexpected comma in json array at", str, j); res = sexp_json_parse_exception(ctx, self, "unexpected comma in json array at", str, j);
break; break;
} else if (s[j] == ',') { } else if (s[j] == ',') {
comma = 1; comma = 1;
@ -182,7 +191,7 @@ sexp parse_json_array (sexp ctx, sexp self, sexp str, const char* s, int* i, con
res = sexp_cons(ctx, tmp, res); res = sexp_cons(ctx, tmp, res);
comma = 0; comma = 0;
} else { } else {
res = sexp_json_exception(ctx, self, "unexpected value in json array at", str, j); res = sexp_json_parse_exception(ctx, self, "unexpected value in json array at", str, j);
break; break;
} }
} }
@ -200,18 +209,18 @@ sexp parse_json_object (sexp ctx, sexp self, sexp str, const char* s, int* i, co
res = SEXP_NULL; res = SEXP_NULL;
while (1) { while (1) {
if (j >= len) { if (j >= len) {
res = sexp_json_exception(ctx, self, "unterminated object in json started at", str, *i); res = sexp_json_parse_exception(ctx, self, "unterminated object in json started at", str, *i);
break; break;
} else if (s[j] == '}') { } else if (s[j] == '}') {
if (comma && res != SEXP_NULL) { if (comma && res != SEXP_NULL) {
res = sexp_json_exception(ctx, self, "missing value after comma in json object at", str, j); res = sexp_json_parse_exception(ctx, self, "missing value after comma in json object at", str, j);
} else { } else {
res = sexp_nreverse(ctx, res); res = sexp_nreverse(ctx, res);
} }
++j; ++j;
break; break;
} else if (s[j] == ',' && comma) { } else if (s[j] == ',' && comma) {
res = sexp_json_exception(ctx, self, "unexpected comma in json object at", str, j); res = sexp_json_parse_exception(ctx, self, "unexpected comma in json object at", str, j);
break; break;
} else if (s[j] == ',') { } else if (s[j] == ',') {
comma = 1; comma = 1;
@ -231,7 +240,7 @@ sexp parse_json_object (sexp ctx, sexp self, sexp str, const char* s, int* i, co
while (j < len && isspace(s[j])) while (j < len && isspace(s[j]))
++j; ++j;
if (s[j] != ':') { if (s[j] != ':') {
res = sexp_json_exception(ctx, self, "missing colon in json object at", str, j); res = sexp_json_parse_exception(ctx, self, "missing colon in json object at", str, j);
break; break;
} }
++j; ++j;
@ -243,7 +252,7 @@ sexp parse_json_object (sexp ctx, sexp self, sexp str, const char* s, int* i, co
res = sexp_cons(ctx, tmp, res); res = sexp_cons(ctx, tmp, res);
comma = 0; comma = 0;
} else { } else {
res = sexp_json_exception(ctx, self, "unexpected value in json object at", str, j); res = sexp_json_parse_exception(ctx, self, "unexpected value in json object at", str, j);
break; break;
} }
} }
@ -286,13 +295,13 @@ sexp parse_json (sexp ctx, sexp self, sexp str, const char* s, int* i, const int
res = parse_json_literal(ctx, self, str, s, &j, len, "false", 5, SEXP_FALSE); res = parse_json_literal(ctx, self, str, s, &j, len, "false", 5, SEXP_FALSE);
break; break;
case '}': case '}':
res = sexp_json_exception(ctx, self, "unexpected closing brace in json at", str, j); res = sexp_json_parse_exception(ctx, self, "unexpected closing brace in json at", str, j);
break; break;
case ']': case ']':
res = sexp_json_exception(ctx, self, "unexpected closing bracket in json at", str, j); res = sexp_json_parse_exception(ctx, self, "unexpected closing bracket in json at", str, j);
break; break;
default: default:
res = sexp_json_exception(ctx, self, "unexpected character in json at", str, j); res = sexp_json_parse_exception(ctx, self, "unexpected character in json at", str, j);
break; break;
} }
*i = j; *i = j;
@ -375,8 +384,8 @@ sexp unparse_json_string(sexp ctx, sexp self, const sexp obj){
chh = (0xD800 - (0x10000 >> 10) + ((ch) >> 10)); chh = (0xD800 - (0x10000 >> 10) + ((ch) >> 10));
chl = (0xDC00 + ((ch) & 0x3FF)); chl = (0xDC00 + ((ch) & 0x3FF));
if (chh > 0xFFFF || chl > 0xFFFF){ if (chh > 0xFFFF || chl > 0xFFFF){
// TODO: Create custom unparse exception res = sexp_json_unparse_exception(ctx, self, "unable to encode string", obj);
res = sexp_json_exception(ctx, self, "unable to encode character at", obj, i); sexp_gc_release2(ctx);
return res; return res;
} }
sprintf(cout, "\\u%04lX\\u%04lX", chh, chl); sprintf(cout, "\\u%04lX\\u%04lX", chh, chl);
@ -407,7 +416,8 @@ sexp unparse_json_array(sexp ctx, sexp self, const sexp obj){
for (int i=0; i!=len; i++){ for (int i=0; i!=len; i++){
tmp = unparse_json(ctx, self, sexp_vector_ref(obj, sexp_make_fixnum(i))); tmp = unparse_json(ctx, self, sexp_vector_ref(obj, sexp_make_fixnum(i)));
if (sexp_exceptionp(tmp)){ if (sexp_exceptionp(tmp)){
goto except; sexp_gc_release2(ctx);
return tmp;
} }
res = sexp_cons(ctx, tmp, res); res = sexp_cons(ctx, tmp, res);
@ -423,7 +433,6 @@ sexp unparse_json_array(sexp ctx, sexp self, const sexp obj){
res = sexp_nreverse(ctx, res); res = sexp_nreverse(ctx, res);
res = sexp_string_concatenate(ctx, res, SEXP_FALSE); res = sexp_string_concatenate(ctx, res, SEXP_FALSE);
except:
sexp_gc_release2(ctx); sexp_gc_release2(ctx);
return res; return res;
} }
@ -442,24 +451,19 @@ sexp unparse_json_object(sexp ctx, sexp self, const sexp obj){
for (int i=0; i!=len; i++){ for (int i=0; i!=len; i++){
cur = sexp_car(it); cur = sexp_car(it);
if (!sexp_pairp(cur)){ if (!sexp_pairp(cur)){
/* res = sexp_json_unparse_exception(ctx, self, "unable to encode key-value pair: not a pair", obj);
* TODO: Raise exception, must be a pair (key . val)
res = exception!
*/
goto except; goto except;
} }
// Key // Key
key = sexp_car(cur); key = sexp_car(cur);
if (!(sexp_symbolp(key) /*|| sexp_stringp(key)*/)){ if (!(sexp_symbolp(key) /*|| sexp_stringp(key)*/)){
/* res = sexp_json_unparse_exception(ctx, self, "unable to encode key: not a symbol", key);
* TODO: Raise exception, key must be symbol (or string?)
res = exception!
*/
goto except; goto except;
} }
tmp = unparse_json(ctx, self, key); tmp = unparse_json(ctx, self, key);
if (sexp_exceptionp(tmp)){ if (sexp_exceptionp(tmp)){
res = tmp;
goto except; goto except;
} }
res = sexp_cons(ctx, tmp, res); res = sexp_cons(ctx, tmp, res);
@ -519,7 +523,7 @@ sexp unparse_json (sexp ctx, sexp self, sexp obj){
} else if (obj == SEXP_NULL){ } else if (obj == SEXP_NULL){
res = sexp_c_string(ctx, "null", -1); res = sexp_c_string(ctx, "null", -1);
} else { } else {
//res = sexp_json_exception(ctx, self, "unable to decode", obj, i); res = sexp_json_unparse_exception(ctx, self, "unable to encode element", obj);
} }
sexp_gc_release1(ctx); sexp_gc_release1(ctx);
return res; return res;