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