Exemplo n.º 1
0
static int insert_ptr(NODE **rootaddr,
					  NODE *node, int (*usrcmp)(void *, void *), int dup)
{
	NODE *root = *rootaddr;
	int cmp;
	int ins;

	SET_PTRCMP(cmp, usrcmp, node->key.ptr, root->key.ptr)
	if (cmp < 0) {
		if (root->left)
			ins = insert_ptr(&root->left, node, usrcmp, dup);
		else {
			root->left = node;
			ins = DEEPER;
		}
		switch (ins) {
			CASE DEEPER : switch (root->bal)
			{
				CASE RIGHT : root->bal = BAL;
				return INS;
				CASE BAL : root->bal = LEFT;
				return DEEPER;
				CASE LEFT : root->bal = LEFTUNBAL;
				return rebalance(rootaddr) == LESS ? INS : DEEPER;
			}
			CASE INS : return INS;
			CASE NOTINS : return NOTINS;
		}
	} else if (cmp > 0 || dup) {
Exemplo n.º 2
0
int MUTABOR_CLASS_FUNCTION(ptrlist,insert)(void * _self,const void * ptr)
{
	MUT_CLASS(ptrlist) *self=_self;
	if (!self->root) {
		self->root=calloc(sizeof(struct mutabor_avl_node_ptr),1);
		self->root->data=ptr;
		return 1;
	}
	return  insert_ptr(&self->root,ptr);
}
Exemplo n.º 3
0
static void move_item(struct btree_page *from, int from_pos,
		      struct btree_page *to, int to_pos)
{
	if (from->height)
		insert_ptr(to, to_pos, PAGE_KEY(from, from_pos),
			   *PAGE_PTR(from, from_pos));
	else
		insert_data(to, to_pos, PAGE_KEY(from, from_pos),
			    PAGE_DATA(from, from_pos));

	delete_item(from, from_pos);
}
Exemplo n.º 4
0
void
objc_hashtable_set_ptr(struct objc_hashtable *h, const void *key, const void *obj)
{
    int64_t idx = index_for_key_ptr(h, key);

    if (idx < 0) {
        insert_ptr(h, key, obj);
        return;
    }

    h->data[idx]->obj = obj;
}
Exemplo n.º 5
0
		switch (ins) {
			CASE DEEPER : switch (root->bal)
			{
				CASE RIGHT : root->bal = BAL;
				return INS;
				CASE BAL : root->bal = LEFT;
				return DEEPER;
				CASE LEFT : root->bal = LEFTUNBAL;
				return rebalance(rootaddr) == LESS ? INS : DEEPER;
			}
			CASE INS : return INS;
			CASE NOTINS : return NOTINS;
		}
	} else if (cmp > 0 || dup) {
		if (root->right)
			ins = insert_ptr(&root->right, node, usrcmp, dup);
		else {
			root->right = node;
			ins = DEEPER;
		}
		switch (ins) {
			CASE DEEPER : switch (root->bal)
			{
				CASE LEFT : root->bal = BAL;
				return INS;
				CASE BAL : root->bal = RIGHT;
				return DEEPER;
				CASE RIGHT : root->bal = RIGHTUNBAL;
				return rebalance(rootaddr) == LESS ? INS : DEEPER;
			}
			CASE INS : return INS;
Exemplo n.º 6
0
int btree_put(btree_t bt, const void *key, const void *data)
{
	const struct btree_def *def = bt->def;
	struct btree_page *new_root = NULL;
	struct btree_page *path_new[MAX_HEIGHT] = {0};
	struct btree_page *path_old[MAX_HEIGHT] = {0};
	int slot_old[MAX_HEIGHT] = {0};
	int h;

	check_btree(bt);

	/* Special case: cursor overwrite */
	if (!key) {
		if (bt->slot[0] < 0) {
			fprintf(stderr, "btree: put at invalid cursor\n");
			return -1;
		}

		memcpy(PAGE_DATA(bt->path[0], bt->slot[0]), data,
		       def->data_size);
		return 1;
	}

	/* Find a path down the tree that leads to the page which should
	 * contain this datum (though the page might be too big to hold it).
	 */
	if (trace_path(bt, key, path_old, slot_old)) {
		/* Special case: overwrite existing item */
		memcpy(PAGE_DATA(path_old[0], slot_old[0]), data,
		       def->data_size);
		return 1;
	}

	/* Trace from the leaf up. If the leaf is at its maximum size, it will
	 * need to split, and cause a pointer to be added in the parent page
	 * of the same node (which may in turn cause it to split).
	 */
	for (h = 0; h <= bt->root->height; h++) {
		if (path_old[h]->num_children < def->branches)
			break;

		path_new[h] = allocate_page(bt, h);
		if (!path_new[h])
			goto fail;
	}

	/* If the split reaches the top (i.e. the root splits), then we need
	 * to allocate a new root node.
	 */
	if (h > bt->root->height) {
		if (h >= MAX_HEIGHT) {
			fprintf(stderr, "btree: maximum height exceeded\n");
			goto fail;
		}

		new_root = allocate_page(bt, h);
		if (!new_root)
			goto fail;
	}

	/* Trace up to one page above the split. At each page that needs
	 * splitting, copy the top half of keys into the new page. Also,
	 * insert a key into one of the pages at all pages from the leaf
	 * to the page above the top of the split.
	 */
	for (h = 0; h <= bt->root->height; h++) {
		int s = slot_old[h] + 1;
		struct btree_page *p = path_old[h];

		/* If there's a split at this level, copy the top half of
		 * the keys from the old page to the new one. Check to see
		 * if the position we were going to insert into is in the
		 * old page or the new one.
		 */
		if (path_new[h]) {
			split_page(path_old[h], path_new[h]);

			if (s > p->num_children) {
				s -= p->num_children;
				p = path_new[h];
			}
		}

		/* Insert the key in the appropriate page */
		if (h)
			insert_ptr(p, s, PAGE_KEY(path_new[h - 1], 0),
				   path_new[h - 1]);
		else
			insert_data(p, s, key, data);

		/* If there was no split at this level, there's nothing to
		 * insert higher up, and we're all done.
		 */
		if (!path_new[h])
			return 0;
	}

	/* If we made it this far, the split reached the top of the tree, and
	 * we need to grow it using the extra page we allocated.
	 */
	assert (new_root);

	if (bt->slot[0] >= 0) {
		/* Fix up the cursor, if active */
		bt->slot[new_root->height] =
			bt->path[bt->root->height] == new_root ? 1 : 0;
		bt->path[new_root->height] = new_root;
	}

	memcpy(PAGE_KEY(new_root, 0), def->zero, def->key_size);
	*PAGE_PTR(new_root, 0) = path_old[h - 1];
	memcpy(PAGE_KEY(new_root, 1), PAGE_KEY(path_new[h - 1], 0),
	       def->key_size);
	*PAGE_PTR(new_root, 1) = path_new[h - 1];
	new_root->num_children = 2;
	bt->root = new_root;

	return 0;

 fail:
	for (h = 0; h <= bt->root->height; h++)
		if (path_new[h])
			free(path_new[h]);
	return -1;
}