mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 07:04:22 +01:00
common/json: move JSON creation routines into lightningd/
It's the only user of them, and it's going to get optimized. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> gossip.pydiff --git a/common/test/run-json.c b/common/test/run-json.c index 956fdda35..db52d6b01 100644
This commit is contained in:
237
common/json.c
237
common/json.c
@@ -1,6 +1,5 @@
|
||||
/* JSON core and helpers */
|
||||
#include "json.h"
|
||||
#include "json_escaped.h"
|
||||
#include <assert.h>
|
||||
#include <ccan/build_assert/build_assert.h>
|
||||
#include <ccan/str/hex/hex.h>
|
||||
@@ -11,14 +10,6 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
struct json_result {
|
||||
/* tal_arr of types we're enclosed in. */
|
||||
jsmntype_t *wrapping;
|
||||
|
||||
/* tal_count() of this is strlen() + 1 */
|
||||
char *s;
|
||||
};
|
||||
|
||||
const char *json_tok_contents(const char *buffer, const jsmntok_t *t)
|
||||
{
|
||||
if (t->type == JSMN_STRING)
|
||||
@@ -225,231 +216,3 @@ again:
|
||||
|
||||
return toks;
|
||||
}
|
||||
|
||||
static void result_append(struct json_result *res, const char *str)
|
||||
{
|
||||
size_t len = tal_count(res->s) - 1;
|
||||
|
||||
tal_resize(&res->s, len + strlen(str) + 1);
|
||||
strcpy(res->s + len, str);
|
||||
}
|
||||
|
||||
static void PRINTF_FMT(2,3)
|
||||
result_append_fmt(struct json_result *res, const char *fmt, ...)
|
||||
{
|
||||
size_t len = tal_count(res->s) - 1, fmtlen;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
fmtlen = vsnprintf(NULL, 0, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
tal_resize(&res->s, len + fmtlen + 1);
|
||||
va_start(ap, fmt);
|
||||
vsprintf(res->s + len, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static bool result_ends_with(struct json_result *res, const char *str)
|
||||
{
|
||||
size_t len = tal_count(res->s) - 1;
|
||||
|
||||
if (strlen(str) > len)
|
||||
return false;
|
||||
return streq(res->s + len - strlen(str), str);
|
||||
}
|
||||
|
||||
static void check_fieldname(const struct json_result *result,
|
||||
const char *fieldname)
|
||||
{
|
||||
size_t n = tal_count(result->wrapping);
|
||||
if (n == 0)
|
||||
/* Can't have a fieldname if not in anything! */
|
||||
assert(!fieldname);
|
||||
else if (result->wrapping[n-1] == JSMN_ARRAY)
|
||||
/* No fieldnames in arrays. */
|
||||
assert(!fieldname);
|
||||
else
|
||||
/* Must have fieldnames in objects. */
|
||||
assert(fieldname);
|
||||
}
|
||||
|
||||
static void result_add_indent(struct json_result *result);
|
||||
|
||||
static void json_start_member(struct json_result *result, const char *fieldname)
|
||||
{
|
||||
/* Prepend comma if required. */
|
||||
if (result->s[0]
|
||||
&& !result_ends_with(result, "{")
|
||||
&& !result_ends_with(result, "["))
|
||||
result_append(result, ", \n");
|
||||
else
|
||||
result_append(result, "\n");
|
||||
|
||||
result_add_indent(result);
|
||||
|
||||
check_fieldname(result, fieldname);
|
||||
if (fieldname)
|
||||
result_append_fmt(result, "\"%s\": ", fieldname);
|
||||
}
|
||||
|
||||
static void result_add_indent(struct json_result *result)
|
||||
{
|
||||
size_t i, indent = tal_count(result->wrapping);
|
||||
|
||||
if (!indent)
|
||||
return;
|
||||
|
||||
for (i = 0; i < indent; i++)
|
||||
result_append(result, " ");
|
||||
}
|
||||
|
||||
static void result_add_wrap(struct json_result *result, jsmntype_t type)
|
||||
{
|
||||
size_t indent = tal_count(result->wrapping);
|
||||
|
||||
tal_resize(&result->wrapping, indent+1);
|
||||
result->wrapping[indent] = type;
|
||||
}
|
||||
|
||||
static void result_pop_wrap(struct json_result *result, jsmntype_t type)
|
||||
{
|
||||
size_t indent = tal_count(result->wrapping);
|
||||
|
||||
assert(indent);
|
||||
assert(result->wrapping[indent-1] == type);
|
||||
tal_resize(&result->wrapping, indent-1);
|
||||
}
|
||||
|
||||
void json_array_start(struct json_result *result, const char *fieldname)
|
||||
{
|
||||
json_start_member(result, fieldname);
|
||||
result_append(result, "[");
|
||||
result_add_wrap(result, JSMN_ARRAY);
|
||||
}
|
||||
|
||||
void json_array_end(struct json_result *result)
|
||||
{
|
||||
result_append(result, "\n");
|
||||
result_pop_wrap(result, JSMN_ARRAY);
|
||||
result_add_indent(result);
|
||||
result_append(result, "]");
|
||||
}
|
||||
|
||||
void json_object_start(struct json_result *result, const char *fieldname)
|
||||
{
|
||||
json_start_member(result, fieldname);
|
||||
result_append(result, "{");
|
||||
result_add_wrap(result, JSMN_OBJECT);
|
||||
}
|
||||
|
||||
void json_object_end(struct json_result *result)
|
||||
{
|
||||
result_append(result, "\n");
|
||||
result_pop_wrap(result, JSMN_OBJECT);
|
||||
result_add_indent(result);
|
||||
result_append(result, "}");
|
||||
}
|
||||
|
||||
void json_add_num(struct json_result *result, const char *fieldname, unsigned int value)
|
||||
{
|
||||
json_start_member(result, fieldname);
|
||||
result_append_fmt(result, "%u", value);
|
||||
}
|
||||
|
||||
void json_add_double(struct json_result *result, const char *fieldname, double value)
|
||||
{
|
||||
json_start_member(result, fieldname);
|
||||
result_append_fmt(result, "%f", value);
|
||||
}
|
||||
|
||||
void json_add_u64(struct json_result *result, const char *fieldname,
|
||||
uint64_t value)
|
||||
{
|
||||
json_start_member(result, fieldname);
|
||||
result_append_fmt(result, "%"PRIu64, value);
|
||||
}
|
||||
|
||||
void json_add_literal(struct json_result *result, const char *fieldname,
|
||||
const char *literal, int len)
|
||||
{
|
||||
json_start_member(result, fieldname);
|
||||
result_append_fmt(result, "%.*s", len, literal);
|
||||
}
|
||||
|
||||
void json_add_string(struct json_result *result, const char *fieldname, const char *value)
|
||||
{
|
||||
struct json_escaped *esc = json_partial_escape(NULL, value);
|
||||
|
||||
json_start_member(result, fieldname);
|
||||
result_append_fmt(result, "\"%s\"", esc->s);
|
||||
tal_free(esc);
|
||||
}
|
||||
|
||||
void json_add_bool(struct json_result *result, const char *fieldname, bool value)
|
||||
{
|
||||
json_start_member(result, fieldname);
|
||||
result_append(result, value ? "true" : "false");
|
||||
}
|
||||
|
||||
void json_add_hex(struct json_result *result, const char *fieldname,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
char *hex = tal_arr(NULL, char, hex_str_size(len));
|
||||
|
||||
hex_encode(data, len, hex, hex_str_size(len));
|
||||
json_add_string(result, fieldname, hex);
|
||||
tal_free(hex);
|
||||
}
|
||||
|
||||
void json_add_hex_talarr(struct json_result *result,
|
||||
const char *fieldname,
|
||||
const tal_t *data)
|
||||
{
|
||||
json_add_hex(result, fieldname, data, tal_bytelen(data));
|
||||
}
|
||||
|
||||
void json_add_object(struct json_result *result, ...)
|
||||
{
|
||||
va_list ap;
|
||||
const char *field;
|
||||
|
||||
va_start(ap, result);
|
||||
json_object_start(result, NULL);
|
||||
while ((field = va_arg(ap, const char *)) != NULL) {
|
||||
jsmntype_t type = va_arg(ap, jsmntype_t);
|
||||
const char *value = va_arg(ap, const char *);
|
||||
if (type == JSMN_STRING)
|
||||
json_add_string(result, field, value);
|
||||
else
|
||||
json_add_literal(result, field, value, strlen(value));
|
||||
}
|
||||
json_object_end(result);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void json_add_escaped_string(struct json_result *result, const char *fieldname,
|
||||
const struct json_escaped *esc TAKES)
|
||||
{
|
||||
json_start_member(result, fieldname);
|
||||
result_append_fmt(result, "\"%s\"", esc->s);
|
||||
if (taken(esc))
|
||||
tal_free(esc);
|
||||
}
|
||||
|
||||
struct json_result *new_json_result(const tal_t *ctx)
|
||||
{
|
||||
struct json_result *r = tal(ctx, struct json_result);
|
||||
|
||||
/* Using tal_arr means that it has a valid count. */
|
||||
r->s = tal_arrz(r, char, 1);
|
||||
r->wrapping = tal_arr(r, jsmntype_t, 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
const char *json_result_string(const struct json_result *result)
|
||||
{
|
||||
assert(tal_count(result->wrapping) == 0);
|
||||
assert(tal_count(result->s) == strlen(result->s) + 1);
|
||||
return result->s;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user