From 38506f71b0bea5580987e999a7b1a69f58aec7ec Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 12 Apr 1999 19:58:18 +0000 Subject: Sets of integers now actually work. Sets of IP will work as soon as compare function is ready. --- filter/tree.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 filter/tree.c (limited to 'filter/tree.c') diff --git a/filter/tree.c b/filter/tree.c new file mode 100644 index 0000000..ea1f18f --- /dev/null +++ b/filter/tree.c @@ -0,0 +1,125 @@ +/* + * Filters: utility functions + * + * Copyright 1998 Pavel Machek + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +#include +#include +#include +#include +#include + +#include "nest/bird.h" +#include "lib/lists.h" +#include "lib/resource.h" +#include "lib/socket.h" +#include "nest/route.h" +#include "nest/protocol.h" +#include "nest/iface.h" +#include "conf/conf.h" +#include "filter/filter.h" + +/* Finds n-th item in list linked by right. Trashes pointers in right. */ +static struct f_tree * +find_nth(struct f_tree *from, int nth) +{ + struct f_tree *pivot; + int lcount = 0, rcount = 0; + struct f_tree *left, *right, *next; + + pivot = from; + + left = right = NULL; + next = from->right; + while (from = next) { + next = from->right; + if (val_compare(pivot->from, from->from)==1) { + from->right = left; + left = from; + lcount++; + } else { + from->right = right; + right = from; + rcount++; + } + } + if (lcount == nth) + return pivot; + if (lcount < nth) + return find_nth(right, nth-lcount-1); + return find_nth(left, nth); +} + +/* Gets list linked by left, finds its median, trashes pointers in right */ +static struct f_tree * +find_median(struct f_tree *from) +{ + struct f_tree *t = from; + int cnt = 0; + + if (!from) + return NULL; + do { + t->right = t->left; + cnt++; + } while (t = t->left); + return find_nth(from, cnt/2); +} + +struct f_tree * +find_tree(struct f_tree *t, struct f_val val) +{ + if (!t) + return 0; + if ((val_compare(t->from, val) != 1) && + (val_compare(t->to, val) != -1)) + return t; + if (val_compare(t->from, val) == -1) + return find_tree(t->right, val); + else + return find_tree(t->left, val); +} + +/* Gets list linked by left */ +struct f_tree * +build_tree(struct f_tree *from) +{ + struct f_tree *median, *t = from, *next, *left = NULL, *right = NULL; + + median = find_median(from); + if (!median) + return NULL; + + do { + next = t->left; + if (t == median) + continue; + + if (val_compare(median->from, t->from)==1) { + t->left = left; + left = t; + } else { + t->left = right; + right = t; + } + } while(t = next); + + median->left = build_tree(left); + median->right = build_tree(right); + return median; +} + +struct f_tree * +f_new_tree(void) +{ + struct f_tree * ret; + ret = cfg_alloc(sizeof(struct f_tree)); + ret->left = ret->right = NULL; + ret->from.type = ret->to.type = T_VOID; + ret->from.val.i = ret->to.val.i = 0; + ret->data = NULL; + return ret; +} -- cgit v1.2.3