Coverage Report

Created: 2026-03-10 08:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/binutils-gdb/libiberty/splay-tree.c
Line
Count
Source
1
/* A splay-tree datatype.  
2
   Copyright (C) 1998-2026 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
912
{
57
912
  splay_tree_node pending = 0;
58
912
  splay_tree_node active = 0;
59
60
912
  if (!node)
61
0
    return;
62
63
964
#define KDEL(x)  if (sp->delete_key) (*sp->delete_key)(x);
64
964
#define VDEL(x)  if (sp->delete_value) (*sp->delete_value)(x);
65
66
912
  KDEL (node->key);
67
912
  VDEL (node->value);
68
69
  /* We use the "key" field to hold the "next" pointer.  */
70
912
  node->key = (splay_tree_key)pending;
71
912
  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
1.87k
  while (pending)
78
964
    {
79
964
      active = pending;
80
964
      pending = 0;
81
1.92k
      while (active)
82
964
  {
83
964
    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
964
    if (active->left)
89
52
      {
90
52
        KDEL (active->left->key);
91
52
        VDEL (active->left->value);
92
52
        active->left->key = (splay_tree_key)pending;
93
52
        pending = (splay_tree_node)(active->left);
94
52
      }
95
964
    if (active->right)
96
0
      {
97
0
        KDEL (active->right->key);
98
0
        VDEL (active->right->value);
99
0
        active->right->key = (splay_tree_key)pending;
100
0
        pending = (splay_tree_node)(active->right);
101
0
      }
102
103
964
    temp = active;
104
964
    active = (splay_tree_node)(temp->key);
105
964
    (*sp->deallocate) ((char*) temp, sp->allocate_data);
106
964
  }
107
964
    }
108
912
#undef KDEL
109
912
#undef VDEL
110
912
}
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
0
{
118
0
  splay_tree_node tmp;
119
0
  tmp = n->right;
120
0
  n->right = p;
121
0
  p->left = tmp;
122
0
  *pp = n;
123
0
}
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
0
{
131
0
  splay_tree_node tmp;
132
0
  tmp = n->left;
133
0
  n->left = p;
134
0
  p->right = tmp;
135
0
  *pp = n;
136
0
}
137
138
/* Bottom up splay of key.  */
139
140
static void
141
splay_tree_splay (splay_tree sp, splay_tree_key key)
142
1.92k
{
143
1.92k
  if (sp->root == 0)
144
1.82k
    return;
145
146
104
  do {
147
104
    int cmp1, cmp2;
148
104
    splay_tree_node n, c;
149
150
104
    n = sp->root;
151
104
    cmp1 = (*sp->comp) (key, n->key);
152
153
    /* Found.  */
154
104
    if (cmp1 == 0)
155
0
      return;
156
157
    /* Left or right?  If no child, then we're done.  */
158
104
    if (cmp1 < 0)
159
0
      c = n->left;
160
104
    else
161
104
      c = n->right;
162
104
    if (!c)
163
104
      return;
164
165
    /* Next one left or right?  If found or no child, we're done
166
       after one rotation.  */
167
0
    cmp2 = (*sp->comp) (key, c->key);
168
0
    if (cmp2 == 0
169
0
        || (cmp2 < 0 && !c->left)
170
0
        || (cmp2 > 0 && !c->right))
171
0
      {
172
0
  if (cmp1 < 0)
173
0
    rotate_left (&sp->root, n, c);
174
0
  else
175
0
    rotate_right (&sp->root, n, c);
176
0
        return;
177
0
      }
178
179
    /* Now we have the four cases of double-rotation.  */
180
0
    if (cmp1 < 0 && cmp2 < 0)
181
0
      {
182
0
  rotate_left (&n->left, c, c->left);
183
0
  rotate_left (&sp->root, n, n->left);
184
0
      }
185
0
    else if (cmp1 > 0 && cmp2 > 0)
186
0
      {
187
0
  rotate_right (&n->right, c, c->right);
188
0
  rotate_right (&sp->root, n, n->right);
189
0
      }
190
0
    else if (cmp1 < 0 && cmp2 > 0)
191
0
      {
192
0
  rotate_right (&n->left, c, c->right);
193
0
  rotate_left (&sp->root, n, n->left);
194
0
      }
195
0
    else if (cmp1 > 0 && cmp2 < 0)
196
0
      {
197
0
  rotate_left (&n->right, c, c->left);
198
0
  rotate_right (&sp->root, n, n->right);
199
0
      }
200
0
  } while (1);
201
104
}
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
0
{
212
0
  int val;
213
0
  splay_tree_node *stack;
214
0
  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
0
#define INITIAL_STACK_SIZE 100
221
0
  stack_size = INITIAL_STACK_SIZE;
222
0
  stack_ptr = 0;
223
0
  stack = XNEWVEC (splay_tree_node, stack_size);
224
0
  val = 0;
225
226
0
  for (;;)
227
0
    {
228
0
      while (node != NULL)
229
0
  {
230
0
    if (stack_ptr == stack_size)
231
0
      {
232
0
        stack_size *= 2;
233
0
        stack = XRESIZEVEC (splay_tree_node, stack, stack_size);
234
0
      }
235
0
    stack[stack_ptr++] = node;
236
0
    node = node->left;
237
0
  }
238
239
0
      if (stack_ptr == 0)
240
0
  break;
241
242
0
      node = stack[--stack_ptr];
243
244
0
      val = (*fn) (node, data);
245
0
      if (val)
246
0
  break;
247
248
0
      node = node->right;
249
0
    }
250
251
0
  XDELETEVEC (stack);
252
0
  return val;
253
0
}
254
255
/* An allocator and deallocator based on xmalloc.  */
256
static void *
257
splay_tree_xmalloc_allocate (int size, void *data ATTRIBUTE_UNUSED)
258
1.87k
{
259
1.87k
  return (void *) xmalloc (size);
260
1.87k
}
261
262
static void
263
splay_tree_xmalloc_deallocate (void *object, void *data ATTRIBUTE_UNUSED)
264
1.87k
{
265
1.87k
  free (object);
266
1.87k
}
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
912
{
279
912
  return (splay_tree_new_with_allocator
280
912
          (compare_fn, delete_key_fn, delete_value_fn,
281
912
           splay_tree_xmalloc_allocate, splay_tree_xmalloc_deallocate, 0));
282
912
}
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
912
{
297
912
  return
298
912
    splay_tree_new_typed_alloc (compare_fn, delete_key_fn, delete_value_fn,
299
912
        allocate_fn, allocate_fn, deallocate_fn,
300
912
        allocate_data);
301
912
}
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
912
{
340
912
  splay_tree sp = (splay_tree) (*tree_allocate_fn)
341
912
    (sizeof (struct splay_tree_s), allocate_data);
342
343
912
  sp->root = 0;
344
912
  sp->comp = compare_fn;
345
912
  sp->delete_key = delete_key_fn;
346
912
  sp->delete_value = delete_value_fn;
347
912
  sp->allocate = node_allocate_fn;
348
912
  sp->deallocate = deallocate_fn;
349
912
  sp->allocate_data = allocate_data;
350
351
912
  return sp;
352
912
}
353
354
/* Deallocate SP.  */
355
356
void 
357
splay_tree_delete (splay_tree sp)
358
912
{
359
912
  splay_tree_delete_helper (sp, sp->root);
360
912
  (*sp->deallocate) ((char*) sp, sp->allocate_data);
361
912
}
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
964
{
370
964
  int comparison = 0;
371
372
964
  splay_tree_splay (sp, key);
373
374
964
  if (sp->root)
375
52
    comparison = (*sp->comp)(sp->root->key, key);
376
377
964
  if (sp->root && comparison == 0)
378
0
    {
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
0
      if (sp->delete_key)
382
0
  (*sp->delete_key) (sp->root->key);
383
0
      if (sp->delete_value)
384
0
  (*sp->delete_value)(sp->root->value);
385
0
      sp->root->key = key;
386
0
      sp->root->value = value;
387
0
    } 
388
964
  else 
389
964
    {
390
      /* Create a new node, and insert it at the root.  */
391
964
      splay_tree_node node;
392
393
964
      node = ((splay_tree_node)
394
964
        (*sp->allocate) (sizeof (struct splay_tree_node_s),
395
964
             sp->allocate_data));
396
964
      node->key = key;
397
964
      node->value = value;
398
      
399
964
      if (!sp->root)
400
912
  node->left = node->right = 0;
401
52
      else if (comparison < 0)
402
52
  {
403
52
    node->left = sp->root;
404
52
    node->right = node->left->right;
405
52
    node->left->right = 0;
406
52
  }
407
0
      else
408
0
  {
409
0
    node->right = sp->root;
410
0
    node->left = node->right->left;
411
0
    node->right->left = 0;
412
0
  }
413
414
964
      sp->root = node;
415
964
    }
416
417
964
  return sp->root;
418
964
}
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
0
{
425
0
  splay_tree_splay (sp, key);
426
427
0
  if (sp->root && (*sp->comp) (sp->root->key, key) == 0)
428
0
    {
429
0
      splay_tree_node left, right;
430
431
0
      left = sp->root->left;
432
0
      right = sp->root->right;
433
434
      /* Delete the root node itself.  */
435
0
      if (sp->delete_key)
436
0
  (*sp->delete_key) (sp->root->key);
437
0
      if (sp->delete_value)
438
0
  (*sp->delete_value) (sp->root->value);
439
0
      (*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
0
      if (left)
444
0
  {
445
0
    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
0
    if (right)
450
0
      {
451
0
        while (left->right)
452
0
    left = left->right;
453
0
        left->right = right;
454
0
      }
455
0
  }
456
0
      else
457
0
  sp->root = right;
458
0
    }
459
0
}
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
964
{
467
964
  splay_tree_splay (sp, key);
468
469
964
  if (sp->root && (*sp->comp)(sp->root->key, key) == 0)
470
0
    return sp->root;
471
964
  else
472
964
    return 0;
473
964
}
474
475
/* Return the node in SP with the greatest key.  */
476
477
splay_tree_node
478
splay_tree_max (splay_tree sp)
479
0
{
480
0
  splay_tree_node n = sp->root;
481
482
0
  if (!n)
483
0
    return NULL;
484
485
0
  while (n->right)
486
0
    n = n->right;
487
488
0
  return n;
489
0
}
490
491
/* Return the node in SP with the smallest key.  */
492
493
splay_tree_node
494
splay_tree_min (splay_tree sp)
495
0
{
496
0
  splay_tree_node n = sp->root;
497
498
0
  if (!n)
499
0
    return NULL;
500
501
0
  while (n->left)
502
0
    n = n->left;
503
504
0
  return n;
505
0
}
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
0
{
513
0
  int comparison;
514
0
  splay_tree_node node;
515
516
  /* If the tree is empty, there is certainly no predecessor.  */
517
0
  if (!sp->root)
518
0
    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
0
  splay_tree_splay (sp, key);
523
0
  comparison = (*sp->comp)(sp->root->key, key);
524
525
  /* If the predecessor is at the root, just return it.  */
526
0
  if (comparison < 0)
527
0
    return sp->root;
528
529
  /* Otherwise, find the rightmost element of the left subtree.  */
530
0
  node = sp->root->left;
531
0
  if (node)
532
0
    while (node->right)
533
0
      node = node->right;
534
535
0
  return node;
536
0
}
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
0
{
544
0
  int comparison;
545
0
  splay_tree_node node;
546
547
  /* If the tree is empty, there is certainly no successor.  */
548
0
  if (!sp->root)
549
0
    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
0
  splay_tree_splay (sp, key);
554
0
  comparison = (*sp->comp)(sp->root->key, key);
555
556
  /* If the successor is at the root, just return it.  */
557
0
  if (comparison > 0)
558
0
    return sp->root;
559
560
  /* Otherwise, find the leftmost element of the right subtree.  */
561
0
  node = sp->root->right;
562
0
  if (node)
563
0
    while (node->left)
564
0
      node = node->left;
565
566
0
  return node;
567
0
}
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
0
{
577
0
  return splay_tree_foreach_helper (sp->root, fn, data);
578
0
}
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
0
{
585
0
  if ((int) k1 < (int) k2)
586
0
    return -1;
587
0
  else if ((int) k1 > (int) k2)
588
0
    return 1;
589
0
  else 
590
0
    return 0;
591
0
}
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
0
{
598
0
  if ((char*) k1 < (char*) k2)
599
0
    return -1;
600
0
  else if ((char*) k1 > (char*) k2)
601
0
    return 1;
602
0
  else 
603
0
    return 0;
604
0
}
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
0
{
611
0
  return strcmp ((char *) k1, (char *) k2);
612
0
}
613
614
/* Splay-tree delete function, simply using free.  */
615
616
void
617
splay_tree_delete_pointers (splay_tree_value value)
618
0
{
619
0
  free ((void *) value);
620
0
}