From: Phil Carmody Date: Wed, 22 Jun 2016 08:17:09 +0000 (+0300) Subject: lib: json-tree - API change to permit more featureful implementation X-Git-Tag: 2.3.0.rc1~3124 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fcd3d6214ce1b8169b6481c78e02d9054901fed3;p=thirdparty%2Fdovecot%2Fcore.git lib: json-tree - API change to permit more featureful implementation Provide accessors for the innards of the tree's nodes, so that the node internals can be changed freely (needed for DAPI). Constify params where sensible. NOTE: this enforced const-correctness may *break* (cause a failure to build) some clients that didn't use const where they could have. Only obox2 is known to break. Add sibling functions with more parameters to expand the range of functionality, and inline rewire the old simple functions to call the more generic ones. Signed-off-by: Phil Carmody --- diff --git a/src/lib/json-tree.c b/src/lib/json-tree.c index b64683acc8..fbbb889d7c 100644 --- a/src/lib/json-tree.c +++ b/src/lib/json-tree.c @@ -8,7 +8,8 @@ struct json_tree { struct json_tree_node *root, *cur, *cur_child; }; -struct json_tree *json_tree_init(void) +struct json_tree * +json_tree_init_type(enum json_type container) { struct json_tree *tree; pool_t pool; @@ -17,7 +18,7 @@ struct json_tree *json_tree_init(void) tree = p_new(pool, struct json_tree, 1); tree->pool = pool; tree->root = tree->cur = p_new(tree->pool, struct json_tree_node, 1); - tree->cur->value_type = JSON_TYPE_OBJECT; + tree->cur->value_type = container == JSON_TYPE_ARRAY ? container : JSON_TYPE_OBJECT; return tree; } @@ -130,14 +131,18 @@ int json_tree_append(struct json_tree *tree, enum json_type type, return 0; } -struct json_tree_node *json_tree_root(struct json_tree *tree) +const struct json_tree_node * +json_tree_root(const struct json_tree *tree) { return tree->root; } -struct json_tree_node * -json_tree_find_key(struct json_tree_node *node, const char *key) +const struct json_tree_node * +json_tree_find_key(const struct json_tree_node *node, const char *key) { + i_assert(node->value_type == JSON_TYPE_OBJECT); + + node = json_tree_get_child(node); for (; node != NULL; node = node->next) { if (node->key != NULL && strcmp(node->key, key) == 0) return node; @@ -145,22 +150,23 @@ json_tree_find_key(struct json_tree_node *node, const char *key) return NULL; } -struct json_tree_node * -json_tree_find_child_with(struct json_tree_node *node, +const struct json_tree_node * +json_tree_find_child_with(const struct json_tree_node *node, const char *key, const char *value) { - struct json_tree_node *child; + const struct json_tree_node *child; i_assert(node->value_type == JSON_TYPE_OBJECT || node->value_type == JSON_TYPE_ARRAY); - for (node = node->value.child; node != NULL; node = node->next) { + for (node = json_tree_get_child(node); node != NULL; node = node->next) { if (node->value_type != JSON_TYPE_OBJECT) continue; - child = json_tree_find_key(node->value.child, key); - if (child != NULL && child->value.str != NULL && - strcmp(child->value.str, value) == 0) + child = json_tree_find_key(node, key); + if (child != NULL && + json_tree_get_value_str(child) != NULL && + strcmp(json_tree_get_value_str(child), value) == 0) return node; } return NULL; diff --git a/src/lib/json-tree.h b/src/lib/json-tree.h index 980d27aceb..a995c755be 100644 --- a/src/lib/json-tree.h +++ b/src/lib/json-tree.h @@ -3,6 +3,9 @@ #include "json-parser.h" +/* Direct access to this structure is not encouraged, use the inline + function accessors where possible, so that the implementation + details can remain fluid, or, even better, hidden. */ struct json_tree_node { /* object key, or NULL if we're in a list */ const char *key; @@ -16,8 +19,26 @@ struct json_tree_node { const char *str; } value; }; +static inline ATTR_PURE const struct json_tree_node *json_tree_get_child(const struct json_tree_node *node) +{ + return node->value.child; +} +static inline ATTR_PURE const char *json_tree_get_value_str(const struct json_tree_node *node) +{ + return node->value.str; +} + +/* You can build a list or an object, nothing else. */ +struct json_tree *json_tree_init_type(enum json_type container); +static inline struct json_tree *json_tree_init(void) +{ + return json_tree_init_type(JSON_TYPE_OBJECT); +} +static inline struct json_tree *json_tree_init_array(void) +{ + return json_tree_init_type(JSON_TYPE_ARRAY); +} -struct json_tree *json_tree_init(void); void json_tree_deinit(struct json_tree **tree); /* Append data to a tree. The type/value should normally come from json-parser. @@ -27,14 +48,15 @@ int json_tree_append(struct json_tree *tree, enum json_type type, const char *value); /* Return the root node. */ -struct json_tree_node *json_tree_root(struct json_tree *tree); -/* Find a node with the specified key (from node's siblings) */ -struct json_tree_node * -json_tree_find_key(struct json_tree_node *node, const char *key); +const struct json_tree_node * +json_tree_root(const struct json_tree *tree); +/* Find a node with the specified key from an OBJECT node */ +const struct json_tree_node * +json_tree_find_key(const struct json_tree_node *node, const char *key); /* Find an object node (from an array), which contains the specified key=value in its values. */ -struct json_tree_node * -json_tree_find_child_with(struct json_tree_node *node, +const struct json_tree_node * +json_tree_find_child_with(const struct json_tree_node *node, const char *key, const char *value); #endif diff --git a/src/lib/test-json-tree.c b/src/lib/test-json-tree.c index edae5dffa4..040e865531 100644 --- a/src/lib/test-json-tree.c +++ b/src/lib/test-json-tree.c @@ -57,7 +57,7 @@ struct { void test_json_tree(void) { struct json_tree *tree; - struct json_tree_node *root, *node, *node1, *node2; + const struct json_tree_node *root, *node, *node1, *node2; unsigned int i; test_begin("json tree"); @@ -70,7 +70,6 @@ void test_json_tree(void) root = json_tree_root(tree); i_assert(root != NULL); test_assert(root->value_type == JSON_TYPE_OBJECT); - root = root->value.child; i_assert(root != NULL); for (i = 0; i < 10+2; i += 2) {