Introduction
Introduction Statistics Contact Development Disclaimer Help
refactor to make it easier to use as a "library". handle errors more gracefully…
git clone git://git.codemadness.org/json2tsv
Log
Files
Refs
README
LICENSE
---
commit f831a4b76c10d7efcb72effd18332f3deac7a4fa
parent 111c9cc55cbabc01fa14e8b7694be0ef940d1702
Author: Hiltjo Posthuma <[email protected]>
Date: Sat, 5 Oct 2019 22:30:49 +0200
refactor to make it easier to use as a "library". handle errors more gracefully
Diffstat:
M json2tsv.c | 114 ++++++++++++++++++-----------…
1 file changed, 67 insertions(+), 47 deletions(-)
---
diff --git a/json2tsv.c b/json2tsv.c
@@ -1,4 +1,5 @@
#include <ctype.h>
+#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -31,13 +32,6 @@ struct json_node {
static int showindices = 0; /* -n flag: show indices count for arrays */
-void
-fatal(const char *s)
-{
- fputs(s, stderr);
- exit(1);
-}
-
int
codepointtoutf8(long r, char *s)
{
@@ -80,35 +74,42 @@ hexdigit(int c)
return 0;
}
-void
+int
capacity(char **value, size_t *sz, size_t cur, size_t inc)
{
size_t need, newsiz;
+ char *newp;
/* check addition overflow */
need = cur + inc;
- if (cur > SIZE_MAX - need || *sz > SIZE_MAX - 16384)
- fatal("overflow\n");
+ if (cur > SIZE_MAX - need || *sz > SIZE_MAX - 16384) {
+ errno = EOVERFLOW;
+ return -1;
+ }
if (*sz == 0 || need > *sz) {
for (newsiz = *sz; newsiz < need; newsiz += 16384)
;
- if (!(*value = realloc(*value, newsiz)))
- fatal("realloc\n");
+ if (!(newp = realloc(*value, newsiz)))
+ return -1; /* up to caller to free memory */
+ *value = newp;
*sz = newsiz;
}
+ return 0;
}
-void
-parsejson(void (*cb)(struct json_node *, size_t, const char *))
+int
+parsejson(void (*cb)(struct json_node *, size_t, const char *), const char **e…
{
struct json_node nodes[JSON_MAX_NODE_DEPTH] = { 0 };
- long cp;
size_t depth = 0, v = 0, vz = 0;
- int c, escape;
+ long cp;
+ int c, i, escape, ret = -1;
char *value = NULL;
- capacity(&(nodes[0].name), &(nodes[0].namesiz), 0, 1);
+ *errstr = "cannot allocate enough memory";
+ if (capacity(&(nodes[0].name), &(nodes[0].namesiz), 0, 1) == -1)
+ goto end;
nodes[0].name[0] = '\0';
while ((c = GETNEXT()) != EOF) {
@@ -120,10 +121,13 @@ parsejson(void (*cb)(struct json_node *, size_t, const ch…
case ':':
nodes[depth].type = TYPE_PRIMITIVE;
if (v) {
- if (!depth || nodes[depth - 1].type != TYPE_OB…
- fatal("object member, but not in an ob…
+ if (!depth || nodes[depth - 1].type != TYPE_OB…
+ *errstr = "object member, but not in a…
+ goto end;
+ }
value[v] = '\0';
- capacity(&(nodes[depth].name), &(nodes[depth].…
+ if (capacity(&(nodes[depth].name), &(nodes[dep…
+ goto end;
memcpy(nodes[depth].name, value, v);
nodes[depth].name[v] = '\0';
v = 0;
@@ -149,43 +153,43 @@ parsejson(void (*cb)(struct json_node *, size_t, const ch…
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
case 'u': /* hex hex hex hex */
- if ((c = GETNEXT()) == EOF || …
- fatal("invalid codepoi…
- cp = (hexdigit(c) << 12);
- if ((c = GETNEXT()) == EOF || …
- fatal("invalid codepoi…
- cp |= (hexdigit(c) << 8);
- if ((c = GETNEXT()) == EOF || …
- fatal("invalid codepoi…
- cp |= (hexdigit(c) << 4);
- if ((c = GETNEXT()) == EOF || …
- fatal("invalid codepoi…
- cp |= (hexdigit(c));
-
- capacity(&value, &vz, v, 5);
+ for (i = 12, cp = 0; i >= 0; i…
+ if ((c = GETNEXT()) ==…
+ *errstr = "inv…
+ goto end;
+ }
+ cp |= (hexdigit(c) << …
+ }
+ if (capacity(&value, &vz, v, 5…
+ goto end;
v += codepointtoutf8(cp, &valu…
continue;
default:
continue; /* ignore unknown es…
}
- capacity(&value, &vz, v, 2);
+ if (capacity(&value, &vz, v, 2) == -1)
+ goto end;
value[v++] = c;
} else if (c == '\\') {
escape = 1;
} else if (c == '"') {
break;
} else {
- capacity(&value, &vz, v, 2);
+ if (capacity(&value, &vz, v, 2) == -1)
+ goto end;
value[v++] = c;
}
}
- capacity(&value, &vz, v, 1);
+ if (capacity(&value, &vz, v, 1) == -1)
+ goto end;
value[v] = '\0';
break;
case '[':
case '{':
- if (depth + 1 >= JSON_MAX_NODE_DEPTH)
- fatal("max depth reached\n");
+ if (depth + 1 >= JSON_MAX_NODE_DEPTH) {
+ *errstr = "max node depth reached";
+ goto end;
+ }
nodes[depth].index = 0;
nodes[depth].type = c == '{' ? TYPE_OBJECT : TYPE_ARRA…
@@ -195,7 +199,8 @@ parsejson(void (*cb)(struct json_node *, size_t, const char…
depth++;
nodes[depth].index = 0;
- capacity(&(nodes[depth].name), &(nodes[depth].namesiz)…
+ if (capacity(&(nodes[depth].name), &(nodes[depth].name…
+ goto end;
nodes[depth].name[0] = '\0';
nodes[depth].type = TYPE_PRIMITIVE;
break;
@@ -211,8 +216,10 @@ parsejson(void (*cb)(struct json_node *, size_t, const cha…
}
if (!depth ||
(nodes[depth - 1].type == TYPE_OBJECT && c == ']')…
- (nodes[depth - 1].type == TYPE_ARRAY && c == '}'))
- fatal("unbalanced nodes\n");
+ (nodes[depth - 1].type == TYPE_ARRAY && c == '}'))…
+ *errstr = "unbalanced nodes";
+ goto end;
+ }
if (c == ']' || c == '}') {
nodes[--depth].index++;
@@ -222,14 +229,20 @@ parsejson(void (*cb)(struct json_node *, size_t, const ch…
}
break;
default:
- capacity(&value, &vz, v, 2);
+ if (capacity(&value, &vz, v, 2) == -1)
+ goto end;
value[v++] = c;
}
}
+ ret = 0; /* success */
+ *errstr = NULL;
+end:
for (depth = 0; depth < sizeof(nodes) / sizeof(nodes[0]); depth++)
free(nodes[depth].name);
free(value);
+
+ return ret;
}
void
@@ -273,7 +286,7 @@ processnode(struct json_node *nodes, size_t depth, const ch…
}
switch (nodes[depth - 1].type) {
- case TYPE_UNKNOWN: fatal("unknown type\n"); return;
+ case TYPE_UNKNOWN: return;
case TYPE_ARRAY: fputs("\ta\t\n", stdout); return;
case TYPE_OBJECT: fputs("\to\t\n", stdout); return;
case TYPE_PRIMITIVE: fputs("\tp\t", stdout); break;
@@ -286,13 +299,20 @@ processnode(struct json_node *nodes, size_t depth, const …
int
main(int argc, char *argv[])
{
- if (pledge("stdio", NULL) == -1)
- fatal("pledge stdio\n");
+ const char *errstr;
+
+ if (pledge("stdio", NULL) == -1) {
+ fprintf(stderr, "pledge stdio: %s\n", strerror(errno));
+ return 1;
+ }
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'n')
showindices = 1;
- parsejson(processnode);
+ if (parsejson(processnode, &errstr) == -1) {
+ fprintf(stderr, "error: %s\n", errstr);
+ return 1;
+ }
return 0;
}
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.