new hide/unhide functions
[wmaker-crm.git] / WINGs / bagtree.c
blob8ad7872ba6f7536a98545117dbae80bccf2e4ff5
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_Bag {
23 W_Node *root;
25 W_Node *nil; /* sentinel */
27 int count;
29 void (*destructor)(void *item);
30 } W_Bag;
34 #define IS_LEFT(node) (node == node->parent->left)
35 #define IS_RIGHT(node) (node == node->parent->right)
39 static void
40 leftRotate(W_Bag *tree, W_Node *node)
42 W_Node *node2;
44 node2 = node->right;
45 node->right = node2->left;
47 node2->left->parent = node;
49 node2->parent = node->parent;
51 if (node->parent == tree->nil) {
52 tree->root = node2;
53 } else {
54 if (IS_LEFT(node)) {
55 node->parent->left = node2;
56 } else {
57 node->parent->right = node2;
60 node2->left = node;
61 node->parent = node2;
66 static void
67 rightRotate(W_Bag *tree, W_Node *node)
69 W_Node *node2;
71 node2 = node->left;
72 node->left = node2->right;
74 node2->right->parent = node;
76 node2->parent = node->parent;
78 if (node->parent == tree->nil) {
79 tree->root = node2;
80 } else {
81 if (IS_LEFT(node)) {
82 node->parent->left = node2;
83 } else {
84 node->parent->right = node2;
87 node2->right = node;
88 node->parent = node2;
92 static void
93 treeInsert(W_Bag *tree, W_Node *node)
95 W_Node *y = tree->nil;
96 W_Node *x = tree->root;
98 while (x != tree->nil) {
99 y = x;
100 if (node->index <= x->index)
101 x = x->left;
102 else
103 x = x->right;
105 node->parent = y;
106 if (y == tree->nil)
107 tree->root = node;
108 else if (node->index <= y->index)
109 y->left = node;
110 else
111 y->right = node;
115 static void
116 rbTreeInsert(W_Bag *tree, W_Node *node)
118 W_Node *y;
120 treeInsert(tree, node);
122 node->color = 'R';
124 while (node != tree->root && node->parent->color == 'R') {
125 if (IS_LEFT(node->parent)) {
126 y = node->parent->parent->right;
128 if (y->color == 'R') {
130 node->parent->color = 'B';
131 y->color = 'B';
132 node->parent->parent->color = 'R';
133 node = node->parent->parent;
135 } else {
136 if (IS_RIGHT(node)) {
137 node = node->parent;
138 leftRotate(tree, node);
140 node->parent->color = 'B';
141 node->parent->parent->color = 'R';
142 rightRotate(tree, node->parent->parent);
144 } else {
145 y = node->parent->parent->left;
147 if (y->color == 'R') {
149 node->parent->color = 'B';
150 y->color = 'B';
151 node->parent->parent->color = 'R';
152 node = node->parent->parent;
154 } else {
155 if (IS_LEFT(node)) {
156 node = node->parent;
157 rightRotate(tree, node);
159 node->parent->color = 'B';
160 node->parent->parent->color = 'R';
161 leftRotate(tree, node->parent->parent);
165 tree->root->color = 'B';
169 static void
170 rbDeleteFixup(W_Bag *tree, W_Node *node)
172 W_Node *w;
174 while (node != tree->root && node->color == 'B') {
175 if (IS_LEFT(node)) {
176 w = node->parent->right;
177 if (w->color == 'R') {
178 w->color = 'B';
179 node->parent->color = 'R';
180 leftRotate(tree, node->parent);
181 w = node->parent->right;
183 if (w->left->color == 'B' && w->right->color == 'B') {
184 w->color = 'R';
185 node = node->parent;
186 } else {
187 if (w->right->color == 'B') {
188 w->left->color = 'B';
189 w->color = 'R';
190 rightRotate(tree, w);
191 w = node->parent->right;
193 w->color = node->parent->color;
194 node->parent->color = 'B';
195 w->right->color = 'B';
196 leftRotate(tree, node->parent);
197 node = tree->root;
199 } else {
200 w = node->parent->left;
201 if (w->color == 'R') {
202 w->color = 'B';
203 node->parent->color = 'R';
204 rightRotate(tree, node->parent);
205 w = node->parent->left;
207 if (w->left->color == 'B' && w->right->color == 'B') {
208 w->color = 'R';
209 node = node->parent;
210 } else {
211 if (w->left->color == 'B') {
212 w->right->color = 'B';
213 w->color = 'R';
214 leftRotate(tree, w);
215 w = node->parent->left;
217 w->color = node->parent->color;
218 node->parent->color = 'B';
219 w->left->color = 'B';
220 rightRotate(tree, node->parent);
221 node = tree->root;
225 node->color = 'B';
230 static W_Node*
231 treeMinimum(W_Node *node, W_Node *nil)
233 while (node->left != nil)
234 node = node->left;
235 return node;
239 static W_Node*
240 treeMaximum(W_Node *node, W_Node *nil)
242 while (node->right != nil)
243 node = node->right;
244 return node;
248 static W_Node*
249 treeSuccessor(W_Node *node, W_Node *nil)
251 W_Node *y;
253 if (node->right != nil) {
254 return treeMinimum(node->right, nil);
256 y = node->parent;
257 while (y != nil && node == y->right) {
258 node = y;
259 y = y->parent;
261 return y;
265 static W_Node*
266 treePredecessor(W_Node *node, W_Node *nil)
268 W_Node *y;
270 if (node->left != nil) {
271 return treeMaximum(node->left, nil);
273 y = node->parent;
274 while (y != nil && node == y->left) {
275 node = y;
276 y = y->parent;
278 return y;
282 static W_Node*
283 rbTreeDelete(W_Bag *tree, W_Node *node)
285 W_Node *nil = tree->nil;
286 W_Node *x, *y;
288 if (node->left == nil || node->right == nil) {
289 y = node;
290 } else {
291 y = treeSuccessor(node, nil);
294 if (y->left != nil) {
295 x = y->left;
296 } else {
297 x = y->right;
300 x->parent = y->parent;
302 if (y->parent == nil) {
303 tree->root = x;
304 } else {
305 if (IS_LEFT(y)) {
306 y->parent->left = x;
307 } else {
308 y->parent->right = x;
311 if (y != node) {
312 node->index = y->index;
313 node->data = y->data;
315 if (y->color == 'B') {
316 rbDeleteFixup(tree, x);
319 return y;
323 static W_Node*
324 treeSearch(W_Node *root, W_Node *nil, int index)
326 if (root == nil || root->index == index) {
327 return root;
330 if (index < root->index) {
331 return treeSearch(root->left, nil, index);
332 } else {
333 return treeSearch(root->right, nil, index);
338 static W_Node*
339 treeFind(W_Node *root, W_Node *nil, void *data)
341 W_Node *tmp;
343 if (root == nil || root->data == data)
344 return root;
346 tmp = treeFind(root->left, nil, data);
347 if (tmp != nil)
348 return tmp;
350 tmp = treeFind(root->right, nil, data);
352 return tmp;
357 #if 0
358 static char buf[512];
360 static void
361 printNodes(W_Node *node, W_Node *nil, int depth)
363 if (node == nil) {
364 return;
367 printNodes(node->left, nil, depth+1);
369 memset(buf, ' ', depth*2);
370 buf[depth*2] = 0;
371 if (IS_LEFT(node))
372 printf("%s/(%2i\n", buf, node->index);
373 else
374 printf("%s\\(%2i\n", buf, node->index);
376 printNodes(node->right, nil, depth+1);
380 void
381 PrintTree(WMBag *bag)
383 W_TreeBag *tree = (W_TreeBag*)bag->data;
385 printNodes(tree->root, tree->nil, 0);
387 #endif
390 WMBag*
391 WMCreateTreeBag(void)
393 return WMCreateTreeBagWithDestructor(NULL);
397 WMBag*
398 WMCreateTreeBagWithDestructor(WMFreeDataProc *destructor)
400 WMBag *bag;
402 bag = wmalloc(sizeof(WMBag));
404 memset(bag, 0, sizeof(WMBag));
406 bag->nil = wmalloc(sizeof(W_Node));
407 memset(bag->nil, 0, sizeof(W_Node));
408 bag->nil->left = bag->nil->right = bag->nil->parent = bag->nil;
409 bag->nil->index = WBNotFound;
411 bag->root = bag->nil;
413 bag->destructor = destructor;
415 return bag;
420 WMGetBagItemCount(WMBag *self)
422 return self->count;
427 WMAppendBag(WMBag *self, WMBag *bag)
429 WMBagIterator ptr;
430 void *data;
432 for (data = WMBagFirst(bag, &ptr); data != NULL; data = WMBagNext(bag, &ptr)) {
433 if (!WMPutInBag(self, data))
434 return 0;
437 return 1;
442 WMPutInBag(WMBag *self, void *item)
444 W_Node *ptr;
446 ptr = wmalloc(sizeof(W_Node));
448 ptr->data = item;
449 ptr->index = self->count;
450 ptr->left = self->nil;
451 ptr->right = self->nil;
452 ptr->parent = self->nil;
454 rbTreeInsert(self, ptr);
456 self->count++;
458 return 1;
463 WMInsertInBag(WMBag *self, int index, void *item)
465 W_Node *ptr;
467 ptr = wmalloc(sizeof(W_Node));
469 ptr->data = item;
470 ptr->index = index;
471 ptr->left = self->nil;
472 ptr->right = self->nil;
473 ptr->parent = self->nil;
475 rbTreeInsert(self, ptr);
477 while ((ptr = treeSuccessor(ptr, self->nil)) != self->nil) {
478 ptr->index++;
482 self->count++;
484 return 1;
489 WMRemoveFromBag(WMBag *self, void *item)
491 W_Node *ptr = treeFind(self->root, self->nil, item);
493 if (ptr != self->nil) {
494 W_Node *tmp;
496 self->count--;
498 tmp = treeSuccessor(ptr, self->nil);
499 while (tmp != self->nil) {
500 tmp->index--;
501 tmp = treeSuccessor(tmp, self->nil);
504 ptr = rbTreeDelete(self, ptr);
505 if (self->destructor)
506 self->destructor(ptr->data);
507 free(ptr);
509 return 1;
510 } else {
511 return 0;
517 WMEraseFromBag(WMBag *self, int index)
519 W_Node *ptr = treeSearch(self->root, self->nil, index);
521 if (ptr != self->nil) {
523 self->count--;
525 ptr = rbTreeDelete(self, ptr);
526 if (self->destructor)
527 self->destructor(ptr->data);
528 free(ptr);
530 wassertrv(self->count == 0||self->root->index >= 0, 1);
532 return 1;
533 } else {
534 return 0;
540 WMDeleteFromBag(WMBag *self, int index)
542 W_Node *ptr = treeSearch(self->root, self->nil, index);
544 if (ptr != self->nil) {
545 W_Node *tmp;
547 self->count--;
549 tmp = treeSuccessor(ptr, self->nil);
550 while (tmp != self->nil) {
551 tmp->index--;
552 tmp = treeSuccessor(tmp, self->nil);
555 ptr = rbTreeDelete(self, ptr);
556 if (self->destructor)
557 self->destructor(ptr->data);
558 free(ptr);
560 wassertrv(self->count == 0||self->root->index >= 0, 1);
562 return 1;
563 } else {
564 return 0;
569 void*
570 WMGetFromBag(WMBag *self, int index)
572 W_Node *node;
574 node = treeSearch(self->root, self->nil, index);
575 if (node != self->nil)
576 return node->data;
577 else
578 return NULL;
583 WMGetFirstInBag(WMBag *self, void *item)
585 W_Node *node;
587 node = treeFind(self->root, self->nil, item);
588 if (node != self->nil)
589 return node->index;
590 else
591 return WBNotFound;
596 static int
597 treeCount(W_Node *root, W_Node *nil, void *item)
599 int count = 0;
601 if (root == nil)
602 return 0;
604 if (root->data == item)
605 count++;
607 if (root->left != nil)
608 count += treeCount(root->left, nil, item);
610 if (root->right != nil)
611 count += treeCount(root->right, nil, item);
613 return count;
619 WMCountInBag(WMBag *self, void *item)
621 return treeCount(self->root, self->nil, item);
625 void*
626 WMReplaceInBag(WMBag *self, int index, void *item)
628 W_Node *ptr = treeSearch(self->root, self->nil, index);
629 void *old = NULL;
631 if (item == NULL) {
632 self->count--;
633 ptr = rbTreeDelete(self, ptr);
634 if (self->destructor)
635 self->destructor(ptr->data);
636 free(ptr);
637 } else if (ptr != self->nil) {
638 old = ptr->data;
639 ptr->data = item;
640 } else {
641 W_Node *ptr;
643 ptr = wmalloc(sizeof(W_Node));
645 ptr->data = item;
646 ptr->index = index;
647 ptr->left = self->nil;
648 ptr->right = self->nil;
649 ptr->parent = self->nil;
651 rbTreeInsert(self, ptr);
653 self->count++;
656 return old;
661 WMSortBag(WMBag *self, WMCompareDataProc *comparer)
663 void **items;
664 W_Node *tmp;
665 int i;
667 if (self->count == 0)
668 return 1;
670 items = wmalloc(sizeof(void*)*self->count);
671 i = 0;
673 tmp = treeMinimum(self->root, self->nil);
674 while (tmp != self->nil) {
675 items[i++] = tmp->data;
676 tmp = treeSuccessor(tmp, self->nil);
679 qsort(&items[0], self->count, sizeof(void*), comparer);
681 i = 0;
682 tmp = treeMinimum(self->root, self->nil);
683 while (tmp != self->nil) {
684 tmp->index = i;
685 tmp->data = items[i++];
686 tmp = treeSuccessor(tmp, self->nil);
689 wfree(items);
691 return 1;
695 static void
696 deleteTree(WMBag *self, W_Node *node)
698 if (node == self->nil)
699 return;
701 deleteTree(self, node->left);
703 if (self->destructor)
704 self->destructor(node->data);
706 deleteTree(self, node->right);
708 free(node);
712 void
713 WMEmptyBag(WMBag *self)
715 deleteTree(self, self->root);
716 self->root = self->nil;
717 self->count = 0;
721 void
722 WMFreeBag(WMBag *self)
724 WMEmptyBag(self);
726 free(self->nil);
728 free(self);
732 static void
733 mapTree(W_Bag *tree, W_Node *node, void (*function)(void*, void*), void *data)
735 if (node == tree->nil)
736 return;
738 mapTree(tree, node->left, function, data);
740 (*function)(node->data, data);
742 mapTree(tree, node->right, function, data);
746 void
747 WMMapBag(WMBag *self, void (*function)(void*, void*), void *data)
749 mapTree(self, self->root, function, data);
754 static int
755 findInTree(W_Bag *tree, W_Node *node, WMMatchDataProc *function, void *cdata)
757 int index;
759 if (node == tree->nil)
760 return WBNotFound;
762 index = findInTree(tree, node->left, function, cdata);
763 if (index != WBNotFound)
764 return index;
766 if ((*function)(node->data, cdata)) {
767 return node->index;
770 return findInTree(tree, node->right, function, cdata);
775 WMFindInBag(WMBag *self, WMMatchDataProc *match, void *cdata)
777 return findInTree(self, self->root, match, cdata);
781 void*
782 WMBagFirst(WMBag *self, WMBagIterator *ptr)
784 W_Node *node;
786 node = treeMinimum(self->root, self->nil);
788 if (node == self->nil) {
789 *ptr = NULL;
791 return NULL;
792 } else {
793 *ptr = node;
795 return node->data;
800 void*
801 WMBagLast(WMBag *self, WMBagIterator *ptr)
804 W_Node *node;
806 node = treeMaximum(self->root, self->nil);
808 if (node == self->nil) {
809 *ptr = NULL;
811 return NULL;
812 } else {
813 *ptr = node;
815 return node->data;
820 void*
821 WMBagNext(WMBag *self, WMBagIterator *ptr)
823 W_Node *node;
825 if (*ptr == NULL)
826 return NULL;
828 node = treeSuccessor(*ptr, self->nil);
830 if (node == self->nil) {
831 *ptr = NULL;
833 return NULL;
834 } else {
835 *ptr = node;
837 return node->data;
842 void*
843 WMBagPrevious(WMBag *self, WMBagIterator *ptr)
845 W_Node *node;
847 if (*ptr == NULL)
848 return NULL;
850 node = treePredecessor(*ptr, self->nil);
852 if (node == self->nil) {
853 *ptr = NULL;
855 return NULL;
856 } else {
857 *ptr = node;
859 return node->data;
864 void*
865 WMBagIteratorAtIndex(WMBag *self, int index, WMBagIterator *ptr)
867 W_Node *node;
869 node = treeSearch(self->root, self->nil, index);
871 if (node == self->nil) {
872 *ptr = NULL;
873 return NULL;
874 } else {
875 *ptr = node;
876 return node->data;
882 WMBagIndexForIterator(WMBag *bag, WMBagIterator ptr)
884 return ((W_Node*)ptr)->index;