sync json parser improvements from json2tsv repo - frontends - front-ends for some sites (experiment)
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
(DIR) commit a5e2f07cb75a19578454e096f2c9f77cebc30084
(DIR) parent f292d66dca2b0154b56fc8fa6935b947bfc74452
(HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date: Wed, 30 Mar 2022 00:01:52 +0200
sync json parser improvements from json2tsv repo
Diffstat:
M json.c | 40 +++++++++++++++++--------------
M json.h | 20 ++++++++++++--------
2 files changed, 34 insertions(+), 26 deletions(-)
---
(DIR) diff --git a/json.c b/json.c
@@ -1,4 +1,3 @@
-#include <ctype.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
@@ -9,6 +8,9 @@
#include "json.h"
+#define ISDIGIT(c) (((unsigned)c) - '0' < 10)
+#define ISXDIGIT(c) ((((unsigned)c) - '0' < 10) || ((unsigned)c | 32) - 'a' < 6)
+
static const unsigned char *json_data;
static size_t json_data_size;
static size_t json_data_off;
@@ -116,7 +118,7 @@ int
parsejson(const char *s, size_t slen,
void (*cb)(struct json_node *, size_t, const char *, void *), void *pp)
{
- struct json_node nodes[JSON_MAX_NODE_DEPTH] = { 0 };
+ struct json_node nodes[JSON_MAX_NODE_DEPTH] = { { 0 } };
size_t depth = 0, p = 0, len, sz = 0;
long cp, hi, lo;
char pri[128], *str = NULL;
@@ -148,7 +150,7 @@ handlechr:
expect = EXPECT_VALUE;
break;
case '"':
- nodes[depth].type = TYPE_STRING;
+ nodes[depth].type = JSON_TYPE_STRING;
escape = 0;
len = 0;
while (1) {
@@ -174,8 +176,8 @@ escchr:
if (capacity(&str, &sz, len, 4) == -1)
goto end;
for (i = 12, cp = 0; i >= 0; i -= 4) {
- if ((c = GETNEXT()) == EOF || !isxdigit(c))
- JSON_INVALID(); /* invalid codepoint */
+ if ((c = GETNEXT()) == EOF || !ISXDIGIT(c))
+ JSON_INVALID(); /* invalid code point */
cp |= (hexdigit(c) << i);
}
/* RFC8259 - 7. Strings - surrogates.
@@ -190,8 +192,8 @@ escchr:
goto escchr;
}
for (hi = cp, i = 12, lo = 0; i >= 0; i -= 4) {
- if ((c = GETNEXT()) == EOF || !isxdigit(c))
- JSON_INVALID(); /* invalid codepoint */
+ if ((c = GETNEXT()) == EOF || !ISXDIGIT(c))
+ JSON_INVALID(); /* invalid code point */
lo |= (hexdigit(c) << i);
}
/* 0xdc00 - 0xdfff - low surrogates */
@@ -248,11 +250,11 @@ escchr:
nodes[depth].index = 0;
if (c == '[') {
- nodes[depth].type = TYPE_ARRAY;
+ nodes[depth].type = JSON_TYPE_ARRAY;
expect = EXPECT_ARRAY_VALUE;
} else if (c == '{') {
iskey = 1;
- nodes[depth].type = TYPE_OBJECT;
+ nodes[depth].type = JSON_TYPE_OBJECT;
expect = EXPECT_OBJECT_STRING;
}
@@ -267,11 +269,12 @@ escchr:
case ']':
case '}':
if (!depth ||
- (c == ']' && nodes[depth - 1].type != TYPE_ARRAY) ||
- (c == '}' && nodes[depth - 1].type != TYPE_OBJECT))
+ (c == ']' && nodes[depth - 1].type != JSON_TYPE_ARRAY) ||
+ (c == '}' && nodes[depth - 1].type != JSON_TYPE_OBJECT))
JSON_INVALID(); /* unbalanced nodes */
- nodes[--depth].index++;
+ depth--;
+ nodes[depth].index++;
expect = EXPECT_END;
break;
case ',':
@@ -279,7 +282,7 @@ escchr:
JSON_INVALID(); /* unbalanced nodes */
nodes[depth - 1].index++;
- if (nodes[depth - 1].type == TYPE_OBJECT) {
+ if (nodes[depth - 1].type == JSON_TYPE_OBJECT) {
iskey = 1;
expect = EXPECT_STRING;
} else {
@@ -289,7 +292,7 @@ escchr:
case 't': /* true */
if (GETNEXT() != 'r' || GETNEXT() != 'u' || GETNEXT() != 'e')
JSON_INVALID();
- nodes[depth].type = TYPE_BOOL;
+ nodes[depth].type = JSON_TYPE_BOOL;
cb(nodes, depth + 1, "true", pp);
expect = EXPECT_END;
break;
@@ -297,26 +300,27 @@ escchr:
if (GETNEXT() != 'a' || GETNEXT() != 'l' || GETNEXT() != 's' ||
GETNEXT() != 'e')
JSON_INVALID();
- nodes[depth].type = TYPE_BOOL;
+ nodes[depth].type = JSON_TYPE_BOOL;
cb(nodes, depth + 1, "false", pp);
expect = EXPECT_END;
break;
case 'n': /* null */
if (GETNEXT() != 'u' || GETNEXT() != 'l' || GETNEXT() != 'l')
JSON_INVALID();
- nodes[depth].type = TYPE_NULL;
+ nodes[depth].type = JSON_TYPE_NULL;
cb(nodes, depth + 1, "null", pp);
expect = EXPECT_END;
break;
default: /* number */
- nodes[depth].type = TYPE_NUMBER;
+ nodes[depth].type = JSON_TYPE_NUMBER;
p = 0;
pri[p++] = c;
expect = EXPECT_END;
while (1) {
c = GETNEXT();
if (c == EOF ||
- !c || !strchr("0123456789eE+-.", c) ||
+ (!ISDIGIT(c) && c != 'e' && c != 'E' &&
+ c != '+' && c != '-' && c != '.') ||
p + 1 >= sizeof(pri)) {
pri[p] = '\0';
cb(nodes, depth + 1, pri, pp);
(DIR) diff --git a/json.h b/json.h
@@ -1,12 +1,15 @@
-#include <stdint.h>
+#ifndef _JSON_H_
+#define _JSON_H_
+
+#include <stddef.h>
enum JSONType {
- TYPE_ARRAY = 'a',
- TYPE_OBJECT = 'o',
- TYPE_STRING = 's',
- TYPE_BOOL = 'b',
- TYPE_NULL = '?',
- TYPE_NUMBER = 'n'
+ JSON_TYPE_ARRAY = 'a',
+ JSON_TYPE_OBJECT = 'o',
+ JSON_TYPE_STRING = 's',
+ JSON_TYPE_BOOL = 'b',
+ JSON_TYPE_NULL = '?',
+ JSON_TYPE_NUMBER = 'n'
};
enum JSONError {
@@ -25,4 +28,5 @@ struct json_node {
int parsejson(const char *, size_t,
void (*cb)(struct json_node *, size_t, const char *, void *),
- void *);
+ void *);
+#endif