static int lex_scan_number(lex_t *lex, int c, json_error_t *error) { const char *saved_text; char *end; double value; lex->token = TOKEN_INVALID; if(c == '-') c = lex_get_save(lex, error); if(c == '0') { c = lex_get_save(lex, error); if(l_isdigit(c)) { lex_unget_unsave(lex, c); goto out; } } else if(l_isdigit(c)) { c = lex_get_save(lex, error); while(l_isdigit(c)) c = lex_get_save(lex, error); } else { lex_unget_unsave(lex, c); goto out; } if(c != '.' && c != 'E' && c != 'e') { json_int_t value; lex_unget_unsave(lex, c); saved_text = strbuffer_value(&lex->saved_text); errno = 0; value = json_strtoint(saved_text, &end, 10); if(errno == ERANGE) { if(value < 0) error_set(error, lex, "too big negative integer"); else error_set(error, lex, "too big integer"); goto out; } assert(end == saved_text + lex->saved_text.length); lex->token = TOKEN_INTEGER; lex->value.integer = value; return 0; } if(c == '.') { c = lex_get(lex, error); if(!l_isdigit(c)) { lex_unget(lex, c); goto out; } lex_save(lex, c); c = lex_get_save(lex, error); while(l_isdigit(c)) c = lex_get_save(lex, error); } if(c == 'E' || c == 'e') { c = lex_get_save(lex, error); if(c == '+' || c == '-') c = lex_get_save(lex, error); if(!l_isdigit(c)) { lex_unget_unsave(lex, c); goto out; } c = lex_get_save(lex, error); while(l_isdigit(c)) c = lex_get_save(lex, error); } lex_unget_unsave(lex, c); if(jsonp_strtod(&lex->saved_text, &value)) { error_set(error, lex, "real number overflow"); goto out; } lex->token = TOKEN_REAL; lex->value.real = value; return 0; out: return -1; }
static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error) { json_t *json; double value; switch(lex->token) { case TOKEN_STRING: { json = json_string_nocheck(lex->value.string); break; } case TOKEN_INTEGER: { if (flags & JSON_DECODE_INT_AS_REAL) { if(jsonp_strtod(&lex->saved_text, &value)) { error_set(error, lex, "real number overflow"); return NULL; } json = json_real(value); } else { json = json_integer(lex->value.integer); } break; } case TOKEN_REAL: { json = json_real(lex->value.real); break; } case TOKEN_TRUE: json = json_true(); break; case TOKEN_FALSE: json = json_false(); break; case TOKEN_NULL: json = json_null(); break; case '{': json = parse_object(lex, flags, error); break; case '[': json = parse_array(lex, flags, error); break; case TOKEN_INVALID: error_set(error, lex, "invalid token"); return NULL; default: error_set(error, lex, "unexpected token"); return NULL; } if(!json) return NULL; return json; }
static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error) { json_t *json; double value; switch(lex->token) { case TOKEN_STRING: { const char *value = lex->value.string.val; size_t len = lex->value.string.len; if(!(flags & JSON_ALLOW_NUL)) { if(memchr(value, '\0', len)) { error_set(error, lex, "\\u0000 is not allowed without JSON_ALLOW_NUL"); return NULL; } } json = jsonp_stringn_nocheck_own(value, len); if(json) { lex->value.string.val = NULL; lex->value.string.len = 0; } break; } case TOKEN_INTEGER: { if (flags & JSON_DECODE_INT_AS_REAL) { if(jsonp_strtod(&lex->saved_text, &value)) { error_set(error, lex, "real number overflow"); return NULL; } json = json_real(value); } else { json = json_integer(lex->value.integer); } break; } case TOKEN_REAL: { json = json_real(lex->value.real); break; } case TOKEN_TRUE: json = json_true(); break; case TOKEN_FALSE: json = json_false(); break; case TOKEN_NULL: json = json_null(); break; case '{': json = parse_object(lex, flags, error); break; case '[': json = parse_array(lex, flags, error); break; case TOKEN_INVALID: error_set(error, lex, "invalid token"); return NULL; default: error_set(error, lex, "unexpected token"); return NULL; } if(!json) return NULL; return json; }