/** * Reads the previous key (order given by @a keycmp function). * @param[in] key * @param[in] tree * @param[out] data Entry value, can be @b NULL. * @return previous key or @b NULL if @a key is the first one. */ const void* piojo_btree_prev(const void *key, const piojo_btree_t *tree, void **data) { iter_t iter; PIOJO_ASSERT(tree); PIOJO_ASSERT(key); iter = search_node(key, tree); PIOJO_ASSERT(iter.bnode != NULL); if (! iter.bnode->leaf_p && iter.eidx < iter.bnode->ecnt + 1){ iter.bnode = iter.bnode->children[iter.eidx]; iter.eidx = iter.bnode->ecnt; search_max(&iter); }else if (iter.eidx > 0){ --iter.eidx; }else{ while (iter.bnode->parent != NULL){ iter.eidx = iter.bnode->pidx; iter.bnode = iter.bnode->parent; if (iter.eidx > 0){ --iter.eidx; if (data != NULL){ *data = entry_val(iter.eidx, iter.bnode, tree); } return entry_key(iter.eidx, iter.bnode, tree); } } return NULL; } if (data != NULL){ *data = entry_val(iter.eidx, iter.bnode, tree); } return entry_key(iter.eidx, iter.bnode, tree); }
/** * Searches an entry by key. * @param[in] key Entry key. * @param[in] tree * @return Entry value or @b NULL if key doesn't exist. */ void* piojo_btree_search(const void *key, const piojo_btree_t *tree) { iter_t iter; PIOJO_ASSERT(tree); PIOJO_ASSERT(key); iter = search_node(key, tree); if (iter.bnode != NULL){ return entry_val(iter.eidx, iter.bnode, tree); } return NULL; }
void LogDefer::add_log(int verbosity, const std::string &msg) { picojson::array entry; struct timeval end_tv; gettimeofday(&end_tv, NULL); entry.push_back(time_delta(&end_tv, &start_tv_)); entry.push_back(picojson::value((double)verbosity)); entry.push_back(picojson::value(msg)); picojson::value entry_val(entry); logs_.push_back(entry_val); }
static void init_entry(const void *key, const void *data, uint8_t eidx, const bnode_t *bnode, const piojo_btree_t *tree) { bool null_p = TRUE; piojo_alloc_if ator = tree->allocator; if (data == NULL){ data = &null_p; } memcpy(entry_key(eidx, bnode, tree), key, tree->eksize); bnode->kvs[eidx].value = ator.alloc_cb(tree->evsize); PIOJO_ASSERT(bnode->kvs[eidx].value); memcpy(entry_val(eidx, bnode, tree), data, tree->evsize); }
/** * Reads the last key in @a tree (order given by @a keycmp function). * @param[in] tree * @param[out] data Entry value, can be @b NULL. * @return last key or @b NULL if @a tree is empty. */ const void* piojo_btree_last(const piojo_btree_t *tree, void **data) { iter_t iter; PIOJO_ASSERT(tree); if (tree->ecount > 0){ iter.tree = tree; iter.eidx = tree->root->ecnt; iter.bnode = tree->root; search_max(&iter); if (data != NULL){ *data = entry_val(iter.eidx, iter.bnode, tree); } return entry_key(iter.eidx, iter.bnode, tree); } return NULL; }
/** * Replaces or inserts an entry. * If @a data is @b NULL, the value is replaced with @b TRUE (useful for sets). * @param[in] key Entry key. * @param[in] data Entry value. * @param[out] tree Tree being modified. * @return @b TRUE if @a key is new, @b FALSE otherwise. */ bool piojo_btree_set(const void *key, const void *data, piojo_btree_t *tree) { iter_t iter; PIOJO_ASSERT(tree); PIOJO_ASSERT(key); PIOJO_ASSERT(data || tree->evsize == sizeof(bool)); iter = insert_node(key, data, tree); if (iter.bnode == NULL){ PIOJO_ASSERT(tree->ecount < SIZE_MAX); ++tree->ecount; return TRUE; } if (data != NULL){ memcpy(entry_val(iter.eidx, iter.bnode, tree), data, tree->evsize); } return FALSE; }
int main(int ac, char **av) { struct database *db; struct group *group = NULL; char *line = NULL; size_t linesz = 0; if (!av[1]) { printf("%s database\n", av[0]); exit(1); } printf("dbtest\n"); db = open_db(av[1], 1); while (printf("> "), fflush(stdout), getline(&line, &linesz, stdin) > 0) { char *p = line + strlen(line) - 1; while (p >= line && isspace(*p)) *p-- = 0; switch (line[0]) { case 's': C(sync_db(db)); break; case 'q': C(close_db(db)); exit(0); case 'g': group = find_group(db, line + 1); if (group) printf("found\n"); break; case 'G': NEEDGROUP; C(delete_group(db, group)); group = NULL; break; case 'a': { int existed = 0; group = add_group(db, line + 1, &existed); if (existed) printf("existed\n"); break; } case 'v': NEEDGROUP; printf("%s\n", entry_val(group, line + 1)); break; case 'c': { p = line + 1; char *entry = strsep(&p, ","); NEEDGROUP; change_entry(db, group, entry, strsep(&p, "")); break; } case 'L': NEEDGROUP; clone_group(db, group, line + 1); break; case 'f': { struct group *g; p = line + 1; char *entry = strsep(&p, ","); char *val = strsep(&p, ""); g = NULL; int nr = 0; while ((g = find_entry(db, g, entry, val)) != NULL) { if (nr == 0) group = g; nr++; dump_group(group, stdout); } if (nr == 0) printf("not found\n"); break; } case 'C': NEEDGROUP; add_comment(db, group, line + 1); break; case 'd': NEEDGROUP; dump_group(group, stdout); break; case 'D': dump_database(db, stdout); break; default: usage(); break; } } return 0; }