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)) {