/src/binutils-gdb/libiberty/splay-tree.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* A splay-tree datatype. |
2 | | Copyright (C) 1998-2025 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 | 1.23k | { |
57 | 1.23k | splay_tree_node pending = 0; |
58 | 1.23k | splay_tree_node active = 0; |
59 | | |
60 | 1.23k | if (!node) |
61 | 0 | return; |
62 | | |
63 | 9.26k | #define KDEL(x) if (sp->delete_key) (*sp->delete_key)(x); |
64 | 9.26k | #define VDEL(x) if (sp->delete_value) (*sp->delete_value)(x); |
65 | | |
66 | 1.23k | KDEL (node->key); |
67 | 1.23k | VDEL (node->value); |
68 | | |
69 | | /* We use the "key" field to hold the "next" pointer. */ |
70 | 1.23k | node->key = (splay_tree_key)pending; |
71 | 1.23k | 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 | 10.4k | while (pending) |
78 | 9.26k | { |
79 | 9.26k | active = pending; |
80 | 9.26k | pending = 0; |
81 | 18.5k | while (active) |
82 | 9.26k | { |
83 | 9.26k | 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 | 9.26k | if (active->left) |
89 | 8.03k | { |
90 | 8.03k | KDEL (active->left->key); |
91 | 8.03k | VDEL (active->left->value); |
92 | 8.03k | active->left->key = (splay_tree_key)pending; |
93 | 8.03k | pending = (splay_tree_node)(active->left); |
94 | 8.03k | } |
95 | 9.26k | 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 | 9.26k | temp = active; |
104 | 9.26k | active = (splay_tree_node)(temp->key); |
105 | 9.26k | (*sp->deallocate) ((char*) temp, sp->allocate_data); |
106 | 9.26k | } |
107 | 9.26k | } |
108 | 1.23k | #undef KDEL |
109 | 1.23k | #undef VDEL |
110 | 1.23k | } |
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 | 18.5k | { |
143 | 18.5k | if (sp->root == 0) |
144 | 2.46k | return; |
145 | | |
146 | 16.0k | do { |
147 | 16.0k | int cmp1, cmp2; |
148 | 16.0k | splay_tree_node n, c; |
149 | | |
150 | 16.0k | n = sp->root; |
151 | 16.0k | cmp1 = (*sp->comp) (key, n->key); |
152 | | |
153 | | /* Found. */ |
154 | 16.0k | if (cmp1 == 0) |
155 | 0 | return; |
156 | | |
157 | | /* Left or right? If no child, then we're done. */ |
158 | 16.0k | if (cmp1 < 0) |
159 | 0 | c = n->left; |
160 | 16.0k | else |
161 | 16.0k | c = n->right; |
162 | 16.0k | if (!c) |
163 | 16.0k | 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 | 16.0k | } |
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 | 10.4k | { |
259 | 10.4k | return (void *) xmalloc (size); |
260 | 10.4k | } |
261 | | |
262 | | static void |
263 | | splay_tree_xmalloc_deallocate (void *object, void *data ATTRIBUTE_UNUSED) |
264 | 10.4k | { |
265 | 10.4k | free (object); |
266 | 10.4k | } |
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 | 1.23k | { |
279 | 1.23k | return (splay_tree_new_with_allocator |
280 | 1.23k | (compare_fn, delete_key_fn, delete_value_fn, |
281 | 1.23k | splay_tree_xmalloc_allocate, splay_tree_xmalloc_deallocate, 0)); |
282 | 1.23k | } |
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 | 1.23k | { |
297 | 1.23k | return |
298 | 1.23k | splay_tree_new_typed_alloc (compare_fn, delete_key_fn, delete_value_fn, |
299 | 1.23k | allocate_fn, allocate_fn, deallocate_fn, |
300 | 1.23k | allocate_data); |
301 | 1.23k | } |
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 | 1.23k | { |
340 | 1.23k | splay_tree sp = (splay_tree) (*tree_allocate_fn) |
341 | 1.23k | (sizeof (struct splay_tree_s), allocate_data); |
342 | | |
343 | 1.23k | sp->root = 0; |
344 | 1.23k | sp->comp = compare_fn; |
345 | 1.23k | sp->delete_key = delete_key_fn; |
346 | 1.23k | sp->delete_value = delete_value_fn; |
347 | 1.23k | sp->allocate = node_allocate_fn; |
348 | 1.23k | sp->deallocate = deallocate_fn; |
349 | 1.23k | sp->allocate_data = allocate_data; |
350 | | |
351 | 1.23k | return sp; |
352 | 1.23k | } |
353 | | |
354 | | /* Deallocate SP. */ |
355 | | |
356 | | void |
357 | | splay_tree_delete (splay_tree sp) |
358 | 1.23k | { |
359 | 1.23k | splay_tree_delete_helper (sp, sp->root); |
360 | 1.23k | (*sp->deallocate) ((char*) sp, sp->allocate_data); |
361 | 1.23k | } |
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 | 9.26k | { |
370 | 9.26k | int comparison = 0; |
371 | | |
372 | 9.26k | splay_tree_splay (sp, key); |
373 | | |
374 | 9.26k | if (sp->root) |
375 | 8.03k | comparison = (*sp->comp)(sp->root->key, key); |
376 | | |
377 | 9.26k | 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 | 9.26k | else |
389 | 9.26k | { |
390 | | /* Create a new node, and insert it at the root. */ |
391 | 9.26k | splay_tree_node node; |
392 | | |
393 | 9.26k | node = ((splay_tree_node) |
394 | 9.26k | (*sp->allocate) (sizeof (struct splay_tree_node_s), |
395 | 9.26k | sp->allocate_data)); |
396 | 9.26k | node->key = key; |
397 | 9.26k | node->value = value; |
398 | | |
399 | 9.26k | if (!sp->root) |
400 | 1.23k | node->left = node->right = 0; |
401 | 8.03k | else if (comparison < 0) |
402 | 8.03k | { |
403 | 8.03k | node->left = sp->root; |
404 | 8.03k | node->right = node->left->right; |
405 | 8.03k | node->left->right = 0; |
406 | 8.03k | } |
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 | 9.26k | sp->root = node; |
415 | 9.26k | } |
416 | | |
417 | 9.26k | return sp->root; |
418 | 9.26k | } |
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 | 9.26k | { |
467 | 9.26k | splay_tree_splay (sp, key); |
468 | | |
469 | 9.26k | if (sp->root && (*sp->comp)(sp->root->key, key) == 0) |
470 | 0 | return sp->root; |
471 | 9.26k | else |
472 | 9.26k | return 0; |
473 | 9.26k | } |
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 | } |