(root)/
gcc-13.2.0/
gcc/
typed-splay-tree.h
       1  /* A typesafe wrapper around libiberty's splay-tree.h.
       2     Copyright (C) 2015-2023 Free Software Foundation, Inc.
       3  
       4  This file is part of GCC.
       5  
       6  GCC is free software; you can redistribute it and/or modify it under
       7  the terms of the GNU General Public License as published by the Free
       8  Software Foundation; either version 3, or (at your option) any later
       9  version.
      10  
      11  GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12  WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14  for more details.
      15  
      16  You should have received a copy of the GNU General Public License
      17  along with GCC; see the file COPYING3.  If not see
      18  <http://www.gnu.org/licenses/>.  */
      19  
      20  #ifndef GCC_TYPED_SPLAY_TREE_H
      21  #define GCC_TYPED_SPLAY_TREE_H
      22  
      23  /* Typesafe wrapper around libiberty's splay-tree.h.  */
      24  template <typename KEY_TYPE, typename VALUE_TYPE>
      25  class typed_splay_tree
      26  {
      27   public:
      28    typedef KEY_TYPE key_type;
      29    typedef VALUE_TYPE value_type;
      30  
      31    typedef int (*compare_fn) (key_type, key_type);
      32    typedef void (*delete_key_fn) (key_type);
      33    typedef void (*delete_value_fn) (value_type);
      34    typedef int (*foreach_fn) (key_type, value_type, void *);
      35  
      36    typed_splay_tree (compare_fn,
      37  		    delete_key_fn,
      38  		    delete_value_fn);
      39    ~typed_splay_tree ();
      40  
      41    value_type lookup (key_type k);
      42    value_type predecessor (key_type k);
      43    value_type successor (key_type k);
      44    void insert (key_type k, value_type v);
      45    void remove (key_type k);
      46    value_type max ();
      47    value_type min ();
      48    int foreach (foreach_fn, void *);
      49  
      50   private:
      51    /* Copy and assignment ops are not supported.  */
      52    typed_splay_tree (const typed_splay_tree &);
      53    typed_splay_tree & operator = (const typed_splay_tree &);
      54  
      55    typedef key_type splay_tree_key;
      56    typedef value_type splay_tree_value;
      57  
      58    /* The nodes in the splay tree.  */
      59    struct splay_tree_node_s {
      60      /* The key.  */
      61      splay_tree_key key;
      62  
      63      /* The value.  */
      64      splay_tree_value value;
      65  
      66      /* The left and right children, respectively.  */
      67      splay_tree_node_s *left, *right;
      68  
      69      /* Used as temporary value for tree traversals.  */
      70      splay_tree_node_s *back;
      71    };
      72    typedef splay_tree_node_s *splay_tree_node;
      73  
      74    inline void KDEL (splay_tree_key);
      75    inline void VDEL (splay_tree_value);
      76    void splay_tree_delete_helper (splay_tree_node);
      77    static inline void rotate_left (splay_tree_node *,
      78  				  splay_tree_node, splay_tree_node);
      79    static inline void rotate_right (splay_tree_node *,
      80  				   splay_tree_node, splay_tree_node);
      81    void splay_tree_splay (splay_tree_key);
      82    static int splay_tree_foreach_helper (splay_tree_node,
      83  					foreach_fn, void*);
      84    splay_tree_node splay_tree_insert (splay_tree_key, splay_tree_value);
      85    void splay_tree_remove (splay_tree_key key);
      86    splay_tree_node splay_tree_lookup (splay_tree_key key);
      87    splay_tree_node splay_tree_predecessor (splay_tree_key);
      88    splay_tree_node splay_tree_successor (splay_tree_key);
      89    splay_tree_node splay_tree_max ();
      90    splay_tree_node splay_tree_min ();
      91  
      92    static value_type node_to_value (splay_tree_node node);
      93  
      94    /* The root of the tree.  */
      95    splay_tree_node root;
      96  
      97    /* The comparision function.  */
      98    compare_fn comp;
      99  
     100    /* The deallocate-key function.  NULL if no cleanup is necessary.  */
     101    delete_key_fn delete_key;
     102  
     103    /* The deallocate-value function.  NULL if no cleanup is necessary.  */
     104    delete_value_fn delete_value;
     105  };
     106  
     107  /* Constructor for typed_splay_tree <K, V>.  */
     108  
     109  template <typename KEY_TYPE, typename VALUE_TYPE>
     110  inline typed_splay_tree<KEY_TYPE, VALUE_TYPE>::
     111    typed_splay_tree (compare_fn compare_fn,
     112  		    delete_key_fn delete_key_fn,
     113  		    delete_value_fn delete_value_fn)
     114  {
     115    root = NULL;
     116    comp = compare_fn;
     117    delete_key = delete_key_fn;
     118    delete_value = delete_value_fn;
     119  }
     120  
     121  /* Destructor for typed_splay_tree <K, V>.  */
     122  
     123  template <typename KEY_TYPE, typename VALUE_TYPE>
     124  inline typed_splay_tree<KEY_TYPE, VALUE_TYPE>::
     125    ~typed_splay_tree ()
     126  {
     127    splay_tree_delete_helper (root);
     128  }
     129  
     130  /* Lookup KEY, returning a value if present, and NULL
     131     otherwise.  */
     132  
     133  template <typename KEY_TYPE, typename VALUE_TYPE>
     134  inline VALUE_TYPE
     135  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::lookup (key_type key)
     136  {
     137    splay_tree_node node = splay_tree_lookup (key);
     138    return node_to_value (node);
     139  }
     140  
     141  /* Return the immediate predecessor of KEY, or NULL if there is no
     142     predecessor.  KEY need not be present in the tree.  */
     143  
     144  template <typename KEY_TYPE, typename VALUE_TYPE>
     145  inline VALUE_TYPE
     146  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::predecessor (key_type key)
     147  {
     148    splay_tree_node node = splay_tree_predecessor (key);
     149    return node_to_value (node);
     150  }
     151  
     152  /* Return the immediate successor of KEY, or NULL if there is no
     153     successor.  KEY need not be present in the tree.  */
     154  
     155  template <typename KEY_TYPE, typename VALUE_TYPE>
     156  inline VALUE_TYPE
     157  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::successor (key_type key)
     158  {
     159    splay_tree_node node = splay_tree_successor (key);
     160    return node_to_value (node);
     161  }
     162  
     163  /* Insert a new node (associating KEY with VALUE).  If a
     164     previous node with the indicated KEY exists, its data is replaced
     165     with the new value.  */
     166  
     167  template <typename KEY_TYPE, typename VALUE_TYPE>
     168  inline void
     169  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::insert (key_type key,
     170  						value_type value)
     171  {
     172    splay_tree_insert (key, value);
     173  }
     174  
     175  /* Remove a node (associating KEY with VALUE).  */
     176  
     177  template <typename KEY_TYPE, typename VALUE_TYPE>
     178  inline void
     179  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::remove (key_type key)
     180  {
     181    splay_tree_remove (key);
     182  }
     183  
     184  /* Get the value with maximal key.  */
     185  
     186  template <typename KEY_TYPE, typename VALUE_TYPE>
     187  inline VALUE_TYPE
     188  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::max ()
     189  {
     190    return node_to_value (splay_tree_max ());
     191  }
     192  
     193  /* Get the value with minimal key.  */
     194  
     195  template <typename KEY_TYPE, typename VALUE_TYPE>
     196  inline VALUE_TYPE
     197  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::min ()
     198  {
     199    return node_to_value (splay_tree_min ());
     200  }
     201  
     202  /* Call OUTER_CB, passing it the OUTER_USER_DATA, for every node,
     203     following an in-order traversal.  If OUTER_CB ever returns a non-zero
     204     value, the iteration ceases immediately, and the value is returned.
     205     Otherwise, this function returns 0.  */
     206  
     207  template <typename KEY_TYPE, typename VALUE_TYPE>
     208  inline int
     209  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::foreach (foreach_fn foreach_fn,
     210  						 void *user_data)
     211  {
     212    return splay_tree_foreach_helper (root, foreach_fn, user_data);
     213  }
     214  
     215  /* Internal function for converting from splay_tree_node to
     216     VALUE_TYPE.  */
     217  template <typename KEY_TYPE, typename VALUE_TYPE>
     218  inline VALUE_TYPE
     219  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::node_to_value (splay_tree_node node)
     220  {
     221    if (node)
     222      return node->value;
     223    else
     224      return 0;
     225  }
     226  
     227  template <typename KEY_TYPE, typename VALUE_TYPE>
     228  inline void
     229  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::KDEL(splay_tree_key x)
     230  {
     231    if (delete_key)
     232      (*delete_key)(x);
     233  }
     234  
     235  template <typename KEY_TYPE, typename VALUE_TYPE>
     236  inline void
     237  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::VDEL(splay_tree_value x)
     238  {
     239    if (delete_value)
     240      (*delete_value)(x);
     241  }
     242  
     243  /* Deallocate NODE (a member of SP), and all its sub-trees.  */
     244  
     245  template <typename KEY_TYPE, typename VALUE_TYPE>
     246  void
     247  typed_splay_tree<KEY_TYPE,
     248  		 VALUE_TYPE>::splay_tree_delete_helper (splay_tree_node node)
     249  {
     250    splay_tree_node pending = NULL;
     251    splay_tree_node active = NULL;
     252  
     253    if (!node)
     254      return;
     255  
     256    KDEL (node->key);
     257    VDEL (node->value);
     258  
     259    /* We use the "back" field to hold the "next" pointer.  */
     260    node->back = pending;
     261    pending = node;
     262  
     263    /* Now, keep processing the pending list until there aren't any
     264       more.  This is a little more complicated than just recursing, but
     265       it doesn't toast the stack for large trees.  */
     266  
     267    while (pending)
     268      {
     269        active = pending;
     270        pending = NULL;
     271        while (active)
     272  	{
     273  	  splay_tree_node temp;
     274  
     275  	  /* active points to a node which has its key and value
     276  	     deallocated, we just need to process left and right.  */
     277  
     278  	  if (active->left)
     279  	    {
     280  	      KDEL (active->left->key);
     281  	      VDEL (active->left->value);
     282  	      active->left->back = pending;
     283  	      pending = active->left;
     284  	    }
     285  	  if (active->right)
     286  	    {
     287  	      KDEL (active->right->key);
     288  	      VDEL (active->right->value);
     289  	      active->right->back = pending;
     290  	      pending = active->right;
     291  	    }
     292  
     293  	  temp = active;
     294  	  active = temp->back;
     295  	  delete temp;
     296  	}
     297      }
     298  }
     299  
     300  /* Rotate the edge joining the left child N with its parent P.  PP is the
     301     grandparents' pointer to P.  */
     302  
     303  template <typename KEY_TYPE, typename VALUE_TYPE>
     304  inline void
     305  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::rotate_left (splay_tree_node *pp,
     306  						     splay_tree_node p,
     307  						     splay_tree_node n)
     308  {
     309    splay_tree_node tmp;
     310    tmp = n->right;
     311    n->right = p;
     312    p->left = tmp;
     313    *pp = n;
     314  }
     315  
     316  /* Rotate the edge joining the right child N with its parent P.  PP is the
     317     grandparents' pointer to P.  */
     318  
     319  template <typename KEY_TYPE, typename VALUE_TYPE>
     320  inline void
     321  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::rotate_right (splay_tree_node *pp,
     322  						      splay_tree_node p,
     323  						      splay_tree_node n)
     324  {
     325    splay_tree_node tmp;
     326    tmp = n->left;
     327    n->left = p;
     328    p->right = tmp;
     329    *pp = n;
     330  }
     331  
     332  /* Bottom up splay of key.  */
     333  
     334  template <typename KEY_TYPE, typename VALUE_TYPE>
     335  void
     336  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_splay (splay_tree_key key)
     337  {
     338    if (root == NULL)
     339      return;
     340  
     341    do {
     342      int cmp1, cmp2;
     343      splay_tree_node n, c;
     344  
     345      n = root;
     346      cmp1 = (*comp) (key, n->key);
     347  
     348      /* Found.  */
     349      if (cmp1 == 0)
     350        return;
     351  
     352      /* Left or right?  If no child, then we're done.  */
     353      if (cmp1 < 0)
     354        c = n->left;
     355      else
     356        c = n->right;
     357      if (!c)
     358        return;
     359  
     360      /* Next one left or right?  If found or no child, we're done
     361         after one rotation.  */
     362      cmp2 = (*comp) (key, c->key);
     363      if (cmp2 == 0
     364  	|| (cmp2 < 0 && !c->left)
     365  	|| (cmp2 > 0 && !c->right))
     366        {
     367  	if (cmp1 < 0)
     368  	  rotate_left (&root, n, c);
     369  	else
     370  	  rotate_right (&root, n, c);
     371  	return;
     372        }
     373  
     374      /* Now we have the four cases of double-rotation.  */
     375      if (cmp1 < 0 && cmp2 < 0)
     376        {
     377  	rotate_left (&n->left, c, c->left);
     378  	rotate_left (&root, n, n->left);
     379        }
     380      else if (cmp1 > 0 && cmp2 > 0)
     381        {
     382  	rotate_right (&n->right, c, c->right);
     383  	rotate_right (&root, n, n->right);
     384        }
     385      else if (cmp1 < 0 && cmp2 > 0)
     386        {
     387  	rotate_right (&n->left, c, c->right);
     388  	rotate_left (&root, n, n->left);
     389        }
     390      else if (cmp1 > 0 && cmp2 < 0)
     391        {
     392  	rotate_left (&n->right, c, c->left);
     393  	rotate_right (&root, n, n->right);
     394        }
     395    } while (1);
     396  }
     397  
     398  /* Call FN, passing it the DATA, for every node below NODE, all of
     399     which are from SP, following an in-order traversal.  If FN every
     400     returns a non-zero value, the iteration ceases immediately, and the
     401     value is returned.  Otherwise, this function returns 0.  */
     402  
     403  template <typename KEY_TYPE, typename VALUE_TYPE>
     404  int
     405  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_foreach_helper (
     406  						splay_tree_node node,
     407  						foreach_fn fn, void *data)
     408  {
     409    int val;
     410    splay_tree_node stack;
     411  
     412    /* A non-recursive implementation is used to avoid filling the stack
     413       for large trees.  Splay trees are worst case O(n) in the depth of
     414       the tree.  */
     415  
     416    stack = NULL;
     417    val = 0;
     418  
     419    for (;;)
     420      {
     421        while (node != NULL)
     422  	{
     423  	  node->back = stack;
     424  	  stack = node;
     425  	  node = node->left;
     426  	}
     427  
     428        if (stack == NULL)
     429  	break;
     430  
     431        node = stack;
     432        stack = stack->back;
     433  
     434        val = (*fn) (node->key, node->value, data);
     435        if (val)
     436  	break;
     437  
     438        node = node->right;
     439      }
     440  
     441    return val;
     442  }
     443  
     444  /* Insert a new node (associating KEY with DATA) into SP.  If a
     445     previous node with the indicated KEY exists, its data is replaced
     446     with the new value.  Returns the new node.  */
     447  
     448  template <typename KEY_TYPE, typename VALUE_TYPE>
     449  typename typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_node
     450  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_insert (
     451  						splay_tree_key key,
     452  						splay_tree_value value)
     453  {
     454    int comparison = 0;
     455  
     456    splay_tree_splay (key);
     457  
     458    if (root)
     459      comparison = (*comp)(root->key, key);
     460  
     461    if (root && comparison == 0)
     462      {
     463        /* If the root of the tree already has the indicated KEY, just
     464  	 replace the value with VALUE.  */
     465        VDEL(root->value);
     466        root->value = value;
     467      }
     468    else
     469      {
     470        /* Create a new node, and insert it at the root.  */
     471        splay_tree_node node;
     472  
     473        node = new splay_tree_node_s;
     474        node->key = key;
     475        node->value = value;
     476  
     477        if (!root)
     478  	node->left = node->right = 0;
     479        else if (comparison < 0)
     480  	{
     481  	  node->left = root;
     482  	  node->right = node->left->right;
     483  	  node->left->right = 0;
     484  	}
     485        else
     486  	{
     487  	  node->right = root;
     488  	  node->left = node->right->left;
     489  	  node->right->left = 0;
     490  	}
     491  
     492        root = node;
     493      }
     494  
     495    return root;
     496  }
     497  
     498  /* Remove KEY from SP.  It is not an error if it did not exist.  */
     499  
     500  template <typename KEY_TYPE, typename VALUE_TYPE>
     501  void
     502  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_remove (splay_tree_key key)
     503  {
     504    splay_tree_splay (key);
     505  
     506    if (root && (*comp) (root->key, key) == 0)
     507      {
     508        splay_tree_node left, right;
     509  
     510        left = root->left;
     511        right = root->right;
     512  
     513        /* Delete the root node itself.  */
     514        VDEL (root->value);
     515        delete root;
     516  
     517        /* One of the children is now the root.  Doesn't matter much
     518  	 which, so long as we preserve the properties of the tree.  */
     519        if (left)
     520  	{
     521  	  root = left;
     522  
     523  	  /* If there was a right child as well, hang it off the
     524  	     right-most leaf of the left child.  */
     525  	  if (right)
     526  	    {
     527  	      while (left->right)
     528  		left = left->right;
     529  	      left->right = right;
     530  	    }
     531  	}
     532        else
     533  	root = right;
     534      }
     535  }
     536  
     537  /* Lookup KEY in SP, returning VALUE if present, and NULL
     538     otherwise.  */
     539  
     540  template <typename KEY_TYPE, typename VALUE_TYPE>
     541  typename typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_node
     542  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_lookup (splay_tree_key key)
     543  {
     544    splay_tree_splay (key);
     545  
     546    if (root && (*comp)(root->key, key) == 0)
     547      return root;
     548    else
     549      return 0;
     550  }
     551  
     552  /* Return the node in SP with the greatest key.  */
     553  
     554  template <typename KEY_TYPE, typename VALUE_TYPE>
     555  typename typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_node
     556  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_max ()
     557  {
     558    splay_tree_node n = root;
     559  
     560    if (!n)
     561      return NULL;
     562  
     563    while (n->right)
     564      n = n->right;
     565  
     566    return n;
     567  }
     568  
     569  /* Return the node in SP with the smallest key.  */
     570  
     571  template <typename KEY_TYPE, typename VALUE_TYPE>
     572  typename typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_node
     573  typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_min ()
     574  {
     575    splay_tree_node n = root;
     576  
     577    if (!n)
     578      return NULL;
     579  
     580    while (n->left)
     581      n = n->left;
     582  
     583    return n;
     584  }
     585  
     586  /* Return the immediate predecessor KEY, or NULL if there is no
     587     predecessor.  KEY need not be present in the tree.  */
     588  
     589  template <typename KEY_TYPE, typename VALUE_TYPE>
     590  typename typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_node
     591  typed_splay_tree<KEY_TYPE,
     592  		 VALUE_TYPE>::splay_tree_predecessor (splay_tree_key key)
     593  {
     594    int comparison;
     595    splay_tree_node node;
     596  
     597    /* If the tree is empty, there is certainly no predecessor.  */
     598    if (!root)
     599      return NULL;
     600  
     601    /* Splay the tree around KEY.  That will leave either the KEY
     602       itself, its predecessor, or its successor at the root.  */
     603    splay_tree_splay (key);
     604    comparison = (*comp)(root->key, key);
     605  
     606    /* If the predecessor is at the root, just return it.  */
     607    if (comparison < 0)
     608      return root;
     609  
     610    /* Otherwise, find the rightmost element of the left subtree.  */
     611    node = root->left;
     612    if (node)
     613      while (node->right)
     614        node = node->right;
     615  
     616    return node;
     617  }
     618  
     619  /* Return the immediate successor KEY, or NULL if there is no
     620     successor.  KEY need not be present in the tree.  */
     621  
     622  template <typename KEY_TYPE, typename VALUE_TYPE>
     623  typename typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_node
     624  typed_splay_tree<KEY_TYPE,
     625  		 VALUE_TYPE>::splay_tree_successor (splay_tree_key key)
     626  {
     627    int comparison;
     628    splay_tree_node node;
     629  
     630    /* If the tree is empty, there is certainly no successor.  */
     631    if (!root)
     632      return NULL;
     633  
     634    /* Splay the tree around KEY.  That will leave either the KEY
     635       itself, its predecessor, or its successor at the root.  */
     636    splay_tree_splay (key);
     637    comparison = (*comp)(root->key, key);
     638  
     639    /* If the successor is at the root, just return it.  */
     640    if (comparison > 0)
     641      return root;
     642  
     643    /* Otherwise, find the leftmost element of the right subtree.  */
     644    node = root->right;
     645    if (node)
     646      while (node->left)
     647        node = node->left;
     648  
     649    return node;
     650  }
     651  
     652  #endif  /* GCC_TYPED_SPLAY_TREE_H  */