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