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: 338 324 95.9 %
Date: 2014-10-23 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               0 : static INLINE void indent(int depth) {
      75               0 :   while (depth != 0) {
      76               0 :     putchar(' ');
      77               0 :     --depth;
      78                 :   }
      79               0 : }
      80                 : 
      81               0 : static void TreePrint(struct NaClIntervalRangeTreeNode *node,
      82                 :                       int                              depth) {
      83               0 :   if (NULL == node) {
      84               0 :     return;
      85                 :   }
      86                 :   /* rotated head view */
      87               0 :   TreePrint(node->right, depth + 1);
      88               0 :   indent(depth);
      89               0 :   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               0 :   TreePrint(node->left, depth + 1);
      93                 : }
      94                 : 
      95        14968540 : static INLINE void NaClIntervalRangeTreePrint(
      96                 :     struct NaClIntervalRangeTreeNode *node) {
      97                 :   if (!DEBUG_THIS) {
      98        14968540 :     return;
      99                 :   }
     100                 :   putchar('\n');
     101                 :   TreePrint(node, 0);
     102                 :   putchar('\n');
     103                 : }
     104                 : 
     105                 : #define NaCl_dprintf(alist) do { if (DEBUG_THIS) printf alist; } while (0)
     106                 : 
     107         1213440 : static void NaClIntervalRangeTreeNodeInit(
     108                 :     struct NaClIntervalRangeTreeNode *node,
     109                 :     uint32_t value,
     110                 :     int lr) {
     111         1213440 :   node->left = NULL;
     112         1213440 :   node->right = NULL;
     113         1213440 :   node->balance = 0;
     114         1213440 :   node->value = value;
     115         1213440 :   node->value_containment_delta = lr; /* 1 or -1 for L or R */
     116         1213440 :   node->refcount = 1;  /* caller */
     117         1213440 :   node->range_left = value;
     118         1213440 :   node->range_right = value;
     119         1213440 :   node->subtree_containment_delta = lr;
     120         1213440 : }
     121                 : 
     122          607528 : static struct NaClIntervalRangeTreeNode *NaClIntervalRangeTreeNodeFactory(
     123                 :     uint32_t value,
     124                 :     int lr) {
     125                 :   struct NaClIntervalRangeTreeNode *obj;
     126          607528 :   obj = (struct NaClIntervalRangeTreeNode *) malloc(sizeof *obj);
     127          607528 :   if (NULL == obj) {
     128               0 :     NaClLog(LOG_FATAL, "NaClIntervalRangeTreeNodeFactory: out of memory!\n");
     129                 :   }
     130          607528 :   NaClIntervalRangeTreeNodeInit(obj, value, lr);
     131          607528 :   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         7981729 : static void NaClRangeStatsUpdate(struct NaClIntervalRangeTreeNode *node) {
     140         7981729 :   uint32_t range_left = node->value;
     141         7981729 :   uint32_t range_right = node->value;
     142         7981729 :   uint32_t cumulative_delta = node->value_containment_delta;
     143                 : 
     144         7981729 :   if (NULL != node->left) {
     145         7077628 :     range_left = node->left->range_left;
     146         7077628 :     cumulative_delta += node->left->subtree_containment_delta;
     147                 :   }
     148         7981729 :   if (NULL != node->right) {
     149         7243623 :     range_right = node->right->range_right;
     150         7243623 :     cumulative_delta += node->right->subtree_containment_delta;
     151                 :   }
     152         7981729 :   node->range_left = range_left;
     153         7981729 :   node->range_right = range_right;
     154         7981729 :   node->subtree_containment_delta = cumulative_delta;
     155         7981729 : }
     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         4572913 : static int NaClAvlTreeInsert(struct NaClIntervalRangeTreeNode **treep,
     164                 :                              struct NaClIntervalRangeTreeNode *node) {
     165                 :   struct NaClIntervalRangeTreeNode *tmp;
     166                 :   struct NaClIntervalRangeTreeNode *tmp_l;
     167                 :   struct NaClIntervalRangeTreeNode *tmp_r;
     168                 :   int higher;
     169                 : 
     170         4572913 :   if (NULL == (tmp = *treep)) {
     171          605972 :     *treep = node;
     172          605972 :     return 1;
     173                 :   }
     174         3966941 :   if (node->value == tmp->value) {
     175            1556 :     tmp->value_containment_delta += node->value_containment_delta;
     176            1556 :     tmp->subtree_containment_delta += node->value_containment_delta;
     177            1556 :     tmp->refcount++;
     178            1556 :     free(node);
     179            1556 :     return 0;
     180         3965385 :   } else if (node->value < tmp->value) {
     181                 :     /* recurse left. */
     182         1896084 :     higher = NaClAvlTreeInsert(&tmp->left, node);
     183         1896084 :     if (!higher) {
     184         1293809 :       NaClRangeStatsUpdate(tmp);
     185         1293809 :       return 0;
     186                 :     }
     187          602275 :     --tmp->balance;
     188          602275 :     if (0 == tmp->balance) {
     189                 :       /* height unchanged */
     190          119778 :       NaClRangeStatsUpdate(tmp);
     191          119778 :       return 0;
     192                 :     }
     193          482497 :     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          366166 :       NaClRangeStatsUpdate(tmp);
     199          366166 :       return 1;
     200                 :     }
     201                 :     /* pivot */
     202          116331 :     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           48200 :       *treep = tmp->left;
     213           48200 :       tmp->left = (*treep)->right;
     214           48200 :       (*treep)->right = tmp;
     215           48200 :       (*treep)->balance = 0;
     216           48200 :       tmp->balance = 0;
     217                 : 
     218           48200 :       tmp = *treep;  /* b */
     219           48200 :       NaClRangeStatsUpdate(tmp->right);  /* d */
     220           48200 :       NaClRangeStatsUpdate(tmp);
     221           48200 :       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           68131 :       tmp = (*treep)->left->right;
     234           68131 :       tmp_l = tmp->left;
     235           68131 :       tmp_r = tmp->right;
     236           68131 :       tmp->left = (*treep)->left;
     237           68131 :       tmp->right = (*treep);
     238           68131 :       *treep = tmp;
     239           68131 :       tmp->left->right = tmp_l;
     240           68131 :       tmp->right->left = tmp_r;
     241           68131 :       tmp->left->balance = (tmp->balance <= 0) ? 0 : -1;
     242           68131 :       tmp->right->balance = (tmp->balance >= 0) ? 0 : 1;
     243           68131 :       tmp->balance = 0;
     244           68131 :       NaClRangeStatsUpdate(tmp->left);
     245           68131 :       NaClRangeStatsUpdate(tmp->right);
     246           68131 :       NaClRangeStatsUpdate(tmp);
     247           68131 :       return 0;
     248                 :     }
     249                 :   } else {
     250                 :     /* node->value > tmp->value */
     251         2069301 :     higher = NaClAvlTreeInsert(&tmp->right, node);
     252         2069301 :     if (!higher) {
     253         1297133 :       NaClRangeStatsUpdate(tmp);
     254         1297133 :       return 0;
     255                 :     }
     256          772168 :     ++tmp->balance;
     257          772168 :     if (0 == tmp->balance) {
     258                 :       /* height unchanged */
     259          107132 :       NaClRangeStatsUpdate(tmp);
     260          107132 :       return 0;
     261                 :     }
     262          665036 :     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          537637 :       NaClRangeStatsUpdate(tmp);
     268          537637 :       return 1;
     269                 :     }
     270                 :     /* pivot */
     271          127399 :     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           90935 :       *treep = tmp->right;
     282           90935 :       tmp->right = (*treep)->left;
     283           90935 :       (*treep)->left = tmp;
     284           90935 :       (*treep)->balance = 0;
     285           90935 :       tmp->balance = 0;
     286                 : 
     287           90935 :       tmp = *treep;
     288           90935 :       NaClRangeStatsUpdate(tmp->left);
     289           90935 :       NaClRangeStatsUpdate(tmp);
     290           90935 :       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           36464 :       tmp = (*treep)->right->left;
     303           36464 :       tmp_l = tmp->left;
     304           36464 :       tmp_r = tmp->right;
     305           36464 :       tmp->right = (*treep)->right;
     306           36464 :       tmp->left = (*treep);
     307           36464 :       *treep = tmp;
     308           36464 :       tmp->right->left = tmp_r;
     309           36464 :       tmp->left->right = tmp_l;
     310           36464 :       tmp->right->balance = (tmp->balance >= 0) ? 0 : 1;
     311           36464 :       tmp->left->balance = (tmp->balance <= 0) ? 0 : -1;
     312           36464 :       tmp->balance = 0;
     313           36464 :       NaClRangeStatsUpdate(tmp->right);
     314           36464 :       NaClRangeStatsUpdate(tmp->left);
     315           36464 :       NaClRangeStatsUpdate(tmp);
     316           36464 :       return 0;
     317                 :     }
     318                 :   }
     319                 : }
     320                 : 
     321                 : /*
     322                 :  * NaClAvlTreeBalanceLeft -- left subtree shrunk.  Adjust balance of
     323                 :  * node, possibly rebalancing.
     324                 :  */
     325          403466 : static void NaClAvlTreeBalanceLeft(
     326                 :     struct NaClIntervalRangeTreeNode **treep,
     327                 :     int *height_changed) {
     328                 :   int bal;
     329                 :   struct NaClIntervalRangeTreeNode *tmp;
     330                 :   struct NaClIntervalRangeTreeNode *tmp_l;
     331                 :   struct NaClIntervalRangeTreeNode *tmp_r;
     332                 : 
     333          403466 :   bal = ++(*treep)->balance;
     334          403466 :   if (0 == bal) {
     335          127643 :     return;
     336                 :   }
     337          275823 :   if (1 == bal) {
     338          217898 :     *height_changed = 0;
     339          217898 :     return;
     340                 :   }
     341                 :   /* Rebalance needed. */
     342           57925 :   tmp = (*treep)->right;
     343           57925 :   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           40742 :     (*treep)->right = tmp->left;
     354           40742 :     tmp->left = (*treep);
     355           40742 :     *treep = tmp;
     356           40742 :     if (0 == tmp->balance) {
     357           22738 :       tmp->balance = -1;
     358           22738 :       tmp->left->balance = 1;
     359           22738 :       *height_changed = 0;
     360                 :     } else {
     361           18004 :       tmp->balance = 0;
     362           18004 :       tmp->left->balance = 0;
     363                 :     }
     364           40742 :     NaClRangeStatsUpdate(tmp->left);
     365           40742 :     NaClRangeStatsUpdate(tmp);
     366                 :   } 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           17183 :     tmp = tmp->left;  /* d */
     378           17183 :     tmp_l = tmp->left;
     379           17183 :     tmp_r = tmp->right;
     380           17183 :     tmp->left = *treep;
     381           17183 :     tmp->right = (*treep)->right;
     382           17183 :     *treep = tmp;
     383           17183 :     tmp->left->right = tmp_l;
     384           17183 :     tmp->right->left = tmp_r;
     385           17183 :     tmp->left->balance = (tmp->balance > 0) ? -1 : 0;
     386           17183 :     tmp->right->balance = (tmp->balance < 0) ? 1 : 0;
     387           17183 :     tmp->balance = 0;
     388                 :     /*
     389                 :      * *h == 1 remains true.
     390                 :      */
     391           17183 :     NaClRangeStatsUpdate(tmp->left);
     392           17183 :     NaClRangeStatsUpdate(tmp->right);
     393           17183 :     NaClRangeStatsUpdate(tmp);
     394                 :   }
     395                 : }
     396                 : 
     397                 : /*
     398                 :  * NaClAvlTreeBalanceRight -- right subtree shrunk.  Adjust balance of
     399                 :  * node, possibly rebalancing.
     400                 :  */
     401          505054 : static void NaClAvlTreeBalanceRight(
     402                 :     struct NaClIntervalRangeTreeNode **treep,
     403                 :     int *height_changed) {
     404                 :   int bal;
     405                 :   struct NaClIntervalRangeTreeNode *tmp;
     406                 :   struct NaClIntervalRangeTreeNode *tmp_l;
     407                 :   struct NaClIntervalRangeTreeNode *tmp_r;
     408                 : 
     409          505054 :   bal = --(*treep)->balance;
     410          505054 :   if (0 == bal) {
     411          233126 :     return;
     412                 :   }
     413          271928 :   if (-1 == bal) {
     414          205308 :     *height_changed = 0;
     415          205308 :     return;
     416                 :   }
     417                 :   /* Rebalance needed. */
     418           66620 :   tmp = (*treep)->left;
     419           66620 :   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           40168 :     (*treep)->left = tmp->right;
     431           40168 :     tmp->right = (*treep);
     432           40168 :     *treep = tmp;
     433           40168 :     if (0 == tmp->balance) {
     434           23116 :       tmp->balance = 1;
     435           23116 :       tmp->right->balance = -1;
     436           23116 :       *height_changed = 0;
     437                 :     } else {
     438           17052 :       tmp->balance = 0;
     439           17052 :       tmp->right->balance = 0;
     440                 :     }
     441           40168 :     NaClRangeStatsUpdate(tmp->right);
     442           40168 :     NaClRangeStatsUpdate(tmp);
     443                 :   } 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           26452 :     tmp = tmp->right;  /* d */
     455           26452 :     tmp_l = tmp->left;
     456           26452 :     tmp_r = tmp->right;
     457           26452 :     tmp->left = (*treep)->left;
     458           26452 :     tmp->right = *treep;
     459           26452 :     *treep = tmp;
     460           26452 :     tmp->left->right = tmp_l;
     461           26452 :     tmp->right->left = tmp_r;
     462           26452 :     tmp->left->balance = (tmp->balance > 0) ? -1 : 0;
     463           26452 :     tmp->right->balance = (tmp->balance < 0) ? 1 : 0;
     464           26452 :     tmp->balance = 0;
     465                 :     /*
     466                 :      * *h == 1 remains true.
     467                 :      */
     468           26452 :     NaClRangeStatsUpdate(tmp->left);
     469           26452 :     NaClRangeStatsUpdate(tmp->right);
     470           26452 :     NaClRangeStatsUpdate(tmp);
     471                 :   }
     472                 : }
     473                 : 
     474          330134 : static struct NaClIntervalRangeTreeNode *NaClAvlFindRightMost(
     475                 :     struct NaClIntervalRangeTreeNode **treep,
     476                 :     int *height_changed) {
     477                 :   struct NaClIntervalRangeTreeNode *tmp;
     478                 : 
     479          330134 :   if (NULL != (*treep)->right) {
     480          182220 :     tmp = NaClAvlFindRightMost(&(*treep)->right, height_changed);
     481          182220 :     NaClRangeStatsUpdate(*treep);
     482          182220 :     if (*height_changed) {
     483          121738 :       NaClAvlTreeBalanceRight(treep, height_changed);
     484                 :     }
     485          182220 :     return tmp;
     486                 :   }
     487          147914 :   tmp = *treep;
     488          147914 :   *treep = tmp->left;
     489          147914 :   *height_changed = 1;
     490          147914 :   return tmp;
     491                 : }
     492                 : 
     493           92256 : static struct NaClIntervalRangeTreeNode *NaClAvlFindLeftMost(
     494                 :     struct NaClIntervalRangeTreeNode **treep,
     495                 :     int *height_changed) {
     496                 :   struct NaClIntervalRangeTreeNode *tmp;
     497                 : 
     498           92256 :   if (NULL != (*treep)->left) {
     499           52478 :     tmp = NaClAvlFindLeftMost(&(*treep)->left, height_changed);
     500           52478 :     NaClRangeStatsUpdate(*treep);
     501           52478 :     if (*height_changed) {
     502           36212 :       NaClAvlTreeBalanceLeft(treep, height_changed);
     503                 :     }
     504           52478 :     return tmp;
     505                 :   }
     506           39778 :   tmp = *treep;
     507           39778 :   *treep = tmp->right;
     508           39778 :   *height_changed = 1;
     509           39778 :   return tmp;
     510                 : }
     511                 : 
     512         3558816 : static struct NaClIntervalRangeTreeNode *NaClAvlTreeExtract(
     513                 :     struct NaClIntervalRangeTreeNode **treep,
     514                 :     struct NaClIntervalRangeTreeNode *key,
     515                 :     int *height_changed) {
     516                 :   struct NaClIntervalRangeTreeNode *p;
     517                 :   struct NaClIntervalRangeTreeNode *tmp;
     518                 : 
     519         3558816 :   if (NULL == *treep) {
     520               0 :     NaClLog(LOG_FATAL, "NaClAvlTreeExtract: node not found\n");
     521                 :   }
     522                 :   NaCl_dprintf(("TreeExtract k->v %u, k->d %d, h %d\n",
     523                 :            key->value, key->value_containment_delta, *height_changed));
     524         3558816 :   NaClIntervalRangeTreePrint(*treep);
     525         3558816 :   if (key->value < (*treep)->value) {
     526         1417355 :     p = NaClAvlTreeExtract(&(*treep)->left, key, height_changed);
     527         1417355 :     NaClRangeStatsUpdate(*treep);
     528         1417355 :     if (*height_changed) {
     529          283767 :       NaClAvlTreeBalanceLeft(treep, height_changed);
     530                 :     }
     531         1417355 :     return p;
     532         2141461 :   } else if (key->value > (*treep)->value) {
     533         1535549 :     p = NaClAvlTreeExtract(&(*treep)->right, key, height_changed);
     534         1535549 :     NaClRangeStatsUpdate(*treep);
     535         1535549 :     if (*height_changed) {
     536          361107 :       NaClAvlTreeBalanceRight(treep, height_changed);
     537                 :     }
     538         1535549 :     return p;
     539                 :   } else {
     540                 :     /*
     541                 :      * found elt
     542                 :      */
     543          605912 :     p = *treep;
     544          605912 :     if (0 != --p->refcount) {
     545            1556 :       p->value_containment_delta -= key->value_containment_delta;
     546            1556 :       p->subtree_containment_delta -= key->value_containment_delta;
     547            1556 :       return NULL;
     548                 :     }
     549                 :     /* zero refcount, should delete */
     550          604356 :     if (NULL == p->right) {
     551          385251 :       *treep = p->left;
     552          385251 :       *height_changed = 1;
     553          219105 :     } else if (NULL == p->left) {
     554           31413 :       *treep = p->right;
     555           31413 :       *height_changed = 1;
     556          187692 :     } else if (p->balance <= 0) {
     557          147914 :       tmp = NaClAvlFindRightMost(&p->left, height_changed);
     558          147914 :       tmp->left = p->left;
     559          147914 :       tmp->right = p->right;
     560          147914 :       tmp->balance = p->balance;
     561          147914 :       NaClRangeStatsUpdate(tmp);
     562          147914 :       *treep = tmp;
     563          147914 :       if (*height_changed) {
     564           83487 :         NaClAvlTreeBalanceLeft(treep, height_changed);
     565                 :       }
     566                 :     } else {
     567           39778 :       tmp = NaClAvlFindLeftMost(&p->right, height_changed);
     568           39778 :       tmp->left = p->left;
     569           39778 :       tmp->right = p->right;
     570           39778 :       tmp->balance = p->balance;
     571           39778 :       NaClRangeStatsUpdate(tmp);
     572           39778 :       *treep = tmp;
     573           39778 :       if (*height_changed) {
     574           22209 :         NaClAvlTreeBalanceRight(treep, height_changed);
     575                 :       }
     576                 :     }
     577          604356 :     p->left = NULL;
     578          604356 :     p->right = NULL;
     579          604356 :     return p;
     580                 :   }
     581                 : }
     582                 : 
     583          605912 : static struct NaClIntervalRangeTreeNode *NaClIntervalRangeTreeExtract(
     584                 :     struct NaClIntervalRangeTree *self,
     585                 :     struct NaClIntervalRangeTreeNode *keyp) {
     586          605912 :   int height_changed = 0;
     587                 : 
     588          605912 :   return NaClAvlTreeExtract(&self->root, keyp, &height_changed);
     589                 : }
     590                 : 
     591          605912 : static void NaClIntervalRangeTreeRemoveVal(struct NaClIntervalRangeTree *self,
     592                 :                                            uint32_t value,
     593                 :                                            int lr) {
     594                 :   struct NaClIntervalRangeTreeNode key;
     595                 :   struct NaClIntervalRangeTreeNode *zero_ref_node;
     596                 : 
     597                 :   NaCl_dprintf(("RemoveVal %u %d\n", value, lr));
     598          605912 :   NaClIntervalRangeTreeNodeInit(&key, value, lr);
     599          605912 :   zero_ref_node = NaClIntervalRangeTreeExtract(self, &key);
     600          605912 :   if (NULL != zero_ref_node) {
     601          604356 :     free(zero_ref_node);
     602                 :   }
     603                 :   NaCl_dprintf(("result tree\n"));
     604          605912 :   NaClIntervalRangeTreePrint(self->root);
     605          605912 : }
     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         9892520 : static uint32_t NaClAvlTreeFindValue(
     626                 :     struct NaClIntervalRangeTreeNode *tree,
     627                 :     uint32_t left_delta,
     628                 :     uint32_t left_range,
     629                 :     uint32_t value,
     630                 :     uint32_t *gap_left) {
     631                 :   uint32_t delta;
     632                 : 
     633                 :   NaCl_dprintf(("TreeFind ld %u lr %u v %u\n", left_delta, left_range, value));
     634         9892520 :   NaClIntervalRangeTreePrint(tree);
     635         9892520 :   if (NULL == tree) {
     636         1540363 :     *gap_left = left_range;
     637         1540363 :     return left_delta;
     638                 :   }
     639         8352157 :   if (value < tree->value) {
     640         4235489 :     return NaClAvlTreeFindValue(tree->left, left_delta, left_range, value,
     641                 :                                 gap_left);
     642         4116668 :   } 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                 :     }
     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                 :     }
     662                 : 
     663                 :     /* *gap_left undefined */
     664              32 :     return delta;
     665                 :   } else {
     666         4116636 :     delta = left_delta;
     667         4116636 :     if (NULL != tree->left) {
     668         3588828 :       delta += tree->left->subtree_containment_delta;
     669                 :     }
     670         4116636 :     delta += tree->value_containment_delta;
     671         4116636 :     left_range = tree->value + 1;
     672                 : 
     673         4116636 :     return NaClAvlTreeFindValue(tree->right,
     674                 :                                 delta,
     675                 :                                 left_range,
     676                 :                                 value,
     677                 :                                 gap_left);
     678                 :   }
     679                 : }
     680                 : 
     681            3228 : void NaClAvlTreeFree(struct NaClIntervalRangeTreeNode *t) {
     682            3228 :   if (NULL == t) {
     683            4844 :     return;
     684                 :   }
     685            1612 :   NaClAvlTreeFree(t->left);
     686            1612 :   t->left = NULL;
     687            1612 :   NaClAvlTreeFree(t->right);
     688            1612 :   t->right = NULL;
     689            1612 :   free(t);
     690                 : }
     691                 : 
     692             316 : int NaClIntervalRangeTreeCtor(struct NaClIntervalRangeTree *self) {
     693             316 :   self->root = NULL;
     694             316 :   self->base.vtbl = &kNaClIntervalRangeTreeVtbl;
     695             316 :   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          303764 : void NaClIntervalRangeTreeAddInterval(struct NaClIntervalMultiset *vself,
     707                 :                                       uint32_t first_val, uint32_t last_val) {
     708                 :   struct NaClIntervalRangeTree *self;
     709                 :   struct NaClIntervalRangeTreeNode *range_start;
     710                 :   struct NaClIntervalRangeTreeNode *range_end;
     711                 : 
     712          303764 :   self = (struct NaClIntervalRangeTree *) vself;
     713          303764 :   range_start = NaClIntervalRangeTreeNodeFactory(first_val, 1);
     714          303764 :   range_end = NaClIntervalRangeTreeNodeFactory(last_val, -1);
     715          303764 :   NaClIntervalRangeTreePrint(self->root);
     716          303764 :   (void) NaClAvlTreeInsert(&self->root, range_start);
     717          303764 :   NaClIntervalRangeTreePrint(self->root);
     718          303764 :   (void) NaClAvlTreeInsert(&self->root, range_end);
     719          303764 :   NaClIntervalRangeTreePrint(self->root);
     720          303764 : }
     721                 : 
     722          302956 : void NaClIntervalRangeTreeRemoveInterval(struct NaClIntervalMultiset *vself,
     723                 :                                          uint32_t first_val,
     724                 :                                          uint32_t last_val) {
     725          302956 :   struct NaClIntervalRangeTree *self = (struct NaClIntervalRangeTree *) vself;
     726                 : 
     727          302956 :   NaClIntervalRangeTreeRemoveVal(self, last_val, -1);
     728          302956 :   NaClIntervalRangeTreeRemoveVal(self, first_val, 1);
     729          302956 : }
     730                 : 
     731          897474 : int NaClIntervalRangeTreeOverlapsWith(struct NaClIntervalMultiset *vself,
     732                 :                                       uint32_t first_val, uint32_t last_val) {
     733          897474 :   struct NaClIntervalRangeTree *self = (struct NaClIntervalRangeTree *) vself;
     734                 :   uint32_t gap_left_first;
     735                 :   uint32_t gap_left_last;
     736                 : 
     737                 :   NaCl_dprintf(("OverlapsWith [%u, %u]\n", first_val, last_val));
     738          897474 :   if (0 != NaClAvlTreeFindValue(self->root, 0, 0, first_val, &gap_left_first)) {
     739                 :     NaCl_dprintf(("left not in gap\n"));
     740          254553 :     return 1;
     741                 :   }
     742          642921 :   if (0 != NaClAvlTreeFindValue(self->root, 0, 0, last_val, &gap_left_last)) {
     743                 :     NaCl_dprintf(("right not in gap\n"));
     744           78706 :     return 1;
     745                 :   }
     746                 : 
     747                 :   NaCl_dprintf(("gap first %u gap last %u\n", gap_left_first, gap_left_last));
     748          564215 :   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          541043 :     return 0;
     754                 :   }
     755           23172 :   return 1;
     756                 : }
     757                 : 
     758                 : struct NaClIntervalMultisetVtbl const kNaClIntervalRangeTreeVtbl = {
     759                 :   NaClIntervalRangeTreeDtor,
     760                 :   NaClIntervalRangeTreeAddInterval,
     761                 :   NaClIntervalRangeTreeRemoveInterval,
     762                 :   NaClIntervalRangeTreeOverlapsWith,
     763                 : };

Generated by: LCOV version 1.7