nginx/src/core/ngx_radix_tree.c

203 lines
3.7 KiB
C
Raw Normal View History

2004-05-25 23:28:46 +08:00
#include <ngx_config.h>
#include <ngx_core.h>
/* STUB: page size */
#define NGX_RADIX_TREE_POOL_SIZE 4096
static void *ngx_radix_alloc(ngx_radix_tree_t *tree, size_t size);
ngx_radix_tree_t *ngx_radix_tree_create(ngx_pool_t *pool)
{
ngx_radix_tree_t *tree;
if (!(tree = ngx_palloc(pool, sizeof(ngx_radix_tree_t)))) {
return NULL;
}
tree->pool = pool;
tree->free = NULL;
2004-05-26 23:30:12 +08:00
tree->start = NULL;
2004-05-25 23:28:46 +08:00
tree->size = 0;
2004-05-27 03:33:53 +08:00
if (!(tree->root = ngx_radix_alloc(tree, sizeof(ngx_radix_node_t)))) {
return NULL;
}
tree->root->value = (uintptr_t) 0;
tree->root->right = NULL;
tree->root->left = NULL;
tree->root->parent = NULL;
2004-05-25 23:28:46 +08:00
return tree;
}
ngx_int_t ngx_radix32tree_insert(ngx_radix_tree_t *tree,
uint32_t key, uint32_t mask, uintptr_t value)
{
uint32_t bit;
2004-05-27 03:33:53 +08:00
ngx_radix_node_t *node, *next;
2004-05-25 23:28:46 +08:00
bit = 0x80000000;
node = tree->root;
2004-05-27 03:33:53 +08:00
next = NULL;
2004-05-25 23:28:46 +08:00
2004-05-27 03:33:53 +08:00
while (bit & mask) {
2004-05-25 23:28:46 +08:00
if (key & bit) {
2004-05-27 03:33:53 +08:00
next = node->right;
2004-05-25 23:28:46 +08:00
} else {
2004-05-27 03:33:53 +08:00
next = node->left;
2004-05-25 23:28:46 +08:00
}
bit >>= 1;
2004-05-27 03:33:53 +08:00
if (next == NULL) {
break;
}
node = next;
2004-05-25 23:28:46 +08:00
}
2004-05-27 03:33:53 +08:00
if (next) {
2004-05-25 23:28:46 +08:00
if (node->value) {
return NGX_BUSY;
}
node->value = value;
return NGX_OK;
}
while (bit & mask) {
2004-05-27 03:33:53 +08:00
if (!(next = ngx_radix_alloc(tree, sizeof(ngx_radix_node_t)))) {
2004-05-25 23:28:46 +08:00
return NGX_ERROR;
}
2004-05-27 03:33:53 +08:00
next->value = value;
next->right = NULL;
next->left = NULL;
next->parent = node;
2004-05-25 23:28:46 +08:00
if (key & bit) {
2004-05-27 03:33:53 +08:00
node->right = next;
2004-05-25 23:28:46 +08:00
} else {
2004-05-27 03:33:53 +08:00
node->left = next;
2004-05-25 23:28:46 +08:00
}
bit >>= 1;
2004-05-27 03:33:53 +08:00
node = next;
2004-05-25 23:28:46 +08:00
}
return NGX_OK;
}
2004-05-27 03:33:53 +08:00
ngx_int_t ngx_radix32tree_delete(ngx_radix_tree_t *tree,
uint32_t key, uint32_t mask)
2004-05-25 23:28:46 +08:00
{
uint32_t bit;
2004-05-27 03:33:53 +08:00
ngx_radix_node_t *node;
2004-05-25 23:28:46 +08:00
bit = 0x80000000;
node = tree->root;
while (node && (bit & mask)) {
if (key & bit) {
node = node->right;
} else {
node = node->left;
}
bit >>= 1;
}
2004-05-27 03:33:53 +08:00
if (node == NULL) {
return NGX_ERROR;
}
2004-05-26 23:30:12 +08:00
2004-05-27 03:33:53 +08:00
if (node->right || node->left) {
node->value = (uintptr_t) 0;
return NGX_OK;
}
2004-05-26 23:30:12 +08:00
2004-05-27 03:33:53 +08:00
for ( ;; ) {
if (node->parent->right == node) {
node->parent->right = NULL;
2004-05-26 23:30:12 +08:00
} else {
2004-05-27 03:33:53 +08:00
node->parent->left = NULL;
}
node->right = tree->free;
tree->free = node;
node = node->parent;
if (node->right || node->left || node->value || node->parent == NULL) {
break;
2004-05-26 23:30:12 +08:00
}
2004-05-25 23:28:46 +08:00
}
2004-05-27 03:33:53 +08:00
return NGX_OK;
2004-05-25 23:28:46 +08:00
}
uintptr_t ngx_radix32tree_find(ngx_radix_tree_t *tree, uint32_t key)
{
uint32_t bit;
uintptr_t value;
ngx_radix_node_t *node;
bit = 0x80000000;
2004-05-26 23:30:12 +08:00
value = (uintptr_t) 0;
2004-05-25 23:28:46 +08:00
node = tree->root;
while (node) {
if (node->value) {
value = node->value;
}
if (key & bit) {
node = node->right;
} else {
node = node->left;
}
bit >>= 1;
}
return value;
}
static void *ngx_radix_alloc(ngx_radix_tree_t *tree, size_t size)
{
char *p;
2004-05-26 23:30:12 +08:00
if (tree->free) {
p = (char *) tree->free;
tree->free = tree->free->right;
return p;
}
2004-05-25 23:28:46 +08:00
if (tree->size < size) {
2004-05-26 23:30:12 +08:00
if (!(tree->start = ngx_palloc(tree->pool, NGX_RADIX_TREE_POOL_SIZE))) {
2004-05-25 23:28:46 +08:00
return NULL;
}
tree->size = NGX_RADIX_TREE_POOL_SIZE;
}
2004-05-26 23:30:12 +08:00
p = tree->start;
tree->start += size;
2004-05-25 23:28:46 +08:00
tree->size -= size;
return p;
}