radix_tree_internal.h [plain text]
#ifndef __RADIX_TREE_INTERNAL_H
#define __RADIX_TREE_INTERNAL_H
#include <radix_tree.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
#define RADIX_LABEL_BITS 11 //max number of label bits per edge
#define RADIX_TREE_KEY_BITS (64 - 12) //number of keybits we use (starting from MSB)
struct radix_edge {
unsigned label : RADIX_LABEL_BITS;
unsigned index : 16;
unsigned labelBits : 4;
unsigned isLeaf : 1;
};
_Static_assert(sizeof(struct radix_edge) == 4, "size of radix_edge must be 4");
struct radix_node {
union {
struct {
struct radix_edge edges[2];
};
struct {
uint64_t stackid : 32;
uint64_t size : 32;
};
struct {
uint16_t next_free;
bool next_free_is_initialized;
};
uint64_t as_u64;
};
};
_Static_assert(sizeof(struct radix_node) == 8, "size of radix_node must be 8");
struct radix_tree {
char header[8];
uint32_t leaf_size_shift;
uint32_t num_nodes;
uint32_t next_free;
struct radix_node nodes[];
};
static inline
uint64_t
leaf_size(struct radix_tree *tree, struct radix_node *node)
{
return ((uint64_t)node->size) << tree->leaf_size_shift;
}
static inline
void
set_leaf_size(struct radix_tree *tree, struct radix_node *node, uint64_t size)
{
node->size = size >> tree->leaf_size_shift;
assert(leaf_size(tree, node) == size);
}
static inline
bool
edge_valid(struct radix_edge *edge)
{
return edge->labelBits != 0;
}
static inline
unsigned
keybits(uint64_t key, int labelBits, int keyshift)
{
uint64_t mask = (1 << labelBits) - 1;
return (unsigned) (key >> (64 - labelBits - keyshift)) & mask;
}
static inline
uint64_t
extend_key(uint64_t key, int labelBits, int keyshift, uint64_t label) {
uint64_t mask __unused = (1 << labelBits) - 1;
assert((label & ~mask) == 0);
int shift = 64 - keyshift - labelBits; assert((key & (mask << shift)) == 0);
return key | (label << shift);
}
static inline
bool
edge_matches(struct radix_edge *edge, uint64_t key, int keyshift)
{
if (!edge_valid(edge)) {
return false;
}
return keybits(key, edge->labelBits, keyshift) == edge->label;
}
static inline
int
count_matching_bits(struct radix_edge *edge, uint64_t key, int keyshift)
{
int labelBits = edge->labelBits;
uint64_t label = edge->label;
while (labelBits) {
if (keybits(key, labelBits, keyshift) == label) {
return labelBits;
}
labelBits--;
label >>= 1;
}
return 0;
}
static inline
struct radix_node *
getnode(struct radix_tree *tree, unsigned index)
{
if (index > tree->num_nodes) {
return NULL;
} else {
return &tree->nodes[index];
}
}
struct radix_tree *
radix_tree_init(void *buf, size_t size);
void
radix_tree_print(struct radix_tree *tree);
bool
radix_tree_fsck(struct radix_tree *tree);
#endif