diff --git a/src/capwap/mavl.c b/src/capwap/mavl.c new file mode 100644 index 00000000..4965d2e5 --- /dev/null +++ b/src/capwap/mavl.c @@ -0,0 +1,229 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +/** + * @file + * @brief Yet another AVL tree implementation + */ + +#include +#include + + +#include "mavl.h" + + + + + +/* + * Delete the node with the highest value + * returns the rebalancing factor + */ + +/* +static int mavl_delete_hi(struct mavlnode **parent, void **data) +{ + struct mavlnode * n = *parent; + + if(n->right!=0){ + int bal = mavl_delete_hi(&n->right,data); + n->bal-=bal; + if (n->bal==-2){ + + // if (rotate_r(n,parent)) + // return 0; + } + + return bal; + } + + *parent=n->left; + *data = n->data; + if (n->left){ + free(n); + return 0; + } + free(n); + return 1; +} +*/ + +//struct mavl * trrr; + + +/* +static int cmp(const void *k1,const void *k2) +{ + int x1 = *((int*)k1); + int x2 = *((int*)k2); + return x1-x2; +} +*/ + +//int data[]={10,37,60,10,5,35,36,26,3,11,18}; +//int data[] = {100,50,75}; +//int data[]={100,200,150,300,400}; +//int data[]={100,200,150,170,470}; +//int data[]={10,20,15,17,47,50,60,70,80}; +//int data[]={9,8,7,6,5,4,3,2,1,0}; + +//int data[]={10,37,60,10,5,35,19,26,3,11,18}; +//int data[]={0,11,14,33,37,20}; +//int data[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; +//int data[]={1,4,3,7,5,6,7,8,9,10}; +//int data[]={11,4,5,6,3,4,3,2,1,0}; +//int data[]={20,16,10,11,5,4,3,2,1,0}; + +/* +struct mavlnode * ar[10000]; +int tpw = 80; + +static void print_tree0(struct mavlnode * n,int d,int l,int r) +{ + int pos = l+(r-l)/2; + ar[d*tpw+pos]=n; + if (n->right) + print_tree0(n->right,d+1,l+(r-l)/2,r); + if(n->left) + print_tree0(n->left,d+1,l,r-(r-l)/2); +} + +void mavl_print(struct mavlnode * n ) +{ + + int y; + int i=0; + for(i=0; i<10000; i++) + ar[i]=0; + + if (n==0){ + + printf("Empty Tree\n"); + return ; + } + + print_tree0(n,0,0,tpw); + for (i=0; i<10; i++) { + for (y=0; ydata),r->bal); + } + else{ + printf("."); + } + } + printf("\n"); + } + + +} + + + +void walk(struct mavlnode *n) +{ + if (n == 0) + return; + walk(n->left); + int x = *((int*)(n->data)); + printf("VAL: %i\n",x); + walk(n->right); +// x = *((int*)(n->data)); +// printf("VALR: %i\n",x); + +} + +*/ + +/* +void mavl_destroy(struct mavl *t) +{ + mavl_del_all(t); + free (t); +} +*/ + + +//#include + + + + + + + + + +/* +//int data[]={5,1,9,7,0,10,8,0,4,3}; +//int data[]={50,10,90,70,00,100,80,00,40,30,1,2,3}; +int data[]={10,20,30,45,1,50,11,51,60,70,80,90,99,25,50,10,90,70,00,100,80,00,40,30,1,2,3}; + + +int main() +{ + struct mavl *t = mavl_create(cmp,0); + trrr=t; + printf("T: %p\n",t); + + srand(time(NULL)); + int i=0; + for (i=0; i<6; i++) + { + int r = rand()%0x3f; // % 0xiff; +// int r = rand(); //%0x3f; // % 0xiff; + + // r = data[7-i]; + r = data[i]; + int * dr = malloc(sizeof(int)); + *dr = r; + + + printf("Insert %i\n",*dr); + + void * d = mavl_insert(t,dr); + printf("After insert %i\n",r); + print_tree(t->root); + + if (d!=dr){ +// printf("exists\n"); + } + + + } + + printf("Here it is\n"); + print_tree(t->root); +// walk(t->root); + void * da; + + int x = 110; + +// void * drc = mavl_delete(t,&x); + mavl_delete_all(t); +// printf("Delete 110 rc = %p\n",drc); + print_tree(t->root); + printf("Count: %i\n",t->count); + return 0; +} + + + +*/ diff --git a/src/capwap/mavl.h b/src/capwap/mavl.h new file mode 100644 index 00000000..1d67a6f9 --- /dev/null +++ b/src/capwap/mavl.h @@ -0,0 +1,192 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . + +*/ + +/** + * @file + * @brief Yet another avl tree implementation! + */ + +#ifndef __AVLTREE_H +#define __AVLTREE_H + +#include +#include +#include + +#include + +/** Maximum AVL Tree depth. + The number of nodes is calculated by 2^depth. + So a value of 32 should be enough for around 4 + billion nodes. */ +#define AVLTREE_MAX_DEPTH 32 + +/** + * Defines the structure of an AVL Node. + */ +struct mavlnode { + void *data; + struct mavlnode *left; + struct mavlnode *right; + int bal; +}; + +/** + * AVL Tree + */ +struct mavl { + struct mavlnode *root; + int (*cmp) (const void *, const void *); + void (*del) (void *); + int count; +}; + +typedef struct mavl * mavl_t; + + +//extern void mavlnode_destroy(struct mavl *t, struct mavlnode *n); + +struct mavl *mavl_create(int (*cmp) (const void *, const void *), + void (*del) (void *)); +//void mavl_destroy(struct mavl *t); + +void mavl_del_all(struct mavl *t); +void *mavl_del(struct mavl *t, void *data); +void *mavl_add(struct mavl *t, void *data); +void * mavl_get(struct mavl *t ,void *data); +struct mavlnode *mavl_get_node(struct mavl *t, void *data); + +extern int mavl_foreach_lr(struct mavlnode *n, int (*callback) (void *, void *), + void *cbpriv); +extern int mavl_foreach_rl(struct mavlnode *n, int (*callback) (void *, void *), + void *cbpriv); +int mavl_foreach_from_lr(struct mavl *t, struct mavlnode *n, void *data, + int (*callback) (void *, void *), void *cbpriv); + + +//extern void mavl_foreach(struct mavl *t, int (*callback)(void *,void*),void *cbpriv,int dir); + +static inline void *mavl_replace_data(struct mavl *t, void *data, int len) +{ + void *df = mavl_get(t, data); + if (!df) + return NULL; + memcpy(df, data, len); + return df; +} + +static inline void *mavl_replace(struct mavl *t,void *data){ + struct mavlnode * node = mavl_get_node(t,data); + if (node){ + t->del(node->data); + return node->data=data; + } + return mavl_add(t,data); +} + + +static inline void mavl_destroy(struct mavl *t) +{ + mavl_del_all(t); + free (t); +} + + + + +#define mavl_find(t,d) mavl_get(t,d) +#define mavl_insert(t,d) mavl_add(t,d) +//#define mavl_walk(t,dir) mavl_foreach(t,dir) + +#define mavl_foreach_asc(t,cb,priv) mavl_foreach_lr((t)->root,cb,priv) +#define mavl_foreach_desc(t,cb,priv) mavl_foreach_rl((t)->root,cb,priv) + +#define mavl_foreach_from_asc(t,d,cb,priv) mavl_foreach_from_lr(t,(t)->root,d,cb,priv); + + +struct mavliter{ + struct mavlnode *stack[AVLTREE_MAX_DEPTH*2]; + + struct mavlnode *cur; + int stack_ptr; + struct mavlnode * root; + int (*cmp) (const void *, const void *); + +}; +typedef struct mavliter mavliter_t; + + +void * mavliter_next(mavliter_t *i); + +static inline void * mavliter_seek_set(struct mavliter *i) +{ + i->stack_ptr=0; + i->cur=i->root; + return mavliter_next(i); +} + +/** + * Init an AVL Tree Iterator. + * + * After initialization #mavliter_next would return the first element. + * The behavior of #mavliter_get would still be undefined. + * @param i AVL Iterator to initialize + * @param t correspondending AVL Tree + * + * @See mavliter_t, + */ +static inline void mavliter_init(mavliter_t *i, mavl_t t){ + i->root = t->root; + i->stack_ptr=0; + i->cmp=t->cmp; +} + + +/** + * Get the element, where AVL Iterator currently is positioned. + * @param i AVL Iterator + * @return element or NULL if not found. + */ +static inline void * mavliter_get(mavliter_t *i){ + if(!i->cur) + return NULL; + return i->cur->data; +} + + +extern void * mavliter_seek(mavliter_t *i,void *d); + + +#define DEFINE_MAVLITER(i,t)\ + mavliter_t i; mavliter_init(&i,t) + + +#define mavliter_foreach(i)\ + for (mavliter_seek_set(i); NULL != mavliter_get(i); mavliter_next(i)) + +#define mavliter_foreach_from(i,from)\ + for (mavliter_seek(i,from); NULL != mavliter_get(i); mavliter_next(i)) + +#define mavliter_foreach_asc(iter,val) \ + while(NULL != (val = mavliter_next(iter))) + + + +#endif + + diff --git a/src/capwap/mavl_add.c b/src/capwap/mavl_add.c new file mode 100644 index 00000000..92798fdb --- /dev/null +++ b/src/capwap/mavl_add.c @@ -0,0 +1,191 @@ +#include "mavl.h" + +static struct mavlnode *mavlnode_create(void *data) +{ + struct mavlnode *n = malloc(sizeof(struct mavlnode)); + if (!n) + return NULL; + + n->left = n->right = 0; + n->bal = 0; + n->data = data; + return n; +} + + + + +static int mavl_add0(struct mavl *t, struct mavlnode **parent, void **data) +{ +// struct mavlnode * rn; + struct mavlnode *tmp; + + struct mavlnode *n = *parent; + int rc = t->cmp(*data, n->data); + + int bal; + if (rc == 0) { + *data = n->data; + return 2; + } + + if (rc < 0) { + if (n->left) { + bal = mavl_add0(t, &n->left, data); + if (bal > 1) + return bal; + + n->bal -= bal; + if (n->bal == 0) + return 0; + + if (n->bal == -2) { + if (n->left->bal == -1) { + n->bal = 0; + n->left->bal = 0; + *parent = n->left; + tmp = n->left->right; + n->left->right = n; + n->left = tmp; + return 0; + } + if (n->left->bal == 1) { + *parent = n->left->right; + if ((*parent)->bal == 1) { + n->bal = 0; + n->left->bal = -1; + } else if ((*parent)->bal == -1) { + n->bal = 1; + n->left->bal = 0; + } else { + n->bal = 0; + n->left->bal = 0; + } + + (*parent)->bal = 0; + n->left->right = (*parent)->left; + (*parent)->left = n->left; + tmp = (*parent)->right; + (*parent)->right = n; + n->left = tmp; + return 0; + + } + //printf("!!!!left bal = %i\n",n->left->bal); + //exit(0); + + } + return bal; + + } + + /* n->left is 0 */ + n->left = mavlnode_create(*data); + if (!n->left) + return 3; + + t->count++; + + if (n->right == 0) { + n->bal = -1; + return 1; + } + + n->bal = 0; + return 0; + + } else { + if (n->right) { + bal = mavl_add0(t, &n->right, data); + if (bal > 1) + return bal; + + n->bal += bal; + if (n->bal == 0) + return 0; + + if (n->bal == 2) { + if (n->right->bal == 1) { + n->bal = 0; + n->right->bal = 0; + *parent = n->right; + tmp = n->right->left; + n->right->left = n; + n->right = tmp; + return 0; + } else if (n->right->bal == -1) { + *parent = n->right->left; + + if ((*parent)->bal == -1) { + n->bal = 0; + n->right->bal = 1; + } else if ((*parent)->bal == 1) { + n->bal = -1; + n->right->bal = 0; + } else { + n->bal = 0; + n->right->bal = 0; + } + + + + + + (*parent)->bal = 0; + n->right->left = (*parent)->right; + (*parent)->right = n->right; + tmp = (*parent)->left; + (*parent)->left = n; + n->right = tmp; + return 0; + } + //printf("!!!!iright bal = %i\n",n->left->bal); + //exit(0); + + + } + return bal; + + } + + /* n->right is 0 */ + + n->right = mavlnode_create(*data); + if (!n->right) + return 3; + + t->count++; + if (n->left == 0) { + n->bal = 1; + return 1; + } + n->bal = 0; + return 0; + } +} + + +/** + * Add an element to an AVL tree + * @t mavl + * @data pointer to element + * @return added alement or NULL if error. + */ +void *mavl_add(struct mavl *t, void *data) +{ + if (t->root == 0) { + t->root = mavlnode_create(data); + if (t->root) + t->count++; + return t->root->data; + } + void *d = data; + int rc = mavl_add0(t, &t->root, &d); + + if (rc > 3) + return NULL; + + return d; +} + + diff --git a/src/capwap/mavl_create.c b/src/capwap/mavl_create.c new file mode 100644 index 00000000..7f49318e --- /dev/null +++ b/src/capwap/mavl_create.c @@ -0,0 +1,22 @@ +#include "mavl.h" + +/** + * Create an AVL tree + * @param cmp pointer compare function + * @param del pointer to delete function which is called when an element will be deletet + * @return pointer to an #mavl struct + */ +struct mavl *mavl_create(int (*cmp) (const void *, const void *), + void (*del) (void *)) +{ + struct mavl *t = malloc(sizeof(struct mavl)); + if (!t) + return NULL; + t->root = 0; + t->count = 0; + t->cmp = cmp; + t->del = del; + return t; +} + + diff --git a/src/capwap/mavl_del.c b/src/capwap/mavl_del.c new file mode 100644 index 00000000..8c38482e --- /dev/null +++ b/src/capwap/mavl_del.c @@ -0,0 +1,252 @@ +#include "mavl.h" + +static void mavlnode_destroy(struct mavl *t, struct mavlnode *n) +{ + if (t->del) { + t->del(n->data); + } + free(n); + t->count--; +} + + + + +static void rot_rl(struct mavlnode *n, struct mavlnode **parent) +{ + struct mavlnode *tmp; + *parent = n->right->left; + n->right->left = (*parent)->right; + (*parent)->right = n->right; + tmp = (*parent)->left; + (*parent)->left = n; + n->right = tmp; +} + +static void rot_lr(struct mavlnode *n, struct mavlnode **parent) +{ + struct mavlnode *tmp; + *parent = n->left->right; + n->left->right = (*parent)->left; + (*parent)->left = n->left; + tmp = (*parent)->right; + (*parent)->right = n; + n->left = tmp; +} + + + +static void rot_l(struct mavlnode *n, struct mavlnode **parent) +{ + struct mavlnode *tmp; + *parent = n->right; + tmp = n->right->left; + n->right->left = n; + n->right = tmp; +} + + +static void rot_r(struct mavlnode *n, struct mavlnode **parent) +{ + struct mavlnode *tmp; + *parent = n->left; + tmp = n->left->right; + n->left->right = n; + n->left = tmp; +} + + + +static int adj_bal_l(struct mavlnode *n, struct mavlnode **parent) +{ + if (n->right->bal == 1) { + n->bal = 0; + n->right->bal = 0; + rot_l(n, parent); + return 1; + } else if (n->right->bal == 0) { + n->bal = 1; + n->right->bal = -1; + rot_l(n, parent); + return 0; + } else if (n->right->bal == -1) { +// int rb; + n->bal = 0; + n->right->bal = 0; +// rb = n->right->left->bal; + n->right->left->bal = 0; + rot_rl(n, parent); + return 1; + } +// printf("adj bal l not handled \n"); +// exit(0); + + return -11; /* that should never happen */ +} + +static int adj_bal_r(struct mavlnode *n, struct mavlnode **parent) +{ + + if (n->left->bal == -1) { + n->bal = 0; + n->left->bal = 0; + rot_r(n, parent); + return 1; + } else if (n->left->bal == 0) { + n->bal = -1; + n->left->bal = 1; + rot_r(n, parent); + return 0; + } else if (n->left->bal == 1) { +// int rb; + n->bal = 0; + n->left->bal = 0; +// rb = n->left->right->bal; + n->left->right->bal = 0; + rot_lr(n, parent); + return 1; + } +// printf("adj bal li left not handled \n"); +// exit(0); + return -11; /* that should never happen */ +} + + + + + + +static int mavl_del_lo(struct mavlnode **parent, void **data) +{ + struct mavlnode *n = *parent; + + if (n->left != 0) { + int bal = mavl_del_lo(&n->left, data); + n->bal += bal; + if (n->bal == 1) { + return 0; + } + if (n->bal != 2) + return bal; + adj_bal_l(n, parent); + return 0; + } + + /* found the lowest element */ + + *parent = n->right; + *data = n->data; + free(n); + return 1; + + + if (n->right) { + free(n); + return 1; + } + free(n); + return 1; + +} + + + + +int mavl_del0(struct mavl *t, struct mavlnode **parent, void **data) +{ + struct mavlnode *n = *parent; + int rc; + int bal; + rc = t->cmp(*data, n->data); + + if (rc == 0) { + if (n->right == 0 && n->left == 0) { + *parent = 0; + mavlnode_destroy(t, n); + return 1; + } + + if (n->right && n->left == 0) { + *parent = n->right; + mavlnode_destroy(t, n); + return 1; + + } + + if (n->left && n->right == 0) { + mavlnode_destroy(t, n); + *parent = n->left; + return 1; + + } + + /* node has two childs */ + + if (t->del) { + t->del(n->data); + } + t->count--; + bal = mavl_del_lo(&n->right, &n->data); + n->bal -= bal; + if (n->bal == -1) + return 0; + + if (n->bal != -2) + return bal; + + return adj_bal_r(n, parent); + + } + + if (rc < 0) { + if (n->left) { + bal = mavl_del0(t, &n->left, data); + if (bal == 2) + return 2; + + n->bal += bal; + if (n->bal == 1) + return 0; + + if (n->bal != 2) + return bal; + + return adj_bal_l(n, parent); + } + return 2; /* not found */ + } else { /* rc must be > 0 */ + if (n->right) { + bal = mavl_del0(t, &n->right, data); + if (bal == 2) + return 2; + + n->bal -= bal; + if (n->bal == -1) + return 0; + + if (n->bal != -2) + return bal; + + return adj_bal_r(n, parent); + + + } + return 2; /* not found */ + + } + +} + +void *mavl_del(struct mavl *t, void *data) +{ + if (!t->root) + return NULL; + + void *d = data; + int rc = mavl_del0(t, &t->root, &d); + if (rc == 2) + return NULL; + return data; +} + + diff --git a/src/capwap/mavl_get.c b/src/capwap/mavl_get.c new file mode 100644 index 00000000..de0f82f3 --- /dev/null +++ b/src/capwap/mavl_get.c @@ -0,0 +1,47 @@ +/* + This file is part of libcapwap. + + libcapwap is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libcapwap is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Foobar. If not, see . +*/ + +/** + * @file + * @brief Implementation of mavl_get + */ + +#include + +#include "mavl.h" + +/** + * Get an AVL tree element. + * @param data Element to get + * @return pointer to element or NULL if not found. + */ +void * mavl_get(struct mavl *t ,void *data) +{ + struct avlnode *n = t->root; + while(n){ + int rc=t->cmp(data,n->data); + if (rc==0) + return n->data; + if (rc<0) + n=n->left; + else + n=n->right; + } + return NULL; +} + +