mirror of
https://github.com/jorisvink/kore
synced 2025-03-09 20:49:01 -04:00
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);
This commit is contained in:
parent
790d020ce9
commit
890eb78fd8
@ -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);
|
||||
|
172
src/json.c
172
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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user