summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: b7ff429)
raw | patch | inline | side by side (parent: b7ff429)
author | Florian Forster <octo@collectd.org> | |
Tue, 16 May 2017 20:44:26 +0000 (22:44 +0200) | ||
committer | Florian Forster <octo@collectd.org> | |
Tue, 16 May 2017 20:49:13 +0000 (22:49 +0200) |
Previously, keys had a "magic" as their first member which was used to
differentiate between the two types when they were returned from the
binary search tree.
This patch creates a new struct, cj_tree_entry_t, which includes an enum
identifying which union member is valid.
differentiate between the two types when they were returned from the
binary search tree.
This patch creates a new struct, cj_tree_entry_t, which includes an enum
identifying which union member is valid.
src/curl_json.c | patch | blob | history | |
src/curl_json_test.c | patch | blob | history |
diff --git a/src/curl_json.c b/src/curl_json.c
index a589cd658eb990adce119a378e9ef6c403c81353..6b50b454de1f231f24a3a4a0890693faaee063e5 100644 (file)
--- a/src/curl_json.c
+++ b/src/curl_json.c
#endif
#define CJ_DEFAULT_HOST "localhost"
-#define CJ_KEY_MAGIC 0x43484b59UL /* CHKY */
-#define CJ_IS_KEY(key) ((key)->magic == CJ_KEY_MAGIC)
#define CJ_ANY "*"
#define COUCH_MIN(x, y) ((x) < (y) ? (x) : (y))
typedef struct cj_key_s cj_key_t;
struct cj_key_s /* {{{ */
{
- unsigned long magic;
char *path;
char *type;
char *instance;
};
/* }}} */
+/* cj_tree_entry_t is a union of either a metric configuration ("key") or a tree
+ * mapping array indexes / map keys to a descendant cj_tree_entry_t*. */
+typedef struct {
+ enum { KEY, TREE } type;
+ union {
+ c_avl_tree_t *tree;
+ cj_key_t *key;
+ };
+} cj_tree_entry_t;
+
+/* cj_state_t is a stack providing the configuration relevant for the context
+ * that is currently being parsed. If entry->type == KEY, the parser should
+ * expect a metric (a numeric value). If entry->type == TREE, the parser should
+ * expect an array of map to descent into. If entry == NULL, no configuration
+ * exists for this part of the JSON structure. */
+typedef struct {
+ cj_tree_entry_t *entry;
+ _Bool in_array;
+ int index;
+ char name[DATA_MAX_NAME_LEN];
+} cj_state_t;
+
struct cj_s /* {{{ */
{
char *instance;
yajl_handle yajl;
c_avl_tree_t *tree;
int depth;
- struct {
- union {
- c_avl_tree_t *tree;
- cj_key_t *key;
- };
- _Bool in_array;
- int index;
- char name[DATA_MAX_NAME_LEN];
- } state[YAJL_MAX_DEPTH];
+ cj_state_t state[YAJL_MAX_DEPTH];
};
typedef struct cj_s cj_t; /* }}} */
} /* }}} size_t cj_curl_callback */
static int cj_get_type(cj_key_t *key) {
- const data_set_t *ds;
-
- if ((key == NULL) || !CJ_IS_KEY(key))
+ if (key == NULL)
return -EINVAL;
- ds = plugin_get_ds(key->type);
+ const data_set_t *ds = plugin_get_ds(key->type);
if (ds == NULL) {
static char type[DATA_MAX_NAME_LEN] = "!!!invalid!!!";
sstrncpy(db->state[db->depth].name, key, sizeof(db->state[db->depth].name));
- c_avl_tree_t *tree = db->state[db->depth - 1].tree;
- if (tree == NULL) {
+ if (db->state[db->depth - 1].entry == NULL ||
+ db->state[db->depth - 1].entry->type != TREE) {
return 0;
}
- /* the parent has a key, so the tree pointer is invalid. */
- if (CJ_IS_KEY(db->state[db->depth - 1].key)) {
- return 0;
- }
+ c_avl_tree_t *tree = db->state[db->depth - 1].entry->tree;
+ cj_tree_entry_t *e = NULL;
- void *value = NULL;
- if (c_avl_get(tree, key, (void *)&value) == 0) {
- if (CJ_IS_KEY((cj_key_t *)value)) {
- db->state[db->depth].key = value;
- } else {
- db->state[db->depth].tree = value;
- }
- } else if (c_avl_get(tree, CJ_ANY, (void *)&value) == 0) {
- if (CJ_IS_KEY((cj_key_t *)value)) {
- db->state[db->depth].key = value;
- } else {
- db->state[db->depth].tree = value;
- }
+ if (c_avl_get(tree, key, (void *)&e) == 0) {
+ db->state[db->depth].entry = e;
+ } else if (c_avl_get(tree, CJ_ANY, (void *)&e) == 0) {
+ db->state[db->depth].entry = e;
} else {
- db->state[db->depth].key = NULL;
+ db->state[db->depth].entry = NULL;
}
return 0;
}
static int cj_cb_number(void *ctx, const char *number, yajl_len_t number_len) {
- char buffer[number_len + 1];
-
cj_t *db = (cj_t *)ctx;
- cj_key_t *key = db->state[db->depth].key;
/* Create a null-terminated version of the string. */
+ char buffer[number_len + 1];
memcpy(buffer, number, number_len);
buffer[sizeof(buffer) - 1] = 0;
-
-
- if (key == NULL) {
- /* no config for this element. */
- cj_advance_array(ctx);
- return CJ_CB_CONTINUE;
- } else if (!CJ_IS_KEY(key)) {
- /* the config expects a map or an array. */
- NOTICE(
- "curl_json plugin: Found \"%s\", but the configuration expects a map.",
- buffer);
+ if (db->state[db->depth].entry == NULL ||
+ db->state[db->depth].entry->type != KEY) {
+ if (db->state[db->depth].entry != NULL) {
+ NOTICE("curl_json plugin: Found \"%s\", but the configuration expects a "
+ "map.",
+ buffer);
+ }
cj_advance_array(ctx);
return CJ_CB_CONTINUE;
}
+ cj_key_t *key = db->state[db->depth].entry->key;
+
int type = cj_get_type(key);
value_t vt;
int status = parse_value(buffer, &vt, type);
static int cj_cb_end(void *ctx) {
cj_t *db = (cj_t *)ctx;
- db->state[db->depth].tree = NULL;
+ memset(&db->state[db->depth], 0, sizeof(db->state[db->depth]));
db->depth--;
cj_advance_array(ctx);
return (CJ_CB_CONTINUE);
static void cj_tree_free(c_avl_tree_t *tree) /* {{{ */
{
char *name;
- void *value;
+ cj_tree_entry_t *e;
- while (c_avl_pick(tree, (void *)&name, (void *)&value) == 0) {
- cj_key_t *key = (cj_key_t *)value;
+ while (c_avl_pick(tree, (void *)&name, (void *)&e) == 0) {
+ sfree(name);
- if (CJ_IS_KEY(key))
- cj_key_free(key);
+ if (e->type == KEY)
+ cj_key_free(e->key);
else
- cj_tree_free((c_avl_tree_t *)value);
-
- sfree(name);
+ cj_tree_free(e->tree);
+ sfree(e);
}
c_avl_destroy(tree);
len = COUCH_MIN(len, sizeof(name) - 1);
sstrncpy(name, start, len + 1);
- c_avl_tree_t *value;
- if (c_avl_get(tree, name, (void *)&value) != 0) {
- value = cj_avl_create();
- c_avl_insert(tree, strdup(name), value);
+ cj_tree_entry_t *e;
+ if (c_avl_get(tree, name, (void *)&e) != 0) {
+ e = calloc(1, sizeof(*e));
+ if (e == NULL)
+ return ENOMEM;
+ e->type = TREE;
+ e->tree = cj_avl_create();
+
+ c_avl_insert(tree, strdup(name), e);
}
- tree = value;
+ if (e->type != TREE)
+ return EINVAL;
+
+ tree = e->tree;
start = end + 1;
}
return -1;
}
- c_avl_insert(tree, strdup(start), key);
+ cj_tree_entry_t *e = calloc(1, sizeof(*e));
+ if (e == NULL)
+ return ENOMEM;
+ e->type = KEY;
+ e->key = key;
+
+ c_avl_insert(tree, strdup(start), e);
return 0;
} /* }}} int cj_append_key */
ERROR("curl_json plugin: calloc failed.");
return (-1);
}
- key->magic = CJ_KEY_MAGIC;
if (strcasecmp("Key", ci->key) == 0) {
status = cf_util_get_string(ci, &key->path);
db->depth = 0;
memset(&db->state, 0, sizeof(db->state));
- db->state[db->depth].tree = db->tree;
+ db->state[0].entry = &(cj_tree_entry_t){
+ .type = TREE, .tree = db->tree,
+ };
+
+ int status = cj_perform(db);
+
+ db->state[0].entry = NULL;
- return cj_perform(db);
+ return status;
} /* }}} int cj_read */
static int cj_init(void) /* {{{ */
diff --git a/src/curl_json_test.c b/src/curl_json_test.c
index 1e4d3b3bb0db7a96d151238a79e1c271591f36f9..4b9846607f794e3a95c12d171fc3fccea7b69686 100644 (file)
--- a/src/curl_json_test.c
+++ b/src/curl_json_test.c
db->curl = (void *)cj_avl_create();
cj_key_t *key = calloc(1, sizeof(*key));
- key->magic = CJ_KEY_MAGIC;
key->path = strdup(key_path);
key->type = strdup("MAGIC");
assert(cj_append_key(db, key) == 0);
- db->state[0].tree = db->tree;
+ db->state[0].entry = &(cj_tree_entry_t){
+ .type = TREE, .tree = db->tree,
+ };
cj_curl_callback(json, strlen(json), 1, db);
#if HAVE_YAJL_V2
yajl_parse_complete(db->yajl);
#endif
+ db->state[0].entry = NULL;
+
return db;
}