Пример #1
0
int hattrie_find_leq (hattrie_t* T, const char* key, size_t len, value_t** dst)
{
    /* create node stack for traceback */
    size_t sp = 0;
    node_ptr bs[NODESTACK_INIT];  /* base stack (will be enough mostly) */
    node_ptr *ns = bs;            /* generic ptr, could point to new mem */
    ns[sp] = T->root;

    /* find node for given key */
    int ret = 1; /* no node on the left matches */
    node_ptr node = hattrie_find_ns(&ns, &sp, NODESTACK_INIT, &key, &len);
    if (node.flag == NULL) {
        *dst = hattrie_walk_left(ns, sp, key, hattrie_find_rightmost);
        if (ns != bs) free(ns);
        if (*dst) {
            return -1; /* found previous */
        }
        return 1; /* no previous key found */
    }

    /* assign value from trie or find in table */
    if (*node.flag & NODE_TYPE_TRIE) {
        *dst = &node.t->val;
        ret = 0;     /* found exact match */
    } else {
        *dst = hhash_find(node.b, key, len);
        if (*dst) {
            ret = 0; /* found exact match */
        } else {     /* look for previous in hashtable */
            ret = hhash_find_leq(node.b, key, len, dst);
        }
    }

    /* return if found equal or left in hashtable */
    if (*dst == 0) {
        /* we're retracing from pure bucket, pop the key */
        if (*node.flag & NODE_TYPE_PURE_BUCKET) {
            --key;
        }
        /* walk up the stack of visited nodes and find closest match on the left */
        *dst = hattrie_walk_left(ns, sp, key, hattrie_find_rightmost);
        if (*dst) {
            ret = -1; /* found previous */
        } else {
            ret = 1; /* no previous key found */
        }
    }

    if (ns != bs) free(ns);
    return ret;
}
Пример #2
0
Файл: hhash.c Проект: idtek/knot
int main(int argc, char *argv[])
{
	plan(11);

	/* Create memory pool context. */
	struct mempool *pool = mp_new(64 * 1024);
	knot_mm_t mm;
	mm.ctx = pool;
	mm.alloc = (knot_mm_alloc_t)mp_alloc;
	mm.free = NULL;

	/* Create hashtable */
	int ret = KNOT_EOK;
	uint16_t len = 0;
	const char *key = "mykey", *cur = NULL, *prev = NULL;
	value_t val = (void*)0xdeadbeef, *rval = NULL;
	hhash_iter_t it;
	hhash_t *tbl = hhash_create_mm(ELEM_COUNT, &mm);
	ok(tbl != NULL, "hhash: create");
	if (tbl == NULL) {
		return KNOT_ERROR; /* No point in testing further on. */
	}

	/* Generate random keys. */
	char *keys[ELEM_COUNT];
	unsigned nfilled = 0;
	for (unsigned i = 0; i < ELEM_COUNT; ++i) {
		keys[i] = test_randstr_mm(&mm);
	}

	/* Insert single element. */
	ret = hhash_insert(tbl, key, KEY_LEN(key), val);
	ok(ret == KNOT_EOK, "hhash: insert single element");

	/* Retrieve nonexistent element. */
	cur = "nokey";
	rval = hhash_find(tbl, cur, KEY_LEN(cur));
	ok(rval == NULL, "hhash: find non-existent element");

	/* Retrieve single element. */
	rval = hhash_find(tbl, key, KEY_LEN(key));
	ok(rval != NULL, "hhash: find existing element");

	/* Fill the table. */
	for (unsigned i = 0; i < ELEM_COUNT; ++i) {
		ret = hhash_insert(tbl, keys[i], KEY_LEN(keys[i]), keys[i]);
		if (ret != KNOT_EOK) {
			nfilled = i;
			break;
		}
	}

	/* Check all keys integrity. */
	unsigned nfound = 0;
	for (unsigned i = 0; i < nfilled; ++i) {
		rval = hhash_find(tbl, keys[i], KEY_LEN(keys[i]));
		if (!rval || memcmp(*rval, keys[i], KEY_LEN(keys[i])) != 0) {
			break; /* Mismatch */
		}
		++nfound;
	}
	is_int(nfilled, nfound, "hhash: found all inserted keys");

	/* Test keys order index. */
	hhash_build_index(tbl);
	hhash_iter_begin(tbl, &it, true);
	while (!hhash_iter_finished(&it)) {
		cur = hhash_iter_key(&it, &len);
		if (!str_check_sort(prev, cur)) {
			break;
		}
		prev = cur;
		int strl = strlen(cur);
		assert(strl + 1 == len);
		hhash_iter_next(&it);
	}
	ok(hhash_iter_finished(&it), "hhash: passed order index checks");

	/* Retrieve all keys. */
	nfound = 0;
	hhash_iter_begin(tbl, &it, false);
	while (!hhash_iter_finished(&it)) {
		cur = hhash_iter_key(&it, &len);
		if (hhash_find(tbl, cur, len) == NULL) {
			break;
		} else {
			++nfound;
		}
		hhash_iter_next(&it);
	}
	ok(hhash_iter_finished(&it), "hhash: found all iterated keys");
	is_int(tbl->weight, nfound, "hhash: all iterated keys found");

	/* Test find less or equal. */
	prev = "mykey0"; /* mykey should precede it */
	hhash_find_leq(tbl, prev, KEY_LEN(prev), &rval);
	ok(rval && *rval == val, "hhash: find less or equal");

	/* Delete key and retrieve it. */
	ret = hhash_del(tbl, key, KEY_LEN(key));
	ok(ret == KNOT_EOK, "hhash: remove key");
	rval = hhash_find(tbl, key, KEY_LEN(key));
	ok(rval == NULL, "hhash: find removed element");

	/* Free all memory. */
	mp_delete(mm.ctx);
	return KNOT_EOK;
}