summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2020-03-11 09:57:34 +0100
committerWim Taymans <wtaymans@redhat.com>2020-09-17 19:37:04 +0200
commit1492e02d902a46e0c88ab0658baa57d4b17b7727 (patch)
treed1fd3283d64986b82ecf6d68e1f2acaaf39022cd
parent57b3caa49a18cdb3b887ceb516a99cdadf2737f7 (diff)
query: cleanups
Add indexes and string union Rename some things Add support for non-null terminated strings.
-rw-r--r--src/tools/json.h6
-rw-r--r--src/tools/ot.h27
-rw-r--r--src/tools/pw-dump.c14
-rw-r--r--src/tools/query.c102
-rw-r--r--src/tools/query.h38
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
}