common/json_stream.c: provide explicit json_add_primitive_fmt and json_add_str_fmt routines.

Rather than a generic "add member", provide two routines: one which
doesn't quote, and one which does.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2022-07-04 13:22:35 +09:30
committed by neil saitug
parent 36a29fbfbc
commit dbae5ae569
9 changed files with 118 additions and 85 deletions

View File

@@ -128,15 +128,6 @@ void json_stream_flush(struct json_stream *js)
io_wake(js);
}
char *json_member_direct(struct json_stream *js,
const char *fieldname, size_t extra)
{
char *dest;
dest = json_out_member_direct(js->jout, fieldname, extra);
return dest;
}
void json_array_start(struct json_stream *js, const char *fieldname)
{
json_out_start(js->jout, fieldname, '[');
@@ -157,18 +148,55 @@ void json_object_end(struct json_stream *js)
json_out_end(js->jout, '}');
}
void json_add_member(struct json_stream *js,
const char *fieldname,
bool quote,
const char *fmt, ...)
void json_add_primitive_fmt(struct json_stream *js,
const char *fieldname,
const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
json_out_addv(js->jout, fieldname, quote, fmt, ap);
json_out_addv(js->jout, fieldname, false, fmt, ap);
va_end(ap);
}
void json_add_str_fmt(struct json_stream *js,
const char *fieldname,
const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
json_out_addv(js->jout, fieldname, true, fmt, ap);
va_end(ap);
}
void json_add_primitive(struct json_stream *js,
const char *fieldname,
const char *val TAKES)
{
json_add_primitive_fmt(js, fieldname, "%s", val);
if (taken(val))
tal_free(val);
}
void json_add_string(struct json_stream *js,
const char *fieldname,
const char *str TAKES)
{
json_out_addstr(js->jout, fieldname, str);
if (taken(str))
tal_free(str);
}
static char *json_member_direct(struct json_stream *js,
const char *fieldname, size_t extra)
{
char *dest;
dest = json_out_member_direct(js->jout, fieldname, extra);
return dest;
}
void json_add_jsonstr(struct json_stream *js,
const char *fieldname,
const char *jsonstr)
@@ -225,76 +253,62 @@ struct io_plan *json_stream_output_(struct json_stream *js,
void json_add_num(struct json_stream *result, const char *fieldname, unsigned int value)
{
json_add_member(result, fieldname, false, "%u", value);
json_add_primitive_fmt(result, fieldname, "%u", value);
}
void json_add_u64(struct json_stream *result, const char *fieldname,
uint64_t value)
{
json_add_member(result, fieldname, false, "%"PRIu64, value);
json_add_primitive_fmt(result, fieldname, "%"PRIu64, value);
}
void json_add_s64(struct json_stream *result, const char *fieldname,
int64_t value)
{
json_add_member(result, fieldname, false, "%"PRIi64, value);
json_add_primitive_fmt(result, fieldname, "%"PRIi64, value);
}
void json_add_u32(struct json_stream *result, const char *fieldname,
uint32_t value)
{
json_add_member(result, fieldname, false, "%u", value);
json_add_primitive_fmt(result, fieldname, "%u", value);
}
void json_add_s32(struct json_stream *result, const char *fieldname,
int32_t value)
{
json_add_member(result, fieldname, false, "%d", value);
}
void json_add_literal(struct json_stream *result, const char *fieldname,
const char *literal, int len)
{
/* Literal may contain quotes, so bypass normal checks */
char *dest = json_member_direct(result, fieldname, len);
memcpy(dest, literal, len);
json_add_primitive_fmt(result, fieldname, "%d", value);
}
void json_add_stringn(struct json_stream *result, const char *fieldname,
const char *value TAKES, size_t value_len)
{
json_add_member(result, fieldname, true, "%.*s", (int)value_len, value);
json_add_str_fmt(result, fieldname, "%.*s", (int)value_len, value);
if (taken(value))
tal_free(value);
}
void json_add_string(struct json_stream *result, const char *fieldname, const char *value TAKES)
{
json_add_stringn(result, fieldname, value, strlen(value));
}
void json_add_bool(struct json_stream *result, const char *fieldname, bool value)
{
json_add_member(result, fieldname, false, value ? "true" : "false");
json_add_primitive(result, fieldname, value ? "true" : "false");
}
void json_add_null(struct json_stream *stream, const char *fieldname)
{
json_add_member(stream, fieldname, false, "null");
json_add_primitive(stream, fieldname, "null");
}
void json_add_hex(struct json_stream *js, const char *fieldname,
const void *data, size_t len)
{
/* Size without NUL term */
size_t hexlen = hex_str_size(len) - 1;
char *dest;
size_t hexlen = hex_str_size(len);
char str[hexlen];
dest = json_member_direct(js, fieldname, 1 + hexlen + 1);
dest[0] = '"';
if (!hex_encode(data, len, dest + 1, hexlen + 1))
if (!hex_encode(data, len, str, hexlen))
abort();
dest[1+hexlen] = '"';
json_add_string(js, fieldname, str);
}
void json_add_hex_talarr(struct json_stream *result,
@@ -321,8 +335,9 @@ void json_add_escaped_string(struct json_stream *result, const char *fieldname,
void json_add_timeabs(struct json_stream *result, const char *fieldname,
struct timeabs t)
{
json_add_member(result, fieldname, false, "%" PRIu64 ".%03" PRIu64,
(u64)t.ts.tv_sec, (u64)t.ts.tv_nsec / 1000000);
json_add_primitive_fmt(result, fieldname,
"%" PRIu64 ".%03" PRIu64,
(u64)t.ts.tv_sec, (u64)t.ts.tv_nsec / 1000000);
}
void json_add_time(struct json_stream *result, const char *fieldname,
@@ -365,7 +380,7 @@ void json_add_tok(struct json_stream *result, const char *fieldname,
void json_add_errcode(struct json_stream *result, const char *fieldname,
errcode_t code)
{
json_add_member(result, fieldname, false, "%"PRIerrcode, code);
json_add_primitive_fmt(result, fieldname, "%" PRIerrcode, code);
}
void json_add_invstring(struct json_stream *result, const char *invstring)
@@ -431,17 +446,17 @@ void json_add_outpoint(struct json_stream *result, const char *fieldname,
{
char hex[hex_str_size(sizeof(out->txid))];
bitcoin_txid_to_hex(&out->txid, hex, sizeof(hex));
json_add_member(result, fieldname, true, "%s:%d", hex, out->n);
json_add_str_fmt(result, fieldname, "%s:%d", hex, out->n);
}
void json_add_short_channel_id(struct json_stream *response,
const char *fieldname,
const struct short_channel_id *scid)
{
json_add_member(response, fieldname, true, "%dx%dx%d",
short_channel_id_blocknum(scid),
short_channel_id_txnum(scid),
short_channel_id_outnum(scid));
json_add_str_fmt(response, fieldname, "%dx%dx%d",
short_channel_id_blocknum(scid),
short_channel_id_txnum(scid),
short_channel_id_outnum(scid));
}
void json_add_address(struct json_stream *response, const char *fieldname,

View File

@@ -107,19 +107,50 @@ void json_object_end(struct json_stream *js);
void json_stream_append(struct json_stream *js, const char *str, size_t len);
/**
* json_add_member - add a generic member.
* json_add_primitive_fmt - add an unquoted literal member.
* @js: the json_stream.
* @fieldname: fieldname (if in object), otherwise must be NULL.
* @quote: true if should be escaped and wrapped in "".
* @fmt...: the printf-style format
*
* The resulting string from @fmt is escaped if quote is true:
* see json_member_direct to avoid quoting.
*/
void json_add_member(struct json_stream *js,
void json_add_primitive_fmt(struct json_stream *js,
const char *fieldname,
const char *fmt, ...) PRINTF_FMT(3,4);
/**
* json_add_primitive - add an unquoted literal member.
* @js: the json_stream.
* @fieldname: fieldname (if in object), otherwise must be NULL.
* @val: the primitive
*/
void json_add_primitive(struct json_stream *js,
const char *fieldname,
const char *val TAKES);
/**
* json_add_str_fmt - add a string member (printf-style).
* @js: the json_stream.
* @fieldname: fieldname (if in object), otherwise must be NULL.
* @fmt...: the printf-style format
*/
void json_add_str_fmt(struct json_stream *js,
const char *fieldname,
const char *fmt, ...) PRINTF_FMT(3,4);
/**
* json_add_string - add a string member.
* @js: the json_stream.
* @fieldname: fieldname (if in object), otherwise must be NULL.
* @str: the string
*/
void json_add_string(struct json_stream *js,
const char *fieldname,
bool quote,
const char *fmt, ...) PRINTF_FMT(4,5);
const char *str TAKES);
/* '"fieldname" : "value"' or '"value"' if fieldname is NULL. String must
* already be JSON escaped as necessary. */
void json_add_escaped_string(struct json_stream *result,
const char *fieldname,
const struct json_escape *esc TAKES);
/**
* json_add_jsonstr - add a JSON entity in a string that is already
@@ -133,17 +164,6 @@ void json_add_jsonstr(struct json_stream *js,
const char *fieldname,
const char *jsonstr);
/**
* json_member_direct - start a generic member.
* @js: the json_stream.
* @fieldname: fieldname (if in object), otherwise must be NULL.
* @extra: the space to reserve.
*
* Returns a ptr to @extra bytes.
*/
char *json_member_direct(struct json_stream *js,
const char *fieldname, size_t extra);
/**
* json_stream_output - start writing out a json_stream to this conn.
* @js: the json_stream

View File

@@ -506,9 +506,9 @@ static void json_command_malformed(struct json_connection *jcon,
json_object_start(js, NULL);
json_add_string(js, "jsonrpc", "2.0");
json_add_literal(js, "id", id, strlen(id));
json_add_primitive(js, "id", id);
json_object_start(js, "error");
json_add_member(js, "code", false, "%" PRIerrcode, JSONRPC2_INVALID_REQUEST);
json_add_errcode(js, "code", JSONRPC2_INVALID_REQUEST);
json_add_string(js, "message", error);
json_object_end(js);
json_object_end(js);
@@ -578,7 +578,7 @@ static struct json_stream *json_start(struct command *cmd)
json_object_start(js, NULL);
json_add_string(js, "jsonrpc", "2.0");
json_add_literal(js, "id", cmd->id, strlen(cmd->id));
json_add_jsonstr(js, "id", cmd->id);
return js;
}
@@ -598,7 +598,7 @@ struct json_stream *json_stream_fail_nodata(struct command *cmd,
assert(code);
json_object_start(js, "error");
json_add_member(js, "code", false, "%" PRIerrcode, code);
json_add_errcode(js, "code", code);
json_add_string(js, "message", errmsg);
return js;

View File

@@ -606,8 +606,8 @@ void json_add_opt_log_levels(struct json_stream *response, struct log *log)
struct print_filter *i;
list_for_each(&log->lr->print_filters, i, list) {
json_add_member(response, "log-level", true, "%s:%s",
log_level_name(i->level), i->prefix);
json_add_str_fmt(response, "log-level", "%s:%s",
log_level_name(i->level), i->prefix);
}
}

View File

@@ -399,7 +399,7 @@ static void sendpay_failure_notification_serialize(struct json_stream *stream,
/* In line with the format of json error returned
* by sendpay_fail(). */
json_add_member(stream, "code", false, "%" PRIerrcode, pay_errcode);
json_add_errcode(stream, "code", pay_errcode);
json_add_string(stream, "message", errmsg);
json_object_start(stream, "data");

View File

@@ -1563,8 +1563,7 @@ static void add_config(struct lightningd *ld,
|| (!streq(buf, "") && strspn(buf, "0123456789.") == strlen(buf))) {
/* Let pure numbers and true/false through as
* literals. */
json_add_literal(response, name0,
buf, strlen(buf));
json_add_primitive(response, name0, buf);
return;
}

View File

@@ -32,12 +32,6 @@ void json_add_hex_talarr(struct json_stream *result UNNEEDED,
const char *fieldname UNNEEDED,
const tal_t *data UNNEEDED)
{ fprintf(stderr, "json_add_hex_talarr called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_add_node_id */
void json_add_node_id(struct json_stream *response UNNEEDED,
const char *fieldname UNNEEDED,
@@ -47,6 +41,11 @@ void json_add_node_id(struct json_stream *response UNNEEDED,
void json_add_num(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED,
unsigned int value UNNEEDED)
{ fprintf(stderr, "json_add_num called!\n"); abort(); }
/* Generated stub for json_add_str_fmt */
void json_add_str_fmt(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_str_fmt called!\n"); abort(); }
/* Generated stub for json_add_string */
void json_add_string(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED, const char *value TAKES UNNEEDED)
{ fprintf(stderr, "json_add_string called!\n"); abort(); }

View File

@@ -208,7 +208,7 @@ struct json_stream *jsonrpc_stream_fail(struct command *cmd,
struct json_stream *js = jsonrpc_stream_start(cmd);
json_object_start(js, "error");
json_add_member(js, "code", false, "%d", code);
json_add_primitive_fmt(js, "code", "%d", code);
json_add_string(js, "message", err);
return js;

View File

@@ -634,7 +634,7 @@ static struct command_result *convert_currency(struct command *cmd,
json_add_stringn(req->js, "currency",
(const char *)ir->offer->currency,
tal_bytelen(ir->offer->currency));
json_add_member(req->js, "amount", false, "%f", double_amount);
json_add_primitive_fmt(req->js, "amount", "%f", double_amount);
return send_outreq(cmd->plugin, req);
}