forked from mirrors/kore
Better parsing of JSON integers and numbers.
Add 2 new types: KORE_JSON_TYPE_INTEGER signed integer type, internally stored as s64. KORE_JSON_TYPE_INTEGER_U64 unsigned integer type, internally stored as u64. Kore JSON parser will prefer marking integers as INTEGER_U64 if it was unsigned and did not have fractions.
This commit is contained in:
parent
760dff8b3c
commit
d7fbce37f5
|
@ -494,11 +494,13 @@ struct kore_buf {
|
|||
size_t offset;
|
||||
};
|
||||
|
||||
#define KORE_JSON_TYPE_OBJECT 1
|
||||
#define KORE_JSON_TYPE_ARRAY 2
|
||||
#define KORE_JSON_TYPE_STRING 3
|
||||
#define KORE_JSON_TYPE_NUMBER 4
|
||||
#define KORE_JSON_TYPE_LITERAL 5
|
||||
#define KORE_JSON_TYPE_OBJECT 0x0001
|
||||
#define KORE_JSON_TYPE_ARRAY 0x0002
|
||||
#define KORE_JSON_TYPE_STRING 0x0004
|
||||
#define KORE_JSON_TYPE_NUMBER 0x0008
|
||||
#define KORE_JSON_TYPE_LITERAL 0x0010
|
||||
#define KORE_JSON_TYPE_INTEGER 0x0020
|
||||
#define KORE_JSON_TYPE_INTEGER_U64 0x0040
|
||||
|
||||
#define KORE_JSON_FALSE 0
|
||||
#define KORE_JSON_TRUE 1
|
||||
|
@ -532,6 +534,12 @@ struct kore_buf {
|
|||
#define kore_json_find_number(j, p) \
|
||||
kore_json_find(j, p, KORE_JSON_TYPE_NUMBER)
|
||||
|
||||
#define kore_json_find_integer(j, p) \
|
||||
kore_json_find(j, p, KORE_JSON_TYPE_INTEGER)
|
||||
|
||||
#define kore_json_find_integer_u64(j, p) \
|
||||
kore_json_find(j, p, KORE_JSON_TYPE_INTEGER_U64)
|
||||
|
||||
#define kore_json_find_literal(j, p) \
|
||||
kore_json_find(j, p, KORE_JSON_TYPE_LITERAL)
|
||||
|
||||
|
@ -547,6 +555,12 @@ struct kore_buf {
|
|||
#define kore_json_create_number(o, n, v) \
|
||||
kore_json_create_item(o, n, KORE_JSON_TYPE_NUMBER, v)
|
||||
|
||||
#define kore_json_create_integer(o, n, v) \
|
||||
kore_json_create_item(o, n, KORE_JSON_TYPE_INTEGER, v)
|
||||
|
||||
#define kore_json_create_integer_u64(o, n, v) \
|
||||
kore_json_create_item(o, n, KORE_JSON_TYPE_INTEGER_U64, v)
|
||||
|
||||
#define kore_json_create_literal(o, n, v) \
|
||||
kore_json_create_item(o, n, KORE_JSON_TYPE_LITERAL, v)
|
||||
|
||||
|
@ -562,7 +576,7 @@ struct kore_json {
|
|||
};
|
||||
|
||||
struct kore_json_item {
|
||||
int type;
|
||||
u_int32_t type;
|
||||
char *name;
|
||||
struct kore_json_item *parent;
|
||||
|
||||
|
@ -571,6 +585,8 @@ struct kore_json_item {
|
|||
char *string;
|
||||
double number;
|
||||
int literal;
|
||||
int64_t s64;
|
||||
u_int64_t u64;
|
||||
} data;
|
||||
|
||||
int (*parse)(struct kore_json *,
|
||||
|
@ -1026,9 +1042,9 @@ void kore_json_item_tobuf(struct kore_json_item *, struct kore_buf *);
|
|||
|
||||
const char *kore_json_strerror(struct kore_json *);
|
||||
struct kore_json_item *kore_json_find(struct kore_json_item *,
|
||||
const char *, int);
|
||||
const char *, u_int32_t);
|
||||
struct kore_json_item *kore_json_create_item(struct kore_json_item *,
|
||||
const char *, int, ...);
|
||||
const char *, u_int32_t, ...);
|
||||
|
||||
void kore_keymgr_run(void);
|
||||
void kore_keymgr_cleanup(int);
|
||||
|
|
82
src/json.c
82
src/json.c
|
@ -24,7 +24,7 @@
|
|||
|
||||
#include "kore.h"
|
||||
|
||||
static int json_guess_type(u_int8_t, int *);
|
||||
static int json_guess_type(u_int8_t, u_int32_t *);
|
||||
static int json_next(struct kore_json *, u_int8_t *);
|
||||
static int json_peek(struct kore_json *, u_int8_t *);
|
||||
|
||||
|
@ -42,7 +42,7 @@ static int json_parse_literal(struct kore_json *, struct kore_json_item *);
|
|||
static struct kore_json_item *json_item_alloc(int, const char *,
|
||||
struct kore_json_item *);
|
||||
static struct kore_json_item *json_find_item(struct kore_json_item *,
|
||||
char **, int, int);
|
||||
char **, u_int32_t, int);
|
||||
|
||||
static u_int8_t json_null_literal[] = { 'n', 'u', 'l', 'l' };
|
||||
static u_int8_t json_true_literal[] = { 't', 'r', 'u', 'e' };
|
||||
|
@ -78,7 +78,7 @@ int
|
|||
kore_json_parse(struct kore_json *json)
|
||||
{
|
||||
u_int8_t ch;
|
||||
int type;
|
||||
u_int32_t type;
|
||||
|
||||
if (json->root)
|
||||
return (KORE_RESULT_OK);
|
||||
|
@ -112,7 +112,7 @@ kore_json_parse(struct kore_json *json)
|
|||
}
|
||||
|
||||
struct kore_json_item *
|
||||
kore_json_find(struct kore_json_item *root, const char *path, int type)
|
||||
kore_json_find(struct kore_json_item *root, const char *path, u_int32_t type)
|
||||
{
|
||||
struct kore_json_item *item;
|
||||
char *copy;
|
||||
|
@ -152,7 +152,7 @@ kore_json_strerror(struct kore_json *json)
|
|||
|
||||
struct kore_json_item *
|
||||
kore_json_create_item(struct kore_json_item *parent, const char *name,
|
||||
int type, ...)
|
||||
u_int32_t type, ...)
|
||||
{
|
||||
const char *p;
|
||||
va_list args;
|
||||
|
@ -177,6 +177,12 @@ kore_json_create_item(struct kore_json_item *parent, const char *name,
|
|||
case KORE_JSON_TYPE_NUMBER:
|
||||
item->data.number = va_arg(args, double);
|
||||
break;
|
||||
case KORE_JSON_TYPE_INTEGER:
|
||||
item->data.s64 = va_arg(args, int64_t);
|
||||
break;
|
||||
case KORE_JSON_TYPE_INTEGER_U64:
|
||||
item->data.u64 = va_arg(args, u_int64_t);
|
||||
break;
|
||||
case KORE_JSON_TYPE_LITERAL:
|
||||
item->data.literal = va_arg(args, int);
|
||||
break;
|
||||
|
@ -237,6 +243,12 @@ kore_json_item_tobuf(struct kore_json_item *item, struct kore_buf *buf)
|
|||
case KORE_JSON_TYPE_NUMBER:
|
||||
kore_buf_appendf(buf, "%f", item->data.number);
|
||||
break;
|
||||
case KORE_JSON_TYPE_INTEGER:
|
||||
kore_buf_appendf(buf, "%" PRId64, item->data.s64);
|
||||
break;
|
||||
case KORE_JSON_TYPE_INTEGER_U64:
|
||||
kore_buf_appendf(buf, "%" PRIu64, item->data.u64);
|
||||
break;
|
||||
case KORE_JSON_TYPE_LITERAL:
|
||||
switch (item->data.literal) {
|
||||
case KORE_JSON_TRUE:
|
||||
|
@ -262,7 +274,8 @@ kore_json_item_tobuf(struct kore_json_item *item, struct kore_buf *buf)
|
|||
}
|
||||
|
||||
static struct kore_json_item *
|
||||
json_find_item(struct kore_json_item *object, char **tokens, int type, int pos)
|
||||
json_find_item(struct kore_json_item *object, char **tokens,
|
||||
u_int32_t type, int pos)
|
||||
{
|
||||
char *p, *str;
|
||||
struct kore_json_item *item, *nitem;
|
||||
|
@ -350,6 +363,8 @@ kore_json_item_free(struct kore_json_item *item)
|
|||
break;
|
||||
case KORE_JSON_TYPE_NUMBER:
|
||||
case KORE_JSON_TYPE_LITERAL:
|
||||
case KORE_JSON_TYPE_INTEGER:
|
||||
case KORE_JSON_TYPE_INTEGER_U64:
|
||||
break;
|
||||
default:
|
||||
fatal("%s: unknown type %d", __func__, item->type);
|
||||
|
@ -381,6 +396,8 @@ json_item_alloc(int type, const char *name, struct kore_json_item *parent)
|
|||
item->parse = json_parse_string;
|
||||
break;
|
||||
case KORE_JSON_TYPE_NUMBER:
|
||||
case KORE_JSON_TYPE_INTEGER:
|
||||
case KORE_JSON_TYPE_INTEGER_U64:
|
||||
item->parse = json_parse_number;
|
||||
break;
|
||||
case KORE_JSON_TYPE_LITERAL:
|
||||
|
@ -453,7 +470,7 @@ json_consume_whitespace(struct kore_json *json)
|
|||
}
|
||||
|
||||
static int
|
||||
json_guess_type(u_int8_t ch, int *type)
|
||||
json_guess_type(u_int8_t ch, u_int32_t *type)
|
||||
{
|
||||
if (ch == '-' || (ch >= '0' && ch <= '9')) {
|
||||
*type = KORE_JSON_TYPE_NUMBER;
|
||||
|
@ -486,9 +503,10 @@ static int
|
|||
json_parse_object(struct kore_json *json, struct kore_json_item *object)
|
||||
{
|
||||
u_int8_t ch;
|
||||
u_int32_t type;
|
||||
char *key;
|
||||
struct kore_json_item *item;
|
||||
int ret, type, hasnext;
|
||||
int ret, hasnext;
|
||||
|
||||
if (json->depth++ >= KORE_JSON_DEPTH_MAX) {
|
||||
json->error = KORE_JSON_ERR_DEPTH;
|
||||
|
@ -586,9 +604,10 @@ static int
|
|||
json_parse_array(struct kore_json *json, struct kore_json_item *array)
|
||||
{
|
||||
u_int8_t ch;
|
||||
u_int32_t type;
|
||||
char *key;
|
||||
struct kore_json_item *item;
|
||||
int ret, type, hasnext;
|
||||
int ret, hasnext;
|
||||
|
||||
if (json->depth++ >= KORE_JSON_DEPTH_MAX) {
|
||||
json->error = KORE_JSON_ERR_DEPTH;
|
||||
|
@ -680,16 +699,32 @@ json_parse_number(struct kore_json *json, struct kore_json_item *number)
|
|||
u_int8_t ch;
|
||||
int ret;
|
||||
char *str;
|
||||
u_int32_t type;
|
||||
|
||||
str = NULL;
|
||||
ret = KORE_RESULT_ERROR;
|
||||
kore_buf_reset(&json->tmpbuf);
|
||||
|
||||
type = KORE_JSON_TYPE_NUMBER | KORE_JSON_TYPE_INTEGER |
|
||||
KORE_JSON_TYPE_INTEGER_U64;
|
||||
|
||||
for (;;) {
|
||||
if (!json_peek(json, &ch))
|
||||
goto cleanup;
|
||||
break;
|
||||
|
||||
switch (ch) {
|
||||
case 'e':
|
||||
case 'E':
|
||||
case '.':
|
||||
type = KORE_JSON_TYPE_NUMBER;
|
||||
kore_buf_append(&json->tmpbuf, &ch, sizeof(ch));
|
||||
json->offset++;
|
||||
continue;
|
||||
case '-':
|
||||
if (json->tmpbuf.offset != 0)
|
||||
goto cleanup;
|
||||
type &= ~KORE_JSON_TYPE_INTEGER_U64;
|
||||
/* FALLTHROUGH */
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
|
@ -701,10 +736,6 @@ json_parse_number(struct kore_json *json, struct kore_json_item *number)
|
|||
case '8':
|
||||
case '9':
|
||||
case '+':
|
||||
case '-':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case '.':
|
||||
kore_buf_append(&json->tmpbuf, &ch, sizeof(ch));
|
||||
json->offset++;
|
||||
continue;
|
||||
|
@ -713,13 +744,30 @@ json_parse_number(struct kore_json *json, struct kore_json_item *number)
|
|||
break;
|
||||
}
|
||||
|
||||
if (type & KORE_JSON_TYPE_INTEGER_U64)
|
||||
type = KORE_JSON_TYPE_INTEGER_U64;
|
||||
|
||||
if (type & KORE_JSON_TYPE_INTEGER)
|
||||
type = KORE_JSON_TYPE_INTEGER;
|
||||
|
||||
str = kore_buf_stringify(&json->tmpbuf, NULL);
|
||||
|
||||
number->data.number = kore_strtodouble(str, -DBL_MAX, DBL_MAX, &ret);
|
||||
if (ret != KORE_RESULT_OK)
|
||||
switch (type) {
|
||||
case KORE_JSON_TYPE_NUMBER:
|
||||
number->data.number =
|
||||
kore_strtodouble(str, -DBL_MAX, DBL_MAX, &ret);
|
||||
break;
|
||||
case KORE_JSON_TYPE_INTEGER:
|
||||
number->data.s64 = (int64_t)kore_strtonum64(str, 1, &ret);
|
||||
break;
|
||||
case KORE_JSON_TYPE_INTEGER_U64:
|
||||
number->data.s64 = kore_strtonum64(str, 0, &ret);
|
||||
break;
|
||||
default:
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
number->type = KORE_JSON_TYPE_NUMBER;
|
||||
number->type = type;
|
||||
|
||||
cleanup:
|
||||
if (ret == KORE_RESULT_ERROR && json->error == 0)
|
||||
|
|
Loading…
Reference in New Issue