blobmsg: make arrays structually the same as tables - simplifies library user code
[project/libubox.git] / avl.c
1 /*
2  * PacketBB handler library (see RFC 5444)
3  * Copyright (c) 2010 Henning Rogge <hrogge@googlemail.com>
4  * Original OLSRd implementation by Hannes Gredler <hannes@gredler.at>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org/git for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  */
40
41 #include <stdbool.h>
42 #include <stddef.h>
43 #include <stdint.h>
44 #include <time.h>
45 #include <string.h>
46
47 #include "avl.h"
48 #include "list.h"
49
50 #define list_merge(_head, _list) list_merge(_list, _head)
51 #define list_is_last(_head, _list) list_is_last(_list, _head)
52 #define list_is_first(_head, _list) list_is_first(_list, _head)
53
54 /**
55  * internal type save inline function to calculate the maximum of
56  * to integers without macro implementation.
57  *
58  * @param x first parameter of maximum function
59  * @param y second parameter of maximum function
60  * @return largest integer of both parameters
61  */
62 static inline int avl_max(int x, int y) {
63   return x > y ? x : y;
64 }
65
66 /**
67  * internal type save inline function to calculate the minimum of
68  * to integers without macro implementation.
69  *
70  * @param x first parameter of minimum function
71  * @param y second parameter of minimum function
72  * @return smallest integer of both parameters
73  */
74 static inline int avl_min(int x, int y) {
75   return x < y ? x : y;
76 }
77
78 static struct avl_node *
79 avl_find_rec(struct avl_node *node, const void *key, avl_tree_comp comp, void *ptr, int *cmp_result);
80 static void avl_insert_before(struct avl_tree *tree, struct avl_node *pos_node, struct avl_node *node);
81 static void avl_insert_after(struct avl_tree *tree, struct avl_node *pos_node, struct avl_node *node);
82 static void post_insert(struct avl_tree *tree, struct avl_node *node);
83 static void avl_delete_worker(struct avl_tree *tree, struct avl_node *node);
84 static void avl_remove(struct avl_tree *tree, struct avl_node *node);
85
86 /**
87  * Initialize a new avl_tree struct
88  * @param tree pointer to avl-tree
89  * @param comp pointer to comparator for the tree
90  * @param allow_dups true if the tree allows multiple
91  *   elements with the same
92  * @param ptr custom parameter for comparator
93  */
94 void
95 avl_init(struct avl_tree *tree, avl_tree_comp comp, bool allow_dups, void *ptr)
96 {
97   list_init_head(&tree->list_head);
98   tree->root = NULL;
99   tree->count = 0;
100   tree->comp = comp;
101   tree->allow_dups = allow_dups;
102   tree->cmp_ptr = ptr;
103 }
104
105 /**
106  * Internal function to support returning the element from a avl tree query
107  * @param tree pointer to avl tree
108  * @param key pointer to key
109  * @param offset offset of node inside the embedded struct
110  * @param mode mode of lookup operation (less equal, equal or greater equal)
111  * @param pointer to elemen, NULL if no fitting one was found
112  */
113 void *
114 __avl_find_element(const struct avl_tree *tree, const void *key, size_t offset, enum avl_find_mode mode) {
115   void *node = NULL;
116
117   switch (mode) {
118     case AVL_FIND_EQUAL:
119       node = avl_find(tree, key);
120       break;
121     case AVL_FIND_LESSEQUAL:
122       node = avl_find_lessequal(tree, key);
123       break;
124     case AVL_FIND_GREATEREQUAL:
125       node = avl_find_greaterequal(tree, key);
126       break;
127   }
128   return node == NULL ? NULL : (((char *)node) - offset);
129 }
130
131 /**
132  * Finds a node in an avl-tree with a certain key
133  * @param tree pointer to avl-tree
134  * @param key pointer to key
135  * @return pointer to avl-node with key, NULL if no node with
136  *    this key exists.
137  */
138 struct avl_node *
139 avl_find(const struct avl_tree *tree, const void *key)
140 {
141   struct avl_node *node;
142   int diff;
143
144   if (tree->root == NULL)
145     return NULL;
146
147   node = avl_find_rec(tree->root, key, tree->comp, tree->cmp_ptr, &diff);
148
149   return diff == 0 ? node : NULL;
150 }
151
152 /**
153  * Finds the last node in an avl-tree with a key less or equal
154  * than the specified key
155  * @param tree pointer to avl-tree
156  * @param key pointer to specified key
157  * @return pointer to avl-node, NULL if no node with
158  *    key less or equal specified key exists.
159  */
160 struct avl_node *
161 avl_find_lessequal(const struct avl_tree *tree, const void *key) {
162   struct avl_node *node, *next;
163   int diff;
164
165   if (tree->root == NULL)
166     return NULL;
167
168   node = avl_find_rec(tree->root, key, tree->comp, tree->cmp_ptr, &diff);
169
170   /* go left as long as key<node.key */
171   while (diff < 0) {
172     if (list_is_first(&tree->list_head, &node->list)) {
173       return NULL;
174     }
175
176     node = (struct avl_node *)node->list.prev;
177     diff = (*tree->comp) (key, node->key, tree->cmp_ptr);
178   }
179
180   /* go right as long as key>=next_node.key */
181   next = node;
182   while (diff >= 0) {
183     node = next;
184     if (list_is_last(&tree->list_head, &node->list)) {
185       break;
186     }
187
188     next = (struct avl_node *)node->list.next;
189     diff = (*tree->comp) (key, next->key, tree->cmp_ptr);
190   }
191   return node;
192 }
193
194 /**
195  * Finds the first node in an avl-tree with a key greater or equal
196  * than the specified key
197  * @param tree pointer to avl-tree
198  * @param key pointer to specified key
199  * @return pointer to avl-node, NULL if no node with
200  *    key greater or equal specified key exists.
201  */
202 struct avl_node *
203 avl_find_greaterequal(const struct avl_tree *tree, const void *key) {
204   struct avl_node *node, *next;
205   int diff;
206
207   if (tree->root == NULL)
208     return NULL;
209
210   node = avl_find_rec(tree->root, key, tree->comp, tree->cmp_ptr, &diff);
211
212   /* go right as long as key>node.key */
213   while (diff > 0) {
214     if (list_is_last(&tree->list_head, &node->list)) {
215       return NULL;
216     }
217
218     node = (struct avl_node *)node->list.next;
219     diff = (*tree->comp) (key, node->key, tree->cmp_ptr);
220   }
221
222   /* go left as long as key<=next_node.key */
223   next = node;
224   while (diff <= 0) {
225     node = next;
226     if (list_is_first(&tree->list_head, &node->list)) {
227       break;
228     }
229
230     next = (struct avl_node *)node->list.prev;
231     diff = (*tree->comp) (key, next->key, tree->cmp_ptr);
232   }
233   return node;
234 }
235
236 /**
237  * Inserts an avl_node into a tree
238  * @param tree pointer to tree
239  * @param new pointer to node
240  * @return 0 if node was inserted successfully, -1 if it was not inserted
241  *   because of a key collision
242  */
243 int
244 avl_insert(struct avl_tree *tree, struct avl_node *new)
245 {
246   struct avl_node *node, *next, *last;
247   int diff;
248
249   new->parent = NULL;
250
251   new->left = NULL;
252   new->right = NULL;
253
254   new->balance = 0;
255   new->leader = true;
256
257   if (tree->root == NULL) {
258     list_add_head(&tree->list_head, &new->list);
259     tree->root = new;
260     tree->count = 1;
261     return 0;
262   }
263
264   node = avl_find_rec(tree->root, new->key, tree->comp, tree->cmp_ptr, &diff);
265
266   last = node;
267
268   while (!list_is_last(&tree->list_head, &last->list)) {
269     next = list_next_element(last, list);
270     if (next->leader) {
271       break;
272     }
273     last = next;
274   }
275
276   diff = (*tree->comp) (new->key, node->key, tree->cmp_ptr);
277
278   if (diff == 0) {
279     if (!tree->allow_dups)
280       return -1;
281
282     new->leader = 0;
283
284     avl_insert_after(tree, last, new);
285     return 0;
286   }
287
288   if (node->balance == 1) {
289     avl_insert_before(tree, node, new);
290
291     node->balance = 0;
292     new->parent = node;
293     node->left = new;
294     return 0;
295   }
296
297   if (node->balance == -1) {
298     avl_insert_after(tree, last, new);
299
300     node->balance = 0;
301     new->parent = node;
302     node->right = new;
303     return 0;
304   }
305
306   if (diff < 0) {
307     avl_insert_before(tree, node, new);
308
309     node->balance = -1;
310     new->parent = node;
311     node->left = new;
312     post_insert(tree, node);
313     return 0;
314   }
315
316   avl_insert_after(tree, last, new);
317
318   node->balance = 1;
319   new->parent = node;
320   node->right = new;
321   post_insert(tree, node);
322   return 0;
323 }
324
325 /**
326  * Remove a node from an avl tree
327  * @param tree pointer to tree
328  * @param node pointer to node
329  */
330 void
331 avl_delete(struct avl_tree *tree, struct avl_node *node)
332 {
333   struct avl_node *next;
334   struct avl_node *parent;
335   struct avl_node *left;
336   struct avl_node *right;
337   if (node->leader) {
338     if (tree->allow_dups
339         && !list_is_last(&tree->list_head, &node->list)
340         && !(next = list_next_element(node, list))->leader) {
341       next->leader = true;
342       next->balance = node->balance;
343
344       parent = node->parent;
345       left = node->left;
346       right = node->right;
347
348       next->parent = parent;
349       next->left = left;
350       next->right = right;
351
352       if (parent == NULL)
353         tree->root = next;
354
355       else {
356         if (node == parent->left)
357           parent->left = next;
358
359         else
360           parent->right = next;
361       }
362
363       if (left != NULL)
364         left->parent = next;
365
366       if (right != NULL)
367         right->parent = next;
368     }
369
370     else
371       avl_delete_worker(tree, node);
372   }
373
374   avl_remove(tree, node);
375 }
376
377 static struct avl_node *
378 avl_find_rec(struct avl_node *node, const void *key, avl_tree_comp comp, void *cmp_ptr, int *cmp_result)
379 {
380   int diff;
381
382   diff = (*comp) (key, node->key, cmp_ptr);
383   *cmp_result = diff;
384
385   if (diff < 0) {
386     if (node->left != NULL)
387       return avl_find_rec(node->left, key, comp, cmp_ptr, cmp_result);
388
389     return node;
390   }
391
392   if (diff > 0) {
393     if (node->right != NULL)
394       return avl_find_rec(node->right, key, comp, cmp_ptr, cmp_result);
395
396     return node;
397   }
398
399   return node;
400 }
401
402 static void
403 avl_rotate_right(struct avl_tree *tree, struct avl_node *node)
404 {
405   struct avl_node *left, *parent;
406
407   left = node->left;
408   parent = node->parent;
409
410   left->parent = parent;
411   node->parent = left;
412
413   if (parent == NULL)
414     tree->root = left;
415
416   else {
417     if (parent->left == node)
418       parent->left = left;
419
420     else
421       parent->right = left;
422   }
423
424   node->left = left->right;
425   left->right = node;
426
427   if (node->left != NULL)
428     node->left->parent = node;
429
430   node->balance += 1 - avl_min(left->balance, 0);
431   left->balance += 1 + avl_max(node->balance, 0);
432 }
433
434 static void
435 avl_rotate_left(struct avl_tree *tree, struct avl_node *node)
436 {
437   struct avl_node *right, *parent;
438
439   right = node->right;
440   parent = node->parent;
441
442   right->parent = parent;
443   node->parent = right;
444
445   if (parent == NULL)
446     tree->root = right;
447
448   else {
449     if (parent->left == node)
450       parent->left = right;
451
452     else
453       parent->right = right;
454   }
455
456   node->right = right->left;
457   right->left = node;
458
459   if (node->right != NULL)
460     node->right->parent = node;
461
462   node->balance -= 1 + avl_max(right->balance, 0);
463   right->balance -= 1 - avl_min(node->balance, 0);
464 }
465
466 static void
467 post_insert(struct avl_tree *tree, struct avl_node *node)
468 {
469   struct avl_node *parent = node->parent;
470
471   if (parent == NULL)
472     return;
473
474   if (node == parent->left) {
475     parent->balance--;
476
477     if (parent->balance == 0)
478       return;
479
480     if (parent->balance == -1) {
481       post_insert(tree, parent);
482       return;
483     }
484
485     if (node->balance == -1) {
486       avl_rotate_right(tree, parent);
487       return;
488     }
489
490     avl_rotate_left(tree, node);
491     avl_rotate_right(tree, node->parent->parent);
492     return;
493   }
494
495   parent->balance++;
496
497   if (parent->balance == 0)
498     return;
499
500   if (parent->balance == 1) {
501     post_insert(tree, parent);
502     return;
503   }
504
505   if (node->balance == 1) {
506     avl_rotate_left(tree, parent);
507     return;
508   }
509
510   avl_rotate_right(tree, node);
511   avl_rotate_left(tree, node->parent->parent);
512 }
513
514 static void
515 avl_insert_before(struct avl_tree *tree, struct avl_node *pos_node, struct avl_node *node)
516 {
517   list_add_before(&pos_node->list, &node->list);
518   tree->count++;
519 }
520
521 static void
522 avl_insert_after(struct avl_tree *tree, struct avl_node *pos_node, struct avl_node *node)
523 {
524   list_add_after(&pos_node->list, &node->list);
525   tree->count++;
526 }
527
528 static void
529 avl_remove(struct avl_tree *tree, struct avl_node *node)
530 {
531   list_remove(&node->list);
532   tree->count--;
533 }
534
535 static void
536 avl_post_delete(struct avl_tree *tree, struct avl_node *node)
537 {
538   struct avl_node *parent;
539
540   if ((parent = node->parent) == NULL)
541     return;
542
543   if (node == parent->left) {
544     parent->balance++;
545
546     if (parent->balance == 0) {
547       avl_post_delete(tree, parent);
548       return;
549     }
550
551     if (parent->balance == 1)
552       return;
553
554     if (parent->right->balance == 0) {
555       avl_rotate_left(tree, parent);
556       return;
557     }
558
559     if (parent->right->balance == 1) {
560       avl_rotate_left(tree, parent);
561       avl_post_delete(tree, parent->parent);
562       return;
563     }
564
565     avl_rotate_right(tree, parent->right);
566     avl_rotate_left(tree, parent);
567     avl_post_delete(tree, parent->parent);
568     return;
569   }
570
571   parent->balance--;
572
573   if (parent->balance == 0) {
574     avl_post_delete(tree, parent);
575     return;
576   }
577
578   if (parent->balance == -1)
579     return;
580
581   if (parent->left->balance == 0) {
582     avl_rotate_right(tree, parent);
583     return;
584   }
585
586   if (parent->left->balance == -1) {
587     avl_rotate_right(tree, parent);
588     avl_post_delete(tree, parent->parent);
589     return;
590   }
591
592   avl_rotate_left(tree, parent->left);
593   avl_rotate_right(tree, parent);
594   avl_post_delete(tree, parent->parent);
595 }
596
597 static struct avl_node *
598 avl_local_min(struct avl_node *node)
599 {
600   while (node->left != NULL)
601     node = node->left;
602
603   return node;
604 }
605
606 #if 0
607 static struct avl_node *
608 avl_local_max(struct avl_node *node)
609 {
610   while (node->right != NULL)
611     node = node->right;
612
613   return node;
614 }
615 #endif
616
617 static void
618 avl_delete_worker(struct avl_tree *tree, struct avl_node *node)
619 {
620   struct avl_node *parent, *min;
621
622   parent = node->parent;
623
624   if (node->left == NULL && node->right == NULL) {
625     if (parent == NULL) {
626       tree->root = NULL;
627       return;
628     }
629
630     if (parent->left == node) {
631       parent->left = NULL;
632       parent->balance++;
633
634       if (parent->balance == 1)
635         return;
636
637       if (parent->balance == 0) {
638         avl_post_delete(tree, parent);
639         return;
640       }
641
642       if (parent->right->balance == 0) {
643         avl_rotate_left(tree, parent);
644         return;
645       }
646
647       if (parent->right->balance == 1) {
648         avl_rotate_left(tree, parent);
649         avl_post_delete(tree, parent->parent);
650         return;
651       }
652
653       avl_rotate_right(tree, parent->right);
654       avl_rotate_left(tree, parent);
655       avl_post_delete(tree, parent->parent);
656       return;
657     }
658
659     if (parent->right == node) {
660       parent->right = NULL;
661       parent->balance--;
662
663       if (parent->balance == -1)
664         return;
665
666       if (parent->balance == 0) {
667         avl_post_delete(tree, parent);
668         return;
669       }
670
671       if (parent->left->balance == 0) {
672         avl_rotate_right(tree, parent);
673         return;
674       }
675
676       if (parent->left->balance == -1) {
677         avl_rotate_right(tree, parent);
678         avl_post_delete(tree, parent->parent);
679         return;
680       }
681
682       avl_rotate_left(tree, parent->left);
683       avl_rotate_right(tree, parent);
684       avl_post_delete(tree, parent->parent);
685       return;
686     }
687   }
688
689   if (node->left == NULL) {
690     if (parent == NULL) {
691       tree->root = node->right;
692       node->right->parent = NULL;
693       return;
694     }
695
696     node->right->parent = parent;
697
698     if (parent->left == node)
699       parent->left = node->right;
700
701     else
702       parent->right = node->right;
703
704     avl_post_delete(tree, node->right);
705     return;
706   }
707
708   if (node->right == NULL) {
709     if (parent == NULL) {
710       tree->root = node->left;
711       node->left->parent = NULL;
712       return;
713     }
714
715     node->left->parent = parent;
716
717     if (parent->left == node)
718       parent->left = node->left;
719
720     else
721       parent->right = node->left;
722
723     avl_post_delete(tree, node->left);
724     return;
725   }
726
727   min = avl_local_min(node->right);
728   avl_delete_worker(tree, min);
729   parent = node->parent;
730
731   min->balance = node->balance;
732   min->parent = parent;
733   min->left = node->left;
734   min->right = node->right;
735
736   if (min->left != NULL)
737     min->left->parent = min;
738
739   if (min->right != NULL)
740     min->right->parent = min;
741
742   if (parent == NULL) {
743     tree->root = min;
744     return;
745   }
746
747   if (parent->left == node) {
748     parent->left = min;
749     return;
750   }
751
752   parent->right = min;
753 }
754
755 /*
756  * Local Variables:
757  * c-basic-offset: 2
758  * indent-tabs-mode: nil
759  * End:
760  */