Browse Source

params: add helper to provide default initialization.

@wythe points out that many cases want a default value, not NULL.
Nicer to do it in the param_parse() call.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 6 years ago
parent
commit
cf86c74870
  1. 11
      lightningd/params.c
  2. 17
      lightningd/params.h
  3. 24
      lightningd/test/run-params.c

11
lightningd/params.c

@ -10,13 +10,14 @@
struct param { struct param {
const char *name; const char *name;
bool is_set; bool is_set;
bool required;
param_cb cb; param_cb cb;
void *arg; void *arg;
size_t argsize; size_t argsize;
}; };
static void param_add(struct param **params, static void param_add(struct param **params,
const char *name, param_cb cb, void *arg, const char *name, bool required, param_cb cb, void *arg,
size_t argsize) size_t argsize)
{ {
#if DEVELOPER #if DEVELOPER
@ -31,6 +32,7 @@ static void param_add(struct param **params,
last->is_set = false; last->is_set = false;
last->name = name; last->name = name;
last->required = required;
last->cb = cb; last->cb = cb;
last->arg = arg; last->arg = arg;
last->argsize = argsize; last->argsize = argsize;
@ -101,7 +103,7 @@ static struct param *post_check(struct command *cmd, struct param *params)
struct param *last = first + tal_count(params); struct param *last = first + tal_count(params);
/* Make sure required params were provided. */ /* Make sure required params were provided. */
while (first != last && first->argsize == 0) { while (first != last && first->required) {
if (!first->is_set) { if (!first->is_set) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"missing required parameter: '%s'", "missing required parameter: '%s'",
@ -214,7 +216,7 @@ static int comp_by_arg(const struct param *a, const struct param *b,
static int comp_req_order(const struct param *a, const struct param *b, static int comp_req_order(const struct param *a, const struct param *b,
void *unused) void *unused)
{ {
if (a->argsize != 0 && b->argsize == 0) if (!a->required && b->required)
return 0; return 0;
return 1; return 1;
} }
@ -294,10 +296,11 @@ bool param_parse(struct command *cmd, const char *buffer,
va_start(ap, tokens); va_start(ap, tokens);
while ((name = va_arg(ap, const char *)) != NULL) { while ((name = va_arg(ap, const char *)) != NULL) {
bool required = va_arg(ap, int);
param_cb cb = va_arg(ap, param_cb); param_cb cb = va_arg(ap, param_cb);
void *arg = va_arg(ap, void *); void *arg = va_arg(ap, void *);
size_t argsize = va_arg(ap, size_t); size_t argsize = va_arg(ap, size_t);
param_add(&params, name, cb, arg, argsize); param_add(&params, name, required, cb, arg, argsize);
} }
va_end(ap); va_end(ap);

17
lightningd/params.h

@ -60,6 +60,7 @@ typedef bool(*param_cb)(const char *buffer, const jsmntok_t *tok, void *arg);
*/ */
#define param_req(name, cb, arg) \ #define param_req(name, cb, arg) \
name"", \ name"", \
true, \
(cb), \ (cb), \
(arg) + 0*sizeof((cb)((const char *)NULL, \ (arg) + 0*sizeof((cb)((const char *)NULL, \
(const jsmntok_t *)NULL, \ (const jsmntok_t *)NULL, \
@ -72,12 +73,27 @@ typedef bool(*param_cb)(const char *buffer, const jsmntok_t *tok, void *arg);
*/ */
#define param_opt(name, cb, arg) \ #define param_opt(name, cb, arg) \
name"", \ name"", \
false, \
(cb), \ (cb), \
(arg) + 0*sizeof((cb)((const char *)NULL, \ (arg) + 0*sizeof((cb)((const char *)NULL, \
(const jsmntok_t *)NULL,\ (const jsmntok_t *)NULL,\
*(arg)) == true), \ *(arg)) == true), \
sizeof(**(arg)) sizeof(**(arg))
/*
* Similar to param_req but for optional parameters.
* If not found during parsing, @arg will be set to @def.
* allocated, otherwise it will be set to NULL.
*/
#define param_opt_default(name, cb, arg, def) \
name"", \
false, \
(cb), \
(arg) + 0*sizeof((cb)((const char *)NULL, \
(const jsmntok_t *)NULL, \
(arg)) == true), \
((void)((*arg) = (def)), 0)
/* /*
* For when you want an optional raw token. * For when you want an optional raw token.
* *
@ -85,6 +101,7 @@ typedef bool(*param_cb)(const char *buffer, const jsmntok_t *tok, void *arg);
*/ */
#define param_opt_tok(name, arg) \ #define param_opt_tok(name, arg) \
name"", \ name"", \
false, \
json_tok_tok, \ json_tok_tok, \
(arg) + 0*sizeof(*(arg) == (jsmntok_t *)NULL), \ (arg) + 0*sizeof(*(arg) == (jsmntok_t *)NULL), \
sizeof(const jsmntok_t *) sizeof(const jsmntok_t *)

24
lightningd/test/run-params.c

@ -198,12 +198,12 @@ static void dup_names(void)
static void null_params(void) static void null_params(void)
{ {
uint64_t *ints = tal_arr(cmd, uint64_t, 4); uint64_t *ints = tal_arr(cmd, uint64_t, 5);
uint64_t **intptrs = tal_arr(cmd, uint64_t *, 3); uint64_t **intptrs = tal_arr(cmd, uint64_t *, 2);
/* no null params */ /* no null params */
struct json *j = struct json *j =
json_parse(cmd, "[ '10', '11', '12', '13', '14', '15', '16']"); json_parse(cmd, "[ '10', '11', '12', '13', '14', '15', '16']");
for (int i = 0; i < tal_count(ints); ++i) for (int i = 0; i < tal_count(ints) - 1; ++i)
ints[i] = i; ints[i] = i;
assert(param_parse(cmd, j->buffer, j->toks, assert(param_parse(cmd, j->buffer, j->toks,
@ -211,9 +211,9 @@ static void null_params(void)
param_req("1", json_tok_u64, &ints[1]), param_req("1", json_tok_u64, &ints[1]),
param_req("2", json_tok_u64, &ints[2]), param_req("2", json_tok_u64, &ints[2]),
param_req("3", json_tok_u64, &ints[3]), param_req("3", json_tok_u64, &ints[3]),
param_opt("4", json_tok_u64, &intptrs[0]), param_opt_default("4", json_tok_u64, &ints[4], 999),
param_opt("5", json_tok_u64, &intptrs[1]), param_opt("5", json_tok_u64, &intptrs[0]),
param_opt("6", json_tok_u64, &intptrs[2]), param_opt("6", json_tok_u64, &intptrs[1]),
NULL)); NULL));
for (int i = 0; i < tal_count(ints); ++i) for (int i = 0; i < tal_count(ints); ++i)
assert(ints[i] == i + 10); assert(ints[i] == i + 10);
@ -234,11 +234,11 @@ static void null_params(void)
param_req("3", json_tok_u64, &ints[3]), param_req("3", json_tok_u64, &ints[3]),
param_opt("4", json_tok_u64, &intptrs[0]), param_opt("4", json_tok_u64, &intptrs[0]),
param_opt("5", json_tok_u64, &intptrs[1]), param_opt("5", json_tok_u64, &intptrs[1]),
param_opt("6", json_tok_u64, &intptrs[2]), param_opt_default("6", json_tok_u64, &ints[4], 888),
NULL)); NULL));
assert(*intptrs[0] == 14); assert(*intptrs[0] == 14);
assert(intptrs[1] == NULL); assert(intptrs[1] == NULL);
assert(intptrs[2] == NULL); assert(ints[4] == 888);
} }
#if DEVELOPER #if DEVELOPER
@ -337,13 +337,13 @@ static void bad_programmer(void)
/* Add required param after optional */ /* Add required param after optional */
struct json *j = struct json *j =
json_parse(cmd, "[ '25', '546', '26', '1.1' ]"); json_parse(cmd, "[ '25', '546', '26', '1.1' ]");
unsigned int *msatoshi; unsigned int msatoshi;
double riskfactor; double riskfactor;
param_parse(cmd, j->buffer, j->toks, param_parse(cmd, j->buffer, j->toks,
param_req("u64", json_tok_u64, &ival), param_req("u64", json_tok_u64, &ival),
param_req("double", json_tok_double, &dval), param_req("double", json_tok_double, &dval),
param_opt("msatoshi", param_opt_default("msatoshi",
json_tok_number, &msatoshi), json_tok_number, &msatoshi, 100),
param_req("riskfactor", json_tok_double, param_req("riskfactor", json_tok_double,
&riskfactor), NULL); &riskfactor), NULL);
restore_assert(old_stderr); restore_assert(old_stderr);
@ -361,7 +361,7 @@ static void add_members(struct param **params,
char *name = tal_fmt(tmpctx, "%i", i); char *name = tal_fmt(tmpctx, "%i", i);
json_add_num(obj, name, i); json_add_num(obj, name, i);
json_add_num(arr, NULL, i); json_add_num(arr, NULL, i);
param_add(params, name, param_add(params, name, true,
typesafe_cb_preargs(bool, void *, typesafe_cb_preargs(bool, void *,
json_tok_number, json_tok_number,
&ints[i], &ints[i],

Loading…
Cancel
Save