/* "number" may not be null terminated, so copy it into a buffer before * parsing. */ static int cj_cb_number (void *ctx, const char *number, unsigned int number_len) { char buffer[number_len + 1]; cj_t *db = (cj_t *)ctx; cj_key_t *key = db->state[db->depth].key; value_t vt; int type; int status; if ((key == NULL) || !CJ_IS_KEY (key)) return (CJ_CB_CONTINUE); memcpy (buffer, number, number_len); buffer[sizeof (buffer) - 1] = 0; type = cj_get_type (key); status = parse_value (buffer, &vt, type); if (status != 0) { NOTICE ("curl_json plugin: Unable to parse number: \"%s\"", buffer); return (CJ_CB_CONTINUE); } cj_submit (db, key, &vt); return (CJ_CB_CONTINUE); } /* int cj_cb_number */
/* Queries the key-tree of the parent context for "in_name" and, if found, * updates the "key" field of the current context. Otherwise, "key" is set to * NULL. */ static int cj_cb_map_key (void *ctx, unsigned char const *in_name, yajl_len_t in_name_len) { cj_t *db = (cj_t *)ctx; c_avl_tree_t *tree; tree = db->state[db->depth-1].tree; if (tree != NULL) { cj_key_t *value = NULL; char *name; size_t name_len; /* Create a null-terminated version of the name. */ name = db->state[db->depth].name; name_len = COUCH_MIN ((size_t) in_name_len, sizeof (db->state[db->depth].name) - 1); memcpy (name, in_name, name_len); name[name_len] = 0; if (c_avl_get (tree, name, (void *) &value) == 0) { if (CJ_IS_KEY((cj_key_t*)value)) { db->state[db->depth].key = value; } else { db->state[db->depth].tree = (c_avl_tree_t*) 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 = (c_avl_tree_t*) value; } else db->state[db->depth].key = NULL; } return (CJ_CB_CONTINUE); }
static void cj_tree_free (c_avl_tree_t *tree) /* {{{ */ { char *name; void *value; while (c_avl_pick (tree, (void *) &name, (void *) &value) == 0) { cj_key_t *key = (cj_key_t *)value; if (CJ_IS_KEY(key)) cj_key_free (key); else cj_tree_free ((c_avl_tree_t *)value); sfree (name); } c_avl_destroy (tree); } /* }}} void cj_tree_free */
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; value_t vt; int type; int status; /* Create a null-terminated version of the string. */ 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); cj_cb_inc_array_index (ctx, /* update_key = */ 1); key = db->state[db->depth].key; if (key == NULL) { return (CJ_CB_CONTINUE); } } else { cj_cb_inc_array_index (ctx, /* update_key = */ 1); } type = cj_get_type (key); status = parse_value (buffer, &vt, type); if (status != 0) { NOTICE ("curl_json plugin: Unable to parse number: \"%s\"", buffer); return (CJ_CB_CONTINUE); } cj_submit (db, key, &vt); return (CJ_CB_CONTINUE); } /* int cj_cb_number */
static int cj_cb_string (void *ctx, const unsigned char *val, unsigned int len) { cj_t *db = (cj_t *)ctx; char str[len + 1]; /* Create a null-terminated version of the string. */ memcpy (str, val, len); str[len] = 0; /* No configuration for this string -> simply return. */ if (db->state[db->depth].key == NULL) return (CJ_CB_CONTINUE); if (!CJ_IS_KEY (db->state[db->depth].key)) { NOTICE ("curl_json plugin: Found string \"%s\", but the configuration " "expects a map here.", str); return (CJ_CB_CONTINUE); } /* Handle the string as if it was a number. */ return (cj_cb_number (ctx, (const char *) val, len)); } /* int cj_cb_string */