Commit 09ddfdf2 authored by Vladimír Čunát's avatar Vladimír Čunát Committed by Daniel Salzman

trie: generalize the sign of key chars and flip it

Nitpick: the byte typedef didn't seem sufficiently useful,
regardless of trie_key_t sign.
parent 8ac079ed
......@@ -28,7 +28,6 @@
#include "contrib/mempattern.h"
#include "libknot/errcode.h"
typedef unsigned char byte;
typedef unsigned int uint;
typedef uint64_t index_t; /*!< nibble index into a key */
typedef uint64_t word; /*!< A type-punned word */
......@@ -51,7 +50,7 @@ typedef char static_assert_pointer_fits_in_word
*/
typedef struct {
uint32_t cow:1, len:KEYLENBITS;
char chars[];
trie_key_t chars[];
} tkey_t;
/*! \brief A trie node is a pair of words.
......@@ -159,7 +158,7 @@ typedef char static_assert_bmp_fits
#define BMP_NOBYTE (BIG1 << TSHIFT_BMP)
/*! \brief Initialize a new leaf, copying the key, and returning failure code. */
static int mkleaf(node_t *leaf, const char *key, uint32_t len, knot_mm_t *mm)
static int mkleaf(node_t *leaf, const trie_key_t *key, uint32_t len, knot_mm_t *mm)
{
if (unlikely((word)len > (BIG1 << KEYLENBITS)))
return KNOT_ENOMEM;
......@@ -253,14 +252,14 @@ static uint twigoff(const node_t *t, bitmap_t bit)
}
/*! \brief Extract a nibble from a key and turn it into a bitmask. */
static bitmap_t keybit(index_t ni, const char *key, uint32_t len)
static bitmap_t keybit(index_t ni, const trie_key_t *key, uint32_t len)
{
index_t bytei = ni >> 1;
if (bytei >= len)
return BMP_NOBYTE;
byte ki = (byte)key[bytei];
uint8_t ki = (uint8_t)key[bytei];
uint nibble = (ni & 1) ? (ki & 0xf) : (ki >> 4);
// skip one for NOBYTE nibbles after the end of the key
......@@ -268,7 +267,7 @@ static bitmap_t keybit(index_t ni, const char *key, uint32_t len)
}
/*! \brief Extract a nibble from a key and turn it into a bitmask. */
static bitmap_t twigbit(const node_t *t, const char *key, uint32_t len)
static bitmap_t twigbit(const node_t *t, const trie_key_t *key, uint32_t len)
{
assert(isbranch(t));
return keybit(branch_index(t), key, len);
......@@ -307,7 +306,8 @@ static uint twig_number(node_t *child, node_t *parent)
}
/*! \brief Simple string comparator. */
static int key_cmp(const char *k1, uint32_t k1_len, const char *k2, uint32_t k2_len)
static int key_cmp(const trie_key_t *k1, uint32_t k1_len,
const trie_key_t *k2, uint32_t k2_len)
{
int ret = memcmp(k1, k2, MIN(k1_len, k2_len));
if (ret != 0) {
......@@ -432,7 +432,7 @@ size_t trie_weight(const trie_t *tbl)
return tbl->weight;
}
trie_val_t* trie_get_try(trie_t *tbl, const char *key, uint32_t len)
trie_val_t* trie_get_try(trie_t *tbl, const trie_key_t *key, uint32_t len)
{
assert(tbl);
if (!tbl->weight)
......@@ -487,7 +487,7 @@ static void del_found(trie_t *tbl, node_t *t, node_t *p, bitmap_t b, trie_val_t
// passed to mm_realloc will not be correct; TODO?
}
int trie_del(trie_t *tbl, const char *key, uint32_t len, trie_val_t *val)
int trie_del(trie_t *tbl, const trie_key_t *key, uint32_t len, trie_val_t *val)
{
assert(tbl);
if (!tbl->weight)
......@@ -599,7 +599,7 @@ static inline int ns_longer(nstack_t *ns)
*
* \return KNOT_EOK or KNOT_ENOMEM.
*/
static int ns_find_branch(nstack_t *ns, const char *key, uint32_t len,
static int ns_find_branch(nstack_t *ns, const trie_key_t *key, uint32_t len,
index_t *idiff, bitmap_t *tbit, bitmap_t *kbit)
{
assert(ns && ns->len && idiff);
......@@ -632,8 +632,8 @@ static int ns_find_branch(nstack_t *ns, const char *key, uint32_t len,
goto success;
}
if (likely(bytei < MIN(len,klen))) {
byte k2 = (byte)lkey->chars[bytei];
byte k1 = (byte)key[bytei];
uint8_t k2 = (uint8_t)lkey->chars[bytei];
uint8_t k1 = (uint8_t)key[bytei];
if (((k1 ^ k2) & 0xf0) == 0)
index += 1;
}
......@@ -788,7 +788,7 @@ static int ns_prefix(nstack_t *ns)
* \return KNOT_EOK for exact match, 1 for previous, KNOT_ENOENT for not-found,
* or KNOT_E*.
*/
static int ns_get_leq(nstack_t *ns, const char *key, uint32_t len)
static int ns_get_leq(nstack_t *ns, const trie_key_t *key, uint32_t len)
{
// First find the key with longest-matching prefix
index_t idiff;
......@@ -830,7 +830,7 @@ static int ns_get_leq(nstack_t *ns, const char *key, uint32_t len)
return 1;
}
int trie_get_leq(trie_t *tbl, const char *key, uint32_t len, trie_val_t **val)
int trie_get_leq(trie_t *tbl, const trie_key_t *key, uint32_t len, trie_val_t **val)
{
assert(tbl && val);
if (tbl->weight == 0) {
......@@ -853,7 +853,7 @@ int trie_get_leq(trie_t *tbl, const char *key, uint32_t len, trie_val_t **val)
return ret;
}
int trie_it_get_leq(trie_it_t *it, const char *key, uint32_t len)
int trie_it_get_leq(trie_it_t *it, const trie_key_t *key, uint32_t len)
{
assert(it && it->stack[0] && it->alen);
const trie_t *tbl = ns_gettrie(it);
......@@ -876,7 +876,7 @@ static int cow_pushdown(trie_cow_t *cow, nstack_t *ns);
/*! \brief implementation of trie_get_ins() and trie_get_cow() */
static trie_val_t* cow_get_ins(trie_cow_t *cow, trie_t *tbl,
const char *key, uint32_t len)
const trie_key_t *key, uint32_t len)
{
assert(tbl);
// First leaf in an empty tbl?
......@@ -944,7 +944,7 @@ err_leaf:
}
}
trie_val_t* trie_get_ins(trie_t *tbl, const char *key, uint32_t len)
trie_val_t* trie_get_ins(trie_t *tbl, const trie_key_t *key, uint32_t len)
{
return cow_get_ins(NULL, tbl, key, len);
}
......@@ -1024,7 +1024,7 @@ trie_it_t *trie_it_clone(const trie_it_t *it)
return it2;
}
const char* trie_it_key(trie_it_t *it, size_t *len)
const trie_key_t* trie_it_key(trie_it_t *it, size_t *len)
{
assert(it && it->len);
node_t *t = it->stack[it->len - 1];
......@@ -1111,7 +1111,7 @@ void trie_it_del(trie_it_t *it)
p = it->stack[it->len - 2];
assert(isbranch(p));
size_t len;
const char *key = trie_it_key(it, &len);
const trie_key_t *key = trie_it_key(it, &len);
b = twigbit(p, key, len);
}
// We could trie_it_{next,prev,...}(it) now, in case we wanted that semantics.
......@@ -1323,12 +1323,12 @@ trie_t* trie_cow_new(trie_cow_t *cow)
return cow->new;
}
trie_val_t* trie_get_cow(trie_cow_t *cow, const char *key, uint32_t len)
trie_val_t* trie_get_cow(trie_cow_t *cow, const trie_key_t *key, uint32_t len)
{
return cow_get_ins(cow, cow->new, key, len);
}
int trie_del_cow(trie_cow_t *cow, const char *key, uint32_t len, trie_val_t *val)
int trie_del_cow(trie_cow_t *cow, const trie_key_t *key, uint32_t len, trie_val_t *val)
{
trie_t *tbl = cow->new;
if (unlikely(!tbl->weight))
......
......@@ -25,7 +25,7 @@
/*!
* \brief Native API of QP-tries:
*
* - keys are char strings, not necessarily zero-terminated,
* - keys are uint8_t strings, not necessarily zero-terminated,
* the structure copies the contents of the passed keys
* - values are void* pointers, typically you get an ephemeral pointer to it
* - key lengths are limited by 2^32-1 ATM
......@@ -33,6 +33,8 @@
/*! \brief Element value. */
typedef void* trie_val_t;
/*! \brief Key for indexing tries. Sign could be flipped easily. */
typedef uint8_t trie_key_t;
/*! \brief Opaque structure holding a QP-trie. */
typedef struct trie trie_t;
......@@ -52,7 +54,7 @@ typedef trie_val_t (*trie_dup_cb)(const trie_val_t val, knot_mm_t *mm);
* \param len The length of key
* \param d Additional user data
*/
typedef void trie_cb(trie_val_t val, const char *key, size_t len, void *d);
typedef void trie_cb(trie_val_t val, const trie_key_t *key, size_t len, void *d);
/*! \brief Opaque type for holding the copy-on-write state for a QP-trie. */
typedef struct trie_cow trie_cow_t;
......@@ -73,10 +75,10 @@ trie_t* trie_dup(const trie_t *orig, trie_dup_cb dup_cb, knot_mm_t *mm);
size_t trie_weight(const trie_t *tbl);
/*! \brief Search the trie, returning NULL on failure. */
trie_val_t* trie_get_try(trie_t *tbl, const char *key, uint32_t len);
trie_val_t* trie_get_try(trie_t *tbl, const trie_key_t *key, uint32_t len);
/*! \brief Search the trie, inserting NULL trie_val_t on failure. */
trie_val_t* trie_get_ins(trie_t *tbl, const char *key, uint32_t len);
trie_val_t* trie_get_ins(trie_t *tbl, const trie_key_t *key, uint32_t len);
/*!
* \brief Search for less-or-equal element.
......@@ -88,7 +90,7 @@ trie_val_t* trie_get_ins(trie_t *tbl, const char *key, uint32_t len);
* \return KNOT_EOK for exact match, 1 for previous, KNOT_ENOENT for not-found,
* or KNOT_E*.
*/
int trie_get_leq(trie_t *tbl, const char *key, uint32_t len, trie_val_t **val);
int trie_get_leq(trie_t *tbl, const trie_key_t *key, uint32_t len, trie_val_t **val);
/*!
* \brief Apply a function to every trie_val_t, in order.
......@@ -102,7 +104,7 @@ int trie_apply(trie_t *tbl, int (*f)(trie_val_t *, void *), void *d);
*
* If val!=NULL and deletion succeeded, the deleted value is set.
*/
int trie_del(trie_t *tbl, const char *key, uint32_t len, trie_val_t *val);
int trie_del(trie_t *tbl, const trie_key_t *key, uint32_t len, trie_val_t *val);
/*! \brief Create a new iterator pointing to the first element (if any).
......@@ -129,7 +131,7 @@ trie_it_t *trie_it_clone(const trie_it_t *it);
* \note The len is uint32_t internally but size_t is better for our usage
* as it is without an additional type conversion.
*/
const char* trie_it_key(trie_it_t *it, size_t *len);
const trie_key_t* trie_it_key(trie_it_t *it, size_t *len);
/*! \brief Return pointer to the value of the current element (writable). */
trie_val_t* trie_it_val(trie_it_t *it);
......@@ -169,7 +171,7 @@ void trie_it_next_nosub(trie_it_t *it);
void trie_it_parent(trie_it_t *it);
/*! \brief trie_get_leq() but with an iterator. */
int trie_it_get_leq(trie_it_t *it, const char *key, uint32_t len);
int trie_it_get_leq(trie_it_t *it, const trie_key_t *key, uint32_t len);
/*! \brief Remove the current element. The iterator will get trie_it_finished() */
void trie_it_del(trie_it_t *it);
......@@ -231,7 +233,7 @@ trie_t* trie_cow_new(trie_cow_t *cow);
* object you must change the original's reachability from shared to old-only.
* New objects (including copies) must have new-only reachability.
*/
trie_val_t* trie_get_cow(trie_cow_t *cow, const char *key, uint32_t len);
trie_val_t* trie_get_cow(trie_cow_t *cow, const trie_key_t *key, uint32_t len);
/*!
* \brief variant of trie_del() for use during COW transactions
......@@ -243,7 +245,7 @@ trie_val_t* trie_get_cow(trie_cow_t *cow, const char *key, uint32_t len);
* If val!=NULL and deletion succeeded, the *val is set to the deleted
* value pointer.
*/
int trie_del_cow(trie_cow_t *cow, const char *key, uint32_t len, trie_val_t *val);
int trie_del_cow(trie_cow_t *cow, const trie_key_t *key, uint32_t len, trie_val_t *val);
/*! \brief clean up the old trie after committing a COW transaction
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment