]>
git.ipfire.org Git - thirdparty/bird.git/blob - filter/tree.c
2 * Filters: utility functions
4 * Copyright 1998 Pavel Machek <pavel@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
9 #include "lib/alloca.h"
10 #include "nest/bird.h"
11 #include "conf/conf.h"
12 #include "filter/filter.h"
13 #include "filter/f-util.h"
17 * @t: tree to search in
20 * Search for given value in the tree. I relies on fact that sorted tree is populated
21 * by &f_val structures (that can be compared by val_compare()). In each node of tree,
22 * either single value (then t->from==t->to) or range is present.
24 * Both set matching and |switch() { }| construction is implemented using this function,
25 * thus both are as fast as they can be.
28 find_tree(const struct f_tree
*t
, const struct f_val
*val
)
32 if ((val_compare(&(t
->from
), val
) != 1) &&
33 (val_compare(&(t
->to
), val
) != -1))
35 if (val_compare(&(t
->from
), val
) == -1)
36 return find_tree(t
->right
, val
);
38 return find_tree(t
->left
, val
);
41 static struct f_tree
*
42 build_tree_rec(struct f_tree
**buf
, int l
, int h
)
52 n
->left
= build_tree_rec(buf
, l
, pos
);
53 n
->right
= build_tree_rec(buf
, pos
+1, h
);
58 tree_compare(const void *p1
, const void *p2
)
60 return val_compare(&((* (struct f_tree
**) p1
)->from
), &((* (struct f_tree
**) p2
)->from
));
65 * @from: degenerated tree (linked by @tree->left) to be transformed into form suitable for find_tree()
67 * Transforms degenerated tree into balanced tree.
70 build_tree(struct f_tree
*from
)
72 struct f_tree
*tmp
, *root
;
80 for (tmp
= from
; tmp
!= NULL
; tmp
= tmp
->left
)
84 buf
= alloca(len
* sizeof(struct f_tree
*));
86 buf
= xmalloc(len
* sizeof(struct f_tree
*));
88 /* Convert a degenerated tree into an sorted array */
90 for (tmp
= from
; tmp
!= NULL
; tmp
= tmp
->left
)
93 qsort(buf
, len
, sizeof(struct f_tree
*), tree_compare
);
95 root
= build_tree_rec(buf
, 0, len
);
107 ret
= cfg_alloc(sizeof(struct f_tree
));
108 ret
->left
= ret
->right
= NULL
;
109 ret
->from
.type
= ret
->to
.type
= T_VOID
;
110 ret
->from
.val
.i
= ret
->to
.val
.i
= 0;
117 * @t1: first tree to be compared
120 * Compares two trees and returns 1 if they are same
123 same_tree(const struct f_tree
*t1
, const struct f_tree
*t2
)
125 if ((!!t1
) != (!!t2
))
129 if (val_compare(&(t1
->from
), &(t2
->from
)))
131 if (val_compare(&(t1
->to
), &(t2
->to
)))
133 if (!same_tree(t1
->left
, t2
->left
))
135 if (!same_tree(t1
->right
, t2
->right
))
137 if (!f_same(t1
->data
, t2
->data
))
144 tree_node_format(const struct f_tree
*t
, buffer
*buf
)
149 tree_node_format(t
->left
, buf
);
151 val_format(&(t
->from
), buf
);
152 if (val_compare(&(t
->from
), &(t
->to
)) != 0)
154 buffer_puts(buf
, "..");
155 val_format(&(t
->to
), buf
);
157 buffer_puts(buf
, ", ");
159 tree_node_format(t
->right
, buf
);
163 tree_format(const struct f_tree
*t
, buffer
*buf
)
165 buffer_puts(buf
, "[");
167 tree_node_format(t
, buf
);
169 if (buf
->pos
== buf
->end
)
172 /* Undo last separator */
173 if (buf
->pos
[-1] != '[')
176 buffer_puts(buf
, "]");