mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
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>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user