json-tutorial
json-tutorial copied to clipboard
lept_parse_number无法处理一些异常情况
lept_parse_number无法处理诸如12a.2这类错误,是否应该用状态机实现?
static int lept_parse_number(lept_context* c, lept_value* v) {
const char* p = c->json;
if (*p == '-')
p++;
if (*p == '0')
p++;
else {
if (!ISDIGIT1TO9(*p))
return LEPT_PARSE_INVALID_VALUE;
for (p++; ISDIGIT(*p); p++);
if(*p != '\0' && *p != '.' && *p != 'e' && *p != 'E')
return LEPT_PARSE_INVALID_VALUE;
}
if (*p == '.') {
p++;
if (!ISDIGIT(*p))
return LEPT_PARSE_INVALID_VALUE;
for (p++; ISDIGIT(*p); p++);
if(*p != '\0' && *p != 'e' && *p != 'E')
return LEPT_PARSE_INVALID_VALUE;
}
if (*p == 'e' || *p == 'E') {
p++;
if (*p == '+' || *p == '-')
p++;
if (!ISDIGIT(*p))
return LEPT_PARSE_INVALID_VALUE;
for (p++; ISDIGIT(*p); p++);
if(*p != '\0')
return LEPT_PARSE_INVALID_VALUE;
}
errno = 0;
v->n = strtod(c->json, NULL);
if (errno == ERANGE && (v->n == HUGE_VAL || v->n == -HUGE_VAL))
return LEPT_PARSE_NUMBER_TOO_BIG;
v->type = LEPT_NUMBER;
c->json = p;
return LEPT_PARSE_OK;
}
这样可以处理
TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "112a.0");
TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "112.0a");
TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "112.012e12a");
此问题与 #21 相同, 因为解析数字的时候一般设计成尽可能多的转换合法字符(例如标准库中的strtod()), 而不是遇到一个不合法字符就抛出错误. 所以 112a.0 的解析结果是 112, 同时也会返回 LEPT_PARSE_ROOT_NOT_SINGULAR 错误.
这样做的话,还要考虑之后的字符可能是 ,、]、}, ws 等。
建议只需要按照 number 的规则,只解析所有合法的字符。