Browse Source

common/json: restore json_delve() for simple plugin parsing.

This was removed (as unused) in 6269a4c55d592e8720b7f2a304c21f61f7931238;
now I've even added tests.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
plugin-7
Rusty Russell 6 years ago
parent
commit
adf08f8914
  1. 37
      common/json.c
  2. 5
      common/json.h
  3. 93
      common/test/run-json.c

37
common/json.c

@ -4,6 +4,7 @@
#include <ccan/build_assert/build_assert.h>
#include <ccan/str/hex/hex.h>
#include <ccan/tal/str/str.h>
#include <common/utils.h>
#include <errno.h>
#include <inttypes.h>
#include <stdarg.h>
@ -273,3 +274,39 @@ void json_tok_remove(jsmntok_t **tokens, jsmntok_t *tok, size_t num)
tal_resize(tokens, tal_count(*tokens) - remove_count);
(*tokens)->size -= num;
}
const jsmntok_t *json_delve(const char *buffer,
const jsmntok_t *tok,
const char *guide)
{
while (*guide) {
const char *key;
size_t len = strcspn(guide+1, ".[]");
key = tal_strndup(tmpctx, guide+1, len);
switch (guide[0]) {
case '.':
if (tok->type != JSMN_OBJECT)
return NULL;
tok = json_get_member(buffer, tok, key);
if (!tok)
return NULL;
break;
case '[':
if (tok->type != JSMN_ARRAY)
return NULL;
tok = json_get_arr(tok, atol(key));
if (!tok)
return NULL;
/* Must be terminated */
assert(guide[1+strlen(key)] == ']');
len++;
break;
default:
abort();
}
guide += len + 1;
}
return tok;
}

5
common/json.h

@ -73,4 +73,9 @@ jsmntok_t *json_tok_copy(const tal_t *ctx, const jsmntok_t *tok);
*/
void json_tok_remove(jsmntok_t **tokens, jsmntok_t *tok, size_t num);
/* Guide is a string with . for members, [] around indexes. */
const jsmntok_t *json_delve(const char *buffer,
const jsmntok_t *tok,
const char *guide);
#endif /* LIGHTNING_COMMON_JSON_H */

93
common/test/run-json.c

@ -1,4 +1,5 @@
#include "../json.c"
#include <ccan/mem/mem.h>
#include <common/utils.h>
#include <stdio.h>
@ -38,11 +39,103 @@ static int test_json_tok_bitcoin_amount(void)
return 0;
}
static void test_json_delve(void)
{
const jsmntok_t *toks, *t;
char *buf;
bool ok;
buf = "{\"1\":\"one\", \"2\":\"two\", \"3\":[\"three\", {\"deeper\": 17}]}";
toks = json_parse_input(tmpctx, buf, strlen(buf), &ok);
assert(ok);
t = json_delve(buf, toks, ".1");
assert(t);
assert(t->type == JSMN_STRING);
assert(json_tok_streq(buf, t, "one"));
assert(t == toks+2);
t = json_delve(buf, toks, ".2");
assert(t);
assert(t->type == JSMN_STRING);
assert(json_tok_streq(buf, t, "two"));
assert(t == toks+4);
t = json_delve(buf, toks, ".3");
assert(t);
assert(t->type == JSMN_ARRAY);
assert(t == toks+6);
t = json_delve(buf, toks, ".3[0]");
assert(t);
assert(t->type == JSMN_STRING);
assert(json_tok_streq(buf, t, "three"));
assert(t == toks+7);
t = json_delve(buf, toks, ".3[1]");
assert(t);
assert(t->type == JSMN_OBJECT);
assert(t == toks+8);
t = json_delve(buf, toks, ".3[1].deeper");
assert(t);
assert(t->type == JSMN_PRIMITIVE);
assert(memeq(buf + t->start, t->end - t->start, "17", strlen("17")));
assert(t == toks+10);
t = json_delve(buf, toks, ".4");
assert(!t);
t = json_delve(buf, toks, "[0]");
assert(!t);
t = json_delve(buf, toks, ".deeper");
assert(!t);
t = json_delve(buf, toks, ".3[2]");
assert(!t);
t = json_delve(buf, toks, ".3[2].deeper");
assert(!t);
t = json_delve(buf, toks, ".3[0].deeper");
assert(!t);
t = json_delve(buf, toks, ".3[1].deeper[0]");
assert(!t);
t = json_delve(buf, toks, ".3[1][0]");
assert(!t);
/* Now a real example. */
buf = "{\n"
" \"jsonrpc\": \"2.0\", \n"
" \"method\": \"init\", \n"
" \"id\": 1, \n"
" \"params\": {\n"
" \"options\": {\n"
" }, \n"
" \"configuration\": {\n"
" \"lightning-dir\": \"/tmp/ltests-n2hyd543/test_pay_plugin_1/lightning-2/\", \n"
" \"rpc-file\": \"lightning-rpc\"\n"
" }\n"
" }\n"
"}\n"
"\n";
toks = json_parse_input(tmpctx, buf, strlen(buf), &ok);
assert(ok);
t = json_delve(buf, toks, ".rpcfile");
assert(!t);
t = json_delve(buf, toks, ".configuration.rpc-file");
assert(!t);
t = json_delve(buf, toks, ".params.configuration.rpc-file");
assert(t);
assert(t->type == JSMN_STRING);
assert(json_tok_streq(buf, t, "lightning-rpc"));
}
int main(void)
{
setup_locale();
setup_tmpctx();
test_json_tok_bitcoin_amount();
test_json_delve();
assert(!taken_any());
take_cleanup();
tal_free(tmpctx);
}

Loading…
Cancel
Save