Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2009 Voice System SRL |
3 | | * |
4 | | * This file is part of opensips, a free SIP server. |
5 | | * |
6 | | * opensips is free software; you can redistribute it and/or modify |
7 | | * it under the terms of the GNU General Public License as published by |
8 | | * the Free Software Foundation; either version 2 of the License, or |
9 | | * (at your option) any later version |
10 | | * |
11 | | * opensips is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License |
17 | | * along with this program; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | * |
20 | | * History: |
21 | | * -------- |
22 | | * 2009-09-16 initial version (andreidragus) |
23 | | * |
24 | | */ |
25 | | |
26 | | #include <assert.h> |
27 | | #include <stdio.h> |
28 | | #include <stdlib.h> |
29 | | #include <string.h> |
30 | | #include "str.h" |
31 | | #include "map.h" |
32 | | |
33 | | #include "mem/mem.h" |
34 | | #include "mem/shm_mem.h" |
35 | | #include "mem/rpm_mem.h" |
36 | | |
37 | 0 | #define avl_malloc(dest,size,flags) do \ |
38 | 0 | { \ |
39 | 0 | if(flags & AVLMAP_SHARED) \ |
40 | 0 | (dest) = shm_malloc(size); \ |
41 | 0 | else if (flags & AVLMAP_PERSISTENT) \ |
42 | 0 | (dest) = rpm_malloc(size); \ |
43 | 0 | else \ |
44 | 0 | (dest) = pkg_malloc(size); \ |
45 | 0 | } while(0) |
46 | | |
47 | 0 | #define avl_free(dest,flags) do \ |
48 | 0 | { \ |
49 | 0 | if(flags & AVLMAP_SHARED) \ |
50 | 0 | shm_free(dest); \ |
51 | 0 | else if (flags & AVLMAP_PERSISTENT) \ |
52 | 0 | rpm_free(dest); \ |
53 | 0 | else \ |
54 | 0 | pkg_free(dest); \ |
55 | 0 | } while(0) |
56 | | |
57 | | |
58 | 0 | #define min(a,b) ((a)<(b))?(a):(b) |
59 | | |
60 | | |
61 | | static int str_cmp(str s1, str s2) |
62 | 0 | { |
63 | 0 | int ret; |
64 | |
|
65 | 0 | ret = strncmp( s1.s, s2.s, min( s1.len, s2.len) ); |
66 | |
|
67 | 0 | if( ret == 0) |
68 | 0 | ret = s1.len - s2.len; |
69 | | |
70 | |
|
71 | 0 | return ret; |
72 | 0 | } |
73 | | |
74 | | |
75 | | /* Creates and returns a new table |
76 | | with comparison function |compare| using parameter |param| |
77 | | and memory allocator |allocator|. |
78 | | Returns |NULL| if memory allocation failed. */ |
79 | | |
80 | | map_t map_create(enum map_flags flags) |
81 | 0 | { |
82 | 0 | map_t tree; |
83 | |
|
84 | 0 | avl_malloc(tree, sizeof *tree, flags); |
85 | |
|
86 | 0 | if (tree == NULL) |
87 | 0 | return NULL; |
88 | | |
89 | 0 | tree->avl_root = NULL; |
90 | 0 | tree->flags = flags; |
91 | 0 | tree->avl_count = 0; |
92 | | |
93 | |
|
94 | 0 | return tree; |
95 | 0 | } |
96 | | |
97 | | /* Search |tree| for an item matching |item|, and return it if found. |
98 | | Otherwise return |NULL|. */ |
99 | | void ** map_find( map_t tree, str key) |
100 | 0 | { |
101 | 0 | struct avl_node *p; |
102 | |
|
103 | 0 | for (p = tree->avl_root; p != NULL;) { |
104 | 0 | int cmp = str_cmp(key, p->key); |
105 | |
|
106 | 0 | if (cmp < 0) |
107 | 0 | p = p->avl_link[0]; |
108 | 0 | else if (cmp > 0) |
109 | 0 | p = p->avl_link[1]; |
110 | 0 | else /* |cmp == 0| */ |
111 | 0 | return & (p->val); |
112 | 0 | } |
113 | | |
114 | 0 | return NULL; |
115 | 0 | } |
116 | | |
117 | | /* Inserts |item| into |tree| and returns a pointer to |item|'s address. |
118 | | If a duplicate item is found in the tree, |
119 | | returns a pointer to the duplicate without inserting |item|. |
120 | | Returns |NULL| in case of memory allocation failure. |
121 | | */ |
122 | | |
123 | | void ** map_get( map_t tree, str key) |
124 | 0 | { |
125 | 0 | struct avl_node *y; /* Top node to update balance factor, and parent. */ |
126 | 0 | struct avl_node *p, *q; /* Iterator, and parent. */ |
127 | 0 | struct avl_node *n; /* Newly inserted node. */ |
128 | 0 | struct avl_node *w; /* New root of rebalanced subtree. */ |
129 | 0 | int dir; /* Direction to descend. */ |
130 | 0 | str key_copy; |
131 | |
|
132 | 0 | y = tree->avl_root; |
133 | 0 | dir = 0; |
134 | 0 | for (q = NULL, p = tree->avl_root; p != NULL; q = p, p = p->avl_link[dir]) { |
135 | 0 | int cmp = str_cmp(key, p->key); |
136 | 0 | if (cmp == 0) |
137 | 0 | return &p->val; |
138 | 0 | dir = cmp > 0; |
139 | |
|
140 | 0 | if (p->avl_balance != 0) |
141 | 0 | y = p; |
142 | 0 | } |
143 | | |
144 | 0 | avl_malloc( n, sizeof *n, tree->flags ); |
145 | |
|
146 | 0 | if (n == NULL) |
147 | 0 | return NULL; |
148 | | |
149 | 0 | tree->avl_count++; |
150 | 0 | n->avl_link[0] = n->avl_link[1] = NULL; |
151 | 0 | n->avl_parent = q; |
152 | |
|
153 | 0 | if( !( tree->flags & AVLMAP_NO_DUPLICATE ) ) |
154 | 0 | { |
155 | 0 | avl_malloc(key_copy.s, key.len, tree->flags ); |
156 | 0 | if (!key_copy.s) |
157 | 0 | return NULL; |
158 | | |
159 | 0 | memcpy(key_copy.s,key.s,key.len); |
160 | 0 | key_copy.len = key.len; |
161 | 0 | n->key = key_copy; |
162 | 0 | } |
163 | 0 | else |
164 | 0 | n->key = key; |
165 | | |
166 | 0 | n->val = NULL; |
167 | 0 | if (q != NULL) |
168 | 0 | q->avl_link[dir] = n; |
169 | 0 | else |
170 | 0 | tree->avl_root = n; |
171 | |
|
172 | 0 | n->avl_balance = 0; |
173 | |
|
174 | 0 | if (tree->avl_root == n) |
175 | 0 | return &n->val; |
176 | | |
177 | 0 | for (p = n; p != y; p = q) { |
178 | 0 | q = p->avl_parent; |
179 | 0 | dir = q->avl_link[0] != p; |
180 | 0 | if (dir == 0) |
181 | 0 | q->avl_balance--; |
182 | 0 | else |
183 | 0 | q->avl_balance++; |
184 | 0 | } |
185 | |
|
186 | 0 | if (y->avl_balance == -2) { |
187 | 0 | struct avl_node *x = y->avl_link[0]; |
188 | 0 | if (x->avl_balance == -1) { |
189 | 0 | w = x; |
190 | 0 | y->avl_link[0] = x->avl_link[1]; |
191 | 0 | x->avl_link[1] = y; |
192 | 0 | x->avl_balance = y->avl_balance = 0; |
193 | 0 | x->avl_parent = y->avl_parent; |
194 | 0 | y->avl_parent = x; |
195 | 0 | if (y->avl_link[0] != NULL) |
196 | 0 | y->avl_link[0]->avl_parent = y; |
197 | 0 | } else { |
198 | 0 | assert(x->avl_balance == +1); |
199 | 0 | w = x->avl_link[1]; |
200 | 0 | x->avl_link[1] = w->avl_link[0]; |
201 | 0 | w->avl_link[0] = x; |
202 | 0 | y->avl_link[0] = w->avl_link[1]; |
203 | 0 | w->avl_link[1] = y; |
204 | 0 | if (w->avl_balance == -1) |
205 | 0 | x->avl_balance = 0, y->avl_balance = +1; |
206 | 0 | else if (w->avl_balance == 0) |
207 | 0 | x->avl_balance = y->avl_balance = 0; |
208 | 0 | else /* |w->avl_balance == +1| */ |
209 | 0 | x->avl_balance = -1, y->avl_balance = 0; |
210 | 0 | w->avl_balance = 0; |
211 | 0 | w->avl_parent = y->avl_parent; |
212 | 0 | x->avl_parent = y->avl_parent = w; |
213 | 0 | if (x->avl_link[1] != NULL) |
214 | 0 | x->avl_link[1]->avl_parent = x; |
215 | 0 | if (y->avl_link[0] != NULL) |
216 | 0 | y->avl_link[0]->avl_parent = y; |
217 | 0 | } |
218 | 0 | } else if (y->avl_balance == +2) { |
219 | 0 | struct avl_node *x = y->avl_link[1]; |
220 | 0 | if (x->avl_balance == +1) { |
221 | 0 | w = x; |
222 | 0 | y->avl_link[1] = x->avl_link[0]; |
223 | 0 | x->avl_link[0] = y; |
224 | 0 | x->avl_balance = y->avl_balance = 0; |
225 | 0 | x->avl_parent = y->avl_parent; |
226 | 0 | y->avl_parent = x; |
227 | 0 | if (y->avl_link[1] != NULL) |
228 | 0 | y->avl_link[1]->avl_parent = y; |
229 | 0 | } else { |
230 | 0 | assert(x->avl_balance == -1); |
231 | 0 | w = x->avl_link[0]; |
232 | 0 | x->avl_link[0] = w->avl_link[1]; |
233 | 0 | w->avl_link[1] = x; |
234 | 0 | y->avl_link[1] = w->avl_link[0]; |
235 | 0 | w->avl_link[0] = y; |
236 | 0 | if (w->avl_balance == +1) |
237 | 0 | x->avl_balance = 0, y->avl_balance = -1; |
238 | 0 | else if (w->avl_balance == 0) |
239 | 0 | x->avl_balance = y->avl_balance = 0; |
240 | 0 | else /* |w->avl_balance == -1| */ |
241 | 0 | x->avl_balance = +1, y->avl_balance = 0; |
242 | 0 | w->avl_balance = 0; |
243 | 0 | w->avl_parent = y->avl_parent; |
244 | 0 | x->avl_parent = y->avl_parent = w; |
245 | 0 | if (x->avl_link[0] != NULL) |
246 | 0 | x->avl_link[0]->avl_parent = x; |
247 | 0 | if (y->avl_link[1] != NULL) |
248 | 0 | y->avl_link[1]->avl_parent = y; |
249 | 0 | } |
250 | 0 | } else |
251 | 0 | return &n->val; |
252 | 0 | if (w->avl_parent != NULL) |
253 | 0 | w->avl_parent->avl_link[y != w->avl_parent->avl_link[0]] = w; |
254 | 0 | else |
255 | 0 | tree->avl_root = w; |
256 | |
|
257 | 0 | return &n->val; |
258 | 0 | } |
259 | | |
260 | | |
261 | | /* Inserts |item| into |table|. |
262 | | Returns |NULL| if |item| was successfully inserted |
263 | | or if a memory allocation error occurred. |
264 | | Otherwise, returns the duplicate item. */ |
265 | | void * map_put( map_t table, str key, void *item) |
266 | 0 | { |
267 | 0 | void **p = map_get(table, key); |
268 | 0 | void * ret; |
269 | | |
270 | |
|
271 | 0 | if( p == NULL ) |
272 | 0 | return p; |
273 | | |
274 | 0 | ret = *p; |
275 | 0 | *p = item; |
276 | |
|
277 | 0 | return ret == item ? NULL : ret; |
278 | 0 | } |
279 | | |
280 | | void * delete_node(map_t tree, struct avl_node * p) |
281 | 0 | { |
282 | 0 | struct avl_node *q; /* Parent of |p|. */ |
283 | 0 | int dir; /* Side of |q| on which |p| is linked. */ |
284 | 0 | void * val; |
285 | |
|
286 | 0 | val = p->val; |
287 | |
|
288 | 0 | q = p->avl_parent; |
289 | 0 | if (q == NULL) { |
290 | 0 | q = (struct avl_node *) & tree->avl_root; |
291 | 0 | dir = 0; |
292 | 0 | } |
293 | 0 | else |
294 | 0 | { |
295 | 0 | if( p == q->avl_link[0] ) |
296 | 0 | dir = 0; |
297 | 0 | else |
298 | 0 | dir = 1; |
299 | 0 | } |
300 | |
|
301 | 0 | if (p->avl_link[1] == NULL) { |
302 | 0 | q->avl_link[dir] = p->avl_link[0]; |
303 | 0 | if (q->avl_link[dir] != NULL) |
304 | 0 | q->avl_link[dir]->avl_parent = p->avl_parent; |
305 | 0 | } else { |
306 | 0 | struct avl_node *r = p->avl_link[1]; |
307 | 0 | if (r->avl_link[0] == NULL) { |
308 | 0 | r->avl_link[0] = p->avl_link[0]; |
309 | 0 | q->avl_link[dir] = r; |
310 | 0 | r->avl_parent = p->avl_parent; |
311 | 0 | if (r->avl_link[0] != NULL) |
312 | 0 | r->avl_link[0]->avl_parent = r; |
313 | 0 | r->avl_balance = p->avl_balance; |
314 | 0 | q = r; |
315 | 0 | dir = 1; |
316 | 0 | } else { |
317 | 0 | struct avl_node *s = r->avl_link[0]; |
318 | 0 | while (s->avl_link[0] != NULL) |
319 | 0 | s = s->avl_link[0]; |
320 | 0 | r = s->avl_parent; |
321 | 0 | r->avl_link[0] = s->avl_link[1]; |
322 | 0 | s->avl_link[0] = p->avl_link[0]; |
323 | 0 | s->avl_link[1] = p->avl_link[1]; |
324 | 0 | q->avl_link[dir] = s; |
325 | 0 | if (s->avl_link[0] != NULL) |
326 | 0 | s->avl_link[0]->avl_parent = s; |
327 | 0 | s->avl_link[1]->avl_parent = s; |
328 | 0 | s->avl_parent = p->avl_parent; |
329 | 0 | if (r->avl_link[0] != NULL) |
330 | 0 | r->avl_link[0]->avl_parent = r; |
331 | 0 | s->avl_balance = p->avl_balance; |
332 | 0 | q = r; |
333 | 0 | dir = 0; |
334 | 0 | } |
335 | 0 | } |
336 | |
|
337 | 0 | if(!( tree->flags & AVLMAP_NO_DUPLICATE ) ) |
338 | 0 | avl_free(p->key.s,tree->flags); |
339 | |
|
340 | 0 | avl_free(p,tree->flags); |
341 | |
|
342 | 0 | while (q != (struct avl_node *) & tree->avl_root) { |
343 | 0 | struct avl_node *y = q; |
344 | |
|
345 | 0 | if (y->avl_parent != NULL) |
346 | 0 | q = y->avl_parent; |
347 | 0 | else |
348 | 0 | q = (struct avl_node *) & tree->avl_root; |
349 | |
|
350 | 0 | if (dir == 0) { |
351 | 0 | dir = q->avl_link[0] != y; |
352 | 0 | y->avl_balance++; |
353 | 0 | if (y->avl_balance == +1) |
354 | 0 | break; |
355 | 0 | else if (y->avl_balance == +2) { |
356 | 0 | struct avl_node *x = y->avl_link[1]; |
357 | 0 | if (x->avl_balance == -1) { |
358 | 0 | struct avl_node *w; |
359 | |
|
360 | 0 | w = x->avl_link[0]; |
361 | 0 | x->avl_link[0] = w->avl_link[1]; |
362 | 0 | w->avl_link[1] = x; |
363 | 0 | y->avl_link[1] = w->avl_link[0]; |
364 | 0 | w->avl_link[0] = y; |
365 | 0 | if (w->avl_balance == +1) |
366 | 0 | x->avl_balance = 0, y->avl_balance = -1; |
367 | 0 | else if (w->avl_balance == 0) |
368 | 0 | x->avl_balance = y->avl_balance = 0; |
369 | 0 | else /* |w->avl_balance == -1| */ |
370 | 0 | x->avl_balance = +1, y->avl_balance = 0; |
371 | 0 | w->avl_balance = 0; |
372 | 0 | w->avl_parent = y->avl_parent; |
373 | 0 | x->avl_parent = y->avl_parent = w; |
374 | 0 | if (x->avl_link[0] != NULL) |
375 | 0 | x->avl_link[0]->avl_parent = x; |
376 | 0 | if (y->avl_link[1] != NULL) |
377 | 0 | y->avl_link[1]->avl_parent = y; |
378 | 0 | q->avl_link[dir] = w; |
379 | 0 | } else { |
380 | 0 | y->avl_link[1] = x->avl_link[0]; |
381 | 0 | x->avl_link[0] = y; |
382 | 0 | x->avl_parent = y->avl_parent; |
383 | 0 | y->avl_parent = x; |
384 | 0 | if (y->avl_link[1] != NULL) |
385 | 0 | y->avl_link[1]->avl_parent = y; |
386 | 0 | q->avl_link[dir] = x; |
387 | 0 | if (x->avl_balance == 0) { |
388 | 0 | x->avl_balance = -1; |
389 | 0 | y->avl_balance = +1; |
390 | 0 | break; |
391 | 0 | } else { |
392 | 0 | x->avl_balance = y->avl_balance = 0; |
393 | 0 | y = x; |
394 | 0 | } |
395 | 0 | } |
396 | 0 | } |
397 | 0 | } else { |
398 | 0 | dir = q->avl_link[0] != y; |
399 | 0 | y->avl_balance--; |
400 | 0 | if (y->avl_balance == -1) |
401 | 0 | break; |
402 | 0 | else if (y->avl_balance == -2) { |
403 | 0 | struct avl_node *x = y->avl_link[0]; |
404 | 0 | if (x->avl_balance == +1) { |
405 | 0 | struct avl_node *w; |
406 | 0 | w = x->avl_link[1]; |
407 | 0 | x->avl_link[1] = w->avl_link[0]; |
408 | 0 | w->avl_link[0] = x; |
409 | 0 | y->avl_link[0] = w->avl_link[1]; |
410 | 0 | w->avl_link[1] = y; |
411 | 0 | if (w->avl_balance == -1) |
412 | 0 | x->avl_balance = 0, y->avl_balance = +1; |
413 | 0 | else if (w->avl_balance == 0) |
414 | 0 | x->avl_balance = y->avl_balance = 0; |
415 | 0 | else /* |w->avl_balance == +1| */ |
416 | 0 | x->avl_balance = -1, y->avl_balance = 0; |
417 | 0 | w->avl_balance = 0; |
418 | 0 | w->avl_parent = y->avl_parent; |
419 | 0 | x->avl_parent = y->avl_parent = w; |
420 | 0 | if (x->avl_link[1] != NULL) |
421 | 0 | x->avl_link[1]->avl_parent = x; |
422 | 0 | if (y->avl_link[0] != NULL) |
423 | 0 | y->avl_link[0]->avl_parent = y; |
424 | 0 | q->avl_link[dir] = w; |
425 | 0 | } else { |
426 | 0 | y->avl_link[0] = x->avl_link[1]; |
427 | 0 | x->avl_link[1] = y; |
428 | 0 | x->avl_parent = y->avl_parent; |
429 | 0 | y->avl_parent = x; |
430 | 0 | if (y->avl_link[0] != NULL) |
431 | 0 | y->avl_link[0]->avl_parent = y; |
432 | 0 | q->avl_link[dir] = x; |
433 | 0 | if (x->avl_balance == 0) { |
434 | 0 | x->avl_balance = +1; |
435 | 0 | y->avl_balance = -1; |
436 | 0 | break; |
437 | 0 | } else { |
438 | 0 | x->avl_balance = y->avl_balance = 0; |
439 | 0 | y = x; |
440 | 0 | } |
441 | 0 | } |
442 | 0 | } |
443 | 0 | } |
444 | 0 | } |
445 | |
|
446 | 0 | tree->avl_count--; |
447 | 0 | return(void *) val; |
448 | |
|
449 | 0 | }; |
450 | | |
451 | | /* Deletes from |tree| and returns an item matching |item|. |
452 | | Returns a null pointer if no matching item found. */ |
453 | | void * map_remove( map_t tree, str key) |
454 | 0 | { |
455 | 0 | struct avl_node *p; /* Traverses tree to find node to delete. */ |
456 | 0 | int dir; /* Side of |q| on which |p| is linked. */ |
457 | |
|
458 | 0 | if (tree->avl_root == NULL) |
459 | 0 | return NULL; |
460 | | |
461 | 0 | p = tree->avl_root; |
462 | 0 | for (;;) { |
463 | 0 | int cmp = str_cmp(key, p->key); |
464 | 0 | if (cmp == 0) |
465 | 0 | break; |
466 | | |
467 | 0 | dir = cmp > 0; |
468 | 0 | p = p->avl_link[dir]; |
469 | 0 | if (p == NULL) |
470 | 0 | return NULL; |
471 | 0 | } |
472 | | |
473 | 0 | return delete_node( tree, p ); |
474 | |
|
475 | 0 | } |
476 | | |
477 | | |
478 | | |
479 | | |
480 | | /* Frees storage allocated for |tree|. |
481 | | If |destroy != NULL|, applies it to each data item in inorder. */ |
482 | | void map_destroy( map_t tree, value_destroy_func destroy) |
483 | 0 | { |
484 | 0 | struct avl_node *p, *q; |
485 | |
|
486 | 0 | for (p = tree->avl_root; p != NULL; p = q) |
487 | 0 | if (p->avl_link[0] == NULL) { |
488 | 0 | q = p->avl_link[1]; |
489 | 0 | if (destroy != NULL && p->val != NULL) |
490 | 0 | destroy(p->val); |
491 | 0 | if( !(tree->flags & AVLMAP_NO_DUPLICATE ) ) |
492 | 0 | avl_free( p->key.s,tree->flags); |
493 | 0 | avl_free( p, tree->flags ); |
494 | 0 | } else { |
495 | 0 | q = p->avl_link[0]; |
496 | 0 | p->avl_link[0] = q->avl_link[1]; |
497 | 0 | q->avl_link[1] = p; |
498 | 0 | } |
499 | |
|
500 | 0 | avl_free( tree, tree->flags ); |
501 | 0 | } |
502 | | |
503 | | int map_size( map_t tree ) |
504 | 0 | { |
505 | 0 | return tree->avl_count; |
506 | 0 | } |
507 | | |
508 | | |
509 | | void process_all( map_t tree, struct avl_node *p, process_each_func f, void * param ); |
510 | | |
511 | | void process_all( map_t tree, struct avl_node *p, process_each_func f, void * param ) |
512 | 0 | { |
513 | 0 | if( tree->ret_code ) |
514 | 0 | return; |
515 | | |
516 | 0 | if( p->avl_link[0] ) |
517 | 0 | process_all( tree, p->avl_link[0], f ,param ); |
518 | |
|
519 | 0 | tree->ret_code |= f( param, p->key, p->val); |
520 | |
|
521 | 0 | if( p->avl_link[1] ) |
522 | 0 | process_all( tree, p->avl_link[1], f ,param ); |
523 | 0 | } |
524 | | |
525 | | int map_for_each( map_t tree, process_each_func f, void * param) |
526 | 0 | { |
527 | 0 | tree->ret_code = 0; |
528 | |
|
529 | 0 | if( tree->avl_root ) |
530 | 0 | process_all( tree, tree->avl_root, f, param); |
531 | |
|
532 | 0 | return tree->ret_code; |
533 | | |
534 | |
|
535 | 0 | } |
536 | | |
537 | | int map_first( map_t map, map_iterator_t * it) |
538 | 0 | { |
539 | 0 | if( map == NULL || it == NULL ) |
540 | 0 | return -1; |
541 | | |
542 | 0 | it->map = map; |
543 | |
|
544 | 0 | it->node = map->avl_root; |
545 | |
|
546 | 0 | if( it->node ) |
547 | 0 | { |
548 | 0 | while( it->node->avl_link[0] ) |
549 | 0 | it->node = it->node->avl_link[0]; |
550 | 0 | } |
551 | |
|
552 | 0 | return 0; |
553 | 0 | } |
554 | | |
555 | | |
556 | | int map_last( map_t map, map_iterator_t * it) |
557 | 0 | { |
558 | 0 | if( map == NULL || it == NULL ) |
559 | 0 | return -1; |
560 | | |
561 | 0 | it->map = map; |
562 | |
|
563 | 0 | it->node = map->avl_root; |
564 | |
|
565 | 0 | if( it->node ) |
566 | 0 | { |
567 | 0 | while( it->node->avl_link[1] ) |
568 | 0 | it->node = it->node->avl_link[1]; |
569 | 0 | } |
570 | |
|
571 | 0 | return 0; |
572 | 0 | } |
573 | | |
574 | | str * iterator_key( map_iterator_t * it ) |
575 | 0 | { |
576 | 0 | if( it == NULL ) |
577 | 0 | return NULL; |
578 | | |
579 | 0 | return &it->node->key; |
580 | 0 | } |
581 | | |
582 | | void** iterator_val( map_iterator_t * it ) |
583 | 0 | { |
584 | 0 | if( it == NULL ) |
585 | 0 | return NULL; |
586 | | |
587 | 0 | return &it->node->val; |
588 | 0 | } |
589 | | |
590 | | int iterator_is_valid( map_iterator_t * it ) |
591 | 0 | { |
592 | 0 | if( it == NULL || it->map ==NULL || it->node == NULL) |
593 | 0 | return 0; |
594 | | |
595 | 0 | return 1; |
596 | 0 | } |
597 | | |
598 | | int iterator_next( map_iterator_t * it ) |
599 | 0 | { |
600 | |
|
601 | 0 | struct avl_node *q, *p; /* Current node and its child. */ |
602 | |
|
603 | 0 | if( it == NULL || it->map ==NULL || it->node == NULL) |
604 | 0 | return -1; |
605 | | |
606 | 0 | if( it->node->avl_link[1] ) |
607 | 0 | { |
608 | 0 | it->node = it->node->avl_link[1]; |
609 | 0 | while( it->node->avl_link[0] ) |
610 | 0 | it->node = it->node->avl_link[0]; |
611 | |
|
612 | 0 | } |
613 | 0 | else |
614 | 0 | { |
615 | |
|
616 | 0 | for (p = it->node, q = p->avl_parent ; ; p = q, q = q->avl_parent) |
617 | 0 | if (q == NULL || p == q->avl_link[0]) |
618 | 0 | { |
619 | 0 | it->node = q; |
620 | 0 | return 0; |
621 | 0 | } |
622 | 0 | } |
623 | | |
624 | 0 | return 0; |
625 | 0 | } |
626 | | |
627 | | |
628 | | int iterator_prev( map_iterator_t * it ) |
629 | 0 | { |
630 | |
|
631 | 0 | struct avl_node *q, *p; /* Current node and its child. */ |
632 | |
|
633 | 0 | if( it == NULL || it->map ==NULL || it->node == NULL) |
634 | 0 | return -1; |
635 | | |
636 | 0 | if( it->node->avl_link[0] ) |
637 | 0 | { |
638 | 0 | it->node = it->node->avl_link[0]; |
639 | 0 | while( it->node->avl_link[1] ) |
640 | 0 | it->node = it->node->avl_link[1]; |
641 | |
|
642 | 0 | } |
643 | 0 | else |
644 | 0 | { |
645 | |
|
646 | 0 | for (p = it->node, q = p->avl_parent ; ; p = q, q = q->avl_parent) |
647 | 0 | if (q == NULL || p == q->avl_link[1]) |
648 | 0 | { |
649 | 0 | it->node = q; |
650 | 0 | return 0; |
651 | 0 | } |
652 | 0 | } |
653 | | |
654 | 0 | return 0; |
655 | 0 | } |
656 | | |
657 | | void * iterator_delete( map_iterator_t * it ) |
658 | 0 | { |
659 | 0 | void * ret; |
660 | |
|
661 | 0 | if( it == NULL || it->map ==NULL || it->node == NULL) |
662 | 0 | return NULL; |
663 | | |
664 | 0 | ret = delete_node( it->map, it->node ); |
665 | |
|
666 | 0 | it->node = NULL; |
667 | |
|
668 | 0 | return ret; |
669 | 0 | } |
670 | | |