mirror of
https://github.com/json-c/json-c.git
synced 2026-04-08 14:59:06 +08:00
Rewrite the json_tokener_state_inf handling in json_tokener to be simpler, and avoid needless copying of the input into a temporary buffer.
This commit is contained in:
@@ -57,7 +57,8 @@
|
|||||||
static const char json_null_str[] = "null";
|
static const char json_null_str[] = "null";
|
||||||
static const int json_null_str_len = sizeof(json_null_str) - 1;
|
static const int json_null_str_len = sizeof(json_null_str) - 1;
|
||||||
static const char json_inf_str[] = "Infinity";
|
static const char json_inf_str[] = "Infinity";
|
||||||
static const int json_inf_str_len = sizeof(json_inf_str) - 1;
|
static const char json_inf_str_lower[] = "infinity";
|
||||||
|
static const unsigned int json_inf_str_len = sizeof(json_inf_str) - 1;
|
||||||
static const char json_nan_str[] = "NaN";
|
static const char json_nan_str[] = "NaN";
|
||||||
static const int json_nan_str_len = sizeof(json_nan_str) - 1;
|
static const int json_nan_str_len = sizeof(json_nan_str) - 1;
|
||||||
static const char json_true_str[] = "true";
|
static const char json_true_str[] = "true";
|
||||||
@@ -383,40 +384,55 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
|
|||||||
tok->depth--;
|
tok->depth--;
|
||||||
goto redo_char;
|
goto redo_char;
|
||||||
|
|
||||||
case json_tokener_state_inf: /* aka starts with 'i' */
|
case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */
|
||||||
{
|
{
|
||||||
size_t size_inf;
|
/* If we were guaranteed to have len set, then we could (usually) handle
|
||||||
|
* the entire "Infinity" check in a single strncmp (strncasecmp), but
|
||||||
|
* since len might be -1 (i.e. "read until \0"), we need to check it
|
||||||
|
* a character at a time.
|
||||||
|
* Trying to handle it both ways would make this code considerably more
|
||||||
|
* complicated with likely little performance benefit.
|
||||||
|
*/
|
||||||
int is_negative = 0;
|
int is_negative = 0;
|
||||||
char *infbuf;
|
const char *_json_inf_str = json_inf_str;
|
||||||
|
if (!(tok->flags & JSON_TOKENER_STRICT))
|
||||||
|
_json_inf_str = json_inf_str_lower;
|
||||||
|
|
||||||
printbuf_memappend_fast(tok->pb, &c, 1);
|
/* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */
|
||||||
size_inf = json_min(tok->st_pos+1, json_inf_str_len);
|
while (tok->st_pos < (int)json_inf_str_len)
|
||||||
infbuf = tok->pb->buf;
|
{
|
||||||
if (*infbuf == '-')
|
char inf_char = *str;
|
||||||
|
if (!(tok->flags & JSON_TOKENER_STRICT))
|
||||||
|
inf_char = tolower(*str);
|
||||||
|
if (inf_char != _json_inf_str[tok->st_pos])
|
||||||
|
{
|
||||||
|
tok->err = json_tokener_error_parse_unexpected;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
tok->st_pos++;
|
||||||
|
(void)ADVANCE_CHAR(str, tok);
|
||||||
|
if (!PEEK_CHAR(c, tok))
|
||||||
|
{
|
||||||
|
/* out of input chars, for now at least */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* We checked the full length of "Infinity", so create the object.
|
||||||
|
* When handling -Infinity, the number parsing code will have dropped
|
||||||
|
* the "-" into tok->pb for us, so check it now.
|
||||||
|
*/
|
||||||
|
if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-')
|
||||||
{
|
{
|
||||||
infbuf++;
|
|
||||||
is_negative = 1;
|
is_negative = 1;
|
||||||
}
|
}
|
||||||
if ((!(tok->flags & JSON_TOKENER_STRICT) &&
|
current = json_object_new_double(is_negative
|
||||||
strncasecmp(json_inf_str, infbuf, size_inf) == 0) ||
|
? -INFINITY : INFINITY);
|
||||||
(strncmp(json_inf_str, infbuf, size_inf) == 0)
|
if (current == NULL)
|
||||||
)
|
|
||||||
{
|
|
||||||
if (tok->st_pos == json_inf_str_len)
|
|
||||||
{
|
|
||||||
current = json_object_new_double(is_negative
|
|
||||||
? -INFINITY : INFINITY);
|
|
||||||
if(current == NULL)
|
|
||||||
goto out;
|
|
||||||
saved_state = json_tokener_state_finish;
|
|
||||||
state = json_tokener_state_eatws;
|
|
||||||
goto redo_char;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tok->err = json_tokener_error_parse_unexpected;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
saved_state = json_tokener_state_finish;
|
||||||
tok->st_pos++;
|
state = json_tokener_state_eatws;
|
||||||
|
goto redo_char;
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case json_tokener_state_null: /* aka starts with 'n' */
|
case json_tokener_state_null: /* aka starts with 'n' */
|
||||||
@@ -934,7 +950,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
|
|||||||
}
|
}
|
||||||
if (!ADVANCE_CHAR(str, tok))
|
if (!ADVANCE_CHAR(str, tok))
|
||||||
goto out;
|
goto out;
|
||||||
} /* while(POP_CHAR) */
|
} /* while(PEEK_CHAR) */
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (c &&
|
if (c &&
|
||||||
|
|||||||
Reference in New Issue
Block a user