diff options
author | Wim Taymans <wtaymans@redhat.com> | 2020-03-11 09:57:34 +0100 |
---|---|---|
committer | Wim Taymans <wtaymans@redhat.com> | 2020-09-17 19:37:04 +0200 |
commit | 1492e02d902a46e0c88ab0658baa57d4b17b7727 (patch) | |
tree | d1fd3283d64986b82ecf6d68e1f2acaaf39022cd | |
parent | 57b3caa49a18cdb3b887ceb516a99cdadf2737f7 (diff) |
query: cleanups
Add indexes and string union
Rename some things
Add support for non-null terminated strings.
-rw-r--r-- | src/tools/json.h | 6 | ||||
-rw-r--r-- | src/tools/ot.h | 27 | ||||
-rw-r--r-- | src/tools/pw-dump.c | 14 | ||||
-rw-r--r-- | src/tools/query.c | 102 | ||||
-rw-r--r-- | src/tools/query.h | 38 |
5 files changed, 116 insertions, 71 deletions
diff --git a/src/tools/json.h b/src/tools/json.h index f8672edc..07e1ed28 100644 --- a/src/tools/json.h +++ b/src/tools/json.h @@ -53,8 +53,8 @@ static inline int ot_json_dump2(struct ot_node *node, struct ot_json_ctx *ctx) #define OUT(fmt,...) printf(fmt, ##__VA_ARGS__) #define IND(fmt,level,...) printf("%*s"fmt, (level)*2, "", ##__VA_ARGS__) - if (node->k) { - IND("%s\"%s\"%s: ", l0, KEY, node->k, NORMAL); + if (node->k.val) { + IND("%s\"%*s\"%s: ", l0, KEY, node->k.len, node->k.val, NORMAL); l0 = 0; } switch (node->type) { @@ -77,7 +77,7 @@ static inline int ot_json_dump2(struct ot_node *node, struct ot_json_ctx *ctx) IND("%s%f%s", l0, NUMBER, node->v.d, NORMAL); break; case OT_STRING: - IND("%s\"%s\"%s", l0, STRING, node->v.s, NORMAL); + IND("%s\"%*s\"%s", l0, STRING, node->v.s.len, node->v.s.val, NORMAL); break; case OT_ARRAY: case OT_OBJECT: diff --git a/src/tools/ot.h b/src/tools/ot.h index 92a6bd29..81a80fbf 100644 --- a/src/tools/ot.h +++ b/src/tools/ot.h @@ -44,13 +44,18 @@ enum ot_type { OT_OBJECT, }; +struct ot_string { + int len; + const char *val; +}; + union ot_val { bool b; int32_t i; int64_t l; float f; double d; - const char *s; + struct ot_string s; const void *cp; void *p; }; @@ -64,7 +69,7 @@ struct ot_node { int32_t index; /**< index of subnode to retrieve, * < 0 for count from last */ - const char *k; /**< key is set when in object */ + struct ot_string k; /**< key is set when in object */ union ot_val v; /**< value of node */ int (*iterate) (struct ot_node *node, struct ot_node *sub); @@ -74,15 +79,15 @@ struct ot_node { char buffer[64]; }; -#define OT_INIT_NULL(_k) (struct ot_node){ .type = OT_NULL, .k = _k } -#define OT_INIT_BOOL(_k,_v) (struct ot_node){ .type = OT_BOOL, .k = _k, .v.b = _v } -#define OT_INIT_INT(_k,_v) (struct ot_node){ .type = OT_INT, .k = _k, .v.i = _v } -#define OT_INIT_LONG(_k,_v) (struct ot_node){ .type = OT_LONG, .k = _k, .v.l = _v } -#define OT_INIT_FLOAT(_k,_v) (struct ot_node){ .type = OT_FLOAT, .k = _k, .v.f = _v } -#define OT_INIT_DOUBLE(_k,_v) (struct ot_node){ .type = OT_DOUBLE, .k = _k, .v.d = _v } -#define OT_INIT_STRING(_k,_v) (struct ot_node){ .type = _v ? OT_STRING : OT_NULL, .k = _k, .v.s = _v } -#define OT_INIT_ARRAY(_k,_i) (struct ot_node){ .type = OT_ARRAY, .k = _k, .iterate = _i } -#define OT_INIT_OBJECT(_k,_i) (struct ot_node){ .type = OT_OBJECT, .k = _k, .iterate = _i } +#define OT_INIT_NULL(_k) (struct ot_node){ .type = OT_NULL, .k = { -1, _k } } +#define OT_INIT_BOOL(_k,_v) (struct ot_node){ .type = OT_BOOL, .k = { -1, _k }, .v.b = _v } +#define OT_INIT_INT(_k,_v) (struct ot_node){ .type = OT_INT, .k = { -1, _k }, .v.i = _v } +#define OT_INIT_LONG(_k,_v) (struct ot_node){ .type = OT_LONG, .k = { -1, _k }, .v.l = _v } +#define OT_INIT_FLOAT(_k,_v) (struct ot_node){ .type = OT_FLOAT, .k = { -1, _k }, .v.f = _v } +#define OT_INIT_DOUBLE(_k,_v) (struct ot_node){ .type = OT_DOUBLE, .k = { -1, _k }, .v.d = _v } +#define OT_INIT_STRING(_k,_v) (struct ot_node){ .type = _v ? OT_STRING : OT_NULL, .k = { -1, _k }, .v.s = { -1, _v } } +#define OT_INIT_ARRAY(_k,_i) (struct ot_node){ .type = OT_ARRAY, .k = { -1, _k} , .iterate = _i } +#define OT_INIT_OBJECT(_k,_i) (struct ot_node){ .type = OT_OBJECT, .k = { -1, _k }, .iterate = _i } /** iterate over node * \returns 1 when a new item is returned in sub, 0 when finished. diff --git a/src/tools/pw-dump.c b/src/tools/pw-dump.c index cf7a23ee..e9bdd37f 100644 --- a/src/tools/pw-dump.c +++ b/src/tools/pw-dump.c @@ -119,7 +119,7 @@ int main(int argc, char *argv[]) struct pw_loop *l; struct pw_properties *props = NULL; struct ot_node root, result; - struct ot_path path[5]; + struct ot_step steps[5]; pw_init(&argc, &argv); @@ -155,14 +155,14 @@ int main(int argc, char *argv[]) pw_tree_get_root(data.tree, &root); - path[0] = OT_INIT_MATCH_SLICE(0,1,1); - path[1] = OT_INIT_MATCH_KEY("info"); - path[2] = OT_INIT_MATCH_ALL(); - path[3] = OT_INIT_MATCH_KEY("object.id"); + steps[0] = OT_INIT_MATCH_SLICE(0,9,1); + steps[1] = OT_INIT_MATCH_KEY("info"); + steps[2] = OT_INIT_MATCH_ALL(); + steps[3] = OT_INIT_MATCH_KEY("object.id"); - ot_query_begin(&root, path, 1, &result); + ot_path_begin(&root, steps, 4, &result); ot_json_dump(&result, 2); - ot_query_end(&result); + ot_path_end(&result); pw_context_destroy(data.context); pw_main_loop_destroy(data.loop); diff --git a/src/tools/query.c b/src/tools/query.c index d6724f8a..bbea001e 100644 --- a/src/tools/query.c +++ b/src/tools/query.c @@ -30,8 +30,8 @@ #include "query.h" struct context { - struct ot_path *path; - uint32_t n_path; + struct ot_step *steps; + uint32_t n_steps; int32_t depth; struct ot_node *root; }; @@ -42,68 +42,92 @@ static int iterate_one(struct ot_node *node, struct ot_node *sub) if (node->index < -1 || node->index > 0) return 0; *sub = *ctx->root; - sub->k = NULL; + sub->k.val = NULL; return 1; } -static void enter_path(struct context *ctx, struct ot_node *root, int32_t depth) +static void enter_step(struct context *ctx, struct ot_node *parent, int32_t depth) { - struct ot_path *next; + struct ot_step *next; ctx->depth = depth; - next = &ctx->path[depth]; - next->root = root; - next->root->index = next->slice.start; + next = &ctx->steps[depth]; + next->parent = parent; + next->parent->index = next->type == OT_MATCH_SLICE ? next->match.slice.start : 0; } -static int iterate_path(struct ot_node *node, struct ot_node *sub) +static int iterate_steps(struct ot_node *node, struct ot_node *sub) { struct context *ctx = node->extra[0].p; uint32_t depth; - struct ot_path *path; - struct ot_node *root; + struct ot_step *step; + struct ot_node *parent; + union ot_match *match, mtch; int32_t index; int res; again: depth = ctx->depth; - path = &ctx->path[depth]; - root = path->root; + step = &ctx->steps[depth]; + parent = step->parent; + match = &step->match; - switch (path->type) { + switch (step->type) { case OT_MATCH_DEEP: break; case OT_MATCH_SLICE: - index = root->index; - if ((path->slice.end >= 0 && index >= path->slice.end) || - (path->slice.end < 0 && index <= path->slice.end)) + index = parent->index; + if ((match->slice.end >= 0 && index >= match->slice.end) || + (match->slice.end < 0 && index <= match->slice.end)) goto back; - if ((res = ot_node_iterate(root, &path->current)) <= 0) + if ((res = ot_node_iterate(parent, &step->current)) <= 0) goto back; - root->index += path->slice.step; + parent->index += match->slice.step; + break; + case OT_MATCH_INDEXES: + do { + index = parent->index; + if (index >= match->indexes.n_indexes) + goto back; + parent->index = match->indexes.indexes[index]; + res = ot_node_iterate(parent, &step->current); + parent->index = index + 1; + } while (res <= 0); break; case OT_MATCH_KEY: - if (root->type != OT_OBJECT) + mtch.keys.n_keys = 1; + mtch.keys.keys = &match->key; + match = &mtch; + /* fallthrough */ + case OT_MATCH_KEYS: + if (parent->type != OT_OBJECT) goto back; - while (true) { - if ((res = ot_node_iterate(root, &path->current)) <= 0) + do { + index = parent->index; + if (index >= match->keys.n_keys) goto back; - root->index++; - if (strcmp(path->current.k, path->key) == 0) - break; - } + parent->index = 0; + do { + if ((res = ot_node_iterate(parent, &step->current)) <= 0) + break; + parent->index++; + } while (strncmp(step->current.k.val, + match->keys.keys[index], + step->current.k.len) != 0); + parent->index = index + 1; + } while (res <= 0); break; default: goto back; } - if (path->check != NULL && - !path->check(path)) + if (step->check != NULL && + !step->check(step)) goto again; - if (++depth < ctx->n_path) { - enter_path(ctx, &path->current, depth); + if (++depth < ctx->n_steps) { + enter_step(ctx, &step->current, depth); goto again; } else { - *sub = path->current; - sub->k = NULL; + *sub = step->current; + sub->k.val = NULL; return 1; } back: @@ -113,27 +137,27 @@ back: goto again; } -int ot_query_begin(struct ot_node *root, struct ot_path *path, uint32_t n_path, struct ot_node *result) +int ot_path_begin(struct ot_node *root, struct ot_step *steps, uint32_t n_steps, struct ot_node *result) { struct context *ctx; if ((ctx = calloc(1, sizeof(*ctx))) == NULL) return -errno; - ctx->path = path; - ctx->n_path = n_path; + ctx->steps = steps; + ctx->n_steps = n_steps; ctx->root = root; - *result = OT_INIT_ARRAY(NULL, n_path > 0 ? iterate_path : iterate_one); + *result = OT_INIT_ARRAY(NULL, n_steps > 0 ? iterate_steps : iterate_one); result->extra[0].p = ctx; - if (n_path > 0) - enter_path(ctx, root, 0); + if (n_steps > 0) + enter_step(ctx, root, 0); return 0; } -void ot_query_end(struct ot_node *result) +void ot_path_end(struct ot_node *result) { free(result->extra[0].p); } diff --git a/src/tools/query.h b/src/tools/query.h index 2a7c06ba..322b7aad 100644 --- a/src/tools/query.h +++ b/src/tools/query.h @@ -31,34 +31,50 @@ extern "C" { #include "ot.h" -enum ot_match { +enum ot_match_type { OT_MATCH_DEEP, OT_MATCH_SLICE, + OT_MATCH_INDEXES, OT_MATCH_KEY, + OT_MATCH_KEYS, }; -struct ot_path { - enum ot_match type; +union ot_match { struct { int32_t start; int32_t end; int32_t step; } slice; const char *key; - struct ot_node *root; + struct { + int32_t *indexes; + int32_t n_indexes; + } indexes; + struct { + const char **keys; + int32_t n_keys; + } keys; +}; + +struct ot_step { + enum ot_match_type type; + union ot_match match; + struct ot_node *parent; struct ot_node current; - int (*check) (struct ot_path *path); + int (*check) (struct ot_step *path); void *data; }; -#define OT_INIT_MATCH_ALL() (struct ot_path){ .type = OT_MATCH_SLICE, .slice = { 0, -1, 1 } } -#define OT_INIT_MATCH_INDEX(i) (struct ot_path){ .type = OT_MATCH_SLICE, .slice = { i, i, 1 } } -#define OT_INIT_MATCH_SLICE(s,e,st) (struct ot_path){ .type = OT_MATCH_SLICE, .slice = { s, e, st } } -#define OT_INIT_MATCH_KEY(k) (struct ot_path){ .type = OT_MATCH_KEY, .slice = { 0, -1, 1 }, .key = k } +#define OT_INIT_MATCH_ALL() (struct ot_step){ .type = OT_MATCH_SLICE, .match.slice = { 0, -1, 1 } } +#define OT_INIT_MATCH_INDEX(i) (struct ot_step){ .type = OT_MATCH_SLICE, .match.slice = { (i), (i)+1, 1 } } +#define OT_INIT_MATCH_INDEXES(idx,n_idx) (struct ot_step){ .type = OT_MATCH_INDEXES, .match.indexes = { idx, n_idx } } +#define OT_INIT_MATCH_SLICE(s,e,st) (struct ot_step){ .type = OT_MATCH_SLICE, .match.slice = { s, e, st } } +#define OT_INIT_MATCH_KEY(k) (struct ot_step){ .type = OT_MATCH_KEY, .match.key = k } +#define OT_INIT_MATCH_KEYS(keys,n_keys) (struct ot_step){ .type = OT_MATCH_KEYS, .match.keys = { keys, n_keys } } -int ot_query_begin(struct ot_node *root, struct ot_path *path, uint32_t n_path, struct ot_node *result); +int ot_path_begin(struct ot_node *root, struct ot_step *steps, uint32_t n_steps, struct ot_node *result); -void ot_query_end(struct ot_node *result); +void ot_path_end(struct ot_node *result); #ifdef __cplusplus } |