- added WMGetLabelText()
[wmaker-crm.git] / WINGs / bagtree.c
blob6550712456193e3343ce865f495e4bc0d79eea81
5 #include <stdlib.h>
6 #include <string.h>
8 #include "WUtil.h"
11 typedef struct W_Node {
12 struct W_Node *parent;
13 struct W_Node *left;
14 struct W_Node *right;
15 int color;
17 void *data;
18 int index;
19 } W_Node;
22 typedef struct W_TreeBag {
23 W_Node *root;
25 W_Node *nil; /* sentinel */
27 int count;
28 } W_TreeBag;
32 static int getItemCount(WMBag *self);
33 static int appendBag(WMBag *self, WMBag *bag);
34 static int putInBag(WMBag *self, void *item);
35 static int insertInBag(WMBag *self, int index, void *item);
36 static int removeFromBag(WMBag *bag, void *item);
37 static int eraseFromBag(WMBag *bag, int index);
38 static int deleteFromBag(WMBag *bag, int index);
39 static void *getFromBag(WMBag *bag, int index);
40 static int countInBag(WMBag *bag, void *item);
41 static int firstInBag(WMBag *bag, void *item);
42 static void *replaceInBag(WMBag *bag, int index, void *item);
43 static int sortBag(WMBag *bag, int (*comparer)(const void*, const void*));
44 static void emptyBag(WMBag *bag);
45 static void freeBag(WMBag *bag);
46 static void mapBag(WMBag *bag, void (*function)(void*, void*), void *data);
47 static int findInBag(WMBag *bag, int (*match)(void*,void*), void *data);
48 static void *first(WMBag *bag, WMBagIterator *ptr);
49 static void *last(WMBag *bag, WMBagIterator *ptr);
50 static void *next(WMBag *bag, WMBagIterator *ptr);
51 static void *previous(WMBag *bag, WMBagIterator *ptr);
52 static void *iteratorAtIndex(WMBag *bag, int index, WMBagIterator *ptr);
53 static int indexForIterator(WMBag *bag, WMBagIterator ptr);
56 static W_BagFunctions bagFunctions = {
57 getItemCount,
58 appendBag,
59 putInBag,
60 insertInBag,
61 removeFromBag,
62 eraseFromBag,
63 deleteFromBag,
64 getFromBag,
65 firstInBag,
66 countInBag,
67 replaceInBag,
68 sortBag,
69 emptyBag,
70 freeBag,
71 mapBag,
72 findInBag,
73 first,
74 last,
75 next,
76 previous,
77 iteratorAtIndex,
78 indexForIterator
84 #define IS_LEFT(node) (node == node->parent->left)
85 #define IS_RIGHT(node) (node == node->parent->right)
89 static void leftRotate(W_TreeBag *tree, W_Node *node)
91 W_Node *node2;
93 node2 = node->right;
94 node->right = node2->left;
96 node2->left->parent = node;
98 node2->parent = node->parent;
100 if (node->parent == tree->nil) {
101 tree->root = node2;
102 } else {
103 if (IS_LEFT(node)) {
104 node->parent->left = node2;
105 } else {
106 node->parent->right = node2;
109 node2->left = node;
110 node->parent = node2;
115 static void rightRotate(W_TreeBag *tree, W_Node *node)
117 W_Node *node2;
119 node2 = node->left;
120 node->left = node2->right;
122 node2->right->parent = node;
124 node2->parent = node->parent;
126 if (node->parent == tree->nil) {
127 tree->root = node2;
128 } else {
129 if (IS_LEFT(node)) {
130 node->parent->left = node2;
131 } else {
132 node->parent->right = node2;
135 node2->right = node;
136 node->parent = node2;
141 static void treeInsert(W_TreeBag *tree, W_Node *node)
143 W_Node *y = tree->nil;
144 W_Node *x = tree->root;
146 while (x != tree->nil) {
147 y = x;
148 if (node->index <= x->index)
149 x = x->left;
150 else
151 x = x->right;
153 node->parent = y;
154 if (y == tree->nil)
155 tree->root = node;
156 else if (node->index <= y->index)
157 y->left = node;
158 else
159 y->right = node;
163 static void rbTreeInsert(W_TreeBag *tree, W_Node *node)
165 W_Node *y;
167 treeInsert(tree, node);
169 node->color = 'R';
171 while (node != tree->root && node->parent->color == 'R') {
172 if (IS_LEFT(node->parent)) {
173 y = node->parent->parent->right;
175 if (y->color == 'R') {
177 node->parent->color = 'B';
178 y->color = 'B';
179 node->parent->parent->color = 'R';
180 node = node->parent->parent;
182 } else {
183 if (IS_RIGHT(node)) {
184 node = node->parent;
185 leftRotate(tree, node);
187 node->parent->color = 'B';
188 node->parent->parent->color = 'R';
189 rightRotate(tree, node->parent->parent);
191 } else {
192 y = node->parent->parent->left;
194 if (y->color == 'R') {
196 node->parent->color = 'B';
197 y->color = 'B';
198 node->parent->parent->color = 'R';
199 node = node->parent->parent;
201 } else {
202 if (IS_LEFT(node)) {
203 node = node->parent;
204 rightRotate(tree, node);
206 node->parent->color = 'B';
207 node->parent->parent->color = 'R';
208 leftRotate(tree, node->parent->parent);
212 tree->root->color = 'B';
217 static void rbDeleteFixup(W_TreeBag *tree, W_Node *node)
219 W_Node *w;
221 while (node != tree->root && node->color == 'B') {
222 if (IS_LEFT(node)) {
223 w = node->parent->right;
224 if (w->color == 'R') {
225 w->color = 'B';
226 node->parent->color = 'R';
227 leftRotate(tree, node->parent);
228 w = node->parent->right;
230 if (w->left->color == 'B' && w->right->color == 'B') {
231 w->color = 'R';
232 node = node->parent;
233 } else {
234 if (w->right->color == 'B') {
235 w->left->color = 'B';
236 w->color = 'R';
237 rightRotate(tree, w);
238 w = node->parent->right;
240 w->color = node->parent->color;
241 node->parent->color = 'B';
242 w->right->color = 'B';
243 leftRotate(tree, node->parent);
244 node = tree->root;
246 } else {
247 w = node->parent->left;
248 if (w->color == 'R') {
249 w->color = 'B';
250 node->parent->color = 'R';
251 rightRotate(tree, node->parent);
252 w = node->parent->left;
254 if (w->left->color == 'B' && w->right->color == 'B') {
255 w->color = 'R';
256 node = node->parent;
257 } else {
258 if (w->left->color == 'B') {
259 w->right->color = 'B';
260 w->color = 'R';
261 leftRotate(tree, w);
262 w = node->parent->left;
264 w->color = node->parent->color;
265 node->parent->color = 'B';
266 w->left->color = 'B';
267 rightRotate(tree, node->parent);
268 node = tree->root;
272 node->color = 'B';
277 static W_Node *treeMinimum(W_Node *node, W_Node *nil)
279 while (node->left != nil)
280 node = node->left;
281 return node;
285 static W_Node *treeMaximum(W_Node *node, W_Node *nil)
287 while (node->right != nil)
288 node = node->right;
289 return node;
293 static W_Node *treeSuccessor(W_Node *node, W_Node *nil)
295 W_Node *y;
297 if (node->right != nil) {
298 return treeMinimum(node->right, nil);
300 y = node->parent;
301 while (y != nil && node == y->right) {
302 node = y;
303 y = y->parent;
305 return y;
309 static W_Node *treePredecessor(W_Node *node, W_Node *nil)
311 W_Node *y;
313 if (node->left != nil) {
314 return treeMaximum(node->left, nil);
316 y = node->parent;
317 while (y != nil && node == y->left) {
318 node = y;
319 y = y->parent;
321 return y;
325 static W_Node *rbTreeDelete(W_TreeBag *tree, W_Node *node)
327 W_Node *nil = tree->nil;
328 W_Node *x, *y;
330 if (node->left == nil || node->right == nil) {
331 y = node;
332 } else {
333 y = treeSuccessor(node, nil);
336 if (y->left != nil) {
337 x = y->left;
338 } else {
339 x = y->right;
342 x->parent = y->parent;
344 if (y->parent == nil) {
345 tree->root = x;
346 } else {
347 if (IS_LEFT(y)) {
348 y->parent->left = x;
349 } else {
350 y->parent->right = x;
353 if (y != node) {
354 node->index = y->index;
355 node->data = y->data;
357 if (y->color == 'B') {
358 rbDeleteFixup(tree, x);
361 return y;
366 static W_Node *treeSearch(W_Node *root, W_Node *nil, int index)
368 if (root == nil || root->index == index) {
369 return root;
372 if (index < root->index) {
373 return treeSearch(root->left, nil, index);
374 } else {
375 return treeSearch(root->right, nil, index);
380 static W_Node *treeFind(W_Node *root, W_Node *nil, void *data)
382 W_Node *tmp;
384 if (root == nil || root->data == data)
385 return root;
387 tmp = treeFind(root->left, nil, data);
388 if (tmp != nil)
389 return tmp;
391 tmp = treeFind(root->right, nil, data);
393 return tmp;
400 #if 0
401 static char buf[512];
403 static void printNodes(W_Node *node, W_Node *nil, int depth)
405 if (node == nil) {
406 return;
409 printNodes(node->left, nil, depth+1);
411 memset(buf, ' ', depth*2);
412 buf[depth*2] = 0;
413 if (IS_LEFT(node))
414 printf("%s/(%2i\n", buf, node->index);
415 else
416 printf("%s\\(%2i\n", buf, node->index);
418 printNodes(node->right, nil, depth+1);
422 void PrintTree(WMBag *bag)
424 W_TreeBag *tree = (W_TreeBag*)bag->data;
426 printNodes(tree->root, tree->nil, 0);
428 #endif
433 #define SELF ((W_TreeBag*)self->data)
435 WMBag *WMCreateTreeBag(void)
437 return WMCreateTreeBagWithDestructor(NULL);
441 WMBag *WMCreateTreeBagWithDestructor(void (*destructor)(void*))
443 WMBag *bag;
444 W_TreeBag *tree;
446 bag = wmalloc(sizeof(WMBag));
448 bag->data = tree = wmalloc(sizeof(W_TreeBag));
449 memset(tree, 0, sizeof(W_TreeBag));
451 tree->nil = wmalloc(sizeof(W_Node));
452 memset(tree->nil, 0, sizeof(W_Node));
453 tree->nil->left = tree->nil->right = tree->nil->parent = tree->nil;
454 tree->nil->index = WBNotFound;
456 tree->root = tree->nil;
458 bag->destructor = destructor;
460 bag->func = bagFunctions;
462 return bag;
466 static int getItemCount(WMBag *self)
468 return SELF->count;
472 static int appendBag(WMBag *self, WMBag *bag)
474 WMBagIterator ptr;
475 void *data;
477 for (data = first(bag, &ptr); data != NULL; data = next(bag, &ptr)) {
478 if (!putInBag(self, data))
479 return 0;
482 return 1;
485 extern WMBag *bla;
487 static int putInBag(WMBag *self, void *item)
489 W_Node *ptr;
492 ptr = wmalloc(sizeof(W_Node));
494 ptr->data = item;
495 ptr->index = SELF->count;
496 ptr->left = SELF->nil;
497 ptr->right = SELF->nil;
498 ptr->parent = SELF->nil;
500 rbTreeInsert(SELF, ptr);
502 SELF->count++;
504 return 1;
508 static int insertInBag(WMBag *self, int index, void *item)
510 W_Node *ptr;
512 ptr = wmalloc(sizeof(W_Node));
514 ptr->data = item;
515 ptr->index = index;
516 ptr->left = SELF->nil;
517 ptr->right = SELF->nil;
518 ptr->parent = SELF->nil;
520 rbTreeInsert(SELF, ptr);
522 while ((ptr = treeSuccessor(ptr, SELF->nil)) != SELF->nil) {
523 ptr->index++;
527 SELF->count++;
529 return 1;
534 static int removeFromBag(WMBag *self, void *item)
536 W_Node *ptr = treeFind(SELF->root, SELF->nil, item);
538 if (ptr != SELF->nil) {
539 W_Node *tmp;
541 SELF->count--;
543 tmp = treeSuccessor(ptr, SELF->nil);
544 while (tmp != SELF->nil) {
545 tmp->index--;
546 tmp = treeSuccessor(tmp, SELF->nil);
549 ptr = rbTreeDelete(SELF, ptr);
550 if (self->destructor)
551 self->destructor(ptr->data);
552 free(ptr);
554 return 1;
555 } else {
556 return 0;
562 static int eraseFromBag(WMBag *self, int index)
564 W_Node *ptr = treeSearch(SELF->root, SELF->nil, index);
566 if (ptr != SELF->nil) {
568 SELF->count--;
570 ptr = rbTreeDelete(SELF, ptr);
571 if (self->destructor)
572 self->destructor(ptr->data);
573 free(ptr);
575 wassertrv(SELF->count == 0||SELF->root->index >= 0, 1);
577 return 1;
578 } else {
579 return 0;
584 static int deleteFromBag(WMBag *self, int index)
586 W_Node *ptr = treeSearch(SELF->root, SELF->nil, index);
588 if (ptr != SELF->nil) {
589 W_Node *tmp;
591 SELF->count--;
593 tmp = treeSuccessor(ptr, SELF->nil);
594 while (tmp != SELF->nil) {
595 tmp->index--;
596 tmp = treeSuccessor(tmp, SELF->nil);
599 ptr = rbTreeDelete(SELF, ptr);
600 if (self->destructor)
601 self->destructor(ptr->data);
602 free(ptr);
604 wassertrv(SELF->count == 0||SELF->root->index >= 0, 1);
606 return 1;
607 } else {
608 return 0;
613 static void *getFromBag(WMBag *self, int index)
615 W_Node *node;
617 node = treeSearch(SELF->root, SELF->nil, index);
618 if (node != SELF->nil)
619 return node->data;
620 else
621 return NULL;
626 static int firstInBag(WMBag *self, void *item)
628 W_Node *node;
630 node = treeFind(SELF->root, SELF->nil, item);
631 if (node != SELF->nil)
632 return node->index;
633 else
634 return WBNotFound;
639 static int treeCount(W_Node *root, W_Node *nil, void *item)
641 int count = 0;
643 if (root == nil)
644 return 0;
646 if (root->data == item)
647 count++;
649 if (root->left != nil)
650 count += treeCount(root->left, nil, item);
652 if (root->right != nil)
653 count += treeCount(root->right, nil, item);
655 return count;
660 static int countInBag(WMBag *self, void *item)
662 return treeCount(SELF->root, SELF->nil, item);
666 static void *replaceInBag(WMBag *self, int index, void *item)
668 W_Node *ptr = treeSearch(SELF->root, SELF->nil, index);
669 void *old = NULL;
671 if (item == NULL) {
672 SELF->count--;
673 ptr = rbTreeDelete(SELF, ptr);
674 if (self->destructor)
675 self->destructor(ptr->data);
676 free(ptr);
677 } else if (ptr != SELF->nil) {
678 old = ptr->data;
679 ptr->data = item;
680 } else {
681 W_Node *ptr;
683 ptr = wmalloc(sizeof(W_Node));
685 ptr->data = item;
686 ptr->index = index;
687 ptr->left = SELF->nil;
688 ptr->right = SELF->nil;
689 ptr->parent = SELF->nil;
691 rbTreeInsert(SELF, ptr);
693 SELF->count++;
696 return old;
702 static int sortBag(WMBag *self, int (*comparer)(const void*, const void*))
704 void **items;
705 W_Node *tmp;
706 int i;
708 if (SELF->count == 0)
709 return 1;
711 items = wmalloc(sizeof(void*)*SELF->count);
712 i = 0;
714 tmp = treeMinimum(SELF->root, SELF->nil);
715 while (tmp != SELF->nil) {
716 items[i++] = tmp->data;
717 tmp = treeSuccessor(tmp, SELF->nil);
720 qsort(&items[0], SELF->count, sizeof(void*), comparer);
722 i = 0;
723 tmp = treeMinimum(SELF->root, SELF->nil);
724 while (tmp != SELF->nil) {
725 tmp->index = i;
726 tmp->data = items[i++];
727 tmp = treeSuccessor(tmp, SELF->nil);
730 wfree(items);
732 return 1;
738 static void deleteTree(WMBag *self, W_Node *node)
740 if (node == SELF->nil)
741 return;
743 deleteTree(self, node->left);
745 if (self->destructor)
746 self->destructor(node->data);
748 deleteTree(self, node->right);
750 free(node);
754 static void emptyBag(WMBag *self)
756 deleteTree(self, SELF->root);
757 SELF->root = SELF->nil;
758 SELF->count = 0;
762 static void freeBag(WMBag *self)
764 emptyBag(self);
766 free(SELF->nil);
767 free(self->data);
769 free(self);
774 static void mapTree(W_TreeBag *tree, W_Node *node,
775 void (*function)(void*, void*), void *data)
777 if (node == tree->nil)
778 return;
780 mapTree(tree, node->left, function, data);
782 (*function)(node->data, data);
784 mapTree(tree, node->right, function, data);
788 static void mapBag(WMBag *self, void (*function)(void*, void*), void *data)
790 mapTree(SELF, SELF->root, function, data);
795 static int findInTree(W_TreeBag *tree, W_Node *node,
796 int (*function)(void*,void*), void *cdata)
798 int index;
800 if (node == tree->nil)
801 return WBNotFound;
803 index = findInTree(tree, node->left, function, cdata);
804 if (index != WBNotFound)
805 return index;
807 if ((*function)(node->data, cdata)) {
808 return node->index;
811 return findInTree(tree, node->right, function, cdata);
815 static int findInBag(WMBag *self, int (*match)(void*,void*), void *cdata)
817 return findInTree(SELF, SELF->root, match, cdata);
823 static void *first(WMBag *self, WMBagIterator *ptr)
825 W_Node *node;
827 node = treeMinimum(SELF->root, SELF->nil);
829 if (node == SELF->nil) {
830 *ptr = NULL;
832 return NULL;
833 } else {
834 *ptr = node;
836 return node->data;
842 static void *last(WMBag *self, WMBagIterator *ptr)
845 W_Node *node;
847 node = treeMaximum(SELF->root, SELF->nil);
849 if (node == SELF->nil) {
850 *ptr = NULL;
852 return NULL;
853 } else {
854 *ptr = node;
856 return node->data;
862 static void *next(WMBag *self, WMBagIterator *ptr)
864 W_Node *node;
866 if (*ptr == NULL)
867 return NULL;
869 node = treeSuccessor(*ptr, SELF->nil);
871 if (node == SELF->nil) {
872 *ptr = NULL;
874 return NULL;
875 } else {
876 *ptr = node;
878 return node->data;
884 static void *previous(WMBag *self, WMBagIterator *ptr)
886 W_Node *node;
888 if (*ptr == NULL)
889 return NULL;
891 node = treePredecessor(*ptr, SELF->nil);
894 if (node == SELF->nil) {
895 *ptr = NULL;
897 return NULL;
898 } else {
899 *ptr = node;
901 return node->data;
907 static void *iteratorAtIndex(WMBag *self, int index, WMBagIterator *ptr)
909 W_Node *node;
911 node = treeSearch(SELF->root, SELF->nil, index);
913 if (node == SELF->nil) {
914 *ptr = NULL;
915 return NULL;
916 } else {
917 *ptr = node;
918 return node->data;
923 static int indexForIterator(WMBag *bag, WMBagIterator ptr)
925 return ((W_Node*)ptr)->index;