ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/patricia.c
Revision: 7843
Committed: Sun Nov 6 13:55:28 2016 UTC (8 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 21652 byte(s)
Log Message:
- patricia.c, patricia.h:New_Patricia() fixed compile warning; removed useless 0 assignments

File Contents

# User Rev Content
1 michael 5042 /*
2 michael 6259 * $Id$
3 michael 5042 * Dave Plonka <plonka@doit.wisc.edu>
4     *
5     * This file had been called "radix.c" in the MRT sources.
6     *
7     * I renamed it to "patricia.c" since it's not an implementation of a general
8     * radix trie. Also I pulled in various requirements from "prefix.c" and
9     * "demo.c" so that it could be used as a standalone API.
10 michael 5046 *
11     * Copyright (c) 1999-2013
12     *
13     * The Regents of the University of Michigan ("The Regents") and Merit
14     * Network, Inc.
15     *
16     * Redistributions of source code must retain the above copyright notice,
17     * this list of conditions and the following disclaimer.
18     *
19     * Redistributions in binary form must reproduce the above copyright
20     * notice, this list of conditions and the following disclaimer in the
21     * documentation and/or other materials provided with the distribution.
22     *
23     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24     * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25     * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26     * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27     * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33     * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 michael 5042 */
35    
36     #include <assert.h> /* assert */
37     #include <ctype.h> /* isdigit */
38     #include <errno.h> /* errno */
39     #include <math.h> /* sin */
40     #include <stddef.h> /* NULL */
41     #include <stdio.h> /* sprintf, fprintf, stderr */
42     #include <stdlib.h> /* free, atol, calloc */
43     #include <string.h> /* memcpy, strchr, strlen */
44     #include <sys/types.h> /* BSD: for inet_addr */
45     #include <sys/socket.h> /* BSD, Linux: for inet_addr */
46     #include <netinet/in.h> /* BSD, Linux: for inet_addr */
47     #include <arpa/inet.h> /* BSD, Linux, Solaris: for inet_addr */
48    
49     #include "patricia.h"
50 michael 5047 #include "memory.h"
51 michael 5042
52     /* { from prefix.c */
53    
54     /* prefix_tochar
55     * convert prefix information to bytes
56     */
57 michael 7806 static unsigned char *
58 michael 7834 prefix_tochar(prefix_t * prefix)
59 michael 5042 {
60 michael 7834 if (prefix == NULL)
61     return NULL;
62     return (unsigned char *)&prefix->add.sin;
63 michael 5042 }
64    
65 michael 6607 static int
66 michael 7834 comp_with_mask(void *addr, void *dest, unsigned int mask)
67 michael 5042 {
68 michael 7834 if ( /* mask/8 == 0 || */ memcmp(addr, dest, mask / 8) == 0)
69     {
70     int n = mask / 8;
71     int m = ((-1) << (8 - (mask % 8)));
72 michael 5042
73 michael 7834 if (mask % 8 == 0 || (((unsigned char *)addr)[n] & m) == (((unsigned char *)dest)[n] & m))
74     return 1;
75     }
76 michael 5042
77 michael 7834 return 0;
78 michael 5042 }
79    
80 michael 6607 /*
81 michael 5042 * convert prefix information to ascii string with length
82     */
83 michael 7824 const char *
84 michael 7839 prefix_toa(const prefix_t *prefix, int with_len)
85 michael 5042 {
86 michael 7839 static char buf[INET6_ADDRSTRLEN + sizeof("/128")];
87 michael 5042
88 michael 7839 assert(prefix);
89 michael 7834 assert(prefix->ref_count >= 0);
90 michael 7839 assert((prefix->family == AF_INET && prefix->bitlen <= 32) ||
91     (prefix->family == AF_INET6 && prefix->bitlen <= 128));
92 michael 7834
93 michael 7839 inet_ntop(prefix->family, &prefix->add.sin6, buf, INET6_ADDRSTRLEN);
94 michael 7834
95 michael 7839 if (with_len)
96     sprintf(buf + strlen(buf), "/%d", prefix->bitlen);
97     return buf;
98 michael 5042 }
99    
100 michael 7814 static prefix_t *
101 michael 7834 New_Prefix2(int family, void *dest, int bitlen, prefix_t *prefix)
102 michael 5042 {
103 michael 7834 int dynamic_allocated = 0;
104 michael 7841 int addr_size = 0;
105 michael 5042
106 michael 7841 switch (family)
107 michael 7834 {
108 michael 7841 case AF_INET:
109     addr_size = sizeof(struct in_addr);
110     break;
111     case AF_INET6:
112     addr_size = sizeof(struct in6_addr);
113     break;
114     default: return NULL;
115 michael 7834 }
116 michael 5042
117 michael 7841 if (!prefix)
118 michael 7834 {
119 michael 7841 prefix = xcalloc(sizeof(prefix_t));
120     dynamic_allocated = 1;
121 michael 7834 }
122    
123 michael 7841 memcpy(&prefix->add.sin6, dest, addr_size);
124     prefix->bitlen = (bitlen >= 0) ? bitlen : addr_size * 8;
125 michael 7834 prefix->family = family;
126 michael 7841 prefix->ref_count = dynamic_allocated == 1;
127 michael 7834
128     /* fprintf(stderr, "[C %s, %d]\n", prefix_toa(prefix), prefix->ref_count); */
129     return prefix;
130 michael 5042 }
131    
132 michael 7814 static prefix_t *
133 michael 5042 New_Prefix (int family, void *dest, int bitlen)
134     {
135 michael 7834 return New_Prefix2(family, dest, bitlen, NULL);
136 michael 5042 }
137    
138     /* ascii2prefix
139     */
140 michael 7814 static prefix_t *
141 michael 7834 ascii2prefix(int family, const char *string)
142 michael 5042 {
143 michael 7842 int bitlen, maxbitlen = 0;
144 michael 7834 char *cp;
145     char save[MAXLINE];
146 michael 7840 union
147     {
148     struct in_addr sin;
149     struct in6_addr sin6;
150     } sin;
151 michael 5042
152 michael 7840 assert(string);
153 michael 5042
154 michael 7840 /* Easy way to handle both families */
155 michael 7834 if (family == 0)
156     {
157     family = AF_INET;
158 michael 5044
159 michael 7834 if (strchr (string, ':'))
160     family = AF_INET6;
161     }
162 michael 5042
163 michael 7834 if (family == AF_INET)
164 michael 7840 maxbitlen = sizeof(struct in_addr) * 8;
165 michael 7834 else if (family == AF_INET6)
166     maxbitlen = sizeof(struct in6_addr) * 8;
167 michael 5042
168 michael 7840 if ((cp = strchr(string, '/')))
169 michael 7834 {
170 michael 7842 bitlen = atoi(cp + 1);
171 michael 5042
172 michael 7834 /* *cp = '\0'; */
173     /* copy the string to save. Avoid destroying the string */
174     assert(cp - string < MAXLINE);
175     memcpy(save, string, cp - string);
176 michael 5045
177 michael 7834 save[cp - string] = '\0';
178     string = save;
179    
180     if (bitlen < 0 || bitlen > maxbitlen)
181     bitlen = maxbitlen;
182     }
183     else
184     bitlen = maxbitlen;
185    
186 michael 7840 if (inet_pton(family, string, &sin) <= 0)
187 michael 7834 return NULL;
188 michael 7840 return New_Prefix(family, &sin, bitlen);
189 michael 5042 }
190    
191 michael 5048 static prefix_t *
192 michael 7834 Ref_Prefix(prefix_t *prefix)
193 michael 5042 {
194 michael 7834 if (prefix == NULL)
195     return NULL;
196    
197     if (prefix->ref_count == 0)
198     {
199     /* make a copy in case of a static prefix */
200     return New_Prefix2(prefix->family, &prefix->add, prefix->bitlen, NULL);
201     }
202    
203     prefix->ref_count++;
204    
205     /* fprintf(stderr, "[A %s, %d]\n", prefix_toa(prefix), prefix->ref_count); */
206     return prefix;
207 michael 5042 }
208    
209 michael 5048 static void
210 michael 7834 Deref_Prefix(prefix_t *prefix)
211 michael 5042 {
212 michael 7834 if (prefix == NULL)
213     return;
214 michael 5042
215 michael 7837 /* For secure programming, raise an assert. No static prefix can call this */
216 michael 7834 assert(prefix->ref_count > 0);
217 michael 7837 if (--prefix->ref_count <= 0)
218 michael 7834 xfree(prefix);
219 michael 5042 }
220    
221     /* } */
222    
223     /* #define PATRICIA_DEBUG 1 */
224    
225     /* these routines support continuous mask only */
226    
227     patricia_tree_t *
228 michael 7843 New_Patricia(unsigned int maxbits)
229 michael 5042 {
230 michael 7834 patricia_tree_t *patricia = xcalloc(sizeof *patricia);
231     patricia->maxbits = maxbits;
232 michael 7830
233 michael 7834 assert(maxbits <= PATRICIA_MAXBITS); /* XXX */
234     return patricia;
235 michael 5042 }
236    
237     /*
238     * if func is supplied, it will be called as func(node->data)
239     * before deleting the node
240     */
241     void
242 michael 7834 Clear_Patricia(patricia_tree_t *patricia, void (*func)(void *))
243 michael 5042 {
244 michael 7834 assert(patricia);
245 michael 5042
246 michael 7834 if (patricia->head)
247     {
248     patricia_node_t *Xstack[PATRICIA_MAXBITS + 1];
249     patricia_node_t **Xsp = Xstack;
250     patricia_node_t *Xrn = patricia->head;
251 michael 5042
252 michael 7834 while (Xrn)
253     {
254     patricia_node_t *l = Xrn->l;
255     patricia_node_t *r = Xrn->r;
256 michael 5042
257 michael 7834 if (Xrn->prefix)
258     {
259     Deref_Prefix(Xrn->prefix);
260 michael 5042
261 michael 7834 if (Xrn->data && func)
262     func(Xrn->data);
263     }
264     else
265     {
266     assert(Xrn->data == NULL);
267     }
268    
269     xfree (Xrn);
270     patricia->num_active_node--;
271    
272     if (l)
273     {
274     if (r)
275     {
276     *Xsp++ = r;
277 michael 5042 }
278 michael 7834
279     Xrn = l;
280     }
281     else if (r)
282     {
283     Xrn = r;
284     }
285     else if (Xsp != Xstack)
286     {
287     Xrn = *(--Xsp);
288     }
289     else
290     {
291     Xrn = NULL;
292     }
293 michael 5042 }
294 michael 7834 }
295    
296     assert(patricia->num_active_node == 0);
297     /* xfree (patricia); */
298 michael 5042 }
299    
300     void
301 michael 7834 Destroy_Patricia(patricia_tree_t *patricia, void (*func)(void *))
302 michael 5042 {
303 michael 7834 Clear_Patricia(patricia, func);
304     xfree(patricia);
305 michael 5042 }
306    
307     /*
308     * if func is supplied, it will be called as func(node->prefix, node->data)
309     */
310     void
311 michael 7834 patricia_process(patricia_tree_t *patricia, void (*func)(prefix_t *, void *))
312 michael 5042 {
313 michael 7834 patricia_node_t *node;
314 michael 5042
315 michael 7834 assert(func);
316    
317     PATRICIA_WALK (patricia->head, node) {
318 michael 7838 func(node->prefix, node->data);
319 michael 7834 } PATRICIA_WALK_END;
320 michael 5042 }
321    
322     patricia_node_t *
323 michael 7834 patricia_search_exact(patricia_tree_t *patricia, prefix_t *prefix)
324 michael 5042 {
325 michael 7834 patricia_node_t *node;
326     unsigned char *addr;
327     unsigned int bitlen;
328 michael 5042
329 michael 7834 assert(patricia);
330     assert(prefix);
331     assert(prefix->bitlen <= patricia->maxbits);
332 michael 5042
333 michael 7834 if (patricia->head == NULL)
334     return NULL;
335 michael 5042
336 michael 7834 node = patricia->head;
337 michael 7838 addr = prefix_touchar(prefix);
338 michael 7834 bitlen = prefix->bitlen;
339 michael 5042
340 michael 7834 while (node->bit < bitlen)
341     {
342     if (BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
343     {
344 michael 5042 #ifdef PATRICIA_DEBUG
345 michael 7834 if (node->prefix)
346     fprintf(stderr, "patricia_search_exact: take right %s/%d\n",
347     prefix_toa(node->prefix), node->prefix->bitlen);
348     else
349     fprintf(stderr, "patricia_search_exact: take right at %u\n", node->bit);
350     #endif /* PATRICIA_DEBUG */
351     node = node->r;
352     }
353     else
354     {
355 michael 5042 #ifdef PATRICIA_DEBUG
356 michael 7834 if (node->prefix)
357     fprintf(stderr, "patricia_search_exact: take left %s/%d\n",
358     prefix_toa(node->prefix), node->prefix->bitlen);
359     else
360     fprintf(stderr, "patricia_search_exact: take left at %u\n", node->bit);
361     #endif /* PATRICIA_DEBUG */
362     node = node->l;
363 michael 5042 }
364    
365 michael 7834 if (node == NULL)
366     return NULL;
367     }
368    
369 michael 5042 #ifdef PATRICIA_DEBUG
370 michael 7834 if (node->prefix)
371     fprintf(stderr, "patricia_search_exact: stop at %s/%d\n",
372     prefix_toa(node->prefix), node->prefix->bitlen);
373     else
374     fprintf(stderr, "patricia_search_exact: stop at %u\n", node->bit);
375     #endif /* PATRICIA_DEBUG */
376    
377     if (node->bit > bitlen || node->prefix == NULL)
378     return NULL;
379    
380     assert(node->bit == bitlen);
381     assert(node->bit == node->prefix->bitlen);
382    
383     if (comp_with_mask(prefix_tochar(node->prefix), prefix_tochar(prefix), bitlen))
384     {
385 michael 5042 #ifdef PATRICIA_DEBUG
386 michael 7834 fprintf(stderr, "patricia_search_exact: found %s/%d\n",
387     prefix_toa(node->prefix), node->prefix->bitlen);
388     #endif /* PATRICIA_DEBUG */
389     return node;
390     }
391    
392     return NULL;
393 michael 5042 }
394    
395     /* if inclusive != 0, "best" may be the given prefix itself */
396     patricia_node_t *
397 michael 7834 patricia_search_best2(patricia_tree_t *patricia, prefix_t *prefix, int inclusive)
398 michael 5042 {
399 michael 7834 patricia_node_t *node;
400     patricia_node_t *stack[PATRICIA_MAXBITS + 1];
401     unsigned char *addr;
402     unsigned int bitlen;
403     int cnt = 0;
404 michael 5042
405 michael 7834 assert(patricia);
406     assert(prefix);
407     assert(prefix->bitlen <= patricia->maxbits);
408 michael 5042
409 michael 7834 if (patricia->head == NULL)
410     return NULL;
411 michael 5042
412 michael 7834 node = patricia->head;
413 michael 7838 addr = prefix_touchar(prefix);
414 michael 7834 bitlen = prefix->bitlen;
415 michael 5042
416 michael 7834 while (node->bit < bitlen)
417     {
418     if (node->prefix)
419     {
420 michael 5042 #ifdef PATRICIA_DEBUG
421 michael 7834 fprintf(stderr, "patricia_search_best: push %s/%d\n",
422     prefix_toa(node->prefix), node->prefix->bitlen);
423     #endif /* PATRICIA_DEBUG */
424     stack[cnt++] = node;
425     }
426 michael 5042
427 michael 7838 if (BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
428 michael 7834 {
429 michael 5042 #ifdef PATRICIA_DEBUG
430 michael 7834 if (node->prefix)
431     fprintf(stderr, "patricia_search_best: take right %s/%d\n",
432     prefix_toa(node->prefix), node->prefix->bitlen);
433     else
434     fprintf(stderr, "patricia_search_best: take right at %u\n", node->bit);
435     #endif /* PATRICIA_DEBUG */
436     node = node->r;
437     }
438     else
439     {
440 michael 5042 #ifdef PATRICIA_DEBUG
441 michael 7834 if (node->prefix)
442     fprintf(stderr, "patricia_search_best: take left %s/%d\n",
443     prefix_toa(node->prefix), node->prefix->bitlen);
444     else
445     fprintf(stderr, "patricia_search_best: take left at %u\n", node->bit);
446     #endif /* PATRICIA_DEBUG */
447     node = node->l;
448 michael 5042 }
449    
450 michael 7834 if (node == NULL)
451     break;
452     }
453 michael 5042
454 michael 7834 if (inclusive && node && node->prefix)
455     stack[cnt++] = node;
456    
457 michael 5042 #ifdef PATRICIA_DEBUG
458 michael 7834 if (node == NULL)
459     fprintf(stderr, "patricia_search_best: stop at null\n");
460     else if (node->prefix)
461     fprintf(stderr, "patricia_search_best: stop at %s/%d\n",
462     prefix_toa(node->prefix), node->prefix->bitlen);
463     else
464     fprintf(stderr, "patricia_search_best: stop at %u\n", node->bit);
465     #endif /* PATRICIA_DEBUG */
466 michael 5042
467 michael 7834 if (cnt <= 0)
468     return NULL;
469 michael 5042
470 michael 7834 while (--cnt >= 0)
471     {
472     node = stack[cnt];
473 michael 5042 #ifdef PATRICIA_DEBUG
474 michael 7834 fprintf(stderr, "patricia_search_best: pop %s/%d\n",
475     prefix_toa(node->prefix), node->prefix->bitlen);
476     #endif /* PATRICIA_DEBUG */
477    
478     if (comp_with_mask(prefix_tochar(node->prefix),
479     prefix_tochar(prefix), node->prefix->bitlen) && node->prefix->bitlen <= bitlen)
480     {
481 michael 5042 #ifdef PATRICIA_DEBUG
482 michael 7834 fprintf(stderr, "patricia_search_best: found %s/%d\n",
483     prefix_toa(node->prefix), node->prefix->bitlen);
484     #endif /* PATRICIA_DEBUG */
485     return node;
486 michael 5042 }
487 michael 7834 }
488    
489     return NULL;
490 michael 5042 }
491    
492     patricia_node_t *
493 michael 7834 patricia_search_best(patricia_tree_t *patricia, prefix_t *prefix)
494 michael 5042 {
495 michael 7834 return patricia_search_best2(patricia, prefix, 1);
496 michael 5042 }
497    
498     patricia_node_t *
499 michael 7834 patricia_lookup(patricia_tree_t *patricia, prefix_t *prefix)
500 michael 5042 {
501 michael 7834 patricia_node_t *node, *new_node, *parent, *glue;
502     unsigned char *addr, *test_addr;
503     unsigned int bitlen, check_bit, differ_bit;
504     int j, r;
505 michael 5042
506 michael 7834 assert(patricia);
507     assert(prefix);
508     assert(prefix->bitlen <= patricia->maxbits);
509 michael 5042
510 michael 7834 if (patricia->head == NULL)
511     {
512     node = xcalloc(sizeof *node);
513     node->bit = prefix->bitlen;
514     node->prefix = Ref_Prefix (prefix);
515     node->parent = NULL;
516     node->l = node->r = NULL;
517     node->data = NULL;
518     patricia->head = node;
519 michael 5042 #ifdef PATRICIA_DEBUG
520 michael 7834 fprintf(stderr, "patricia_lookup: new_node #0 %s/%d (head)\n",
521     prefix_toa(prefix), prefix->bitlen);
522     #endif /* PATRICIA_DEBUG */
523     patricia->num_active_node++;
524     return node;
525     }
526 michael 5042
527 michael 7838 addr = prefix_touchar(prefix);
528 michael 7834 bitlen = prefix->bitlen;
529     node = patricia->head;
530 michael 5042
531 michael 7834 while (node->bit < bitlen || node->prefix == NULL)
532     {
533     if (node->bit < patricia->maxbits && BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
534     {
535     if (node->r == NULL)
536     break;
537     #ifdef PATRICIA_DEBUG
538     if (node->prefix)
539     fprintf(stderr, "patricia_lookup: take right %s/%d\n",
540     prefix_toa(node->prefix), node->prefix->bitlen);
541     else
542     fprintf(stderr, "patricia_lookup: take right at %u\n", node->bit);
543     #endif /* PATRICIA_DEBUG */
544 michael 5042
545 michael 7834 node = node->r;
546     }
547     else
548     {
549     if (node->l == NULL)
550     break;
551 michael 5042 #ifdef PATRICIA_DEBUG
552 michael 7834 if (node->prefix)
553     fprintf(stderr, "patricia_lookup: take left %s/%d\n",
554     prefix_toa(node->prefix), node->prefix->bitlen);
555     else
556     fprintf(stderr, "patricia_lookup: take left at %u\n", node->bit);
557     #endif /* PATRICIA_DEBUG */
558 michael 5042
559 michael 7834 node = node->l;
560 michael 5042 }
561    
562 michael 7834 assert(node);
563     }
564    
565 michael 7838 assert(node->prefix);
566 michael 5042 #ifdef PATRICIA_DEBUG
567 michael 7834 fprintf(stderr, "patricia_lookup: stop at %s/%d\n",
568     prefix_toa(node->prefix), node->prefix->bitlen);
569 michael 5042 #endif /* PATRICIA_DEBUG */
570    
571 michael 7838 test_addr = prefix_touchar(node->prefix);
572 michael 7834
573     /* Find the first bit different */
574     check_bit = (node->bit < bitlen) ? node->bit : bitlen;
575     differ_bit = 0;
576    
577     for (unsigned int i = 0; i * 8 < check_bit; i++)
578     {
579     if ((r = (addr[i] ^ test_addr[i])) == 0)
580     {
581     differ_bit = (i + 1) * 8;
582     continue;
583 michael 5042 }
584 michael 7834
585     /* I know the better way, but for now */
586     for (j = 0; j < 8; j++)
587     {
588     if (BIT_TEST (r, (0x80 >> j)))
589     break;
590     }
591    
592     /* Must be found */
593 michael 7838 assert(j < 8);
594 michael 7834 differ_bit = i * 8 + j;
595     break;
596     }
597    
598     if (differ_bit > check_bit)
599     differ_bit = check_bit;
600 michael 5042 #ifdef PATRICIA_DEBUG
601 michael 7834 fprintf(stderr, "patricia_lookup: differ_bit %d\n", differ_bit);
602     #endif /* PATRICIA_DEBUG */
603 michael 5042
604 michael 7834 parent = node->parent;
605    
606     while (parent && parent->bit >= differ_bit)
607     {
608     node = parent;
609 michael 5042 parent = node->parent;
610 michael 7834
611 michael 5042 #ifdef PATRICIA_DEBUG
612 michael 7834 if (node->prefix)
613     fprintf(stderr, "patricia_lookup: up to %s/%d\n",
614     prefix_toa(node->prefix), node->prefix->bitlen);
615     else
616     fprintf(stderr, "patricia_lookup: up to %u\n", node->bit);
617     #endif /* PATRICIA_DEBUG */
618     }
619    
620     if (differ_bit == bitlen && node->bit == bitlen)
621     {
622     if (node->prefix)
623     {
624     #ifdef PATRICIA_DEBUG
625     fprintf(stderr, "patricia_lookup: found %s/%d\n",
626     prefix_toa(node->prefix), node->prefix->bitlen);
627     #endif /* PATRICIA_DEBUG */
628    
629     return node;
630 michael 5042 }
631    
632 michael 7834 node->prefix = Ref_Prefix(prefix);
633 michael 6607 #ifdef PATRICIA_DEBUG
634 michael 7834 fprintf(stderr, "patricia_lookup: new node #1 %s/%d (glue mod)\n",
635     prefix_toa(prefix), prefix->bitlen);
636     #endif /* PATRICIA_DEBUG */
637    
638     assert(node->data == NULL);
639     return node;
640     }
641    
642     new_node = xcalloc(sizeof *new_node);
643     new_node->bit = prefix->bitlen;
644     new_node->prefix = Ref_Prefix (prefix);
645     new_node->parent = NULL;
646     new_node->l = new_node->r = NULL;
647     new_node->data = NULL;
648     patricia->num_active_node++;
649    
650     if (node->bit == differ_bit)
651     {
652     new_node->parent = node;
653    
654     if (node->bit < patricia->maxbits && BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
655     {
656     assert(node->r == NULL);
657     node->r = new_node;
658     }
659     else
660     {
661     assert(node->l == NULL);
662     node->l = new_node;
663     }
664 michael 5042 #ifdef PATRICIA_DEBUG
665 michael 7834 fprintf(stderr, "patricia_lookup: new_node #2 %s/%d (child)\n",
666     prefix_toa(prefix), prefix->bitlen);
667     #endif /* PATRICIA_DEBUG */
668     return new_node;
669     }
670    
671     if (bitlen == differ_bit)
672     {
673     if (bitlen < patricia->maxbits && BIT_TEST(test_addr[bitlen >> 3], 0x80 >> (bitlen & 0x07)))
674     {
675     new_node->r = node;
676 michael 5042 }
677 michael 7834 else
678     {
679     new_node->l = node;
680     }
681 michael 5042
682 michael 7834 new_node->parent = node->parent;
683 michael 5042
684 michael 7834 if (node->parent == NULL)
685     {
686     assert(patricia->head == node);
687     patricia->head = new_node;
688 michael 5042 }
689 michael 7834 else if (node->parent->r == node)
690     {
691     node->parent->r = new_node;
692     }
693     else
694     {
695     node->parent->l = new_node;
696     }
697 michael 5042
698 michael 7834 node->parent = new_node;
699 michael 5042 #ifdef PATRICIA_DEBUG
700 michael 7834 fprintf(stderr, "patricia_lookup: new_node #3 %s/%d (parent)\n",
701     prefix_toa(prefix), prefix->bitlen);
702     #endif /* PATRICIA_DEBUG */
703     }
704     else
705     {
706     glue = xcalloc(sizeof *glue);
707     glue->bit = differ_bit;
708     glue->prefix = NULL;
709     glue->parent = node->parent;
710     glue->data = NULL;
711     patricia->num_active_node++;
712    
713     if (differ_bit < patricia->maxbits && BIT_TEST(addr[differ_bit >> 3], 0x80 >> (differ_bit & 0x07)))
714     {
715     glue->r = new_node;
716     glue->l = node;
717 michael 5042 }
718 michael 7834 else
719     {
720     glue->r = node;
721     glue->l = new_node;
722     }
723 michael 5042
724 michael 7834 new_node->parent = glue;
725    
726     if (node->parent == NULL)
727     {
728     assert(patricia->head == node);
729     patricia->head = glue;
730     }
731     else if (node->parent->r == node)
732     {
733     node->parent->r = glue;
734     }
735     else
736     {
737     node->parent->l = glue;
738     }
739    
740     node->parent = glue;
741 michael 5042 #ifdef PATRICIA_DEBUG
742 michael 7834 fprintf(stderr, "patricia_lookup: new_node #4 %s/%d (glue+node)\n",
743     prefix_toa(prefix), prefix->bitlen);
744     #endif /* PATRICIA_DEBUG */
745     }
746    
747     return new_node;
748 michael 5042 }
749    
750     void
751 michael 7834 patricia_remove(patricia_tree_t *patricia, patricia_node_t *node)
752 michael 5042 {
753 michael 7834 patricia_node_t *parent, *child;
754 michael 5042
755 michael 7834 assert(patricia);
756     assert(node);
757 michael 5042
758 michael 7834 if (node->r && node->l)
759     {
760 michael 5042 #ifdef PATRICIA_DEBUG
761 michael 7834 fprintf(stderr, "patricia_remove: #0 %s/%d (r & l)\n",
762     prefix_toa(node->prefix), node->prefix->bitlen);
763     #endif /* PATRICIA_DEBUG */
764 michael 5042
765 michael 7834 /*
766     * This might be a placeholder node -- have to check and make sure
767     * there is a prefix associated with it !
768     */
769     if (node->prefix != NULL)
770     Deref_Prefix(node->prefix);
771 michael 5042
772 michael 7834 node->prefix = NULL;
773     /* Also I needed to clear data pointer -- masaki */
774     node->data = NULL;
775     return;
776     }
777 michael 5042
778 michael 7834 if (node->r == NULL && node->l == NULL)
779     {
780     #ifdef PATRICIA_DEBUG
781     fprintf(stderr, "patricia_remove: #1 %s/%d (!r & !l)\n",
782     prefix_toa(node->prefix), node->prefix->bitlen);
783     #endif /* PATRICIA_DEBUG */
784 michael 5042
785 michael 7834 parent = node->parent;
786     Deref_Prefix(node->prefix);
787     xfree(node);
788     patricia->num_active_node--;
789 michael 5042
790 michael 7834 if (parent == NULL)
791     {
792     assert(patricia->head == node);
793     patricia->head = NULL;
794     return;
795     }
796 michael 5042
797 michael 7834 if (parent->r == node)
798     {
799     parent->r = NULL;
800     child = parent->l;
801 michael 5042 }
802 michael 7834 else
803     {
804     assert(parent->l == node);
805 michael 5042
806 michael 7834 parent->l = NULL;
807     child = parent->r;
808 michael 5042 }
809 michael 7834
810     if (parent->prefix)
811     return;
812    
813     /* We need to remove parent too */
814     if (parent->parent == NULL)
815     {
816     assert(patricia->head == parent);
817     patricia->head = child;
818 michael 5042 }
819 michael 7834 else if (parent->parent->r == parent)
820     {
821     parent->parent->r = child;
822     }
823     else
824     {
825     assert(parent->parent->l == parent);
826     parent->parent->l = child;
827     }
828 michael 5042
829 michael 7834 child->parent = parent->parent;
830     xfree(parent);
831 michael 5042 patricia->num_active_node--;
832 michael 7834 return;
833     }
834 michael 5042
835 michael 7834 #ifdef PATRICIA_DEBUG
836     fprintf(stderr, "patricia_remove: #2 %s/%d (r ^ l)\n",
837     prefix_toa(node->prefix), node->prefix->bitlen);
838     #endif /* PATRICIA_DEBUG */
839 michael 5042
840 michael 7834 if (node->r)
841     {
842     child = node->r;
843     }
844     else
845     {
846     assert(node->l);
847     child = node->l;
848     }
849    
850     parent = node->parent;
851     child->parent = parent;
852    
853     Deref_Prefix(node->prefix);
854     xfree(node);
855     patricia->num_active_node--;
856    
857     if (parent == NULL)
858     {
859     assert(patricia->head == node);
860     patricia->head = child;
861     return;
862     }
863    
864     if (parent->r == node)
865     {
866     parent->r = child;
867     }
868     else
869     {
870     assert(parent->l == node);
871     parent->l = child;
872     }
873 michael 5042 }
874    
875     /* { from demo.c */
876     patricia_node_t *
877 michael 7834 make_and_lookup(patricia_tree_t *tree, const char *string)
878 michael 5042 {
879 michael 7834 prefix_t *prefix = ascii2prefix(0, string);
880 michael 5042
881 michael 7834 if (prefix)
882     {
883     patricia_node_t *node = patricia_lookup(tree, prefix);
884     Deref_Prefix(prefix);
885     return node;
886     }
887    
888     return NULL;
889 michael 5042 }
890    
891     patricia_node_t *
892 michael 7834 try_search_exact(patricia_tree_t *tree, const char *string)
893 michael 5042 {
894 michael 7834 prefix_t *prefix = ascii2prefix(0, string);
895 michael 7809
896 michael 7834 if (prefix)
897     {
898     patricia_node_t *node = patricia_search_exact(tree, prefix);
899     Deref_Prefix(prefix);
900     return node;
901     }
902    
903     return NULL;
904 michael 5042 }
905    
906     void
907 michael 7834 lookup_then_remove(patricia_tree_t *tree, const char *string)
908 michael 5042 {
909 michael 7834 patricia_node_t *node;
910 michael 5042
911 michael 7834 if ((node = try_search_exact(tree, string)))
912     patricia_remove(tree, node);
913 michael 5042 }
914    
915     patricia_node_t *
916 michael 7834 try_search_best(patricia_tree_t *tree, const char *string)
917 michael 5042 {
918 michael 7834 prefix_t *prefix = ascii2prefix(0, string);
919 michael 5042
920 michael 7834 if (prefix)
921     {
922     patricia_node_t *node = patricia_search_best(tree, prefix);
923     Deref_Prefix(prefix);
924     return node;
925     }
926    
927     return NULL;
928 michael 5042 }
929     /* } */

Properties

Name Value
svn:eol-style native
svn:keywords Id