qemu/util/qtree.c
<<
>>
Prefs
   1/*
   2 * GLIB - Library of useful routines for C programming
   3 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
   4 *
   5 * SPDX-License-Identifier: LGPL-2.1-or-later
   6 *
   7 * This library is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU Lesser General Public
   9 * License as published by the Free Software Foundation; either
  10 * version 2.1 of the License, or (at your option) any later version.
  11 *
  12 * This library is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * Lesser General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU Lesser General Public
  18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  19 */
  20
  21/*
  22 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
  23 * file for a list of people on the GLib Team.  See the ChangeLog
  24 * files for a list of changes.  These files are distributed with
  25 * GLib at ftp://ftp.gtk.org/pub/gtk/.
  26 */
  27
  28/*
  29 * MT safe
  30 */
  31
  32#include "qemu/osdep.h"
  33#include "qemu/qtree.h"
  34
  35/**
  36 * SECTION:trees-binary
  37 * @title: Balanced Binary Trees
  38 * @short_description: a sorted collection of key/value pairs optimized
  39 *                     for searching and traversing in order
  40 *
  41 * The #QTree structure and its associated functions provide a sorted
  42 * collection of key/value pairs optimized for searching and traversing
  43 * in order. This means that most of the operations  (access, search,
  44 * insertion, deletion, ...) on #QTree are O(log(n)) in average and O(n)
  45 * in worst case for time complexity. But, note that maintaining a
  46 * balanced sorted #QTree of n elements is done in time O(n log(n)).
  47 *
  48 * To create a new #QTree use q_tree_new().
  49 *
  50 * To insert a key/value pair into a #QTree use q_tree_insert()
  51 * (O(n log(n))).
  52 *
  53 * To remove a key/value pair use q_tree_remove() (O(n log(n))).
  54 *
  55 * To look up the value corresponding to a given key, use
  56 * q_tree_lookup() and q_tree_lookup_extended().
  57 *
  58 * To find out the number of nodes in a #QTree, use q_tree_nnodes(). To
  59 * get the height of a #QTree, use q_tree_height().
  60 *
  61 * To traverse a #QTree, calling a function for each node visited in
  62 * the traversal, use q_tree_foreach().
  63 *
  64 * To destroy a #QTree, use q_tree_destroy().
  65 **/
  66
  67#define MAX_GTREE_HEIGHT 40
  68
  69/**
  70 * QTree:
  71 *
  72 * The QTree struct is an opaque data structure representing a
  73 * [balanced binary tree][glib-Balanced-Binary-Trees]. It should be
  74 * accessed only by using the following functions.
  75 */
  76struct _QTree {
  77    QTreeNode        *root;
  78    GCompareDataFunc  key_compare;
  79    GDestroyNotify    key_destroy_func;
  80    GDestroyNotify    value_destroy_func;
  81    gpointer          key_compare_data;
  82    guint             nnodes;
  83    gint              ref_count;
  84};
  85
  86struct _QTreeNode {
  87    gpointer   key;         /* key for this node */
  88    gpointer   value;       /* value stored at this node */
  89    QTreeNode *left;        /* left subtree */
  90    QTreeNode *right;       /* right subtree */
  91    gint8      balance;     /* height (right) - height (left) */
  92    guint8     left_child;
  93    guint8     right_child;
  94};
  95
  96
  97static QTreeNode *q_tree_node_new(gpointer       key,
  98                                  gpointer       value);
  99static QTreeNode *q_tree_insert_internal(QTree *tree,
 100                                         gpointer key,
 101                                         gpointer value,
 102                                         gboolean replace);
 103static gboolean   q_tree_remove_internal(QTree         *tree,
 104                                         gconstpointer  key,
 105                                         gboolean       steal);
 106static QTreeNode *q_tree_node_balance(QTreeNode     *node);
 107static QTreeNode *q_tree_find_node(QTree         *tree,
 108                                   gconstpointer  key);
 109static QTreeNode *q_tree_node_search(QTreeNode *node,
 110                                     GCompareFunc search_func,
 111                                     gconstpointer data);
 112static QTreeNode *q_tree_node_rotate_left(QTreeNode     *node);
 113static QTreeNode *q_tree_node_rotate_right(QTreeNode     *node);
 114#ifdef Q_TREE_DEBUG
 115static void       q_tree_node_check(QTreeNode     *node);
 116#endif
 117
 118static QTreeNode*
 119q_tree_node_new(gpointer key,
 120                gpointer value)
 121{
 122    QTreeNode *node = g_new(QTreeNode, 1);
 123
 124    node->balance = 0;
 125    node->left = NULL;
 126    node->right = NULL;
 127    node->left_child = FALSE;
 128    node->right_child = FALSE;
 129    node->key = key;
 130    node->value = value;
 131
 132    return node;
 133}
 134
 135/**
 136 * q_tree_new:
 137 * @key_compare_func: the function used to order the nodes in the #QTree.
 138 *   It should return values similar to the standard strcmp() function -
 139 *   0 if the two arguments are equal, a negative value if the first argument
 140 *   comes before the second, or a positive value if the first argument comes
 141 *   after the second.
 142 *
 143 * Creates a new #QTree.
 144 *
 145 * Returns: a newly allocated #QTree
 146 */
 147QTree *
 148q_tree_new(GCompareFunc key_compare_func)
 149{
 150    g_return_val_if_fail(key_compare_func != NULL, NULL);
 151
 152    return q_tree_new_full((GCompareDataFunc) key_compare_func, NULL,
 153                           NULL, NULL);
 154}
 155
 156/**
 157 * q_tree_new_with_data:
 158 * @key_compare_func: qsort()-style comparison function
 159 * @key_compare_data: data to pass to comparison function
 160 *
 161 * Creates a new #QTree with a comparison function that accepts user data.
 162 * See q_tree_new() for more details.
 163 *
 164 * Returns: a newly allocated #QTree
 165 */
 166QTree *
 167q_tree_new_with_data(GCompareDataFunc key_compare_func,
 168                     gpointer         key_compare_data)
 169{
 170    g_return_val_if_fail(key_compare_func != NULL, NULL);
 171
 172    return q_tree_new_full(key_compare_func, key_compare_data,
 173                           NULL, NULL);
 174}
 175
 176/**
 177 * q_tree_new_full:
 178 * @key_compare_func: qsort()-style comparison function
 179 * @key_compare_data: data to pass to comparison function
 180 * @key_destroy_func: a function to free the memory allocated for the key
 181 *   used when removing the entry from the #QTree or %NULL if you don't
 182 *   want to supply such a function
 183 * @value_destroy_func: a function to free the memory allocated for the
 184 *   value used when removing the entry from the #QTree or %NULL if you
 185 *   don't want to supply such a function
 186 *
 187 * Creates a new #QTree like q_tree_new() and allows to specify functions
 188 * to free the memory allocated for the key and value that get called when
 189 * removing the entry from the #QTree.
 190 *
 191 * Returns: a newly allocated #QTree
 192 */
 193QTree *
 194q_tree_new_full(GCompareDataFunc key_compare_func,
 195                gpointer         key_compare_data,
 196                GDestroyNotify   key_destroy_func,
 197                GDestroyNotify   value_destroy_func)
 198{
 199    QTree *tree;
 200
 201    g_return_val_if_fail(key_compare_func != NULL, NULL);
 202
 203    tree = g_new(QTree, 1);
 204    tree->root               = NULL;
 205    tree->key_compare        = key_compare_func;
 206    tree->key_destroy_func   = key_destroy_func;
 207    tree->value_destroy_func = value_destroy_func;
 208    tree->key_compare_data   = key_compare_data;
 209    tree->nnodes             = 0;
 210    tree->ref_count          = 1;
 211
 212    return tree;
 213}
 214
 215/**
 216 * q_tree_node_first:
 217 * @tree: a #QTree
 218 *
 219 * Returns the first in-order node of the tree, or %NULL
 220 * for an empty tree.
 221 *
 222 * Returns: (nullable) (transfer none): the first node in the tree
 223 *
 224 * Since: 2.68 in GLib. Internal in Qtree, i.e. not in the public API.
 225 */
 226static QTreeNode *
 227q_tree_node_first(QTree *tree)
 228{
 229    QTreeNode *tmp;
 230
 231    g_return_val_if_fail(tree != NULL, NULL);
 232
 233    if (!tree->root) {
 234        return NULL;
 235    }
 236
 237    tmp = tree->root;
 238
 239    while (tmp->left_child) {
 240        tmp = tmp->left;
 241    }
 242
 243    return tmp;
 244}
 245
 246/**
 247 * q_tree_node_previous
 248 * @node: a #QTree node
 249 *
 250 * Returns the previous in-order node of the tree, or %NULL
 251 * if the passed node was already the first one.
 252 *
 253 * Returns: (nullable) (transfer none): the previous node in the tree
 254 *
 255 * Since: 2.68 in GLib. Internal in Qtree, i.e. not in the public API.
 256 */
 257static QTreeNode *
 258q_tree_node_previous(QTreeNode *node)
 259{
 260    QTreeNode *tmp;
 261
 262    g_return_val_if_fail(node != NULL, NULL);
 263
 264    tmp = node->left;
 265
 266    if (node->left_child) {
 267        while (tmp->right_child) {
 268            tmp = tmp->right;
 269        }
 270    }
 271
 272    return tmp;
 273}
 274
 275/**
 276 * q_tree_node_next
 277 * @node: a #QTree node
 278 *
 279 * Returns the next in-order node of the tree, or %NULL
 280 * if the passed node was already the last one.
 281 *
 282 * Returns: (nullable) (transfer none): the next node in the tree
 283 *
 284 * Since: 2.68 in GLib. Internal in Qtree, i.e. not in the public API.
 285 */
 286static QTreeNode *
 287q_tree_node_next(QTreeNode *node)
 288{
 289    QTreeNode *tmp;
 290
 291    g_return_val_if_fail(node != NULL, NULL);
 292
 293    tmp = node->right;
 294
 295    if (node->right_child) {
 296        while (tmp->left_child) {
 297            tmp = tmp->left;
 298        }
 299    }
 300
 301    return tmp;
 302}
 303
 304/**
 305 * q_tree_remove_all:
 306 * @tree: a #QTree
 307 *
 308 * Removes all nodes from a #QTree and destroys their keys and values,
 309 * then resets the #QTree’s root to %NULL.
 310 *
 311 * Since: 2.70 in GLib. Internal in Qtree, i.e. not in the public API.
 312 */
 313static void QEMU_DISABLE_CFI
 314q_tree_remove_all(QTree *tree)
 315{
 316    QTreeNode *node;
 317    QTreeNode *next;
 318
 319    g_return_if_fail(tree != NULL);
 320
 321    node = q_tree_node_first(tree);
 322
 323    while (node) {
 324        next = q_tree_node_next(node);
 325
 326        if (tree->key_destroy_func) {
 327            tree->key_destroy_func(node->key);
 328        }
 329        if (tree->value_destroy_func) {
 330            tree->value_destroy_func(node->value);
 331        }
 332        g_free(node);
 333
 334#ifdef Q_TREE_DEBUG
 335        g_assert(tree->nnodes > 0);
 336        tree->nnodes--;
 337#endif
 338
 339        node = next;
 340    }
 341
 342#ifdef Q_TREE_DEBUG
 343    g_assert(tree->nnodes == 0);
 344#endif
 345
 346    tree->root = NULL;
 347#ifndef Q_TREE_DEBUG
 348    tree->nnodes = 0;
 349#endif
 350}
 351
 352/**
 353 * q_tree_ref:
 354 * @tree: a #QTree
 355 *
 356 * Increments the reference count of @tree by one.
 357 *
 358 * It is safe to call this function from any thread.
 359 *
 360 * Returns: the passed in #QTree
 361 *
 362 * Since: 2.22
 363 */
 364QTree *
 365q_tree_ref(QTree *tree)
 366{
 367    g_return_val_if_fail(tree != NULL, NULL);
 368
 369    g_atomic_int_inc(&tree->ref_count);
 370
 371    return tree;
 372}
 373
 374/**
 375 * q_tree_unref:
 376 * @tree: a #QTree
 377 *
 378 * Decrements the reference count of @tree by one.
 379 * If the reference count drops to 0, all keys and values will
 380 * be destroyed (if destroy functions were specified) and all
 381 * memory allocated by @tree will be released.
 382 *
 383 * It is safe to call this function from any thread.
 384 *
 385 * Since: 2.22
 386 */
 387void
 388q_tree_unref(QTree *tree)
 389{
 390    g_return_if_fail(tree != NULL);
 391
 392    if (g_atomic_int_dec_and_test(&tree->ref_count)) {
 393        q_tree_remove_all(tree);
 394        g_free(tree);
 395    }
 396}
 397
 398/**
 399 * q_tree_destroy:
 400 * @tree: a #QTree
 401 *
 402 * Removes all keys and values from the #QTree and decreases its
 403 * reference count by one. If keys and/or values are dynamically
 404 * allocated, you should either free them first or create the #QTree
 405 * using q_tree_new_full(). In the latter case the destroy functions
 406 * you supplied will be called on all keys and values before destroying
 407 * the #QTree.
 408 */
 409void
 410q_tree_destroy(QTree *tree)
 411{
 412    g_return_if_fail(tree != NULL);
 413
 414    q_tree_remove_all(tree);
 415    q_tree_unref(tree);
 416}
 417
 418/**
 419 * q_tree_insert_node:
 420 * @tree: a #QTree
 421 * @key: the key to insert
 422 * @value: the value corresponding to the key
 423 *
 424 * Inserts a key/value pair into a #QTree.
 425 *
 426 * If the given key already exists in the #QTree its corresponding value
 427 * is set to the new value. If you supplied a @value_destroy_func when
 428 * creating the #QTree, the old value is freed using that function. If
 429 * you supplied a @key_destroy_func when creating the #QTree, the passed
 430 * key is freed using that function.
 431 *
 432 * The tree is automatically 'balanced' as new key/value pairs are added,
 433 * so that the distance from the root to every leaf is as small as possible.
 434 * The cost of maintaining a balanced tree while inserting new key/value
 435 * result in a O(n log(n)) operation where most of the other operations
 436 * are O(log(n)).
 437 *
 438 * Returns: (transfer none): the inserted (or set) node.
 439 *
 440 * Since: 2.68 in GLib. Internal in Qtree, i.e. not in the public API.
 441 */
 442static QTreeNode *
 443q_tree_insert_node(QTree    *tree,
 444                   gpointer  key,
 445                   gpointer  value)
 446{
 447    QTreeNode *node;
 448
 449    g_return_val_if_fail(tree != NULL, NULL);
 450
 451    node = q_tree_insert_internal(tree, key, value, FALSE);
 452
 453#ifdef Q_TREE_DEBUG
 454    q_tree_node_check(tree->root);
 455#endif
 456
 457    return node;
 458}
 459
 460/**
 461 * q_tree_insert:
 462 * @tree: a #QTree
 463 * @key: the key to insert
 464 * @value: the value corresponding to the key
 465 *
 466 * Inserts a key/value pair into a #QTree.
 467 *
 468 * Inserts a new key and value into a #QTree as q_tree_insert_node() does,
 469 * only this function does not return the inserted or set node.
 470 */
 471void
 472q_tree_insert(QTree    *tree,
 473              gpointer  key,
 474              gpointer  value)
 475{
 476    q_tree_insert_node(tree, key, value);
 477}
 478
 479/**
 480 * q_tree_replace_node:
 481 * @tree: a #QTree
 482 * @key: the key to insert
 483 * @value: the value corresponding to the key
 484 *
 485 * Inserts a new key and value into a #QTree similar to q_tree_insert_node().
 486 * The difference is that if the key already exists in the #QTree, it gets
 487 * replaced by the new key. If you supplied a @value_destroy_func when
 488 * creating the #QTree, the old value is freed using that function. If you
 489 * supplied a @key_destroy_func when creating the #QTree, the old key is
 490 * freed using that function.
 491 *
 492 * The tree is automatically 'balanced' as new key/value pairs are added,
 493 * so that the distance from the root to every leaf is as small as possible.
 494 *
 495 * Returns: (transfer none): the inserted (or set) node.
 496 *
 497 * Since: 2.68 in GLib. Internal in Qtree, i.e. not in the public API.
 498 */
 499static QTreeNode *
 500q_tree_replace_node(QTree    *tree,
 501                    gpointer  key,
 502                    gpointer  value)
 503{
 504    QTreeNode *node;
 505
 506    g_return_val_if_fail(tree != NULL, NULL);
 507
 508    node = q_tree_insert_internal(tree, key, value, TRUE);
 509
 510#ifdef Q_TREE_DEBUG
 511    q_tree_node_check(tree->root);
 512#endif
 513
 514    return node;
 515}
 516
 517/**
 518 * q_tree_replace:
 519 * @tree: a #QTree
 520 * @key: the key to insert
 521 * @value: the value corresponding to the key
 522 *
 523 * Inserts a new key and value into a #QTree as q_tree_replace_node() does,
 524 * only this function does not return the inserted or set node.
 525 */
 526void
 527q_tree_replace(QTree    *tree,
 528               gpointer  key,
 529               gpointer  value)
 530{
 531    q_tree_replace_node(tree, key, value);
 532}
 533
 534/* internal insert routine */
 535static QTreeNode * QEMU_DISABLE_CFI
 536q_tree_insert_internal(QTree    *tree,
 537                       gpointer  key,
 538                       gpointer  value,
 539                       gboolean  replace)
 540{
 541    QTreeNode *node, *retnode;
 542    QTreeNode *path[MAX_GTREE_HEIGHT];
 543    int idx;
 544
 545    g_return_val_if_fail(tree != NULL, NULL);
 546
 547    if (!tree->root) {
 548        tree->root = q_tree_node_new(key, value);
 549        tree->nnodes++;
 550        return tree->root;
 551    }
 552
 553    idx = 0;
 554    path[idx++] = NULL;
 555    node = tree->root;
 556
 557    while (1) {
 558        int cmp = tree->key_compare(key, node->key, tree->key_compare_data);
 559
 560        if (cmp == 0) {
 561            if (tree->value_destroy_func) {
 562                tree->value_destroy_func(node->value);
 563            }
 564
 565            node->value = value;
 566
 567            if (replace) {
 568                if (tree->key_destroy_func) {
 569                    tree->key_destroy_func(node->key);
 570                }
 571
 572                node->key = key;
 573            } else {
 574                /* free the passed key */
 575                if (tree->key_destroy_func) {
 576                    tree->key_destroy_func(key);
 577                }
 578            }
 579
 580            return node;
 581        } else if (cmp < 0) {
 582            if (node->left_child) {
 583                path[idx++] = node;
 584                node = node->left;
 585            } else {
 586                QTreeNode *child = q_tree_node_new(key, value);
 587
 588                child->left = node->left;
 589                child->right = node;
 590                node->left = child;
 591                node->left_child = TRUE;
 592                node->balance -= 1;
 593
 594                tree->nnodes++;
 595
 596                retnode = child;
 597                break;
 598            }
 599        } else {
 600            if (node->right_child) {
 601                path[idx++] = node;
 602                node = node->right;
 603            } else {
 604                QTreeNode *child = q_tree_node_new(key, value);
 605
 606                child->right = node->right;
 607                child->left = node;
 608                node->right = child;
 609                node->right_child = TRUE;
 610                node->balance += 1;
 611
 612                tree->nnodes++;
 613
 614                retnode = child;
 615                break;
 616            }
 617        }
 618    }
 619
 620    /*
 621     * Restore balance. This is the goodness of a non-recursive
 622     * implementation, when we are done with balancing we 'break'
 623     * the loop and we are done.
 624     */
 625    while (1) {
 626        QTreeNode *bparent = path[--idx];
 627        gboolean left_node = (bparent && node == bparent->left);
 628        g_assert(!bparent || bparent->left == node || bparent->right == node);
 629
 630        if (node->balance < -1 || node->balance > 1) {
 631            node = q_tree_node_balance(node);
 632            if (bparent == NULL) {
 633                tree->root = node;
 634            } else if (left_node) {
 635                bparent->left = node;
 636            } else {
 637                bparent->right = node;
 638            }
 639        }
 640
 641        if (node->balance == 0 || bparent == NULL) {
 642            break;
 643        }
 644
 645        if (left_node) {
 646            bparent->balance -= 1;
 647        } else {
 648            bparent->balance += 1;
 649        }
 650
 651        node = bparent;
 652    }
 653
 654    return retnode;
 655}
 656
 657/**
 658 * q_tree_remove:
 659 * @tree: a #QTree
 660 * @key: the key to remove
 661 *
 662 * Removes a key/value pair from a #QTree.
 663 *
 664 * If the #QTree was created using q_tree_new_full(), the key and value
 665 * are freed using the supplied destroy functions, otherwise you have to
 666 * make sure that any dynamically allocated values are freed yourself.
 667 * If the key does not exist in the #QTree, the function does nothing.
 668 *
 669 * The cost of maintaining a balanced tree while removing a key/value
 670 * result in a O(n log(n)) operation where most of the other operations
 671 * are O(log(n)).
 672 *
 673 * Returns: %TRUE if the key was found (prior to 2.8, this function
 674 *     returned nothing)
 675 */
 676gboolean
 677q_tree_remove(QTree         *tree,
 678              gconstpointer  key)
 679{
 680    gboolean removed;
 681
 682    g_return_val_if_fail(tree != NULL, FALSE);
 683
 684    removed = q_tree_remove_internal(tree, key, FALSE);
 685
 686#ifdef Q_TREE_DEBUG
 687    q_tree_node_check(tree->root);
 688#endif
 689
 690    return removed;
 691}
 692
 693/**
 694 * q_tree_steal:
 695 * @tree: a #QTree
 696 * @key: the key to remove
 697 *
 698 * Removes a key and its associated value from a #QTree without calling
 699 * the key and value destroy functions.
 700 *
 701 * If the key does not exist in the #QTree, the function does nothing.
 702 *
 703 * Returns: %TRUE if the key was found (prior to 2.8, this function
 704 *     returned nothing)
 705 */
 706gboolean
 707q_tree_steal(QTree         *tree,
 708             gconstpointer  key)
 709{
 710    gboolean removed;
 711
 712    g_return_val_if_fail(tree != NULL, FALSE);
 713
 714    removed = q_tree_remove_internal(tree, key, TRUE);
 715
 716#ifdef Q_TREE_DEBUG
 717    q_tree_node_check(tree->root);
 718#endif
 719
 720    return removed;
 721}
 722
 723/* internal remove routine */
 724static gboolean QEMU_DISABLE_CFI
 725q_tree_remove_internal(QTree         *tree,
 726                       gconstpointer  key,
 727                       gboolean       steal)
 728{
 729    QTreeNode *node, *parent, *balance;
 730    QTreeNode *path[MAX_GTREE_HEIGHT];
 731    int idx;
 732    gboolean left_node;
 733
 734    g_return_val_if_fail(tree != NULL, FALSE);
 735
 736    if (!tree->root) {
 737        return FALSE;
 738    }
 739
 740    idx = 0;
 741    path[idx++] = NULL;
 742    node = tree->root;
 743
 744    while (1) {
 745        int cmp = tree->key_compare(key, node->key, tree->key_compare_data);
 746
 747        if (cmp == 0) {
 748            break;
 749        } else if (cmp < 0) {
 750            if (!node->left_child) {
 751                return FALSE;
 752            }
 753
 754            path[idx++] = node;
 755            node = node->left;
 756        } else {
 757            if (!node->right_child) {
 758                return FALSE;
 759            }
 760
 761            path[idx++] = node;
 762            node = node->right;
 763        }
 764    }
 765
 766    /*
 767     * The following code is almost equal to q_tree_remove_node,
 768     * except that we do not have to call q_tree_node_parent.
 769     */
 770    balance = parent = path[--idx];
 771    g_assert(!parent || parent->left == node || parent->right == node);
 772    left_node = (parent && node == parent->left);
 773
 774    if (!node->left_child) {
 775        if (!node->right_child) {
 776            if (!parent) {
 777                tree->root = NULL;
 778            } else if (left_node) {
 779                parent->left_child = FALSE;
 780                parent->left = node->left;
 781                parent->balance += 1;
 782            } else {
 783                parent->right_child = FALSE;
 784                parent->right = node->right;
 785                parent->balance -= 1;
 786            }
 787        } else {
 788            /* node has a right child */
 789            QTreeNode *tmp = q_tree_node_next(node);
 790            tmp->left = node->left;
 791
 792            if (!parent) {
 793                tree->root = node->right;
 794            } else if (left_node) {
 795                parent->left = node->right;
 796                parent->balance += 1;
 797            } else {
 798                parent->right = node->right;
 799                parent->balance -= 1;
 800            }
 801        }
 802    } else {
 803        /* node has a left child */
 804        if (!node->right_child) {
 805            QTreeNode *tmp = q_tree_node_previous(node);
 806            tmp->right = node->right;
 807
 808            if (parent == NULL) {
 809                tree->root = node->left;
 810            } else if (left_node) {
 811                parent->left = node->left;
 812                parent->balance += 1;
 813            } else {
 814                parent->right = node->left;
 815                parent->balance -= 1;
 816            }
 817        } else {
 818            /* node has a both children (pant, pant!) */
 819            QTreeNode *prev = node->left;
 820            QTreeNode *next = node->right;
 821            QTreeNode *nextp = node;
 822            int old_idx = idx + 1;
 823            idx++;
 824
 825            /* path[idx] == parent */
 826            /* find the immediately next node (and its parent) */
 827            while (next->left_child) {
 828                path[++idx] = nextp = next;
 829                next = next->left;
 830            }
 831
 832            path[old_idx] = next;
 833            balance = path[idx];
 834
 835            /* remove 'next' from the tree */
 836            if (nextp != node) {
 837                if (next->right_child) {
 838                    nextp->left = next->right;
 839                } else {
 840                    nextp->left_child = FALSE;
 841                }
 842                nextp->balance += 1;
 843
 844                next->right_child = TRUE;
 845                next->right = node->right;
 846            } else {
 847                node->balance -= 1;
 848            }
 849
 850            /* set the prev to point to the right place */
 851            while (prev->right_child) {
 852                prev = prev->right;
 853            }
 854            prev->right = next;
 855
 856            /* prepare 'next' to replace 'node' */
 857            next->left_child = TRUE;
 858            next->left = node->left;
 859            next->balance = node->balance;
 860
 861            if (!parent) {
 862                tree->root = next;
 863            } else if (left_node) {
 864                parent->left = next;
 865            } else {
 866                parent->right = next;
 867            }
 868        }
 869    }
 870
 871    /* restore balance */
 872    if (balance) {
 873        while (1) {
 874            QTreeNode *bparent = path[--idx];
 875            g_assert(!bparent ||
 876                     bparent->left == balance ||
 877                     bparent->right == balance);
 878            left_node = (bparent && balance == bparent->left);
 879
 880            if (balance->balance < -1 || balance->balance > 1) {
 881                balance = q_tree_node_balance(balance);
 882                if (!bparent) {
 883                    tree->root = balance;
 884                } else if (left_node) {
 885                    bparent->left = balance;
 886                } else {
 887                    bparent->right = balance;
 888                }
 889            }
 890
 891            if (balance->balance != 0 || !bparent) {
 892                break;
 893            }
 894
 895            if (left_node) {
 896                bparent->balance += 1;
 897            } else {
 898                bparent->balance -= 1;
 899            }
 900
 901            balance = bparent;
 902        }
 903    }
 904
 905    if (!steal) {
 906        if (tree->key_destroy_func) {
 907            tree->key_destroy_func(node->key);
 908        }
 909        if (tree->value_destroy_func) {
 910            tree->value_destroy_func(node->value);
 911        }
 912    }
 913
 914    g_free(node);
 915
 916    tree->nnodes--;
 917
 918    return TRUE;
 919}
 920
 921/**
 922 * q_tree_lookup_node:
 923 * @tree: a #QTree
 924 * @key: the key to look up
 925 *
 926 * Gets the tree node corresponding to the given key. Since a #QTree is
 927 * automatically balanced as key/value pairs are added, key lookup
 928 * is O(log n) (where n is the number of key/value pairs in the tree).
 929 *
 930 * Returns: (nullable) (transfer none): the tree node corresponding to
 931 *          the key, or %NULL if the key was not found
 932 *
 933 * Since: 2.68 in GLib. Internal in Qtree, i.e. not in the public API.
 934 */
 935static QTreeNode *
 936q_tree_lookup_node(QTree         *tree,
 937                   gconstpointer  key)
 938{
 939    g_return_val_if_fail(tree != NULL, NULL);
 940
 941    return q_tree_find_node(tree, key);
 942}
 943
 944/**
 945 * q_tree_lookup:
 946 * @tree: a #QTree
 947 * @key: the key to look up
 948 *
 949 * Gets the value corresponding to the given key. Since a #QTree is
 950 * automatically balanced as key/value pairs are added, key lookup
 951 * is O(log n) (where n is the number of key/value pairs in the tree).
 952 *
 953 * Returns: the value corresponding to the key, or %NULL
 954 *     if the key was not found
 955 */
 956gpointer
 957q_tree_lookup(QTree         *tree,
 958              gconstpointer  key)
 959{
 960    QTreeNode *node;
 961
 962    node = q_tree_lookup_node(tree, key);
 963
 964    return node ? node->value : NULL;
 965}
 966
 967/**
 968 * q_tree_lookup_extended:
 969 * @tree: a #QTree
 970 * @lookup_key: the key to look up
 971 * @orig_key: (out) (optional) (nullable): returns the original key
 972 * @value: (out) (optional) (nullable): returns the value associated with
 973 *         the key
 974 *
 975 * Looks up a key in the #QTree, returning the original key and the
 976 * associated value. This is useful if you need to free the memory
 977 * allocated for the original key, for example before calling
 978 * q_tree_remove().
 979 *
 980 * Returns: %TRUE if the key was found in the #QTree
 981 */
 982gboolean
 983q_tree_lookup_extended(QTree         *tree,
 984                       gconstpointer  lookup_key,
 985                       gpointer      *orig_key,
 986                       gpointer      *value)
 987{
 988    QTreeNode *node;
 989
 990    g_return_val_if_fail(tree != NULL, FALSE);
 991
 992    node = q_tree_find_node(tree, lookup_key);
 993
 994    if (node) {
 995        if (orig_key) {
 996            *orig_key = node->key;
 997        }
 998        if (value) {
 999            *value = node->value;
1000        }
1001        return TRUE;
1002    } else {
1003        return FALSE;
1004    }
1005}
1006
1007/**
1008 * q_tree_foreach:
1009 * @tree: a #QTree
1010 * @func: the function to call for each node visited.
1011 *     If this function returns %TRUE, the traversal is stopped.
1012 * @user_data: user data to pass to the function
1013 *
1014 * Calls the given function for each of the key/value pairs in the #QTree.
1015 * The function is passed the key and value of each pair, and the given
1016 * @data parameter. The tree is traversed in sorted order.
1017 *
1018 * The tree may not be modified while iterating over it (you can't
1019 * add/remove items). To remove all items matching a predicate, you need
1020 * to add each item to a list in your #GTraverseFunc as you walk over
1021 * the tree, then walk the list and remove each item.
1022 */
1023void
1024q_tree_foreach(QTree         *tree,
1025               GTraverseFunc  func,
1026               gpointer       user_data)
1027{
1028    QTreeNode *node;
1029
1030    g_return_if_fail(tree != NULL);
1031
1032    if (!tree->root) {
1033        return;
1034    }
1035
1036    node = q_tree_node_first(tree);
1037
1038    while (node) {
1039        if ((*func)(node->key, node->value, user_data)) {
1040            break;
1041        }
1042
1043        node = q_tree_node_next(node);
1044    }
1045}
1046
1047/**
1048 * q_tree_search_node:
1049 * @tree: a #QTree
1050 * @search_func: a function used to search the #QTree
1051 * @user_data: the data passed as the second argument to @search_func
1052 *
1053 * Searches a #QTree using @search_func.
1054 *
1055 * The @search_func is called with a pointer to the key of a key/value
1056 * pair in the tree, and the passed in @user_data. If @search_func returns
1057 * 0 for a key/value pair, then the corresponding node is returned as
1058 * the result of q_tree_search(). If @search_func returns -1, searching
1059 * will proceed among the key/value pairs that have a smaller key; if
1060 * @search_func returns 1, searching will proceed among the key/value
1061 * pairs that have a larger key.
1062 *
1063 * Returns: (nullable) (transfer none): the node corresponding to the
1064 *          found key, or %NULL if the key was not found
1065 *
1066 * Since: 2.68 in GLib. Internal in Qtree, i.e. not in the public API.
1067 */
1068static QTreeNode *
1069q_tree_search_node(QTree         *tree,
1070                   GCompareFunc   search_func,
1071                   gconstpointer  user_data)
1072{
1073    g_return_val_if_fail(tree != NULL, NULL);
1074
1075    if (!tree->root) {
1076        return NULL;
1077    }
1078
1079    return q_tree_node_search(tree->root, search_func, user_data);
1080}
1081
1082/**
1083 * q_tree_search:
1084 * @tree: a #QTree
1085 * @search_func: a function used to search the #QTree
1086 * @user_data: the data passed as the second argument to @search_func
1087 *
1088 * Searches a #QTree using @search_func.
1089 *
1090 * The @search_func is called with a pointer to the key of a key/value
1091 * pair in the tree, and the passed in @user_data. If @search_func returns
1092 * 0 for a key/value pair, then the corresponding value is returned as
1093 * the result of q_tree_search(). If @search_func returns -1, searching
1094 * will proceed among the key/value pairs that have a smaller key; if
1095 * @search_func returns 1, searching will proceed among the key/value
1096 * pairs that have a larger key.
1097 *
1098 * Returns: the value corresponding to the found key, or %NULL
1099 *     if the key was not found
1100 */
1101gpointer
1102q_tree_search(QTree         *tree,
1103              GCompareFunc   search_func,
1104              gconstpointer  user_data)
1105{
1106    QTreeNode *node;
1107
1108    node = q_tree_search_node(tree, search_func, user_data);
1109
1110    return node ? node->value : NULL;
1111}
1112
1113/**
1114 * q_tree_height:
1115 * @tree: a #QTree
1116 *
1117 * Gets the height of a #QTree.
1118 *
1119 * If the #QTree contains no nodes, the height is 0.
1120 * If the #QTree contains only one root node the height is 1.
1121 * If the root node has children the height is 2, etc.
1122 *
1123 * Returns: the height of @tree
1124 */
1125gint
1126q_tree_height(QTree *tree)
1127{
1128    QTreeNode *node;
1129    gint height;
1130
1131    g_return_val_if_fail(tree != NULL, 0);
1132
1133    if (!tree->root) {
1134        return 0;
1135    }
1136
1137    height = 0;
1138    node = tree->root;
1139
1140    while (1) {
1141        height += 1 + MAX(node->balance, 0);
1142
1143        if (!node->left_child) {
1144            return height;
1145        }
1146
1147        node = node->left;
1148    }
1149}
1150
1151/**
1152 * q_tree_nnodes:
1153 * @tree: a #QTree
1154 *
1155 * Gets the number of nodes in a #QTree.
1156 *
1157 * Returns: the number of nodes in @tree
1158 */
1159gint
1160q_tree_nnodes(QTree *tree)
1161{
1162    g_return_val_if_fail(tree != NULL, 0);
1163
1164    return tree->nnodes;
1165}
1166
1167static QTreeNode *
1168q_tree_node_balance(QTreeNode *node)
1169{
1170    if (node->balance < -1) {
1171        if (node->left->balance > 0) {
1172            node->left = q_tree_node_rotate_left(node->left);
1173        }
1174        node = q_tree_node_rotate_right(node);
1175    } else if (node->balance > 1) {
1176        if (node->right->balance < 0) {
1177            node->right = q_tree_node_rotate_right(node->right);
1178        }
1179        node = q_tree_node_rotate_left(node);
1180    }
1181
1182    return node;
1183}
1184
1185static QTreeNode * QEMU_DISABLE_CFI
1186q_tree_find_node(QTree        *tree,
1187                 gconstpointer key)
1188{
1189    QTreeNode *node;
1190    gint cmp;
1191
1192    node = tree->root;
1193    if (!node) {
1194        return NULL;
1195    }
1196
1197    while (1) {
1198        cmp = tree->key_compare(key, node->key, tree->key_compare_data);
1199        if (cmp == 0) {
1200            return node;
1201        } else if (cmp < 0) {
1202            if (!node->left_child) {
1203                return NULL;
1204            }
1205
1206            node = node->left;
1207        } else {
1208            if (!node->right_child) {
1209                return NULL;
1210            }
1211
1212            node = node->right;
1213        }
1214    }
1215}
1216
1217static QTreeNode *
1218q_tree_node_search(QTreeNode     *node,
1219                   GCompareFunc   search_func,
1220                   gconstpointer  data)
1221{
1222    gint dir;
1223
1224    if (!node) {
1225        return NULL;
1226    }
1227
1228    while (1) {
1229        dir = (*search_func)(node->key, data);
1230        if (dir == 0) {
1231            return node;
1232        } else if (dir < 0) {
1233            if (!node->left_child) {
1234                return NULL;
1235            }
1236
1237            node = node->left;
1238        } else {
1239            if (!node->right_child) {
1240                return NULL;
1241            }
1242
1243            node = node->right;
1244        }
1245    }
1246}
1247
1248static QTreeNode *
1249q_tree_node_rotate_left(QTreeNode *node)
1250{
1251    QTreeNode *right;
1252    gint a_bal;
1253    gint b_bal;
1254
1255    right = node->right;
1256
1257    if (right->left_child) {
1258        node->right = right->left;
1259    } else {
1260        node->right_child = FALSE;
1261        right->left_child = TRUE;
1262    }
1263    right->left = node;
1264
1265    a_bal = node->balance;
1266    b_bal = right->balance;
1267
1268    if (b_bal <= 0) {
1269        if (a_bal >= 1) {
1270            right->balance = b_bal - 1;
1271        } else {
1272            right->balance = a_bal + b_bal - 2;
1273        }
1274        node->balance = a_bal - 1;
1275    } else {
1276        if (a_bal <= b_bal) {
1277            right->balance = a_bal - 2;
1278        } else {
1279            right->balance = b_bal - 1;
1280        }
1281        node->balance = a_bal - b_bal - 1;
1282    }
1283
1284    return right;
1285}
1286
1287static QTreeNode *
1288q_tree_node_rotate_right(QTreeNode *node)
1289{
1290    QTreeNode *left;
1291    gint a_bal;
1292    gint b_bal;
1293
1294    left = node->left;
1295
1296    if (left->right_child) {
1297        node->left = left->right;
1298    } else {
1299        node->left_child = FALSE;
1300        left->right_child = TRUE;
1301    }
1302    left->right = node;
1303
1304    a_bal = node->balance;
1305    b_bal = left->balance;
1306
1307    if (b_bal <= 0) {
1308        if (b_bal > a_bal) {
1309            left->balance = b_bal + 1;
1310        } else {
1311            left->balance = a_bal + 2;
1312        }
1313        node->balance = a_bal - b_bal + 1;
1314    } else {
1315        if (a_bal <= -1) {
1316            left->balance = b_bal + 1;
1317        } else {
1318            left->balance = a_bal + b_bal + 2;
1319        }
1320        node->balance = a_bal + 1;
1321    }
1322
1323    return left;
1324}
1325
1326#ifdef Q_TREE_DEBUG
1327static gint
1328q_tree_node_height(QTreeNode *node)
1329{
1330    gint left_height;
1331    gint right_height;
1332
1333    if (node) {
1334        left_height = 0;
1335        right_height = 0;
1336
1337        if (node->left_child) {
1338            left_height = q_tree_node_height(node->left);
1339        }
1340
1341        if (node->right_child) {
1342            right_height = q_tree_node_height(node->right);
1343        }
1344
1345        return MAX(left_height, right_height) + 1;
1346    }
1347
1348    return 0;
1349}
1350
1351static void q_tree_node_check(QTreeNode *node)
1352{
1353    gint left_height;
1354    gint right_height;
1355    gint balance;
1356    QTreeNode *tmp;
1357
1358    if (node) {
1359        if (node->left_child) {
1360            tmp = q_tree_node_previous(node);
1361            g_assert(tmp->right == node);
1362        }
1363
1364        if (node->right_child) {
1365            tmp = q_tree_node_next(node);
1366            g_assert(tmp->left == node);
1367        }
1368
1369        left_height = 0;
1370        right_height = 0;
1371
1372        if (node->left_child) {
1373            left_height = q_tree_node_height(node->left);
1374        }
1375        if (node->right_child) {
1376            right_height = q_tree_node_height(node->right);
1377        }
1378
1379        balance = right_height - left_height;
1380        g_assert(balance == node->balance);
1381
1382        if (node->left_child) {
1383            q_tree_node_check(node->left);
1384        }
1385        if (node->right_child) {
1386            q_tree_node_check(node->right);
1387        }
1388    }
1389}
1390#endif
1391