Browse Source

json_tokener: optimize parsing of integer values

speedup for 32-bit: ~8%
speedup for 64-bit: ~9%
tags/json-c-0.16-20220414
Ramiro Polla 7 years ago
parent
commit
c9a0ac5886
3 changed files with 42 additions and 13 deletions
  1. +1
    -1
      json_tokener.c
  2. +40
    -12
      json_util.c
  3. +1
    -0
      json_util.h

+ 1
- 1
json_tokener.c View File

@@ -824,7 +824,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
{
int64_t num64;
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' &&
(tok->flags & JSON_TOKENER_STRICT)) {
/* in strict mode, number must not start with 0 */


+ 40
- 12
json_util.c View File

@@ -39,10 +39,6 @@
#endif /* HAVE_UNISTD_H */

#ifdef WIN32
# if MSC_VER < 1800
/* strtoll is available only since Visual Studio 2013 */
# define strtoll _strtoi64
# endif
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <io.h>
@@ -195,16 +191,48 @@ int json_parse_double(const char *buf, double *retval)
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)
{
char *end = NULL;
int64_t val;

errno = 0;
val = strtoll(buf, &end, 10);
if (end != buf)
*retval = val;
return ((val == 0 && errno != 0) || (end == buf)) ? 1 : 0;
size_t len = 0;
// Skip leading white spaces.
while (isspace(*buf))
buf++;
// Calculate length of valid input.
if (buf[len] == '-')
len++;
while (buf[len] >= '0' && buf[len] <= '9')
len++;
if (len == 0)
return 1;
return json_parse_sanitized_int64(buf, len, retval);
}

#ifndef HAVE_REALLOC


+ 1
- 0
json_util.h View File

@@ -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);


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_double(const char *buf, double *retval);



Loading…
Cancel
Save