json.c: add len argument to callback - json2tsv - JSON to TSV converter
 (HTM) git clone git://git.codemadness.org/json2tsv
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 403d7765995d21fbe24fda7318e8ac85c87bd4b1
 (DIR) parent 55e9552c536fcb18f28d6742cfbec3ae10766473
 (HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
       Date:   Tue,  4 Apr 2023 18:13:10 +0200
       
       json.c: add len argument to callback
       
       Not important for json2tsv itself, but for other uses of json.{c,h} it saves a
       strlen() call in some cases.
       
       Note that NUL bytes (via \u0000 or so) are discarded in json.c codepointtoutf8().
       
       Diffstat:
         M json.c                              |      14 +++++++-------
         M json.h                              |       2 +-
         M json2tsv.c                          |      22 ++++++++++++++--------
       
       3 files changed, 22 insertions(+), 16 deletions(-)
       ---
 (DIR) diff --git a/json.c b/json.c
       @@ -94,7 +94,7 @@ capacity(char **value, size_t *sz, size_t cur, size_t inc)
        #define JSON_INVALID()       do { ret = JSON_ERROR_INVALID; goto end; } while (0);
        
        int
       -parsejson(void (*cb)(struct json_node *, size_t, const char *))
       +parsejson(void (*cb)(struct json_node *, size_t, const char *, size_t))
        {
                struct json_node nodes[JSON_MAX_NODE_DEPTH] = { { 0 } };
                size_t depth = 0, p = 0, len, sz = 0;
       @@ -205,7 +205,7 @@ escchr:
                                                                goto end;
                                                        memcpy(nodes[depth].name, str, len);
                                                } else {
       -                                                cb(nodes, depth + 1, str);
       +                                                cb(nodes, depth + 1, str, len - 1); /* length excluding NUL byte */
                                                }
                                                break;
                                        } else {
       @@ -234,7 +234,7 @@ escchr:
                                        expect = EXPECT_OBJECT_STRING;
                                }
        
       -                        cb(nodes, depth + 1, "");
       +                        cb(nodes, depth + 1, "", 0);
        
                                depth++;
                                nodes[depth].index = 0;
       @@ -269,7 +269,7 @@ escchr:
                                if (GETNEXT() != 'r' || GETNEXT() != 'u' || GETNEXT() != 'e')
                                        JSON_INVALID();
                                nodes[depth].type = JSON_TYPE_BOOL;
       -                        cb(nodes, depth + 1, "true");
       +                        cb(nodes, depth + 1, "true", 4);
                                expect = EXPECT_END;
                                break;
                        case 'f': /* false */
       @@ -277,14 +277,14 @@ escchr:
                                    GETNEXT() != 'e')
                                        JSON_INVALID();
                                nodes[depth].type = JSON_TYPE_BOOL;
       -                        cb(nodes, depth + 1, "false");
       +                        cb(nodes, depth + 1, "false", 5);
                                expect = EXPECT_END;
                                break;
                        case 'n': /* null */
                                if (GETNEXT() != 'u' || GETNEXT() != 'l' || GETNEXT() != 'l')
                                        JSON_INVALID();
                                nodes[depth].type = JSON_TYPE_NULL;
       -                        cb(nodes, depth + 1, "null");
       +                        cb(nodes, depth + 1, "null", 4);
                                expect = EXPECT_END;
                                break;
                        default: /* number */
       @@ -299,7 +299,7 @@ escchr:
                                             c != '+' && c != '-' && c != '.') ||
                                            p + 1 >= sizeof(pri)) {
                                                pri[p] = '\0';
       -                                        cb(nodes, depth + 1, pri);
       +                                        cb(nodes, depth + 1, pri, p);
                                                goto handlechr; /* do not read next char, handle this */
                                        } else {
                                                pri[p++] = c;
 (DIR) diff --git a/json.h b/json.h
       @@ -26,5 +26,5 @@ struct json_node {
                size_t index; /* count/index for array or object type */
        };
        
       -int parsejson(void (*cb)(struct json_node *, size_t, const char *));
       +int parsejson(void (*cb)(struct json_node *, size_t, const char *, size_t));
        #endif
 (DIR) diff --git a/json2tsv.c b/json2tsv.c
       @@ -21,12 +21,15 @@ static int nflag = 0; /* -n flag: show indices count for arrays */
        static int rflag = 0; /* -r flag: show all control-characters */
        static int fs = '\t', rs = '\n';
        
       -static void (*printvalue)(const char *);
       +static void (*printvalue)(const char *, size_t);
        
        void
       -tsv_printvalue(const char *s)
       +tsv_printvalue(const char *s, size_t len)
        {
       -        for (; *s; s++) {
       +        const char *e;
       +
       +        e = s + len;
       +        for (; s != e; s++) {
                        /* escape some chars */
                        switch (*s) {
                        case '\n': putchar('\\'); putchar('n'); break;
       @@ -42,9 +45,12 @@ tsv_printvalue(const char *s)
        }
        
        void
       -rs_printvalue(const char *s)
       +rs_printvalue(const char *s, size_t len)
        {
       -        for (; *s; s++) {
       +        const char *e;
       +
       +        e = e + len;
       +        for (; s != e; s++) {
                        if (*s == fs || *s == rs)
                                continue;
        
       @@ -86,12 +92,12 @@ printnum(uintmax_t x)
        }
        
        void
       -processnode(struct json_node *nodes, size_t depth, const char *value)
       +processnode(struct json_node *nodes, size_t depth, const char *value, size_t valuelen)
        {
                size_t i;
        
                for (i = 0; i < depth; i++) {
       -                printvalue(nodes[i].name);
       +                printvalue(nodes[i].name, strlen(nodes[i].name));
        
                        if (i + 1 == depth &&
                            (nodes[i].type == JSON_TYPE_OBJECT ||
       @@ -111,7 +117,7 @@ processnode(struct json_node *nodes, size_t depth, const char *value)
                putchar(fs);
                putchar(nodes[depth - 1].type);
                putchar(fs);
       -        printvalue(value);
       +        printvalue(value, valuelen);
                putchar(rs);
        
                if (ferror(stdout)) {