gpointer li_radixtree_lookup_exact(liRadixTree *tree, const void *key, guint32 bits) { liRadixNode *node; rdxBase input[INPUT_SIZE(bits)], current; guint32 pos = 0; rdx_get_input(input, key, bits); pos = 0; current = input[0]; node = tree->zero; while (node) { rdxBase mask = RDX_MASK(node->width); if (node->width > bits) break; /* prefix longer than key */ if ((current & mask) != node->key) break; /* doesn't match */ if (node->width == bits) return node->data; /* exact match */ if (mask & 0x1) { /* next "layer" */ current = input[++pos]; bits -= RDXBITS; node = (current & RDX_BIT(0)) ? node->right : node->left; } else { node = (current & RDX_BIT(node->width)) ? node->right : node->left; } } return NULL; }
gpointer li_radixtree_remove(liRadixTree *tree, const void *key, guint32 bits) { rdxBase input[INPUT_SIZE(bits)]; gpointer data; rdx_get_input(input, key, bits); data = radixtree_remove(&tree->zero, input, bits); return data; }
gpointer li_radixtree_lookup(liRadixTree *tree, const void *key, guint32 bits) { /* longest matching prefix */ liRadixNode *node; rdxBase input[INPUT_SIZE(bits)], current; guint32 pos = 0; gpointer data = NULL; rdx_get_input(input, key, bits); pos = 0; current = input[0]; node = tree->zero; while (node) { rdxBase mask = RDX_MASK(node->width); if (node->width > bits) break; /* prefix longer than key */ if ((current & mask) != node->key) break; /* doesn't match */ if (node->data) data = node->data; /* longest matching prefix */ if (node->width == bits) break; /* "end of key" */ if (mask & 0x1) { /* next "layer" */ current = input[++pos]; bits -= RDXBITS; node = (current & (1 << (RDXBITS-1))) ? node->right : node->left; } else { node = (current & (1 << (RDXBITS-node->width-1))) ? node->right : node->left; } } return data; }
gpointer li_radixtree_insert(liRadixTree *tree, const void *key, guint32 bits, gpointer data) { liRadixNode *node, **nodeloc; rdxBase input[INPUT_SIZE(bits)], current; guint32 pos = 0; rdx_get_input(input, key, bits); if (!data) return NULL; pos = 0; current = input[0]; nodeloc = &tree->zero; while (NULL != (node = *nodeloc)) { rdxBase mask = RDX_MASK(node->width); if (node->width > bits || (current & mask) != node->key) { /* prefix longer than key or key doesn't match */ /* split node */ liRadixNode *newnode; guint32 width = (node->width > bits) ? bits : node->width; assert(width <= RDXBITS); mask = RDX_MASK(width); while ((current & mask) != (node->key & mask)) { width--; mask <<= 1; } assert(width <= RDXBITS-1); newnode = g_slice_new0(liRadixNode); newnode->width = width; newnode->key = current & mask; if (node->key & RDX_BIT(width)) { /* current may not have a "next" bit */ newnode->right = node; *nodeloc = newnode; nodeloc = &newnode->left; } else { newnode->left = node; *nodeloc = newnode; nodeloc = &newnode->right; } if (width == bits) { newnode->data = data; return NULL; } else { /* NULL == *nodeloc */ break; } } if (node->width == bits) { /* exact match */ gpointer olddata = node->data; node->data = data; return olddata; } if (mask & 0x1) { /* next "layer" */ current = input[++pos]; bits -= RDXBITS; nodeloc = (current & RDX_BIT(0)) ? &node->right : &node->left; } else { nodeloc = (current & RDX_BIT(node->width)) ? &node->right : &node->left; } } while (bits > RDXBITS) { node = g_slice_new0(liRadixNode); node->width = RDXBITS; node->key = current; *nodeloc = node; /* next "layer" */ current = input[++pos]; bits -= RDXBITS; nodeloc = (current & RDX_BIT(0)) ? &node->right : &node->left; } node = g_slice_new0(liRadixNode); node->width = bits; node->key = current & RDX_MASK(bits); node->data = data; *nodeloc = node; return NULL; }