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>