This source file includes following definitions.
- ngx_radix_tree_create
 
- ngx_radix32tree_insert
 
- ngx_radix32tree_delete
 
- ngx_radix32tree_find
 
- ngx_radix128tree_insert
 
- ngx_radix128tree_delete
 
- ngx_radix128tree_find
 
- ngx_radix_alloc
 
#include <ngx_config.h>
#include <ngx_core.h>
static ngx_radix_node_t *ngx_radix_alloc(ngx_radix_tree_t *tree);
ngx_radix_tree_t *
ngx_radix_tree_create(ngx_pool_t *pool, ngx_int_t preallocate)
{
    uint32_t           key, mask, inc;
    ngx_radix_tree_t  *tree;
    tree = ngx_palloc(pool, sizeof(ngx_radix_tree_t));
    if (tree == NULL) {
        return NULL;
    }
    tree->pool = pool;
    tree->free = NULL;
    tree->start = NULL;
    tree->size = 0;
    tree->root = ngx_radix_alloc(tree);
    if (tree->root == NULL) {
        return NULL;
    }
    tree->root->right = NULL;
    tree->root->left = NULL;
    tree->root->parent = NULL;
    tree->root->value = NGX_RADIX_NO_VALUE;
    if (preallocate == 0) {
        return tree;
    }
    
    if (preallocate == -1) {
        switch (ngx_pagesize / sizeof(ngx_radix_node_t)) {
        
        case 128:
            preallocate = 6;
            break;
        
        case 256:
            preallocate = 7;
            break;
        
        default:
            preallocate = 8;
        }
    }
    mask = 0;
    inc = 0x80000000;
    while (preallocate--) {
        key = 0;
        mask >>= 1;
        mask |= 0x80000000;
        do {
            if (ngx_radix32tree_insert(tree, key, mask, NGX_RADIX_NO_VALUE)
                != NGX_OK)
            {
                return NULL;
            }
            key += inc;
        } while (key);
        inc >>= 1;
    }
    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 = tree->root;
    while (bit & mask) {
        if (key & bit) {
            next = node->right;
        } else {
            next = node->left;
        }
        if (next == NULL) {
            break;
        }
        bit >>= 1;
        node = next;
    }
    if (next) {
        if (node->value != NGX_RADIX_NO_VALUE) {
            return NGX_BUSY;
        }
        node->value = value;
        return NGX_OK;
    }
    while (bit & mask) {
        next = ngx_radix_alloc(tree);
        if (next == NULL) {
            return NGX_ERROR;
        }
        next->right = NULL;
        next->left = NULL;
        next->parent = node;
        next->value = NGX_RADIX_NO_VALUE;
        if (key & bit) {
            node->right = next;
        } else {
            node->left = next;
        }
        bit >>= 1;
        node = next;
    }
    node->value = value;
    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) {
        if (node->value != NGX_RADIX_NO_VALUE) {
            node->value = NGX_RADIX_NO_VALUE;
            return NGX_OK;
        }
        return NGX_ERROR;
    }
    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) {
            break;
        }
        if (node->value != NGX_RADIX_NO_VALUE) {
            break;
        }
        if (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 = NGX_RADIX_NO_VALUE;
    node = tree->root;
    while (node) {
        if (node->value != NGX_RADIX_NO_VALUE) {
            value = node->value;
        }
        if (key & bit) {
            node = node->right;
        } else {
            node = node->left;
        }
        bit >>= 1;
    }
    return value;
}
#if (NGX_HAVE_INET6)
ngx_int_t
ngx_radix128tree_insert(ngx_radix_tree_t *tree, u_char *key, u_char *mask,
    uintptr_t value)
{
    u_char             bit;
    ngx_uint_t         i;
    ngx_radix_node_t  *node, *next;
    i = 0;
    bit = 0x80;
    node = tree->root;
    next = tree->root;
    while (bit & mask[i]) {
        if (key[i] & bit) {
            next = node->right;
        } else {
            next = node->left;
        }
        if (next == NULL) {
            break;
        }
        bit >>= 1;
        node = next;
        if (bit == 0) {
            if (++i == 16) {
                break;
            }
            bit = 0x80;
        }
    }
    if (next) {
        if (node->value != NGX_RADIX_NO_VALUE) {
            return NGX_BUSY;
        }
        node->value = value;
        return NGX_OK;
    }
    while (bit & mask[i]) {
        next = ngx_radix_alloc(tree);
        if (next == NULL) {
            return NGX_ERROR;
        }
        next->right = NULL;
        next->left = NULL;
        next->parent = node;
        next->value = NGX_RADIX_NO_VALUE;
        if (key[i] & bit) {
            node->right = next;
        } else {
            node->left = next;
        }
        bit >>= 1;
        node = next;
        if (bit == 0) {
            if (++i == 16) {
                break;
            }
            bit = 0x80;
        }
    }
    node->value = value;
    return NGX_OK;
}
ngx_int_t
ngx_radix128tree_delete(ngx_radix_tree_t *tree, u_char *key, u_char *mask)
{
    u_char             bit;
    ngx_uint_t         i;
    ngx_radix_node_t  *node;
    i = 0;
    bit = 0x80;
    node = tree->root;
    while (node && (bit & mask[i])) {
        if (key[i] & bit) {
            node = node->right;
        } else {
            node = node->left;
        }
        bit >>= 1;
        if (bit == 0) {
            if (++i == 16) {
                break;
            }
            bit = 0x80;
        }
    }
    if (node == NULL) {
        return NGX_ERROR;
    }
    if (node->right || node->left) {
        if (node->value != NGX_RADIX_NO_VALUE) {
            node->value = NGX_RADIX_NO_VALUE;
            return NGX_OK;
        }
        return NGX_ERROR;
    }
    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) {
            break;
        }
        if (node->value != NGX_RADIX_NO_VALUE) {
            break;
        }
        if (node->parent == NULL) {
            break;
        }
    }
    return NGX_OK;
}
uintptr_t
ngx_radix128tree_find(ngx_radix_tree_t *tree, u_char *key)
{
    u_char             bit;
    uintptr_t          value;
    ngx_uint_t         i;
    ngx_radix_node_t  *node;
    i = 0;
    bit = 0x80;
    value = NGX_RADIX_NO_VALUE;
    node = tree->root;
    while (node) {
        if (node->value != NGX_RADIX_NO_VALUE) {
            value = node->value;
        }
        if (key[i] & bit) {
            node = node->right;
        } else {
            node = node->left;
        }
        bit >>= 1;
        if (bit == 0) {
            i++;
            bit = 0x80;
        }
    }
    return value;
}
#endif
static ngx_radix_node_t *
ngx_radix_alloc(ngx_radix_tree_t *tree)
{
    ngx_radix_node_t  *p;
    if (tree->free) {
        p = tree->free;
        tree->free = tree->free->right;
        return p;
    }
    if (tree->size < sizeof(ngx_radix_node_t)) {
        tree->start = ngx_pmemalign(tree->pool, ngx_pagesize, ngx_pagesize);
        if (tree->start == NULL) {
            return NULL;
        }
        tree->size = ngx_pagesize;
    }
    p = (ngx_radix_node_t *) tree->start;
    tree->start += sizeof(ngx_radix_node_t);
    tree->size -= sizeof(ngx_radix_node_t);
    return p;
}