#define CJ_CB_CONTINUE 1
static int cj_cb_boolean(void *ctx, int boolVal) {
- cj_cb_inc_array_index(ctx, /* update_key = */ 0);
+ cj_advance_array(ctx);
- return (CJ_CB_CONTINUE);
+ return CJ_CB_CONTINUE;
}
static int cj_cb_null(void *ctx) {
- cj_cb_inc_array_index(ctx, /* update_key = */ 0);
+ cj_advance_array(ctx);
- return (CJ_CB_CONTINUE);
+ return CJ_CB_CONTINUE;
}
static int cj_cb_number(void *ctx, const char *number, yajl_len_t number_len) {
memcpy(buffer, number, number_len);
buffer[sizeof(buffer) - 1] = 0;
-
- if ((key == NULL) || !CJ_IS_KEY(key)) {
- if (key != NULL &&
- !db->state[db->depth].in_array /*can be inhomogeneous*/) {
- NOTICE("curl_json plugin: Found \"%s\", but the configuration expects"
- " a map.",
- buffer);
- return CJ_CB_CONTINUE;
- }
--
- cj_cb_inc_array_index(ctx, /* update_key = */ 1);
- key = db->state[db->depth].key;
- if ((key == NULL) || !CJ_IS_KEY(key)) {
- return CJ_CB_CONTINUE;
- }
- } else {
- cj_cb_inc_array_index(ctx, /* update_key = */ 1);
+ 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);
+ cj_advance_array(ctx);
+ return CJ_CB_CONTINUE;
}
- type = cj_get_type(key);
- status = parse_value(buffer, &vt, type);
+ int type = cj_get_type(key);
+ value_t vt;
+ int status = parse_value(buffer, &vt, type);
if (status != 0) {
NOTICE("curl_json plugin: Unable to parse number: \"%s\"", buffer);
- return (CJ_CB_CONTINUE);
+ cj_advance_array(ctx);
+ return CJ_CB_CONTINUE;
}
cj_submit(db, key, &vt);
- return (CJ_CB_CONTINUE);
+ cj_advance_array(ctx);
+ return CJ_CB_CONTINUE;
} /* int cj_cb_number */
/* Queries the key-tree of the parent context for "in_name" and, if found,
static int cj_cb_string(void *ctx, const unsigned char *val, yajl_len_t len) {
/* Handle the string as if it was a number. */
- return (cj_cb_number(ctx, (const char *)val, len));
+ return cj_cb_number(ctx, (const char *)val, len);
} /* int cj_cb_string */
-static int cj_cb_start(void *ctx) {
- cj_t *db = (cj_t *)ctx;
- if (++db->depth >= YAJL_MAX_DEPTH) {
- ERROR("curl_json plugin: %s depth exceeds max, aborting.",
- db->url ? db->url : db->sock);
- return CJ_CB_ABORT;
- }
- return CJ_CB_CONTINUE;
-}
-
static int cj_cb_end(void *ctx) {
cj_t *db = (cj_t *)ctx;
db->state[db->depth].tree = NULL;
- --db->depth;
+ db->depth--;
+ cj_advance_array(ctx);
- return (CJ_CB_CONTINUE);
+ return CJ_CB_CONTINUE;
}
static int cj_cb_start_map(void *ctx) {
- cj_cb_inc_array_index(ctx, /* update_key = */ 1);
- return cj_cb_start(ctx);
+ cj_t *db = (cj_t *)ctx;
+
+ if ((db->depth + 1) >= YAJL_MAX_DEPTH) {
+ ERROR("curl_json plugin: %s depth exceeds max, aborting.",
+ db->url ? db->url : db->sock);
- return (CJ_CB_ABORT);
++ return CJ_CB_ABORT;
+ }
+ db->depth++;
- return (CJ_CB_CONTINUE);
++ return CJ_CB_CONTINUE;
}
static int cj_cb_end_map(void *ctx) { return cj_cb_end(ctx); }
*dest = temp;
- return (0);
+ return 0;
} /* }}} int cj_config_append_string */
+/* cj_append_key adds key to the configuration stored in db.
+ *
+ * For example:
+ * "httpd/requests/count",
+ * "httpd/requests/current" ->
+ * { "httpd": { "requests": { "count": $key, "current": $key } } }
+ */
+static int cj_append_key(cj_t *db, cj_key_t *key) { /* {{{ */
+ if (db->tree == NULL)
+ db->tree = cj_avl_create();
+
+ c_avl_tree_t *tree = db->tree;
+
+ char const *start = key->path;
+ if (*start == '/')
+ ++start;
+
+ char const *end;
+ while ((end = strchr(start, '/')) != NULL) {
+ char name[PATH_MAX];
+
+ size_t len = end - start;
+ if (len == 0)
+ break;
+
+ 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);
+ }
+
+ tree = value;
+ start = end + 1;
+ }
+
+ if (strlen(start) == 0) {
+ ERROR("curl_json plugin: invalid key: %s", key->path);
+ return -1;
+ }
+
+ c_avl_insert(tree, strdup(start), key);
+ return 0;
+} /* }}} int cj_append_key */
+
static int cj_config_add_key(cj_t *db, /* {{{ */
oconfig_item_t *ci) {
cj_key_t *key;
if (key->type == NULL) {
WARNING("curl_json plugin: `Type' missing in `Key' block.");
cj_key_free(key);
- return (-1);
+ return -1;
}
- /* store path in a tree that will match the json map structure, example:
- * "httpd/requests/count",
- * "httpd/requests/current" ->
- * { "httpd": { "requests": { "count": $key, "current": $key } } }
- */
- char *ptr;
- char *name;
- c_avl_tree_t *tree;
-
- if (db->tree == NULL)
- db->tree = cj_avl_create();
-
- tree = db->tree;
- ptr = key->path;
- if (*ptr == '/')
- ++ptr;
-
- name = ptr;
- while ((ptr = strchr(name, '/')) != NULL) {
- char ent[PATH_MAX];
- c_avl_tree_t *value;
- size_t len;
-
- len = ptr - name;
- if (len == 0)
- break;
-
- len = COUCH_MIN(len, sizeof(ent) - 1);
- sstrncpy(ent, name, len + 1);
-
- if (c_avl_get(tree, ent, (void *)&value) != 0) {
- value = cj_avl_create();
- c_avl_insert(tree, strdup(ent), value);
- }
-
- tree = value;
- name = ptr + 1;
- }
-
- if (strlen(name) == 0) {
- ERROR("curl_json plugin: invalid key: %s", key->path);
+ status = cj_append_key(db, key);
+ if (status != 0) {
cj_key_free(key);
return -1;
}