util: po files reports warning with fuzzy
[wmaker-crm.git] / WINGs / bagtree.c
blobbf1ac488a93d0e7d16d9fdc8b5416ce36a7f82e0
2 #include <stdlib.h>
3 #include <string.h>
5 #include "WUtil.h"
7 typedef struct W_Node {
8 struct W_Node *parent;
9 struct W_Node *left;
10 struct W_Node *right;
11 int color;
13 void *data;
14 int index;
15 } W_Node;
17 typedef struct W_Bag {
18 W_Node *root;
20 W_Node *nil; /* sentinel */
22 int count;
24 void (*destructor) (void *item);
25 } W_Bag;
27 #define IS_LEFT(node) (node == node->parent->left)
28 #define IS_RIGHT(node) (node == node->parent->right)
30 static void leftRotate(W_Bag * tree, W_Node * node)
32 W_Node *node2;
34 node2 = node->right;
35 node->right = node2->left;
37 node2->left->parent = node;
39 node2->parent = node->parent;
41 if (node->parent == tree->nil) {
42 tree->root = node2;
43 } else {
44 if (IS_LEFT(node)) {
45 node->parent->left = node2;
46 } else {
47 node->parent->right = node2;
50 node2->left = node;
51 node->parent = node2;
54 static void rightRotate(W_Bag * tree, W_Node * node)
56 W_Node *node2;
58 node2 = node->left;
59 node->left = node2->right;
61 node2->right->parent = node;
63 node2->parent = node->parent;
65 if (node->parent == tree->nil) {
66 tree->root = node2;
67 } else {
68 if (IS_LEFT(node)) {
69 node->parent->left = node2;
70 } else {
71 node->parent->right = node2;
74 node2->right = node;
75 node->parent = node2;
78 static void treeInsert(W_Bag * tree, W_Node * node)
80 W_Node *y = tree->nil;
81 W_Node *x = tree->root;
83 while (x != tree->nil) {
84 y = x;
85 if (node->index <= x->index)
86 x = x->left;
87 else
88 x = x->right;
90 node->parent = y;
91 if (y == tree->nil)
92 tree->root = node;
93 else if (node->index <= y->index)
94 y->left = node;
95 else
96 y->right = node;
99 static void rbTreeInsert(W_Bag * tree, W_Node * node)
101 W_Node *y;
103 treeInsert(tree, node);
105 node->color = 'R';
107 while (node != tree->root && node->parent->color == 'R') {
108 if (IS_LEFT(node->parent)) {
109 y = node->parent->parent->right;
111 if (y->color == 'R') {
113 node->parent->color = 'B';
114 y->color = 'B';
115 node->parent->parent->color = 'R';
116 node = node->parent->parent;
118 } else {
119 if (IS_RIGHT(node)) {
120 node = node->parent;
121 leftRotate(tree, node);
123 node->parent->color = 'B';
124 node->parent->parent->color = 'R';
125 rightRotate(tree, node->parent->parent);
127 } else {
128 y = node->parent->parent->left;
130 if (y->color == 'R') {
132 node->parent->color = 'B';
133 y->color = 'B';
134 node->parent->parent->color = 'R';
135 node = node->parent->parent;
137 } else {
138 if (IS_LEFT(node)) {
139 node = node->parent;
140 rightRotate(tree, node);
142 node->parent->color = 'B';
143 node->parent->parent->color = 'R';
144 leftRotate(tree, node->parent->parent);
148 tree->root->color = 'B';
151 static void rbDeleteFixup(W_Bag * tree, W_Node * node)
153 W_Node *w;
155 while (node != tree->root && node->color == 'B') {
156 if (IS_LEFT(node)) {
157 w = node->parent->right;
158 if (w->color == 'R') {
159 w->color = 'B';
160 node->parent->color = 'R';
161 leftRotate(tree, node->parent);
162 w = node->parent->right;
164 if (w->left->color == 'B' && w->right->color == 'B') {
165 w->color = 'R';
166 node = node->parent;
167 } else {
168 if (w->right->color == 'B') {
169 w->left->color = 'B';
170 w->color = 'R';
171 rightRotate(tree, w);
172 w = node->parent->right;
174 w->color = node->parent->color;
175 node->parent->color = 'B';
176 w->right->color = 'B';
177 leftRotate(tree, node->parent);
178 node = tree->root;
180 } else {
181 w = node->parent->left;
182 if (w->color == 'R') {
183 w->color = 'B';
184 node->parent->color = 'R';
185 rightRotate(tree, node->parent);
186 w = node->parent->left;
188 if (w->left->color == 'B' && w->right->color == 'B') {
189 w->color = 'R';
190 node = node->parent;
191 } else {
192 if (w->left->color == 'B') {
193 w->right->color = 'B';
194 w->color = 'R';
195 leftRotate(tree, w);
196 w = node->parent->left;
198 w->color = node->parent->color;
199 node->parent->color = 'B';
200 w->left->color = 'B';
201 rightRotate(tree, node->parent);
202 node = tree->root;
206 node->color = 'B';
210 static W_Node *treeMinimum(W_Node * node, W_Node * nil)
212 while (node->left != nil)
213 node = node->left;
214 return node;
217 static W_Node *treeMaximum(W_Node * node, W_Node * nil)
219 while (node->right != nil)
220 node = node->right;
221 return node;
224 static W_Node *treeSuccessor(W_Node * node, W_Node * nil)
226 W_Node *y;
228 if (node->right != nil) {
229 return treeMinimum(node->right, nil);
231 y = node->parent;
232 while (y != nil && node == y->right) {
233 node = y;
234 y = y->parent;
236 return y;
239 static W_Node *treePredecessor(W_Node * node, W_Node * nil)
241 W_Node *y;
243 if (node->left != nil) {
244 return treeMaximum(node->left, nil);
246 y = node->parent;
247 while (y != nil && node == y->left) {
248 node = y;
249 y = y->parent;
251 return y;
254 static W_Node *rbTreeDelete(W_Bag * tree, W_Node * node)
256 W_Node *nil = tree->nil;
257 W_Node *x, *y;
259 if (node->left == nil || node->right == nil) {
260 y = node;
261 } else {
262 y = treeSuccessor(node, nil);
265 if (y->left != nil) {
266 x = y->left;
267 } else {
268 x = y->right;
271 x->parent = y->parent;
273 if (y->parent == nil) {
274 tree->root = x;
275 } else {
276 if (IS_LEFT(y)) {
277 y->parent->left = x;
278 } else {
279 y->parent->right = x;
282 if (y != node) {
283 node->index = y->index;
284 node->data = y->data;
286 if (y->color == 'B') {
287 rbDeleteFixup(tree, x);
290 return y;
293 static W_Node *treeSearch(W_Node * root, W_Node * nil, int index)
295 if (root == nil || root->index == index) {
296 return root;
299 if (index < root->index) {
300 return treeSearch(root->left, nil, index);
301 } else {
302 return treeSearch(root->right, nil, index);
306 static W_Node *treeFind(W_Node * root, W_Node * nil, void *data)
308 W_Node *tmp;
310 if (root == nil || root->data == data)
311 return root;
313 tmp = treeFind(root->left, nil, data);
314 if (tmp != nil)
315 return tmp;
317 tmp = treeFind(root->right, nil, data);
319 return tmp;
322 #if 0
323 static char buf[512];
325 static void printNodes(W_Node * node, W_Node * nil, int depth)
327 if (node == nil) {
328 return;
331 printNodes(node->left, nil, depth + 1);
333 memset(buf, ' ', depth * 2);
334 buf[depth * 2] = 0;
335 if (IS_LEFT(node))
336 printf("%s/(%2i\n", buf, node->index);
337 else
338 printf("%s\\(%2i\n", buf, node->index);
340 printNodes(node->right, nil, depth + 1);
343 void PrintTree(WMBag * bag)
345 W_TreeBag *tree = (W_TreeBag *) bag->data;
347 printNodes(tree->root, tree->nil, 0);
349 #endif
351 WMBag *WMCreateTreeBag(void)
353 return WMCreateTreeBagWithDestructor(NULL);
356 WMBag *WMCreateTreeBagWithDestructor(WMFreeDataProc * destructor)
358 WMBag *bag;
360 bag = wmalloc(sizeof(WMBag));
361 bag->nil = wmalloc(sizeof(W_Node));
362 bag->nil->left = bag->nil->right = bag->nil->parent = bag->nil;
363 bag->nil->index = WBNotFound;
364 bag->root = bag->nil;
365 bag->destructor = destructor;
367 return bag;
370 int WMGetBagItemCount(WMBag * self)
372 return self->count;
375 void WMAppendBag(WMBag * self, WMBag * bag)
377 WMBagIterator ptr;
378 void *data;
380 for (data = WMBagFirst(bag, &ptr); data != NULL; data = WMBagNext(bag, &ptr)) {
381 WMPutInBag(self, data);
385 void WMPutInBag(WMBag * self, void *item)
387 W_Node *ptr;
389 ptr = wmalloc(sizeof(W_Node));
391 ptr->data = item;
392 ptr->index = self->count;
393 ptr->left = self->nil;
394 ptr->right = self->nil;
395 ptr->parent = self->nil;
397 rbTreeInsert(self, ptr);
399 self->count++;
402 void WMInsertInBag(WMBag * self, int index, void *item)
404 W_Node *ptr;
406 ptr = wmalloc(sizeof(W_Node));
408 ptr->data = item;
409 ptr->index = index;
410 ptr->left = self->nil;
411 ptr->right = self->nil;
412 ptr->parent = self->nil;
414 rbTreeInsert(self, ptr);
416 while ((ptr = treeSuccessor(ptr, self->nil)) != self->nil) {
417 ptr->index++;
420 self->count++;
423 int WMRemoveFromBag(WMBag * self, void *item)
425 W_Node *ptr = treeFind(self->root, self->nil, item);
427 if (ptr != self->nil) {
428 W_Node *tmp;
430 self->count--;
432 tmp = treeSuccessor(ptr, self->nil);
433 while (tmp != self->nil) {
434 tmp->index--;
435 tmp = treeSuccessor(tmp, self->nil);
438 ptr = rbTreeDelete(self, ptr);
439 if (self->destructor)
440 self->destructor(ptr->data);
441 wfree(ptr);
443 return 1;
444 } else {
445 return 0;
449 int WMEraseFromBag(WMBag * self, int index)
451 W_Node *ptr = treeSearch(self->root, self->nil, index);
453 if (ptr != self->nil) {
455 self->count--;
457 ptr = rbTreeDelete(self, ptr);
458 if (self->destructor)
459 self->destructor(ptr->data);
460 wfree(ptr);
462 wassertrv(self->count == 0 || self->root->index >= 0, 1);
464 return 1;
465 } else {
466 return 0;
470 int WMDeleteFromBag(WMBag * self, int index)
472 W_Node *ptr = treeSearch(self->root, self->nil, index);
474 if (ptr != self->nil) {
475 W_Node *tmp;
477 self->count--;
479 tmp = treeSuccessor(ptr, self->nil);
480 while (tmp != self->nil) {
481 tmp->index--;
482 tmp = treeSuccessor(tmp, self->nil);
485 ptr = rbTreeDelete(self, ptr);
486 if (self->destructor)
487 self->destructor(ptr->data);
488 wfree(ptr);
490 wassertrv(self->count == 0 || self->root->index >= 0, 1);
492 return 1;
493 } else {
494 return 0;
498 void *WMGetFromBag(WMBag * self, int index)
500 W_Node *node;
502 node = treeSearch(self->root, self->nil, index);
503 if (node != self->nil)
504 return node->data;
505 else
506 return NULL;
509 int WMGetFirstInBag(WMBag * self, void *item)
511 W_Node *node;
513 node = treeFind(self->root, self->nil, item);
514 if (node != self->nil)
515 return node->index;
516 else
517 return WBNotFound;
520 static int treeCount(W_Node * root, W_Node * nil, void *item)
522 int count = 0;
524 if (root == nil)
525 return 0;
527 if (root->data == item)
528 count++;
530 if (root->left != nil)
531 count += treeCount(root->left, nil, item);
533 if (root->right != nil)
534 count += treeCount(root->right, nil, item);
536 return count;
539 int WMCountInBag(WMBag * self, void *item)
541 return treeCount(self->root, self->nil, item);
544 void *WMReplaceInBag(WMBag * self, int index, void *item)
546 W_Node *ptr = treeSearch(self->root, self->nil, index);
547 void *old = NULL;
549 if (item == NULL) {
550 self->count--;
551 ptr = rbTreeDelete(self, ptr);
552 if (self->destructor)
553 self->destructor(ptr->data);
554 wfree(ptr);
555 } else if (ptr != self->nil) {
556 old = ptr->data;
557 ptr->data = item;
558 } else {
559 W_Node *ptr;
561 ptr = wmalloc(sizeof(W_Node));
563 ptr->data = item;
564 ptr->index = index;
565 ptr->left = self->nil;
566 ptr->right = self->nil;
567 ptr->parent = self->nil;
569 rbTreeInsert(self, ptr);
571 self->count++;
574 return old;
577 void WMSortBag(WMBag * self, WMCompareDataProc * comparer)
579 void **items;
580 W_Node *tmp;
581 int i;
583 if (self->count == 0)
584 return;
586 items = wmalloc(sizeof(void *) * self->count);
587 i = 0;
589 tmp = treeMinimum(self->root, self->nil);
590 while (tmp != self->nil) {
591 items[i++] = tmp->data;
592 tmp = treeSuccessor(tmp, self->nil);
595 qsort(&items[0], self->count, sizeof(void *), comparer);
597 i = 0;
598 tmp = treeMinimum(self->root, self->nil);
599 while (tmp != self->nil) {
600 tmp->index = i;
601 tmp->data = items[i++];
602 tmp = treeSuccessor(tmp, self->nil);
605 wfree(items);
608 static void deleteTree(WMBag * self, W_Node * node)
610 if (node == self->nil)
611 return;
613 deleteTree(self, node->left);
615 if (self->destructor)
616 self->destructor(node->data);
618 deleteTree(self, node->right);
620 wfree(node);
623 void WMEmptyBag(WMBag * self)
625 deleteTree(self, self->root);
626 self->root = self->nil;
627 self->count = 0;
630 void WMFreeBag(WMBag * self)
632 WMEmptyBag(self);
633 wfree(self->nil);
634 wfree(self);
637 static void mapTree(W_Bag * tree, W_Node * node, void (*function) (void *, void *), void *data)
639 if (node == tree->nil)
640 return;
642 mapTree(tree, node->left, function, data);
644 (*function) (node->data, data);
646 mapTree(tree, node->right, function, data);
649 void WMMapBag(WMBag * self, void (*function) (void *, void *), void *data)
651 mapTree(self, self->root, function, data);
654 static int findInTree(W_Bag * tree, W_Node * node, WMMatchDataProc * function, void *cdata)
656 int index;
658 if (node == tree->nil)
659 return WBNotFound;
661 index = findInTree(tree, node->left, function, cdata);
662 if (index != WBNotFound)
663 return index;
665 if ((*function) (node->data, cdata)) {
666 return node->index;
669 return findInTree(tree, node->right, function, cdata);
672 int WMFindInBag(WMBag * self, WMMatchDataProc * match, void *cdata)
674 return findInTree(self, self->root, match, cdata);
677 void *WMBagFirst(WMBag * self, WMBagIterator * ptr)
679 W_Node *node;
681 node = treeMinimum(self->root, self->nil);
683 if (node == self->nil) {
684 *ptr = NULL;
685 return NULL;
686 } else {
687 *ptr = node;
688 return node->data;
692 void *WMBagLast(WMBag * self, WMBagIterator * ptr)
695 W_Node *node;
697 node = treeMaximum(self->root, self->nil);
699 if (node == self->nil) {
700 *ptr = NULL;
701 return NULL;
702 } else {
703 *ptr = node;
704 return node->data;
708 void *WMBagNext(WMBag * self, WMBagIterator * ptr)
710 W_Node *node;
712 if (*ptr == NULL)
713 return NULL;
715 node = treeSuccessor(*ptr, self->nil);
717 if (node == self->nil) {
718 *ptr = NULL;
719 return NULL;
720 } else {
721 *ptr = node;
722 return node->data;
726 void *WMBagPrevious(WMBag * self, WMBagIterator * ptr)
728 W_Node *node;
730 if (*ptr == NULL)
731 return NULL;
733 node = treePredecessor(*ptr, self->nil);
735 if (node == self->nil) {
736 *ptr = NULL;
737 return NULL;
738 } else {
739 *ptr = node;
740 return node->data;
744 void *WMBagIteratorAtIndex(WMBag * self, int index, WMBagIterator * ptr)
746 W_Node *node;
748 node = treeSearch(self->root, self->nil, index);
750 if (node == self->nil) {
751 *ptr = NULL;
752 return NULL;
753 } else {
754 *ptr = node;
755 return node->data;
759 int WMBagIndexForIterator(WMBag * bag, WMBagIterator ptr)
761 return ((W_Node *) ptr)->index;