1 /* A typesafe wrapper around libiberty's splay-tree.h. 2 Copyright (C) 2015-2022 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 */ 653