LCOV - code coverage report
Current view: directory - src/trusted/interval_multiset - nacl_interval_range_tree.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 408 404 99.0 %
Date: 2014-06-18 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : #define DEBUG_THIS 0
       8                 : /*
       9                 :  * Define as 1 to get debugging output.  Compiler's dead code
      10                 :  * elimination should remove debug statements when defined as 0.
      11                 :  */
      12                 : 
      13                 : #include <stdio.h>  /* tree print */
      14                 : 
      15                 : #include "native_client/src/include/nacl_compiler_annotations.h"
      16                 : #include "native_client/src/shared/platform/nacl_log.h"
      17                 : #include "native_client/src/trusted/interval_multiset/nacl_interval_multiset.h"
      18                 : #include "native_client/src/trusted/interval_multiset/nacl_interval_range_tree.h"
      19                 : #include "native_client/src/trusted/interval_multiset/nacl_interval_range_tree_intern.h"
      20                 : 
      21                 : struct NaClIntervalRangeTreeNode {
      22                 :   struct NaClIntervalRangeTreeNode *left;
      23                 :   struct NaClIntervalRangeTreeNode *right;
      24                 :   int balance;  /* AVL height balance: -1, 0, 1 */
      25                 : 
      26                 :   uint32_t value;
      27                 :   /* the value at this interval end point */
      28                 : 
      29                 :   uint32_t value_containment_delta;
      30                 :   /*
      31                 :    * Each interval that uses |value| as the start point would
      32                 :    * increment |value_containment_delta| by 1; and each range that
      33                 :    * uses it as the end point would decrement it by 1.  Can never be
      34                 :    * negative, but may be zero, e.g., [x,y] [y,z] would make y's
      35                 :    * value_containment_delta be zero.  We cannot distinguish
      36                 :    * [x,y][y,z] from [x1,y][x2,y][y,z1][y,z2] when looking at y.
      37                 :    */
      38                 : 
      39                 :   uint32_t refcount;
      40                 :   /*
      41                 :    * We could keep right_delta and left_delta for counting the number
      42                 :    * of ranges that end and start at this value respectively, but that
      43                 :    * would require a subtraction whenever we re-computed range
      44                 :    * information.  Keeping a summed delta and a refcount simplifies
      45                 :    * the updates, at the cost of a reduced maximum number of
      46                 :    * (overlapped) ranges.  If we didn't do either of the above, then
      47                 :    * overlaps could cause the summed delta to be zero after a delete,
      48                 :    * and we cannot determine whether we can actually remove the tree
      49                 :    * node or not.
      50                 :    */
      51                 : 
      52                 :   /*
      53                 :    * Cumulative information about the subtree rooted at this node.
      54                 :    */
      55                 :   uint32_t range_left;
      56                 :   uint32_t range_right;
      57                 :   /* invariant: range_left <= value <= range_right */
      58                 :   int32_t subtree_containment_delta;
      59                 :   /*
      60                 :    * The subtree_containment_delta is the number of intervals that a
      61                 :    * point would be contained in, if a probe point were moved from
      62                 :    * just to the left of this subtree to just the right of the
      63                 :    * subtree, i.e., from just less than range_left to just greater
      64                 :    * than range_right.
      65                 :    *
      66                 :    * subtree_containment_delta = value_containment_delta +
      67                 :    *  (NULL != left) ? left->subtree_containment_delta : 0 +
      68                 :    *  (NULL != right) ? right->subtree_containment_delta : 0;
      69                 :    */
      70                 : };
      71                 : 
      72                 : struct NaClIntervalMultisetVtbl const kNaClIntervalRangeTreeVtbl;  /* fwd */
      73                 : 
      74                 : static INLINE void indent(int depth) {
      75                 :   while (depth != 0) {
      76                 :     putchar(' ');
      77                 :     --depth;
      78                 :   }
      79                 : }
      80                 : 
      81                 : static void TreePrint(struct NaClIntervalRangeTreeNode *node,
      82                 :                       int                              depth) {
      83                 :   if (NULL == node) {
      84                 :     return;
      85                 :   }
      86                 :   /* rotated head view */
      87                 :   TreePrint(node->right, depth + 1);
      88                 :   indent(depth);
      89                 :   printf("v=%d [b=%d, d=%d, rl=%u, rr=%u, dd=%d]\n",
      90                 :          node->value, node->balance, node->value_containment_delta,
      91                 :          node->range_left, node->range_right, node->subtree_containment_delta);
      92                 :   TreePrint(node->left, depth + 1);
      93                 : }
      94                 : 
      95                 : static INLINE void NaClIntervalRangeTreePrint(
      96        15080902 :     struct NaClIntervalRangeTreeNode *node) {
      97                 :   if (!DEBUG_THIS) {
      98                 :     return;
      99                 :   }
     100                 :   putchar('\n');
     101                 :   TreePrint(node, 0);
     102                 :   putchar('\n');
     103        15080902 : }
     104                 : 
     105                 : #define NaCl_dprintf(alist) do { if (DEBUG_THIS) printf alist; } while (0)
     106                 : 
     107                 : static void NaClIntervalRangeTreeNodeInit(
     108         1210006 :     struct NaClIntervalRangeTreeNode *node,
     109         1210006 :     uint32_t value,
     110         1210006 :     int lr) {
     111         1210006 :   node->left = NULL;
     112         1210006 :   node->right = NULL;
     113         1210006 :   node->balance = 0;
     114         1210006 :   node->value = value;
     115         1210006 :   node->value_containment_delta = lr; /* 1 or -1 for L or R */
     116         1210006 :   node->refcount = 1;  /* caller */
     117         1210006 :   node->range_left = value;
     118         1210006 :   node->range_right = value;
     119         1210006 :   node->subtree_containment_delta = lr;
     120         1210006 : }
     121                 : 
     122                 : static struct NaClIntervalRangeTreeNode *NaClIntervalRangeTreeNodeFactory(
     123          605290 :     uint32_t value,
     124          605290 :     int lr) {
     125          605290 :   struct NaClIntervalRangeTreeNode *obj;
     126          605290 :   obj = (struct NaClIntervalRangeTreeNode *) malloc(sizeof *obj);
     127          605290 :   if (NULL == obj) {
     128               0 :     NaClLog(LOG_FATAL, "NaClIntervalRangeTreeNodeFactory: out of memory!\n");
     129               0 :   }
     130          605290 :   NaClIntervalRangeTreeNodeInit(obj, value, lr);
     131          605290 :   return obj;
     132                 : }
     133                 : 
     134                 : /*
     135                 :  * Updates |node|'s range_left, range_right, and
     136                 :  * subtree_containment_delta based on its left and right children.
     137                 :  * Does not recursively walk!  |node| must not be NULL.
     138                 :  */
     139         7694253 : static void NaClRangeStatsUpdate(struct NaClIntervalRangeTreeNode *node) {
     140         7694253 :   uint32_t range_left = node->value;
     141         7694253 :   uint32_t range_right = node->value;
     142         7694253 :   uint32_t cumulative_delta = node->value_containment_delta;
     143                 : 
     144         7694253 :   if (NULL != node->left) {
     145         6770427 :     range_left = node->left->range_left;
     146         6770427 :     cumulative_delta += node->left->subtree_containment_delta;
     147         6770427 :   }
     148         7694253 :   if (NULL != node->right) {
     149         6950194 :     range_right = node->right->range_right;
     150         6950194 :     cumulative_delta += node->right->subtree_containment_delta;
     151         6950194 :   }
     152         7694253 :   node->range_left = range_left;
     153         7694253 :   node->range_right = range_right;
     154         7694253 :   node->subtree_containment_delta = cumulative_delta;
     155         7694253 : }
     156                 : 
     157                 : /*
     158                 :  * returns 1 if (sub)tree at |*treep| grew in height, 0 otherwise.
     159                 :  * |node| should be initialized, and this takes ownership.  The
     160                 :  * refcount may be transferred to another pre-exsting node in the
     161                 :  * tree, and |node| freed.
     162                 :  */
     163         4418211 : static int NaClAvlTreeInsert(struct NaClIntervalRangeTreeNode **treep,
     164         4418211 :                              struct NaClIntervalRangeTreeNode *node) {
     165         4418211 :   struct NaClIntervalRangeTreeNode *tmp;
     166         4418211 :   struct NaClIntervalRangeTreeNode *tmp_l;
     167         4418211 :   struct NaClIntervalRangeTreeNode *tmp_r;
     168         4418211 :   int higher;
     169                 : 
     170         4418211 :   if (NULL == (tmp = *treep)) {
     171          603742 :     *treep = node;
     172          603742 :     return 1;
     173                 :   }
     174         3814469 :   if (node->value == tmp->value) {
     175            1548 :     tmp->value_containment_delta += node->value_containment_delta;
     176            1548 :     tmp->subtree_containment_delta += node->value_containment_delta;
     177            1548 :     tmp->refcount++;
     178            1548 :     free(node);
     179            1548 :     return 0;
     180         3812921 :   } else if (node->value < tmp->value) {
     181                 :     /* recurse left. */
     182         1811349 :     higher = NaClAvlTreeInsert(&tmp->left, node);
     183         1811349 :     if (!higher) {
     184         1207678 :       NaClRangeStatsUpdate(tmp);
     185         1207678 :       return 0;
     186                 :     }
     187          603671 :     --tmp->balance;
     188          603671 :     if (0 == tmp->balance) {
     189                 :       /* height unchanged */
     190          113581 :       NaClRangeStatsUpdate(tmp);
     191          113581 :       return 0;
     192                 :     }
     193          490090 :     if (-1 == tmp->balance) {
     194                 :       /*
     195                 :        * Left tree grew, but we're still within AVL balance criteria
     196                 :        * for this subtree.  Subtree height grew, so let caller know.
     197                 :        */
     198          364961 :       NaClRangeStatsUpdate(tmp);
     199          364961 :       return 1;
     200                 :     }
     201                 :     /* pivot */
     202          125129 :     if (-1 == tmp->left->balance) {
     203                 :       /*
     204                 :        * L rotation:
     205                 :        *
     206                 :        *      x                    x
     207                 :        *
     208                 :        *      d                    b
     209                 :        *   b     e      ->      a     d
     210                 :        *  a c                        c e
     211                 :        */
     212           46571 :       *treep = tmp->left;
     213           46571 :       tmp->left = (*treep)->right;
     214           46571 :       (*treep)->right = tmp;
     215           46571 :       (*treep)->balance = 0;
     216           46571 :       tmp->balance = 0;
     217                 : 
     218           46571 :       tmp = *treep;  /* b */
     219           46571 :       NaClRangeStatsUpdate(tmp->right);  /* d */
     220           46571 :       NaClRangeStatsUpdate(tmp);
     221           46571 :       return 0;
     222                 :     } else {
     223                 :       /*
     224                 :        * LR rotation:
     225                 :        *
     226                 :        *        x                      x
     227                 :        *
     228                 :        *        f                      d
     229                 :        *    b       g      ->      b       f
     230                 :        *  a   d                  a   c   e   g
     231                 :        *     c e
     232                 :        */
     233           78558 :       tmp = (*treep)->left->right;
     234           78558 :       tmp_l = tmp->left;
     235           78558 :       tmp_r = tmp->right;
     236           78558 :       tmp->left = (*treep)->left;
     237           78558 :       tmp->right = (*treep);
     238           78558 :       *treep = tmp;
     239           78558 :       tmp->left->right = tmp_l;
     240           78558 :       tmp->right->left = tmp_r;
     241           78558 :       tmp->left->balance = (tmp->balance <= 0) ? 0 : -1;
     242           78558 :       tmp->right->balance = (tmp->balance >= 0) ? 0 : 1;
     243           78558 :       tmp->balance = 0;
     244           78558 :       NaClRangeStatsUpdate(tmp->left);
     245           78558 :       NaClRangeStatsUpdate(tmp->right);
     246           78558 :       NaClRangeStatsUpdate(tmp);
     247           78558 :       return 0;
     248                 :     }
     249                 :   } else {
     250                 :     /* node->value > tmp->value */
     251         2001572 :     higher = NaClAvlTreeInsert(&tmp->right, node);
     252         2001572 :     if (!higher) {
     253         1202038 :       NaClRangeStatsUpdate(tmp);
     254         1202038 :       return 0;
     255                 :     }
     256          799534 :     ++tmp->balance;
     257          799534 :     if (0 == tmp->balance) {
     258                 :       /* height unchanged */
     259          102464 :       NaClRangeStatsUpdate(tmp);
     260          102464 :       return 0;
     261                 :     }
     262          697070 :     if (1 == tmp->balance) {
     263                 :       /*
     264                 :        * Right tree grew, but we're still within AVL balance criteria
     265                 :        * for this subtree.  Subtree height grew, so let caller know.
     266                 :        */
     267          561370 :       NaClRangeStatsUpdate(tmp);
     268          561370 :       return 1;
     269                 :     }
     270                 :     /* pivot */
     271          135700 :     if (1 == tmp->right->balance) {
     272                 :       /*
     273                 :        * R rotation:
     274                 :        *
     275                 :        *      x                    x
     276                 :        *
     277                 :        *      b                    d
     278                 :        *   a     d      ->      b     e
     279                 :        *        c e            a c
     280                 :        */
     281          100376 :       *treep = tmp->right;
     282          100376 :       tmp->right = (*treep)->left;
     283          100376 :       (*treep)->left = tmp;
     284          100376 :       (*treep)->balance = 0;
     285          100376 :       tmp->balance = 0;
     286                 : 
     287          100376 :       tmp = *treep;
     288          100376 :       NaClRangeStatsUpdate(tmp->left);
     289          100376 :       NaClRangeStatsUpdate(tmp);
     290          100376 :       return 0;
     291                 :     } else {
     292                 :       /*
     293                 :        * RL rotation:
     294                 :        *
     295                 :        *       x                      x
     296                 :        *
     297                 :        *       b                      d
     298                 :        *   a       f      ->      b       f
     299                 :        *         d   g          a   c   e   g
     300                 :        *        c e
     301                 :        */
     302           35324 :       tmp = (*treep)->right->left;
     303           35324 :       tmp_l = tmp->left;
     304           35324 :       tmp_r = tmp->right;
     305           35324 :       tmp->right = (*treep)->right;
     306           35324 :       tmp->left = (*treep);
     307           35324 :       *treep = tmp;
     308           35324 :       tmp->right->left = tmp_r;
     309           35324 :       tmp->left->right = tmp_l;
     310           35324 :       tmp->right->balance = (tmp->balance >= 0) ? 0 : 1;
     311           35324 :       tmp->left->balance = (tmp->balance <= 0) ? 0 : -1;
     312           35324 :       tmp->balance = 0;
     313           35324 :       NaClRangeStatsUpdate(tmp->right);
     314           35324 :       NaClRangeStatsUpdate(tmp->left);
     315           35324 :       NaClRangeStatsUpdate(tmp);
     316           35324 :       return 0;
     317                 :     }
     318                 :   }
     319         4418211 : }
     320                 : 
     321                 : /*
     322                 :  * NaClAvlTreeBalanceLeft -- left subtree shrunk.  Adjust balance of
     323                 :  * node, possibly rebalancing.
     324                 :  */
     325                 : static void NaClAvlTreeBalanceLeft(
     326          405562 :     struct NaClIntervalRangeTreeNode **treep,
     327          405562 :     int *height_changed) {
     328          405562 :   int bal;
     329          405562 :   struct NaClIntervalRangeTreeNode *tmp;
     330          405562 :   struct NaClIntervalRangeTreeNode *tmp_l;
     331          405562 :   struct NaClIntervalRangeTreeNode *tmp_r;
     332                 : 
     333          405562 :   bal = ++(*treep)->balance;
     334          405562 :   if (0 == bal) {
     335          124152 :     return;
     336                 :   }
     337          281410 :   if (1 == bal) {
     338          216574 :     *height_changed = 0;
     339          216574 :     return;
     340                 :   }
     341                 :   /* Rebalance needed. */
     342           64836 :   tmp = (*treep)->right;
     343           64836 :   if (tmp->balance >= 0) {
     344                 :     /*
     345                 :      * RR rotation (same rotation as R, but balance adjusts differ)
     346                 :      *
     347                 :      *      x                    x
     348                 :      *
     349                 :      *      b                    d
     350                 :      *   a     d      ->      b     e
     351                 :      *        c e            a c
     352                 :      */
     353           43807 :     (*treep)->right = tmp->left;
     354           43807 :     tmp->left = (*treep);
     355           43807 :     *treep = tmp;
     356           43807 :     if (0 == tmp->balance) {
     357           24530 :       tmp->balance = -1;
     358           24530 :       tmp->left->balance = 1;
     359           24530 :       *height_changed = 0;
     360           24530 :     } else {
     361           19277 :       tmp->balance = 0;
     362           19277 :       tmp->left->balance = 0;
     363                 :     }
     364           43807 :     NaClRangeStatsUpdate(tmp->left);
     365           43807 :     NaClRangeStatsUpdate(tmp);
     366           43807 :   } else {
     367                 :     /*
     368                 :      * RL rotation.
     369                 :      *
     370                 :      *       x                      x
     371                 :      *
     372                 :      *       b                      d
     373                 :      *   a       f      ->      b       f
     374                 :      *         d   g          a   c   e   g
     375                 :      *        c e
     376                 :      */
     377           21029 :     tmp = tmp->left;  /* d */
     378           21029 :     tmp_l = tmp->left;
     379           21029 :     tmp_r = tmp->right;
     380           21029 :     tmp->left = *treep;
     381           21029 :     tmp->right = (*treep)->right;
     382           21029 :     *treep = tmp;
     383           21029 :     tmp->left->right = tmp_l;
     384           21029 :     tmp->right->left = tmp_r;
     385           21029 :     tmp->left->balance = (tmp->balance > 0) ? -1 : 0;
     386           21029 :     tmp->right->balance = (tmp->balance < 0) ? 1 : 0;
     387           21029 :     tmp->balance = 0;
     388                 :     /*
     389                 :      * *h == 1 remains true.
     390                 :      */
     391           21029 :     NaClRangeStatsUpdate(tmp->left);
     392           21029 :     NaClRangeStatsUpdate(tmp->right);
     393           21029 :     NaClRangeStatsUpdate(tmp);
     394                 :   }
     395          405562 : }
     396                 : 
     397                 : /*
     398                 :  * NaClAvlTreeBalanceRight -- right subtree shrunk.  Adjust balance of
     399                 :  * node, possibly rebalancing.
     400                 :  */
     401                 : static void NaClAvlTreeBalanceRight(
     402          503887 :     struct NaClIntervalRangeTreeNode **treep,
     403          503887 :     int *height_changed) {
     404          503887 :   int bal;
     405          503887 :   struct NaClIntervalRangeTreeNode *tmp;
     406          503887 :   struct NaClIntervalRangeTreeNode *tmp_l;
     407          503887 :   struct NaClIntervalRangeTreeNode *tmp_r;
     408                 : 
     409          503887 :   bal = --(*treep)->balance;
     410          503887 :   if (0 == bal) {
     411          223421 :     return;
     412                 :   }
     413          280466 :   if (-1 == bal) {
     414          210991 :     *height_changed = 0;
     415          210991 :     return;
     416                 :   }
     417                 :   /* Rebalance needed. */
     418           69475 :   tmp = (*treep)->left;
     419           69475 :   if (tmp->balance <= 0) {
     420                 :     /*
     421                 :      * LL rotation (same rotation as L, but balance adjusts differ)
     422                 :      *
     423                 :      *
     424                 :      *      x                    x
     425                 :      *
     426                 :      *      d                    b
     427                 :      *   b     e      ->      a     d
     428                 :      *  a c                        c e
     429                 :      */
     430           41151 :     (*treep)->left = tmp->right;
     431           41151 :     tmp->right = (*treep);
     432           41151 :     *treep = tmp;
     433           41151 :     if (0 == tmp->balance) {
     434           24238 :       tmp->balance = 1;
     435           24238 :       tmp->right->balance = -1;
     436           24238 :       *height_changed = 0;
     437           24238 :     } else {
     438           16913 :       tmp->balance = 0;
     439           16913 :       tmp->right->balance = 0;
     440                 :     }
     441           41151 :     NaClRangeStatsUpdate(tmp->right);
     442           41151 :     NaClRangeStatsUpdate(tmp);
     443           41151 :   } else {
     444                 :     /*
     445                 :      * LR rotation.
     446                 :      *
     447                 :      *        x                      x
     448                 :      *
     449                 :      *        f                      d
     450                 :      *    b       g      ->      b       f
     451                 :      *  a   d                  a   c   e   g
     452                 :      *     c e
     453                 :      */
     454           28324 :     tmp = tmp->right;  /* d */
     455           28324 :     tmp_l = tmp->left;
     456           28324 :     tmp_r = tmp->right;
     457           28324 :     tmp->left = (*treep)->left;
     458           28324 :     tmp->right = *treep;
     459           28324 :     *treep = tmp;
     460           28324 :     tmp->left->right = tmp_l;
     461           28324 :     tmp->right->left = tmp_r;
     462           28324 :     tmp->left->balance = (tmp->balance > 0) ? -1 : 0;
     463           28324 :     tmp->right->balance = (tmp->balance < 0) ? 1 : 0;
     464           28324 :     tmp->balance = 0;
     465                 :     /*
     466                 :      * *h == 1 remains true.
     467                 :      */
     468           28324 :     NaClRangeStatsUpdate(tmp->left);
     469           28324 :     NaClRangeStatsUpdate(tmp->right);
     470           28324 :     NaClRangeStatsUpdate(tmp);
     471                 :   }
     472          503887 : }
     473                 : 
     474                 : static struct NaClIntervalRangeTreeNode *NaClAvlFindRightMost(
     475          342219 :     struct NaClIntervalRangeTreeNode **treep,
     476          342219 :     int *height_changed) {
     477          342219 :   struct NaClIntervalRangeTreeNode *tmp;
     478                 : 
     479          342219 :   if (NULL != (*treep)->right) {
     480          189610 :     tmp = NaClAvlFindRightMost(&(*treep)->right, height_changed);
     481          189610 :     NaClRangeStatsUpdate(*treep);
     482          189610 :     if (*height_changed) {
     483          125940 :       NaClAvlTreeBalanceRight(treep, height_changed);
     484          125940 :     }
     485          189610 :     return tmp;
     486                 :   }
     487          152609 :   tmp = *treep;
     488          152609 :   *treep = tmp->left;
     489          152609 :   *height_changed = 1;
     490          152609 :   return tmp;
     491          342219 : }
     492                 : 
     493                 : static struct NaClIntervalRangeTreeNode *NaClAvlFindLeftMost(
     494           90441 :     struct NaClIntervalRangeTreeNode **treep,
     495           90441 :     int *height_changed) {
     496           90441 :   struct NaClIntervalRangeTreeNode *tmp;
     497                 : 
     498           90441 :   if (NULL != (*treep)->left) {
     499           54225 :     tmp = NaClAvlFindLeftMost(&(*treep)->left, height_changed);
     500           54225 :     NaClRangeStatsUpdate(*treep);
     501           54225 :     if (*height_changed) {
     502           36572 :       NaClAvlTreeBalanceLeft(treep, height_changed);
     503           36572 :     }
     504           54225 :     return tmp;
     505                 :   }
     506           36216 :   tmp = *treep;
     507           36216 :   *treep = tmp->right;
     508           36216 :   *height_changed = 1;
     509           36216 :   return tmp;
     510           90441 : }
     511                 : 
     512                 : static struct NaClIntervalRangeTreeNode *NaClAvlTreeExtract(
     513         3360702 :     struct NaClIntervalRangeTreeNode **treep,
     514         3360702 :     struct NaClIntervalRangeTreeNode *key,
     515         3360702 :     int *height_changed) {
     516         3360702 :   struct NaClIntervalRangeTreeNode *p;
     517         3360702 :   struct NaClIntervalRangeTreeNode *tmp;
     518                 : 
     519         3360702 :   if (NULL == *treep) {
     520               0 :     NaClLog(LOG_FATAL, "NaClAvlTreeExtract: node not found\n");
     521               0 :   }
     522         6721404 :   NaCl_dprintf(("TreeExtract k->v %u, k->d %d, h %d\n",
     523                 :            key->value, key->value_containment_delta, *height_changed));
     524         3360702 :   NaClIntervalRangeTreePrint(*treep);
     525         3360702 :   if (key->value < (*treep)->value) {
     526         1323231 :     p = NaClAvlTreeExtract(&(*treep)->left, key, height_changed);
     527         1323231 :     NaClRangeStatsUpdate(*treep);
     528         1323231 :     if (*height_changed) {
     529          284231 :       NaClAvlTreeBalanceLeft(treep, height_changed);
     530          284231 :     }
     531         1323231 :     return p;
     532         2037471 :   } else if (key->value > (*treep)->value) {
     533         1432755 :     p = NaClAvlTreeExtract(&(*treep)->right, key, height_changed);
     534         1432755 :     NaClRangeStatsUpdate(*treep);
     535         1432755 :     if (*height_changed) {
     536          360843 :       NaClAvlTreeBalanceRight(treep, height_changed);
     537          360843 :     }
     538         1432755 :     return p;
     539                 :   } else {
     540                 :     /*
     541                 :      * found elt
     542                 :      */
     543          604716 :     p = *treep;
     544          604716 :     if (0 != --p->refcount) {
     545            1548 :       p->value_containment_delta -= key->value_containment_delta;
     546            1548 :       p->subtree_containment_delta -= key->value_containment_delta;
     547            1548 :       return NULL;
     548                 :     }
     549                 :     /* zero refcount, should delete */
     550          603168 :     if (NULL == p->right) {
     551          380927 :       *treep = p->left;
     552          380927 :       *height_changed = 1;
     553          603168 :     } else if (NULL == p->left) {
     554           33416 :       *treep = p->right;
     555           33416 :       *height_changed = 1;
     556          222241 :     } else if (p->balance <= 0) {
     557          152609 :       tmp = NaClAvlFindRightMost(&p->left, height_changed);
     558          152609 :       tmp->left = p->left;
     559          152609 :       tmp->right = p->right;
     560          152609 :       tmp->balance = p->balance;
     561          152609 :       NaClRangeStatsUpdate(tmp);
     562          152609 :       *treep = tmp;
     563          152609 :       if (*height_changed) {
     564           84759 :         NaClAvlTreeBalanceLeft(treep, height_changed);
     565           84759 :       }
     566          152609 :     } else {
     567           36216 :       tmp = NaClAvlFindLeftMost(&p->right, height_changed);
     568           36216 :       tmp->left = p->left;
     569           36216 :       tmp->right = p->right;
     570           36216 :       tmp->balance = p->balance;
     571           36216 :       NaClRangeStatsUpdate(tmp);
     572           36216 :       *treep = tmp;
     573           36216 :       if (*height_changed) {
     574           17104 :         NaClAvlTreeBalanceRight(treep, height_changed);
     575           17104 :       }
     576                 :     }
     577          603168 :     p->left = NULL;
     578          603168 :     p->right = NULL;
     579          603168 :     return p;
     580                 :   }
     581         3360702 : }
     582                 : 
     583                 : static struct NaClIntervalRangeTreeNode *NaClIntervalRangeTreeExtract(
     584          604716 :     struct NaClIntervalRangeTree *self,
     585          604716 :     struct NaClIntervalRangeTreeNode *keyp) {
     586          604716 :   int height_changed = 0;
     587                 : 
     588          604716 :   return NaClAvlTreeExtract(&self->root, keyp, &height_changed);
     589                 : }
     590                 : 
     591          604716 : static void NaClIntervalRangeTreeRemoveVal(struct NaClIntervalRangeTree *self,
     592          604716 :                                            uint32_t value,
     593          604716 :                                            int lr) {
     594          604716 :   struct NaClIntervalRangeTreeNode key;
     595          604716 :   struct NaClIntervalRangeTreeNode *zero_ref_node;
     596                 : 
     597         1209432 :   NaCl_dprintf(("RemoveVal %u %d\n", value, lr));
     598          604716 :   NaClIntervalRangeTreeNodeInit(&key, value, lr);
     599          604716 :   zero_ref_node = NaClIntervalRangeTreeExtract(self, &key);
     600          604716 :   if (NULL != zero_ref_node) {
     601          603168 :     free(zero_ref_node);
     602          603168 :   }
     603         1209432 :   NaCl_dprintf(("result tree\n"));
     604          604716 :   NaClIntervalRangeTreePrint(self->root);
     605          604716 : }
     606                 : 
     607                 : /*
     608                 :  * Returns a lower bound for the containment count at |value| (number
     609                 :  * of intervals in the interval set that contains it).  This lower
     610                 :  * bound will never be zero if the actual containment count is
     611                 :  * non-zero.  If the count is zero, then the memory pointed to by
     612                 :  * |gap_left| is written with the starting value of the open interval
     613                 :  * that is the gap containing the value, i.e., *gap_left will be one
     614                 :  * larger than the range_right value of the closed interval
     615                 :  * immediately to the left.  NB: 0 is possible for this value, i.e.,
     616                 :  * when there are no interval that bound the gap from the left.  The
     617                 :  * value is undefined when the return value is non-zero.
     618                 :  *
     619                 :  * We could also provide gap_right, but it's not necessary for the
     620                 :  * correctness of our algorithm.
     621                 :  *
     622                 :  * This function is called with |left_delta| equal to zero,
     623                 :  * |left_range| equal to 0, and |tree| the root of the tree.
     624                 :  */
     625                 : static uint32_t NaClAvlTreeFindValue(
     626        10207549 :     struct NaClIntervalRangeTreeNode *tree,
     627        10207549 :     uint32_t left_delta,
     628        10207549 :     uint32_t left_range,
     629        10207549 :     uint32_t value,
     630        10207549 :     uint32_t *gap_left) {
     631        10207549 :   uint32_t delta;
     632                 : 
     633        20415098 :   NaCl_dprintf(("TreeFind ld %u lr %u v %u\n", left_delta, left_range, value));
     634        10207549 :   NaClIntervalRangeTreePrint(tree);
     635        10207549 :   if (NULL == tree) {
     636         1372809 :     *gap_left = left_range;
     637         1372809 :     return left_delta;
     638                 :   }
     639         8834740 :   if (value < tree->value) {
     640         4504616 :     return NaClAvlTreeFindValue(tree->left, left_delta, left_range, value,
     641                 :                                 gap_left);
     642         4330124 :   } else if (value == tree->value) {
     643              32 :     delta = left_delta;
     644              32 :     if (NULL != tree->left) {
     645              12 :       delta += tree->left->subtree_containment_delta;
     646              12 :     }
     647              32 :     delta += tree->value_containment_delta;
     648              32 :     if (0 == delta) {
     649                 :       /*
     650                 :        * This case occurs if interval set contains [x,y] and we probed
     651                 :        * for y.  Since this is an inclusive interval, we need to
     652                 :        * increment rv -- the containment count cannot possibly be zero
     653                 :        * at a closed-interval end point.  The returned value can be a
     654                 :        * lower bound for other reasons, e.g., if the set contained
     655                 :        * intervals [x,y][y,z] and we probed for y, the
     656                 :        * value_containment_delta will be zero because y is both the
     657                 :        * end and the start of intervals, and we'd return 1 when in
     658                 :        * reality y is included in two intervals.
     659                 :        */
     660              10 :       delta = 1;
     661              10 :     }
     662                 : 
     663                 :     /* *gap_left undefined */
     664              32 :     return delta;
     665                 :   } else {
     666         4330092 :     delta = left_delta;
     667         4330092 :     if (NULL != tree->left) {
     668         3766955 :       delta += tree->left->subtree_containment_delta;
     669         3766955 :     }
     670         4330092 :     delta += tree->value_containment_delta;
     671         4330092 :     left_range = tree->value + 1;
     672                 : 
     673         4330092 :     return NaClAvlTreeFindValue(tree->right,
     674                 :                                 delta,
     675                 :                                 left_range,
     676                 :                                 value,
     677                 :                                 gap_left);
     678                 :   }
     679        10207549 : }
     680                 : 
     681            1144 : void NaClAvlTreeFree(struct NaClIntervalRangeTreeNode *t) {
     682            1144 :   if (NULL == t) {
     683             574 :     return;
     684                 :   }
     685             570 :   NaClAvlTreeFree(t->left);
     686             570 :   t->left = NULL;
     687             570 :   NaClAvlTreeFree(t->right);
     688             570 :   t->right = NULL;
     689             570 :   free(t);
     690            1714 : }
     691                 : 
     692             299 : int NaClIntervalRangeTreeCtor(struct NaClIntervalRangeTree *self) {
     693             299 :   self->root = NULL;
     694             299 :   self->base.vtbl = &kNaClIntervalRangeTreeVtbl;
     695             299 :   return 1;
     696                 : }
     697                 : 
     698               4 : void NaClIntervalRangeTreeDtor(struct NaClIntervalMultiset *vself) {
     699               4 :   struct NaClIntervalRangeTree  *self = (struct NaClIntervalRangeTree *) vself;
     700                 : 
     701               4 :   NaClAvlTreeFree(self->root);
     702               4 :   self->root = NULL;
     703               4 :   self->base.vtbl = NULL;
     704               4 : }
     705                 : 
     706          302645 : void NaClIntervalRangeTreeAddInterval(struct NaClIntervalMultiset *vself,
     707          302645 :                                       uint32_t first_val, uint32_t last_val) {
     708          302645 :   struct NaClIntervalRangeTree *self;
     709          302645 :   struct NaClIntervalRangeTreeNode *range_start;
     710          302645 :   struct NaClIntervalRangeTreeNode *range_end;
     711                 : 
     712          302645 :   self = (struct NaClIntervalRangeTree *) vself;
     713          302645 :   range_start = NaClIntervalRangeTreeNodeFactory(first_val, 1);
     714          302645 :   range_end = NaClIntervalRangeTreeNodeFactory(last_val, -1);
     715          302645 :   NaClIntervalRangeTreePrint(self->root);
     716          302645 :   (void) NaClAvlTreeInsert(&self->root, range_start);
     717          302645 :   NaClIntervalRangeTreePrint(self->root);
     718          302645 :   (void) NaClAvlTreeInsert(&self->root, range_end);
     719          302645 :   NaClIntervalRangeTreePrint(self->root);
     720          302645 : }
     721                 : 
     722          302358 : void NaClIntervalRangeTreeRemoveInterval(struct NaClIntervalMultiset *vself,
     723          302358 :                                          uint32_t first_val,
     724          302358 :                                          uint32_t last_val) {
     725          302358 :   struct NaClIntervalRangeTree *self = (struct NaClIntervalRangeTree *) vself;
     726                 : 
     727          302358 :   NaClIntervalRangeTreeRemoveVal(self, last_val, -1);
     728          302358 :   NaClIntervalRangeTreeRemoveVal(self, first_val, 1);
     729          302358 : }
     730                 : 
     731          771811 : int NaClIntervalRangeTreeOverlapsWith(struct NaClIntervalMultiset *vself,
     732          771811 :                                       uint32_t first_val, uint32_t last_val) {
     733          771811 :   struct NaClIntervalRangeTree *self = (struct NaClIntervalRangeTree *) vself;
     734          771811 :   uint32_t gap_left_first;
     735          771811 :   uint32_t gap_left_last;
     736                 : 
     737         1543622 :   NaCl_dprintf(("OverlapsWith [%u, %u]\n", first_val, last_val));
     738          771811 :   if (0 != NaClAvlTreeFindValue(self->root, 0, 0, first_val, &gap_left_first)) {
     739          341562 :     NaCl_dprintf(("left not in gap\n"));
     740          170781 :     return 1;
     741                 :   }
     742          601030 :   if (0 != NaClAvlTreeFindValue(self->root, 0, 0, last_val, &gap_left_last)) {
     743          159186 :     NaCl_dprintf(("right not in gap\n"));
     744           79593 :     return 1;
     745                 :   }
     746                 : 
     747         1042874 :   NaCl_dprintf(("gap first %u gap last %u\n", gap_left_first, gap_left_last));
     748          521437 :   if (gap_left_first == gap_left_last) {
     749                 :     /*
     750                 :      * Both first_val and last_val had a containment count of zero,
     751                 :      * and they are in the same gap.
     752                 :      */
     753          492005 :     return 0;
     754                 :   }
     755           29432 :   return 1;
     756          771811 : }
     757                 : 
     758                 : struct NaClIntervalMultisetVtbl const kNaClIntervalRangeTreeVtbl = {
     759                 :   NaClIntervalRangeTreeDtor,
     760                 :   NaClIntervalRangeTreeAddInterval,
     761                 :   NaClIntervalRangeTreeRemoveInterval,
     762                 :   NaClIntervalRangeTreeOverlapsWith,
     763                 : };

Generated by: LCOV version 1.7