/* * Copyright (C) Igor Sysoev */ #include #include 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; tree->start = NULL; tree->size = 0; 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; 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; ngx_radix_node_t *node, *next; bit = 0x80000000; node = tree->root; next = NULL; while (bit & mask) { if (key & bit) { next = node->right; } else { next = node->left; } bit >>= 1; if (next == NULL) { break; } node = next; } if (next) { if (node->value) { return NGX_BUSY; } node->value = value; return NGX_OK; } while (bit & mask) { if (!(next = ngx_radix_alloc(tree, sizeof(ngx_radix_node_t)))) { return NGX_ERROR; } next->value = value; next->right = NULL; next->left = NULL; next->parent = node; if (key & bit) { node->right = next; } else { node->left = next; } bit >>= 1; node = next; } return NGX_OK; } ngx_int_t ngx_radix32tree_delete(ngx_radix_tree_t *tree, uint32_t key, uint32_t mask) { uint32_t bit; ngx_radix_node_t *node; bit = 0x80000000; node = tree->root; while (node && (bit & mask)) { if (key & bit) { node = node->right; } else { node = node->left; } bit >>= 1; } if (node == NULL) { return NGX_ERROR; } if (node->right || node->left) { node->value = (uintptr_t) 0; return NGX_OK; } for ( ;; ) { if (node->parent->right == node) { node->parent->right = NULL; } else { 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; } } return NGX_OK; } 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; value = (uintptr_t) 0; 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; if (tree->free) { p = (char *) tree->free; tree->free = tree->free->right; return p; } if (tree->size < size) { if (!(tree->start = ngx_palloc(tree->pool, ngx_pagesize))) { return NULL; } tree->size = ngx_pagesize; } p = tree->start; tree->start += size; tree->size -= size; return p; }