commit 890eb78fd867cac2d96e0542f3f5275d070dd216
parent 790d020ce9a0289850f52bd092e31346ffda263e
Author: Joris Vink <joris@coders.se>
Date: Tue, 22 Oct 2019 23:56:47 +0200
Improve our new JSON api a bit.
Allow JSON to be constructed via kore_json_create_item and its
handy macro family:
- kore_json_create_object()
- kore_json_create_array()
- kore_json_create_string()
- kore_json_create_number()
- kore_json_create_literal().
Adds kore_json_item_tobuf() to convert a JSON item into a string
representation in a kore_buf data structure.
Renames the kore_json_get* family to kore_json_find* instead.
Allows for quite clean code:
struct kore_buf buf;
struct kore_json_item *root;
root = kore_json_create_object(NULL, NULL);
kore_json_create_string(root, "hello", "world");
kore_json_create_number(root, "value", 2.241);
kore_buf_init(&buf, 128);
kore_json_item_tobuf(root, &buf);
kore_json_item_free(root);
kore_buf_cleanup(&buf);
Diffstat:
include/kore/kore.h | | | 41 | ++++++++++++++++++++++++++++++----------- |
src/json.c | | | 172 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- |
2 files changed, 171 insertions(+), 42 deletions(-)
diff --git a/include/kore/kore.h b/include/kore/kore.h
@@ -490,20 +490,35 @@ struct kore_buf {
#define KORE_JSON_ERR_TYPE_MISMATCH 11
#define KORE_JSON_ERR_LAST KORE_JSON_ERR_TYPE_MISMATCH
-#define kore_json_object(j, p) \
- kore_json_get(j, p, KORE_JSON_TYPE_OBJECT)
+#define kore_json_find_object(j, p) \
+ kore_json_find(j, p, KORE_JSON_TYPE_OBJECT)
-#define kore_json_array(j, p) \
- kore_json_get(j, p, KORE_JSON_TYPE_ARRAY)
+#define kore_json_find_array(j, p) \
+ kore_json_find(j, p, KORE_JSON_TYPE_ARRAY)
-#define kore_json_string(j, p) \
- kore_json_get(j, p, KORE_JSON_TYPE_STRING)
+#define kore_json_find_string(j, p) \
+ kore_json_find(j, p, KORE_JSON_TYPE_STRING)
-#define kore_json_number(j, p) \
- kore_json_get(j, p, KORE_JSON_TYPE_NUMBER)
+#define kore_json_find_number(j, p) \
+ kore_json_find(j, p, KORE_JSON_TYPE_NUMBER)
-#define kore_json_literal(j, p) \
- kore_json_get(j, p, KORE_JSON_TYPE_LITERAL)
+#define kore_json_find_literal(j, p) \
+ kore_json_find(j, p, KORE_JSON_TYPE_LITERAL)
+
+#define kore_json_create_object(o, n) \
+ kore_json_create_item(o, n, KORE_JSON_TYPE_OBJECT)
+
+#define kore_json_create_array(o, n) \
+ kore_json_create_item(o, n, KORE_JSON_TYPE_ARRAY)
+
+#define kore_json_create_string(o, n, v) \
+ kore_json_create_item(o, n, KORE_JSON_TYPE_STRING, v)
+
+#define kore_json_create_number(o, n, v) \
+ kore_json_create_item(o, n, KORE_JSON_TYPE_NUMBER, v)
+
+#define kore_json_create_literal(o, n, v) \
+ kore_json_create_item(o, n, KORE_JSON_TYPE_LITERAL, v)
struct kore_json {
const u_int8_t *data;
@@ -946,10 +961,14 @@ void kore_buf_replace_string(struct kore_buf *,
int kore_json_parse(struct kore_json *);
void kore_json_cleanup(struct kore_json *);
+void kore_json_item_free(struct kore_json_item *);
void kore_json_init(struct kore_json *, const u_int8_t *, size_t);
+void kore_json_item_tobuf(struct kore_json_item *, struct kore_buf *);
const char *kore_json_strerror(struct kore_json *);
-struct kore_json_item *kore_json_get(struct kore_json *, const char *, int);
+struct kore_json_item *kore_json_find(struct kore_json *, const char *, int);
+struct kore_json_item *kore_json_create_item(struct kore_json_item *,
+ const char *, int, ...);
void kore_keymgr_run(void);
void kore_keymgr_cleanup(int);
diff --git a/src/json.c b/src/json.c
@@ -39,7 +39,6 @@ static int json_parse_string(struct kore_json *, struct kore_json_item *);
static int json_parse_number(struct kore_json *, struct kore_json_item *);
static int json_parse_literal(struct kore_json *, struct kore_json_item *);
-static void json_item_free(struct kore_json_item *);
static struct kore_json_item *json_item_alloc(int, const char *,
struct kore_json_item *);
static struct kore_json_item *json_find_item(struct kore_json *,
@@ -92,7 +91,7 @@ kore_json_parse(struct kore_json *json)
return (KORE_RESULT_ERROR);
}
- json->root = json_item_alloc(type, "<root>", NULL);
+ json->root = json_item_alloc(type, NULL, NULL);
if (!json->root->parse(json, json->root)) {
if (json->error == 0)
@@ -104,7 +103,7 @@ kore_json_parse(struct kore_json *json)
}
struct kore_json_item *
-kore_json_get(struct kore_json *json, const char *path, int type)
+kore_json_find(struct kore_json *json, const char *path, int type)
{
struct kore_json_item *item;
char *copy;
@@ -131,7 +130,7 @@ void
kore_json_cleanup(struct kore_json *json)
{
kore_buf_cleanup(&json->tmpbuf);
- json_item_free(json->root);
+ kore_json_item_free(json->root);
}
const char *
@@ -143,6 +142,117 @@ kore_json_strerror(struct kore_json *json)
return ("unknown JSON error");
}
+struct kore_json_item *
+kore_json_create_item(struct kore_json_item *parent, const char *name,
+ int type, ...)
+{
+ const char *p;
+ va_list args;
+ struct kore_json_item *item;
+
+ item = kore_calloc(1, sizeof(*item));
+ item->type = type;
+
+ va_start(args, type);
+
+ switch (item->type) {
+ case KORE_JSON_TYPE_OBJECT:
+ TAILQ_INIT(&item->data.items);
+ break;
+ case KORE_JSON_TYPE_ARRAY:
+ TAILQ_INIT(&item->data.items);
+ break;
+ case KORE_JSON_TYPE_STRING:
+ p = va_arg(args, const char *);
+ item->data.string = kore_strdup(p);
+ break;
+ case KORE_JSON_TYPE_NUMBER:
+ item->data.number = va_arg(args, double);
+ break;
+ case KORE_JSON_TYPE_LITERAL:
+ item->data.literal = va_arg(args, int);
+ break;
+ default:
+ fatal("%s: unknown type %d", __func__, item->type);
+ }
+
+ if (name)
+ item->name = kore_strdup(name);
+
+ if (parent) {
+ if (parent->type != KORE_JSON_TYPE_OBJECT &&
+ parent->type != KORE_JSON_TYPE_ARRAY) {
+ fatal("%s: invalid parent type (%d)",
+ __func__, parent->type);
+ }
+
+ TAILQ_INSERT_TAIL(&parent->data.items, item, list);
+ }
+
+ va_end(args);
+
+ return (item);
+}
+
+void
+kore_json_item_tobuf(struct kore_json_item *item, struct kore_buf *buf)
+{
+ struct kore_json_item *nitem;
+
+ if (item->name)
+ kore_buf_appendf(buf, "\"%s\":", item->name);
+
+ switch (item->type) {
+ case KORE_JSON_TYPE_OBJECT:
+ kore_buf_appendf(buf, "{");
+ TAILQ_FOREACH(nitem, &item->data.items, list) {
+ kore_json_item_tobuf(nitem, buf);
+
+ if (TAILQ_NEXT(nitem, list))
+ kore_buf_appendf(buf, ",");
+ }
+ kore_buf_appendf(buf, "}");
+ break;
+ case KORE_JSON_TYPE_ARRAY:
+ kore_buf_appendf(buf, "[");
+ TAILQ_FOREACH(nitem, &item->data.items, list) {
+ kore_json_item_tobuf(nitem, buf);
+
+ if (TAILQ_NEXT(nitem, list))
+ kore_buf_appendf(buf, ",");
+ }
+ kore_buf_appendf(buf, "]");
+ break;
+ case KORE_JSON_TYPE_STRING:
+ kore_buf_appendf(buf, "\"%s\"", item->data.string);
+ break;
+ case KORE_JSON_TYPE_NUMBER:
+ kore_buf_appendf(buf, "%f", item->data.number);
+ break;
+ case KORE_JSON_TYPE_LITERAL:
+ switch (item->data.literal) {
+ case KORE_JSON_TRUE:
+ kore_buf_append(buf,
+ json_true_literal, sizeof(json_true_literal));
+ break;
+ case KORE_JSON_FALSE:
+ kore_buf_append(buf,
+ json_false_literal, sizeof(json_false_literal));
+ break;
+ case KORE_JSON_NULL:
+ kore_buf_append(buf,
+ json_null_literal, sizeof(json_null_literal));
+ break;
+ default:
+ fatal("%s: unknown literal %d", __func__,
+ item->data.literal);
+ }
+ break;
+ default:
+ fatal("%s: unknown type %d", __func__, item->type);
+ }
+}
+
static struct kore_json_item *
json_find_item(struct kore_json *json, struct kore_json_item *object,
char **tokens, int type, int pos)
@@ -218,6 +328,33 @@ json_find_item(struct kore_json *json, struct kore_json_item *object,
return (item);
}
+void
+kore_json_item_free(struct kore_json_item *item)
+{
+ struct kore_json_item *node;
+
+ switch (item->type) {
+ case KORE_JSON_TYPE_OBJECT:
+ case KORE_JSON_TYPE_ARRAY:
+ while ((node = TAILQ_FIRST(&item->data.items)) != NULL) {
+ TAILQ_REMOVE(&item->data.items, node, list);
+ kore_json_item_free(node);
+ }
+ break;
+ case KORE_JSON_TYPE_STRING:
+ kore_free(item->data.string);
+ break;
+ case KORE_JSON_TYPE_NUMBER:
+ case KORE_JSON_TYPE_LITERAL:
+ break;
+ default:
+ fatal("%s: unknown type %d", __func__, item->type);
+ }
+
+ kore_free(item->name);
+ kore_free(item);
+}
+
static struct kore_json_item *
json_item_alloc(int type, const char *name, struct kore_json_item *parent)
{
@@ -265,33 +402,6 @@ json_item_alloc(int type, const char *name, struct kore_json_item *parent)
return (item);
}
-static void
-json_item_free(struct kore_json_item *item)
-{
- struct kore_json_item *node;
-
- switch (item->type) {
- case KORE_JSON_TYPE_OBJECT:
- case KORE_JSON_TYPE_ARRAY:
- while ((node = TAILQ_FIRST(&item->data.items)) != NULL) {
- TAILQ_REMOVE(&item->data.items, node, list);
- json_item_free(node);
- }
- break;
- case KORE_JSON_TYPE_STRING:
- kore_free(item->data.string);
- break;
- case KORE_JSON_TYPE_NUMBER:
- case KORE_JSON_TYPE_LITERAL:
- break;
- default:
- fatal("%s: unknown type %d", __func__, item->type);
- }
-
- kore_free(item->name);
- kore_free(item);
-}
-
static int
json_peek(struct kore_json *json, u_int8_t *ch)
{