json_tokener: optimize parsing of integer values
speedup for 32-bit: ~8% speedup for 64-bit: ~9%
This commit is contained in:
@@ -824,7 +824,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
|
|||||||
{
|
{
|
||||||
int64_t num64;
|
int64_t num64;
|
||||||
double numd;
|
double numd;
|
||||||
if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) {
|
if (!tok->is_double && json_parse_sanitized_int64(tok->pb->buf, tok->pb->bpos, &num64) == 0) {
|
||||||
if (num64 && tok->pb->buf[0]=='0' &&
|
if (num64 && tok->pb->buf[0]=='0' &&
|
||||||
(tok->flags & JSON_TOKENER_STRICT)) {
|
(tok->flags & JSON_TOKENER_STRICT)) {
|
||||||
/* in strict mode, number must not start with 0 */
|
/* in strict mode, number must not start with 0 */
|
||||||
|
|||||||
52
json_util.c
52
json_util.c
@@ -39,10 +39,6 @@
|
|||||||
#endif /* HAVE_UNISTD_H */
|
#endif /* HAVE_UNISTD_H */
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
# if MSC_VER < 1800
|
|
||||||
/* strtoll is available only since Visual Studio 2013 */
|
|
||||||
# define strtoll _strtoi64
|
|
||||||
# endif
|
|
||||||
# define WIN32_LEAN_AND_MEAN
|
# define WIN32_LEAN_AND_MEAN
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
@@ -195,16 +191,48 @@ int json_parse_double(const char *buf, double *retval)
|
|||||||
return end == buf ? 1 : 0;
|
return end == buf ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The input buffer 'buf' must contain only digits (0 to 9), except
|
||||||
|
// for the first character, which may be a negative sign '-'.
|
||||||
|
int json_parse_sanitized_int64(const char *buf, size_t len, int64_t *retval)
|
||||||
|
{
|
||||||
|
uint64_t uval = 0;
|
||||||
|
int is_negative = (*buf == '-');
|
||||||
|
size_t ii = is_negative ? 1 : 0;
|
||||||
|
|
||||||
|
if (ii == len || buf[ii] == '\0')
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
while (ii < len)
|
||||||
|
{
|
||||||
|
uint64_t tmp = (uval * 10) + buf[ii++] - '0';
|
||||||
|
// Check for overflow.
|
||||||
|
if ((int64_t) uval > (int64_t) tmp)
|
||||||
|
{
|
||||||
|
*retval = is_negative ? INT64_MIN : INT64_MAX;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uval = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
*retval = is_negative ? -uval : uval;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int json_parse_int64(const char *buf, int64_t *retval)
|
int json_parse_int64(const char *buf, int64_t *retval)
|
||||||
{
|
{
|
||||||
char *end = NULL;
|
size_t len = 0;
|
||||||
int64_t val;
|
// Skip leading white spaces.
|
||||||
|
while (isspace(*buf))
|
||||||
errno = 0;
|
buf++;
|
||||||
val = strtoll(buf, &end, 10);
|
// Calculate length of valid input.
|
||||||
if (end != buf)
|
if (buf[len] == '-')
|
||||||
*retval = val;
|
len++;
|
||||||
return ((val == 0 && errno != 0) || (end == buf)) ? 1 : 0;
|
while (buf[len] >= '0' && buf[len] <= '9')
|
||||||
|
len++;
|
||||||
|
if (len == 0)
|
||||||
|
return 1;
|
||||||
|
return json_parse_sanitized_int64(buf, len, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HAVE_REALLOC
|
#ifndef HAVE_REALLOC
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ extern int json_object_to_fd(int fd, struct json_object *obj, int flags);
|
|||||||
const char *json_util_get_last_err(void);
|
const char *json_util_get_last_err(void);
|
||||||
|
|
||||||
|
|
||||||
|
extern int json_parse_sanitized_int64(const char *buf, size_t len, int64_t *retval);
|
||||||
extern int json_parse_int64(const char *buf, int64_t *retval);
|
extern int json_parse_int64(const char *buf, int64_t *retval);
|
||||||
extern int json_parse_double(const char *buf, double *retval);
|
extern int json_parse_double(const char *buf, double *retval);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user