LCOV - code coverage report
Current view: top level - include - osi_tree.h (source / functions) Hit Total Coverage
Test: gfs2-utils.info Lines: 131 206 63.6 %
Date: 2023-09-27 13:48:55 Functions: 12 12 100.0 %

          Line data    Source code
       1             : #ifndef __OSI_RBTREE_DOT_H__
       2             : #define __OSI_RBTREE_DOT_H__
       3             : 
       4             : #include <stdlib.h>
       5             : #include <stddef.h>
       6             : #include <assert.h>
       7             : 
       8             : /* Adapted from the kernel's rbtree.c */
       9             : struct osi_node {
      10             :         unsigned long  osi_parent_color;
      11             : #define OSI_RED         0
      12             : #define OSI_BLACK       1
      13             :         struct osi_node *osi_left;
      14             :         struct osi_node *osi_right;
      15             : };
      16             : 
      17             : #define osi_parent(r)   ((struct osi_node *)((r)->osi_parent_color & ~3))
      18             : #define osi_color(r)   ((r)->osi_parent_color & 1)
      19             : #define osi_is_red(r)   (!osi_color(r))
      20             : #define osi_is_black(r) osi_color(r)
      21             : #define osi_set_red(r)  do { (r)->osi_parent_color &= ~1; } while (0)
      22             : #define osi_set_black(r)  do { (r)->osi_parent_color |= 1; } while (0)
      23             : #define OSI_EMPTY_NODE(node) (osi_parent(node) == node)
      24             : 
      25             : struct osi_root
      26             : {
      27             :         struct osi_node *osi_node;
      28             : };
      29             : 
      30             : #define OSI_EMPTY_ROOT(root)  ((root)->osi_node == NULL)
      31             : 
      32     9330991 : static inline void osi_set_parent(struct osi_node *rb, struct osi_node *p)
      33             : {
      34     9330991 :         rb->osi_parent_color = (rb->osi_parent_color & 3) | (unsigned long)p;
      35     9330991 : }
      36             : 
      37       27978 : static inline void osi_set_color(struct osi_node *rb, int color)
      38             : {
      39       27978 :         rb->osi_parent_color = (rb->osi_parent_color & ~1) | color;
      40       27978 : }
      41             : 
      42     2137767 : static inline void osi_link_node(struct osi_node *node,
      43             :                                  struct osi_node *parent,
      44             :                                  struct osi_node **osi_link)
      45             : {
      46     2137767 :         node->osi_parent_color = (unsigned long )parent;
      47     2137767 :         node->osi_left = node->osi_right = NULL;
      48             : 
      49     2137767 :         *osi_link = node;
      50     2137767 : }
      51             : 
      52     3110560 : static inline void __osi_rotate_left(struct osi_node *node,
      53             :                                      struct osi_root *root)
      54             : {
      55     3110560 :         struct osi_node *right = node->osi_right;
      56     3110560 :         struct osi_node *parent = osi_parent(node);
      57             : 
      58     3110560 :         if ((node->osi_right = right->osi_left))
      59     2043752 :                 osi_set_parent(right->osi_left, node);
      60     3110560 :         right->osi_left = node;
      61             : 
      62     3110560 :         osi_set_parent(right, parent);
      63             : 
      64     3110560 :         if (parent) {
      65     3026329 :                 if (node == parent->osi_left)
      66      982257 :                         parent->osi_left = right;
      67             :                 else
      68     2044072 :                         parent->osi_right = right;
      69             :         }
      70             :         else
      71       84231 :                 root->osi_node = right;
      72     3110560 :         osi_set_parent(node, right);
      73     3110560 : }
      74             : 
      75         113 : static inline void __osi_rotate_right(struct osi_node *node,
      76             :                                       struct osi_root *root)
      77             : {
      78         113 :         struct osi_node *left = node->osi_left;
      79         113 :         struct osi_node *parent = osi_parent(node);
      80             : 
      81         113 :         if ((node->osi_left = left->osi_right))
      82           0 :                 osi_set_parent(left->osi_right, node);
      83         113 :         left->osi_right = node;
      84             : 
      85         113 :         osi_set_parent(left, parent);
      86             : 
      87         113 :         if (parent) {
      88         113 :                 if (node == parent->osi_right)
      89         113 :                         parent->osi_right = left;
      90             :                 else
      91           0 :                         parent->osi_left = left;
      92             :         } else
      93           0 :                 root->osi_node = left;
      94         113 :         osi_set_parent(node, left);
      95         113 : }
      96             : 
      97     2137767 : static inline void osi_insert_color(struct osi_node *node,
      98             :                                     struct osi_root *root)
      99             : {
     100             :         struct osi_node *parent, *gparent;
     101             : 
     102     6258638 :         while ((parent = osi_parent(node)) && osi_is_red(parent)) {
     103     4120871 :                 gparent = osi_parent(parent);
     104             : 
     105     4120871 :                 if (parent == gparent->osi_left) {
     106             :                         {
     107           0 :                                 register struct osi_node *uncle = gparent->osi_right;
     108           0 :                                 if (uncle && osi_is_red(uncle)) {
     109           0 :                                         osi_set_black(uncle);
     110           0 :                                         osi_set_black(parent);
     111           0 :                                         osi_set_red(gparent);
     112           0 :                                         node = gparent;
     113           0 :                                         continue;
     114             :                                 }
     115             :                         }
     116             : 
     117           0 :                         if (parent->osi_right == node) {
     118             :                                 register struct osi_node *tmp;
     119             : 
     120           0 :                                 __osi_rotate_left(parent, root);
     121           0 :                                 tmp = parent;
     122           0 :                                 parent = node;
     123           0 :                                 node = tmp;
     124             :                         }
     125             : 
     126           0 :                         osi_set_black(parent);
     127           0 :                         osi_set_red(gparent);
     128           0 :                         __osi_rotate_right(gparent, root);
     129             :                 } else {
     130             :                         {
     131     4120871 :                                 register struct osi_node *uncle = gparent->osi_left;
     132     4120871 :                                 if (uncle && osi_is_red(uncle)) {
     133     2047908 :                                         osi_set_black(uncle);
     134     2047908 :                                         osi_set_black(parent);
     135     2047908 :                                         osi_set_red(gparent);
     136     2047908 :                                         node = gparent;
     137     2047908 :                                         continue;
     138             :                                 }
     139             :                         }
     140             : 
     141     2072963 :                         if (parent->osi_left == node) {
     142             :                                 register struct osi_node *tmp;
     143          56 :                                 __osi_rotate_right(parent, root);
     144          56 :                                 tmp = parent;
     145          56 :                                 parent = node;
     146          56 :                                 node = tmp;
     147             :                         }
     148             : 
     149     2072963 :                         osi_set_black(parent);
     150     2072963 :                         osi_set_red(gparent);
     151     2072963 :                         __osi_rotate_left(gparent, root);
     152             :                 }
     153             :         }
     154             : 
     155     2137767 :         osi_set_black(root->osi_node);
     156     2137767 : }
     157             : 
     158     2137007 : static inline void __osi_erase_color(struct osi_node *node,
     159             :                                      struct osi_node *parent,
     160             :                                      struct osi_root *root)
     161             : {
     162             :         struct osi_node *other;
     163             : 
     164     4184293 :         while ((!node || osi_is_black(node)) && node != root->osi_node) {
     165     2075264 :                 if (parent->osi_left == node) {
     166     2075264 :                         other = parent->osi_right;
     167     2075264 :                         if (osi_is_red(other)) {
     168     1009619 :                                 osi_set_black(other);
     169     1009619 :                                 osi_set_red(parent);
     170     1009619 :                                 __osi_rotate_left(parent, root);
     171     1009619 :                                 other = parent->osi_right;
     172             :                         }
     173     2075264 :                         if ((!other->osi_left || osi_is_black(other->osi_left)) &&
     174     2051046 :                             (!other->osi_right || osi_is_black(other->osi_right)))
     175             :                         {
     176     2047286 :                                 osi_set_red(other);
     177     2047286 :                                 node = parent;
     178     2047286 :                                 parent = osi_parent(node);
     179             :                         } else {
     180       27978 :                                 if (!other->osi_right || osi_is_black(other->osi_right))
     181             :                                 {
     182             :                                         struct osi_node *o_left;
     183          57 :                                         if ((o_left = other->osi_left))
     184          57 :                                                 osi_set_black(o_left);
     185          57 :                                         osi_set_red(other);
     186          57 :                                         __osi_rotate_right(other, root);
     187          57 :                                         other = parent->osi_right;
     188             :                                 }
     189       27978 :                                 osi_set_color(other, osi_color(parent));
     190       27978 :                                 osi_set_black(parent);
     191       27978 :                                 if (other->osi_right)
     192       27978 :                                         osi_set_black(other->osi_right);
     193       27978 :                                 __osi_rotate_left(parent, root);
     194       27978 :                                 node = root->osi_node;
     195       27978 :                                 break;
     196             :                         }
     197             :                 } else {
     198           0 :                         other = parent->osi_left;
     199           0 :                         if (osi_is_red(other)) {
     200           0 :                                 osi_set_black(other);
     201           0 :                                 osi_set_red(parent);
     202           0 :                                 __osi_rotate_right(parent, root);
     203           0 :                                 other = parent->osi_left;
     204             :                         }
     205           0 :                         if ((!other->osi_left || osi_is_black(other->osi_left)) &&
     206           0 :                             (!other->osi_right || osi_is_black(other->osi_right)))
     207             :                         {
     208           0 :                                 osi_set_red(other);
     209           0 :                                 node = parent;
     210           0 :                                 parent = osi_parent(node);
     211             :                         } else {
     212           0 :                                 if (!other->osi_left || osi_is_black(other->osi_left))
     213             :                                 {
     214             :                                         register struct osi_node *o_right;
     215           0 :                                         if ((o_right = other->osi_right))
     216           0 :                                                 osi_set_black(o_right);
     217           0 :                                         osi_set_red(other);
     218           0 :                                         __osi_rotate_left(other, root);
     219           0 :                                         other = parent->osi_left;
     220             :                                 }
     221           0 :                                 osi_set_color(other, osi_color(parent));
     222           0 :                                 osi_set_black(parent);
     223           0 :                                 if (other->osi_left)
     224           0 :                                         osi_set_black(other->osi_left);
     225           0 :                                 __osi_rotate_right(parent, root);
     226           0 :                                 node = root->osi_node;
     227           0 :                                 break;
     228             :                         }
     229             :                 }
     230             :         }
     231     2137007 :         if (node)
     232     2132327 :                 osi_set_black(node);
     233     2137007 : }
     234             : 
     235     2137013 : static inline void osi_erase(struct osi_node *node, struct osi_root *root)
     236             : {
     237             :         struct osi_node *child, *parent;
     238             :         int color;
     239             : 
     240     2137013 :         if (!node->osi_left)
     241     2137013 :                 child = node->osi_right;
     242           0 :         else if (!node->osi_right)
     243           0 :                 child = node->osi_left;
     244             :         else {
     245           0 :                 struct osi_node *old = node, *left;
     246             : 
     247           0 :                 node = node->osi_right;
     248           0 :                 while ((left = node->osi_left) != NULL)
     249           0 :                         node = left;
     250             : 
     251           0 :                 if (osi_parent(old)) {
     252           0 :                         if (osi_parent(old)->osi_left == old)
     253           0 :                                 osi_parent(old)->osi_left = node;
     254             :                         else
     255           0 :                                 osi_parent(old)->osi_right = node;
     256             :                 } else
     257           0 :                         root->osi_node = node;
     258             : 
     259           0 :                 child = node->osi_right;
     260           0 :                 parent = osi_parent(node);
     261           0 :                 color = osi_color(node);
     262             : 
     263           0 :                 if (parent == old) {
     264           0 :                         parent = node;
     265             :                 } else {
     266           0 :                         if (child)
     267           0 :                                 osi_set_parent(child, parent);
     268           0 :                         parent->osi_left = child;
     269             : 
     270           0 :                         node->osi_right = old->osi_right;
     271           0 :                         osi_set_parent(old->osi_right, node);
     272             :                 }
     273             : 
     274           0 :                 node->osi_parent_color = old->osi_parent_color;
     275           0 :                 node->osi_left = old->osi_left;
     276           0 :                 osi_set_parent(old->osi_left, node);
     277             : 
     278           0 :                 goto color;
     279             :         }
     280             : 
     281     2137013 :         parent = osi_parent(node);
     282     2137013 :         color = osi_color(node);
     283             : 
     284     2137013 :         if (child)
     285     1065893 :                 osi_set_parent(child, parent);
     286     2137013 :         if (parent)
     287             :         {
     288     2127657 :                 if (parent->osi_left == node)
     289     2127657 :                         parent->osi_left = child;
     290             :                 else
     291           0 :                         parent->osi_right = child;
     292             :         }
     293             :         else
     294        9356 :                 root->osi_node = child;
     295             : 
     296     2137013 :  color:
     297     2137013 :         if (color == OSI_BLACK)
     298             :                 /* coverity[var_deref_model:SUPPRESS] */
     299     2137007 :                 __osi_erase_color(child, parent, root);
     300     2137013 : }
     301             : 
     302             : /*
     303             :  * This function returns the first node (in sort order) of the tree.
     304             :  */
     305     2229602 : static inline struct osi_node *osi_first(struct osi_root *root)
     306             : {
     307             :         struct osi_node *n;
     308             : 
     309     2229602 :         n = root->osi_node;
     310     2229602 :         if (!n)
     311        5015 :                 return NULL;
     312    14873785 :         while (n->osi_left)
     313    12649198 :                 n = n->osi_left;
     314     2224587 :         return n;
     315             : }
     316             : 
     317       11559 : static inline struct osi_node *osi_last(struct osi_root *root)
     318             : {
     319             :         struct osi_node *n;
     320             : 
     321       11559 :         n = root->osi_node;
     322       11559 :         if (!n)
     323          82 :                 return NULL;
     324      127132 :         while (n->osi_right)
     325      115655 :                 n = n->osi_right;
     326       11477 :         return n;
     327             : }
     328             : 
     329      165948 : static inline struct osi_node *osi_next(struct osi_node *node)
     330             : {
     331             :         struct osi_node *parent;
     332             : 
     333      165948 :         if (OSI_EMPTY_NODE(node))
     334           0 :                 return NULL;
     335             : 
     336             :         /* If we have a right-hand child, go down and then left as far
     337             :            as we can. */
     338      165948 :         if (node->osi_right) {
     339       45036 :                 node = node->osi_right;
     340       76539 :                 while (node->osi_left)
     341       31503 :                         node=node->osi_left;
     342       45036 :                 return node;
     343             :         }
     344             : 
     345             :         /* No right-hand children.  Everything down and left is
     346             :            smaller than us, so any 'next' node must be in the general
     347             :            direction of our parent. Go up the tree; any time the
     348             :            ancestor is a right-hand child of its parent, keep going
     349             :            up. First time it's a left-hand child of its parent, said
     350             :            parent is our 'next' node. */
     351      160126 :         while ((parent = osi_parent(node)) && node == parent->osi_right)
     352       39214 :                 node = parent;
     353             : 
     354      120912 :         return parent;
     355             : }
     356             : 
     357        6429 : static inline struct osi_node *osi_prev(struct osi_node *node)
     358             : {
     359             :         struct osi_node *parent;
     360             : 
     361        6429 :         if (OSI_EMPTY_NODE(node))
     362           0 :                 return NULL;
     363             : 
     364             :         /* If we have a left-hand child, go down and then right as far
     365             :            as we can. */
     366        6429 :         if (node->osi_left) {
     367           0 :                 node = node->osi_left;
     368           0 :                 while (node->osi_right)
     369           0 :                         node=node->osi_right;
     370           0 :                 return node;
     371             :         }
     372             : 
     373             :         /* No left-hand children. Go up till we find an ancestor which
     374             :            is a right-hand child of its parent */
     375        6429 :         while ((parent = osi_parent(node)) && node == parent->osi_left)
     376           0 :                 node = parent;
     377             : 
     378        6429 :         return parent;
     379             : }
     380             : 
     381             : static inline void osi_replace_node(struct osi_node *victim,
     382             :                                     struct osi_node *new,
     383             :                                     struct osi_root *root)
     384             : {
     385             :         struct osi_node *parent = osi_parent(victim);
     386             : 
     387             :         /* Set the surrounding nodes to point to the replacement */
     388             :         if (parent) {
     389             :                 if (victim == parent->osi_left)
     390             :                         parent->osi_left = new;
     391             :                 else
     392             :                         parent->osi_right = new;
     393             :         } else {
     394             :                 root->osi_node = new;
     395             :         }
     396             :         if (victim->osi_left)
     397             :                 osi_set_parent(victim->osi_left, new);
     398             :         if (victim->osi_right)
     399             :                 osi_set_parent(victim->osi_right, new);
     400             : 
     401             :         /* Copy the pointers/colour from the victim to the replacement */
     402             :         *new = *victim;
     403             : }
     404             : 
     405             : #endif

Generated by: LCOV version 1.14