Annotation of embedaddon/bird/filter/tree.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *     Filters: utility functions
                      3:  *
                      4:  *     Copyright 1998 Pavel Machek <pavel@ucw.cz>
                      5:  *
                      6:  *     Can be freely distributed and used under the terms of the GNU GPL.
                      7:  */
                      8: 
                      9: #include "lib/alloca.h"
                     10: #include "nest/bird.h"
                     11: #include "conf/conf.h"
                     12: #include "filter/filter.h"
                     13: 
                     14: /**
                     15:  * find_tree
                     16:  * @t: tree to search in
                     17:  * @val: value to find
                     18:  *
                     19:  * Search for given value in the tree. I relies on fact that sorted tree is populated
                     20:  * by &f_val structures (that can be compared by val_compare()). In each node of tree, 
                     21:  * either single value (then t->from==t->to) or range is present.
                     22:  *
                     23:  * Both set matching and |switch() { }| construction is implemented using this function,
                     24:  * thus both are as fast as they can be.
                     25:  */
                     26: struct f_tree *
                     27: find_tree(struct f_tree *t, struct f_val val)
                     28: {
                     29:   if (!t)
                     30:     return NULL;
                     31:   if ((val_compare(t->from, val) != 1) &&
                     32:       (val_compare(t->to, val) != -1))
                     33:     return t;
                     34:   if (val_compare(t->from, val) == -1)
                     35:     return find_tree(t->right, val);
                     36:   else
                     37:     return find_tree(t->left, val);
                     38: }
                     39: 
                     40: static struct f_tree *
                     41: build_tree_rec(struct f_tree **buf, int l, int h)
                     42: {
                     43:   struct f_tree *n;
                     44:   int pos;
                     45: 
                     46:   if (l >= h)
                     47:     return NULL;
                     48: 
                     49:   pos = (l+h)/2;
                     50:   n = buf[pos];
                     51:   n->left = build_tree_rec(buf, l, pos);
                     52:   n->right = build_tree_rec(buf, pos+1, h);
                     53:   return n;
                     54: }
                     55: 
                     56: static int 
                     57: tree_compare(const void *p1, const void *p2)
                     58: {
                     59:   return val_compare((* (struct f_tree **) p1)->from, (* (struct f_tree **) p2)->from);
                     60: }
                     61: 
                     62: /**
                     63:  * build_tree
                     64:  * @from: degenerated tree (linked by @tree->left) to be transformed into form suitable for find_tree()
                     65:  *
                     66:  * Transforms degenerated tree into balanced tree.
                     67:  */
                     68: struct f_tree *
                     69: build_tree(struct f_tree *from)
                     70: {
                     71:   struct f_tree *tmp, *root;
                     72:   struct f_tree **buf;
                     73:   int len, i;
                     74: 
                     75:   if (from == NULL)
                     76:     return NULL;
                     77: 
                     78:   len = 0;
                     79:   for (tmp = from; tmp != NULL; tmp = tmp->left)
                     80:     len++;
                     81: 
                     82:   if (len <= 1024)
                     83:     buf = alloca(len * sizeof(struct f_tree *));
                     84:   else
                     85:     buf = xmalloc(len * sizeof(struct f_tree *));
                     86: 
                     87:   /* Convert a degenerated tree into an sorted array */
                     88:   i = 0;
                     89:   for (tmp = from; tmp != NULL; tmp = tmp->left)
                     90:     buf[i++] = tmp;
                     91: 
                     92:   qsort(buf, len, sizeof(struct f_tree *), tree_compare);
                     93: 
                     94:   root = build_tree_rec(buf, 0, len);
                     95: 
                     96:   if (len > 1024)
                     97:     xfree(buf);
                     98: 
                     99:   return root;
                    100: }
                    101: 
                    102: struct f_tree *
                    103: f_new_tree(void)
                    104: {
                    105:   struct f_tree * ret;
                    106:   ret = cfg_alloc(sizeof(struct f_tree));
                    107:   ret->left = ret->right = NULL;
                    108:   ret->from.type = ret->to.type = T_VOID;
                    109:   ret->from.val.i = ret->to.val.i = 0;
                    110:   ret->data = NULL;
                    111:   return ret;
                    112: }
                    113: 
                    114: /**
                    115:  * same_tree
                    116:  * @t1: first tree to be compared
                    117:  * @t2: second one
                    118:  *
                    119:  * Compares two trees and returns 1 if they are same
                    120:  */
                    121: int
                    122: same_tree(struct f_tree *t1, struct f_tree *t2)
                    123: {
                    124:   if ((!!t1) != (!!t2))
                    125:     return 0;
                    126:   if (!t1)
                    127:     return 1;
                    128:   if (val_compare(t1->from, t2->from))
                    129:     return 0;
                    130:   if (val_compare(t1->to, t2->to))
                    131:     return 0;
                    132:   if (!same_tree(t1->left, t2->left))
                    133:     return 0;
                    134:   if (!same_tree(t1->right, t2->right))
                    135:     return 0;
                    136:   if (!i_same(t1->data, t2->data))
                    137:     return 0;
                    138:   return 1;
                    139: }
                    140: 
                    141: 
                    142: static void
                    143: tree_node_format(struct f_tree *t, buffer *buf)
                    144: {
                    145:   if (t == NULL)
                    146:     return;
                    147: 
                    148:   tree_node_format(t->left, buf);
                    149: 
                    150:   val_format(t->from, buf);
                    151:   if (val_compare(t->from, t->to) != 0)
                    152:   {
                    153:     buffer_puts(buf, "..");
                    154:     val_format(t->to, buf);
                    155:   }
                    156:   buffer_puts(buf, ", ");
                    157: 
                    158:   tree_node_format(t->right, buf);
                    159: }
                    160: 
                    161: void
                    162: tree_format(struct f_tree *t, buffer *buf)
                    163: {
                    164:   buffer_puts(buf, "[");
                    165: 
                    166:   tree_node_format(t, buf);
                    167: 
                    168:   if (buf->pos == buf->end)
                    169:     return;
                    170: 
                    171:   /* Undo last separator */
                    172:   if (buf->pos[-1] != '[')
                    173:     buf->pos -= 2;
                    174: 
                    175:   buffer_puts(buf, "]");
                    176: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>