blob: 5c7a801d889f128ad45e6befcc88f5b52c0749c8 [file] [log] [blame]
Igor Sysoev822834e2004-05-25 15:28:46 +00001
2#include <ngx_config.h>
3#include <ngx_core.h>
4
5
Igor Sysoev822834e2004-05-25 15:28:46 +00006static void *ngx_radix_alloc(ngx_radix_tree_t *tree, size_t size);
7
8
9ngx_radix_tree_t *ngx_radix_tree_create(ngx_pool_t *pool)
10{
11 ngx_radix_tree_t *tree;
12
13 if (!(tree = ngx_palloc(pool, sizeof(ngx_radix_tree_t)))) {
14 return NULL;
15 }
16
Igor Sysoev822834e2004-05-25 15:28:46 +000017 tree->pool = pool;
18 tree->free = NULL;
Igor Sysoeva20b6e62004-05-26 15:30:12 +000019 tree->start = NULL;
Igor Sysoev822834e2004-05-25 15:28:46 +000020 tree->size = 0;
21
Igor Sysoev87a7d1c2004-05-26 19:33:53 +000022 if (!(tree->root = ngx_radix_alloc(tree, sizeof(ngx_radix_node_t)))) {
23 return NULL;
24 }
25
26 tree->root->value = (uintptr_t) 0;
27 tree->root->right = NULL;
28 tree->root->left = NULL;
29 tree->root->parent = NULL;
30
Igor Sysoev822834e2004-05-25 15:28:46 +000031 return tree;
32}
33
34
35ngx_int_t ngx_radix32tree_insert(ngx_radix_tree_t *tree,
36 uint32_t key, uint32_t mask, uintptr_t value)
37{
38 uint32_t bit;
Igor Sysoev87a7d1c2004-05-26 19:33:53 +000039 ngx_radix_node_t *node, *next;
Igor Sysoev822834e2004-05-25 15:28:46 +000040
41 bit = 0x80000000;
42 node = tree->root;
Igor Sysoev87a7d1c2004-05-26 19:33:53 +000043 next = NULL;
Igor Sysoev822834e2004-05-25 15:28:46 +000044
Igor Sysoev87a7d1c2004-05-26 19:33:53 +000045 while (bit & mask) {
Igor Sysoev822834e2004-05-25 15:28:46 +000046 if (key & bit) {
Igor Sysoev87a7d1c2004-05-26 19:33:53 +000047 next = node->right;
Igor Sysoev822834e2004-05-25 15:28:46 +000048
49 } else {
Igor Sysoev87a7d1c2004-05-26 19:33:53 +000050 next = node->left;
Igor Sysoev822834e2004-05-25 15:28:46 +000051 }
52
53 bit >>= 1;
Igor Sysoev87a7d1c2004-05-26 19:33:53 +000054
55 if (next == NULL) {
56 break;
57 }
58
59 node = next;
Igor Sysoev822834e2004-05-25 15:28:46 +000060 }
61
Igor Sysoev87a7d1c2004-05-26 19:33:53 +000062 if (next) {
Igor Sysoev822834e2004-05-25 15:28:46 +000063 if (node->value) {
64 return NGX_BUSY;
65 }
66
67 node->value = value;
68 return NGX_OK;
69 }
70
71 while (bit & mask) {
Igor Sysoev87a7d1c2004-05-26 19:33:53 +000072 if (!(next = ngx_radix_alloc(tree, sizeof(ngx_radix_node_t)))) {
Igor Sysoev822834e2004-05-25 15:28:46 +000073 return NGX_ERROR;
74 }
75
Igor Sysoev87a7d1c2004-05-26 19:33:53 +000076 next->value = value;
77 next->right = NULL;
78 next->left = NULL;
79 next->parent = node;
Igor Sysoev822834e2004-05-25 15:28:46 +000080
81 if (key & bit) {
Igor Sysoev87a7d1c2004-05-26 19:33:53 +000082 node->right = next;
Igor Sysoev822834e2004-05-25 15:28:46 +000083
84 } else {
Igor Sysoev87a7d1c2004-05-26 19:33:53 +000085 node->left = next;
Igor Sysoev822834e2004-05-25 15:28:46 +000086 }
87
88 bit >>= 1;
Igor Sysoev87a7d1c2004-05-26 19:33:53 +000089 node = next;
Igor Sysoev822834e2004-05-25 15:28:46 +000090 }
91
92 return NGX_OK;
93}
94
95
Igor Sysoev87a7d1c2004-05-26 19:33:53 +000096ngx_int_t ngx_radix32tree_delete(ngx_radix_tree_t *tree,
97 uint32_t key, uint32_t mask)
Igor Sysoev822834e2004-05-25 15:28:46 +000098{
99 uint32_t bit;
Igor Sysoev87a7d1c2004-05-26 19:33:53 +0000100 ngx_radix_node_t *node;
Igor Sysoev822834e2004-05-25 15:28:46 +0000101
102 bit = 0x80000000;
103 node = tree->root;
104
105 while (node && (bit & mask)) {
106 if (key & bit) {
107 node = node->right;
108
109 } else {
110 node = node->left;
111 }
112
113 bit >>= 1;
114 }
115
Igor Sysoev87a7d1c2004-05-26 19:33:53 +0000116 if (node == NULL) {
117 return NGX_ERROR;
118 }
Igor Sysoeva20b6e62004-05-26 15:30:12 +0000119
Igor Sysoev87a7d1c2004-05-26 19:33:53 +0000120 if (node->right || node->left) {
121 node->value = (uintptr_t) 0;
122 return NGX_OK;
123 }
Igor Sysoeva20b6e62004-05-26 15:30:12 +0000124
Igor Sysoev87a7d1c2004-05-26 19:33:53 +0000125 for ( ;; ) {
126 if (node->parent->right == node) {
127 node->parent->right = NULL;
Igor Sysoeva20b6e62004-05-26 15:30:12 +0000128 } else {
Igor Sysoev87a7d1c2004-05-26 19:33:53 +0000129 node->parent->left = NULL;
130 }
131
132 node->right = tree->free;
133 tree->free = node;
134
135 node = node->parent;
136
137 if (node->right || node->left || node->value || node->parent == NULL) {
138 break;
Igor Sysoeva20b6e62004-05-26 15:30:12 +0000139 }
Igor Sysoev822834e2004-05-25 15:28:46 +0000140 }
Igor Sysoev87a7d1c2004-05-26 19:33:53 +0000141
142 return NGX_OK;
Igor Sysoev822834e2004-05-25 15:28:46 +0000143}
144
145
146uintptr_t ngx_radix32tree_find(ngx_radix_tree_t *tree, uint32_t key)
147{
148 uint32_t bit;
149 uintptr_t value;
150 ngx_radix_node_t *node;
151
152 bit = 0x80000000;
Igor Sysoeva20b6e62004-05-26 15:30:12 +0000153 value = (uintptr_t) 0;
Igor Sysoev822834e2004-05-25 15:28:46 +0000154 node = tree->root;
155
156 while (node) {
157 if (node->value) {
158 value = node->value;
159 }
160
161 if (key & bit) {
162 node = node->right;
163
164 } else {
165 node = node->left;
166 }
167
168 bit >>= 1;
169 }
170
171 return value;
172}
173
174
175static void *ngx_radix_alloc(ngx_radix_tree_t *tree, size_t size)
176{
177 char *p;
178
Igor Sysoeva20b6e62004-05-26 15:30:12 +0000179 if (tree->free) {
180 p = (char *) tree->free;
181 tree->free = tree->free->right;
182 return p;
183 }
184
Igor Sysoev822834e2004-05-25 15:28:46 +0000185 if (tree->size < size) {
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000186 if (!(tree->start = ngx_palloc(tree->pool, ngx_pagesize))) {
Igor Sysoev822834e2004-05-25 15:28:46 +0000187 return NULL;
188 }
189
Igor Sysoev0ed19cc2004-06-10 18:36:57 +0000190 tree->size = ngx_pagesize;
Igor Sysoev822834e2004-05-25 15:28:46 +0000191 }
192
Igor Sysoeva20b6e62004-05-26 15:30:12 +0000193 p = tree->start;
194 tree->start += size;
Igor Sysoev822834e2004-05-25 15:28:46 +0000195 tree->size -= size;
196
197 return p;
198}