| /* | 
 |  * GLIB - Library of useful routines for C programming | 
 |  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald | 
 |  * | 
 |  * SPDX-License-Identifier: LGPL-2.1-or-later | 
 |  * | 
 |  * This library is free software; you can redistribute it and/or | 
 |  * modify it under the terms of the GNU Lesser General Public | 
 |  * License as published by the Free Software Foundation; either | 
 |  * version 2.1 of the License, or (at your option) any later version. | 
 |  * | 
 |  * This library is distributed in the hope that it will be useful, | 
 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 |  * Lesser General Public License for more details. | 
 |  * | 
 |  * You should have received a copy of the GNU Lesser General Public | 
 |  * License along with this library; if not, see <http://www.gnu.org/licenses/>. | 
 |  */ | 
 |  | 
 | /* | 
 |  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS | 
 |  * file for a list of people on the GLib Team.  See the ChangeLog | 
 |  * files for a list of changes.  These files are distributed with | 
 |  * GLib at ftp://ftp.gtk.org/pub/gtk/. | 
 |  */ | 
 |  | 
 | /* | 
 |  * MT safe | 
 |  */ | 
 |  | 
 | #include "qemu/osdep.h" | 
 | #include "qemu/qtree.h" | 
 |  | 
 | /** | 
 |  * SECTION:trees-binary | 
 |  * @title: Balanced Binary Trees | 
 |  * @short_description: a sorted collection of key/value pairs optimized | 
 |  *                     for searching and traversing in order | 
 |  * | 
 |  * The #QTree structure and its associated functions provide a sorted | 
 |  * collection of key/value pairs optimized for searching and traversing | 
 |  * in order. This means that most of the operations  (access, search, | 
 |  * insertion, deletion, ...) on #QTree are O(log(n)) in average and O(n) | 
 |  * in worst case for time complexity. But, note that maintaining a | 
 |  * balanced sorted #QTree of n elements is done in time O(n log(n)). | 
 |  * | 
 |  * To create a new #QTree use q_tree_new(). | 
 |  * | 
 |  * To insert a key/value pair into a #QTree use q_tree_insert() | 
 |  * (O(n log(n))). | 
 |  * | 
 |  * To remove a key/value pair use q_tree_remove() (O(n log(n))). | 
 |  * | 
 |  * To look up the value corresponding to a given key, use | 
 |  * q_tree_lookup() and q_tree_lookup_extended(). | 
 |  * | 
 |  * To find out the number of nodes in a #QTree, use q_tree_nnodes(). To | 
 |  * get the height of a #QTree, use q_tree_height(). | 
 |  * | 
 |  * To traverse a #QTree, calling a function for each node visited in | 
 |  * the traversal, use q_tree_foreach(). | 
 |  * | 
 |  * To destroy a #QTree, use q_tree_destroy(). | 
 |  **/ | 
 |  | 
 | #define MAX_GTREE_HEIGHT 40 | 
 |  | 
 | /** | 
 |  * QTree: | 
 |  * | 
 |  * The QTree struct is an opaque data structure representing a | 
 |  * [balanced binary tree][glib-Balanced-Binary-Trees]. It should be | 
 |  * accessed only by using the following functions. | 
 |  */ | 
 | struct _QTree { | 
 |     QTreeNode        *root; | 
 |     GCompareDataFunc  key_compare; | 
 |     GDestroyNotify    key_destroy_func; | 
 |     GDestroyNotify    value_destroy_func; | 
 |     gpointer          key_compare_data; | 
 |     guint             nnodes; | 
 |     gint              ref_count; | 
 | }; | 
 |  | 
 | struct _QTreeNode { | 
 |     gpointer   key;         /* key for this node */ | 
 |     gpointer   value;       /* value stored at this node */ | 
 |     QTreeNode *left;        /* left subtree */ | 
 |     QTreeNode *right;       /* right subtree */ | 
 |     gint8      balance;     /* height (right) - height (left) */ | 
 |     guint8     left_child; | 
 |     guint8     right_child; | 
 | }; | 
 |  | 
 |  | 
 | static QTreeNode *q_tree_node_new(gpointer       key, | 
 |                                   gpointer       value); | 
 | static QTreeNode *q_tree_insert_internal(QTree *tree, | 
 |                                          gpointer key, | 
 |                                          gpointer value, | 
 |                                          gboolean replace); | 
 | static gboolean   q_tree_remove_internal(QTree         *tree, | 
 |                                          gconstpointer  key, | 
 |                                          gboolean       steal); | 
 | static QTreeNode *q_tree_node_balance(QTreeNode     *node); | 
 | static QTreeNode *q_tree_find_node(QTree         *tree, | 
 |                                    gconstpointer  key); | 
 | static QTreeNode *q_tree_node_search(QTreeNode *node, | 
 |                                      GCompareFunc search_func, | 
 |                                      gconstpointer data); | 
 | static QTreeNode *q_tree_node_rotate_left(QTreeNode     *node); | 
 | static QTreeNode *q_tree_node_rotate_right(QTreeNode     *node); | 
 | #ifdef Q_TREE_DEBUG | 
 | static void       q_tree_node_check(QTreeNode     *node); | 
 | #endif | 
 |  | 
 | static QTreeNode* | 
 | q_tree_node_new(gpointer key, | 
 |                 gpointer value) | 
 | { | 
 |     QTreeNode *node = g_new(QTreeNode, 1); | 
 |  | 
 |     node->balance = 0; | 
 |     node->left = NULL; | 
 |     node->right = NULL; | 
 |     node->left_child = FALSE; | 
 |     node->right_child = FALSE; | 
 |     node->key = key; | 
 |     node->value = value; | 
 |  | 
 |     return node; | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_new: | 
 |  * @key_compare_func: the function used to order the nodes in the #QTree. | 
 |  *   It should return values similar to the standard strcmp() function - | 
 |  *   0 if the two arguments are equal, a negative value if the first argument | 
 |  *   comes before the second, or a positive value if the first argument comes | 
 |  *   after the second. | 
 |  * | 
 |  * Creates a new #QTree. | 
 |  * | 
 |  * Returns: a newly allocated #QTree | 
 |  */ | 
 | QTree * | 
 | q_tree_new(GCompareFunc key_compare_func) | 
 | { | 
 |     g_return_val_if_fail(key_compare_func != NULL, NULL); | 
 |  | 
 |     return q_tree_new_full((GCompareDataFunc) key_compare_func, NULL, | 
 |                            NULL, NULL); | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_new_with_data: | 
 |  * @key_compare_func: qsort()-style comparison function | 
 |  * @key_compare_data: data to pass to comparison function | 
 |  * | 
 |  * Creates a new #QTree with a comparison function that accepts user data. | 
 |  * See q_tree_new() for more details. | 
 |  * | 
 |  * Returns: a newly allocated #QTree | 
 |  */ | 
 | QTree * | 
 | q_tree_new_with_data(GCompareDataFunc key_compare_func, | 
 |                      gpointer         key_compare_data) | 
 | { | 
 |     g_return_val_if_fail(key_compare_func != NULL, NULL); | 
 |  | 
 |     return q_tree_new_full(key_compare_func, key_compare_data, | 
 |                            NULL, NULL); | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_new_full: | 
 |  * @key_compare_func: qsort()-style comparison function | 
 |  * @key_compare_data: data to pass to comparison function | 
 |  * @key_destroy_func: a function to free the memory allocated for the key | 
 |  *   used when removing the entry from the #QTree or %NULL if you don't | 
 |  *   want to supply such a function | 
 |  * @value_destroy_func: a function to free the memory allocated for the | 
 |  *   value used when removing the entry from the #QTree or %NULL if you | 
 |  *   don't want to supply such a function | 
 |  * | 
 |  * Creates a new #QTree like q_tree_new() and allows to specify functions | 
 |  * to free the memory allocated for the key and value that get called when | 
 |  * removing the entry from the #QTree. | 
 |  * | 
 |  * Returns: a newly allocated #QTree | 
 |  */ | 
 | QTree * | 
 | q_tree_new_full(GCompareDataFunc key_compare_func, | 
 |                 gpointer         key_compare_data, | 
 |                 GDestroyNotify   key_destroy_func, | 
 |                 GDestroyNotify   value_destroy_func) | 
 | { | 
 |     QTree *tree; | 
 |  | 
 |     g_return_val_if_fail(key_compare_func != NULL, NULL); | 
 |  | 
 |     tree = g_new(QTree, 1); | 
 |     tree->root               = NULL; | 
 |     tree->key_compare        = key_compare_func; | 
 |     tree->key_destroy_func   = key_destroy_func; | 
 |     tree->value_destroy_func = value_destroy_func; | 
 |     tree->key_compare_data   = key_compare_data; | 
 |     tree->nnodes             = 0; | 
 |     tree->ref_count          = 1; | 
 |  | 
 |     return tree; | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_node_first: | 
 |  * @tree: a #QTree | 
 |  * | 
 |  * Returns the first in-order node of the tree, or %NULL | 
 |  * for an empty tree. | 
 |  * | 
 |  * Returns: (nullable) (transfer none): the first node in the tree | 
 |  * | 
 |  * Since: 2.68 in GLib. Internal in Qtree, i.e. not in the public API. | 
 |  */ | 
 | static QTreeNode * | 
 | q_tree_node_first(QTree *tree) | 
 | { | 
 |     QTreeNode *tmp; | 
 |  | 
 |     g_return_val_if_fail(tree != NULL, NULL); | 
 |  | 
 |     if (!tree->root) { | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     tmp = tree->root; | 
 |  | 
 |     while (tmp->left_child) { | 
 |         tmp = tmp->left; | 
 |     } | 
 |  | 
 |     return tmp; | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_node_previous | 
 |  * @node: a #QTree node | 
 |  * | 
 |  * Returns the previous in-order node of the tree, or %NULL | 
 |  * if the passed node was already the first one. | 
 |  * | 
 |  * Returns: (nullable) (transfer none): the previous node in the tree | 
 |  * | 
 |  * Since: 2.68 in GLib. Internal in Qtree, i.e. not in the public API. | 
 |  */ | 
 | static QTreeNode * | 
 | q_tree_node_previous(QTreeNode *node) | 
 | { | 
 |     QTreeNode *tmp; | 
 |  | 
 |     g_return_val_if_fail(node != NULL, NULL); | 
 |  | 
 |     tmp = node->left; | 
 |  | 
 |     if (node->left_child) { | 
 |         while (tmp->right_child) { | 
 |             tmp = tmp->right; | 
 |         } | 
 |     } | 
 |  | 
 |     return tmp; | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_node_next | 
 |  * @node: a #QTree node | 
 |  * | 
 |  * Returns the next in-order node of the tree, or %NULL | 
 |  * if the passed node was already the last one. | 
 |  * | 
 |  * Returns: (nullable) (transfer none): the next node in the tree | 
 |  * | 
 |  * Since: 2.68 in GLib. Internal in Qtree, i.e. not in the public API. | 
 |  */ | 
 | static QTreeNode * | 
 | q_tree_node_next(QTreeNode *node) | 
 | { | 
 |     QTreeNode *tmp; | 
 |  | 
 |     g_return_val_if_fail(node != NULL, NULL); | 
 |  | 
 |     tmp = node->right; | 
 |  | 
 |     if (node->right_child) { | 
 |         while (tmp->left_child) { | 
 |             tmp = tmp->left; | 
 |         } | 
 |     } | 
 |  | 
 |     return tmp; | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_remove_all: | 
 |  * @tree: a #QTree | 
 |  * | 
 |  * Removes all nodes from a #QTree and destroys their keys and values, | 
 |  * then resets the #QTree’s root to %NULL. | 
 |  * | 
 |  * Since: 2.70 in GLib. Internal in Qtree, i.e. not in the public API. | 
 |  */ | 
 | static void QEMU_DISABLE_CFI | 
 | q_tree_remove_all(QTree *tree) | 
 | { | 
 |     QTreeNode *node; | 
 |     QTreeNode *next; | 
 |  | 
 |     g_return_if_fail(tree != NULL); | 
 |  | 
 |     node = q_tree_node_first(tree); | 
 |  | 
 |     while (node) { | 
 |         next = q_tree_node_next(node); | 
 |  | 
 |         if (tree->key_destroy_func) { | 
 |             tree->key_destroy_func(node->key); | 
 |         } | 
 |         if (tree->value_destroy_func) { | 
 |             tree->value_destroy_func(node->value); | 
 |         } | 
 |         g_free(node); | 
 |  | 
 | #ifdef Q_TREE_DEBUG | 
 |         g_assert(tree->nnodes > 0); | 
 |         tree->nnodes--; | 
 | #endif | 
 |  | 
 |         node = next; | 
 |     } | 
 |  | 
 | #ifdef Q_TREE_DEBUG | 
 |     g_assert(tree->nnodes == 0); | 
 | #endif | 
 |  | 
 |     tree->root = NULL; | 
 | #ifndef Q_TREE_DEBUG | 
 |     tree->nnodes = 0; | 
 | #endif | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_ref: | 
 |  * @tree: a #QTree | 
 |  * | 
 |  * Increments the reference count of @tree by one. | 
 |  * | 
 |  * It is safe to call this function from any thread. | 
 |  * | 
 |  * Returns: the passed in #QTree | 
 |  * | 
 |  * Since: 2.22 | 
 |  */ | 
 | QTree * | 
 | q_tree_ref(QTree *tree) | 
 | { | 
 |     g_return_val_if_fail(tree != NULL, NULL); | 
 |  | 
 |     g_atomic_int_inc(&tree->ref_count); | 
 |  | 
 |     return tree; | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_unref: | 
 |  * @tree: a #QTree | 
 |  * | 
 |  * Decrements the reference count of @tree by one. | 
 |  * If the reference count drops to 0, all keys and values will | 
 |  * be destroyed (if destroy functions were specified) and all | 
 |  * memory allocated by @tree will be released. | 
 |  * | 
 |  * It is safe to call this function from any thread. | 
 |  * | 
 |  * Since: 2.22 | 
 |  */ | 
 | void | 
 | q_tree_unref(QTree *tree) | 
 | { | 
 |     g_return_if_fail(tree != NULL); | 
 |  | 
 |     if (g_atomic_int_dec_and_test(&tree->ref_count)) { | 
 |         q_tree_remove_all(tree); | 
 |         g_free(tree); | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_destroy: | 
 |  * @tree: a #QTree | 
 |  * | 
 |  * Removes all keys and values from the #QTree and decreases its | 
 |  * reference count by one. If keys and/or values are dynamically | 
 |  * allocated, you should either free them first or create the #QTree | 
 |  * using q_tree_new_full(). In the latter case the destroy functions | 
 |  * you supplied will be called on all keys and values before destroying | 
 |  * the #QTree. | 
 |  */ | 
 | void | 
 | q_tree_destroy(QTree *tree) | 
 | { | 
 |     g_return_if_fail(tree != NULL); | 
 |  | 
 |     q_tree_remove_all(tree); | 
 |     q_tree_unref(tree); | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_insert_node: | 
 |  * @tree: a #QTree | 
 |  * @key: the key to insert | 
 |  * @value: the value corresponding to the key | 
 |  * | 
 |  * Inserts a key/value pair into a #QTree. | 
 |  * | 
 |  * If the given key already exists in the #QTree its corresponding value | 
 |  * is set to the new value. If you supplied a @value_destroy_func when | 
 |  * creating the #QTree, the old value is freed using that function. If | 
 |  * you supplied a @key_destroy_func when creating the #QTree, the passed | 
 |  * key is freed using that function. | 
 |  * | 
 |  * The tree is automatically 'balanced' as new key/value pairs are added, | 
 |  * so that the distance from the root to every leaf is as small as possible. | 
 |  * The cost of maintaining a balanced tree while inserting new key/value | 
 |  * result in a O(n log(n)) operation where most of the other operations | 
 |  * are O(log(n)). | 
 |  * | 
 |  * Returns: (transfer none): the inserted (or set) node. | 
 |  * | 
 |  * Since: 2.68 in GLib. Internal in Qtree, i.e. not in the public API. | 
 |  */ | 
 | static QTreeNode * | 
 | q_tree_insert_node(QTree    *tree, | 
 |                    gpointer  key, | 
 |                    gpointer  value) | 
 | { | 
 |     QTreeNode *node; | 
 |  | 
 |     g_return_val_if_fail(tree != NULL, NULL); | 
 |  | 
 |     node = q_tree_insert_internal(tree, key, value, FALSE); | 
 |  | 
 | #ifdef Q_TREE_DEBUG | 
 |     q_tree_node_check(tree->root); | 
 | #endif | 
 |  | 
 |     return node; | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_insert: | 
 |  * @tree: a #QTree | 
 |  * @key: the key to insert | 
 |  * @value: the value corresponding to the key | 
 |  * | 
 |  * Inserts a key/value pair into a #QTree. | 
 |  * | 
 |  * Inserts a new key and value into a #QTree as q_tree_insert_node() does, | 
 |  * only this function does not return the inserted or set node. | 
 |  */ | 
 | void | 
 | q_tree_insert(QTree    *tree, | 
 |               gpointer  key, | 
 |               gpointer  value) | 
 | { | 
 |     q_tree_insert_node(tree, key, value); | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_replace_node: | 
 |  * @tree: a #QTree | 
 |  * @key: the key to insert | 
 |  * @value: the value corresponding to the key | 
 |  * | 
 |  * Inserts a new key and value into a #QTree similar to q_tree_insert_node(). | 
 |  * The difference is that if the key already exists in the #QTree, it gets | 
 |  * replaced by the new key. If you supplied a @value_destroy_func when | 
 |  * creating the #QTree, the old value is freed using that function. If you | 
 |  * supplied a @key_destroy_func when creating the #QTree, the old key is | 
 |  * freed using that function. | 
 |  * | 
 |  * The tree is automatically 'balanced' as new key/value pairs are added, | 
 |  * so that the distance from the root to every leaf is as small as possible. | 
 |  * | 
 |  * Returns: (transfer none): the inserted (or set) node. | 
 |  * | 
 |  * Since: 2.68 in GLib. Internal in Qtree, i.e. not in the public API. | 
 |  */ | 
 | static QTreeNode * | 
 | q_tree_replace_node(QTree    *tree, | 
 |                     gpointer  key, | 
 |                     gpointer  value) | 
 | { | 
 |     QTreeNode *node; | 
 |  | 
 |     g_return_val_if_fail(tree != NULL, NULL); | 
 |  | 
 |     node = q_tree_insert_internal(tree, key, value, TRUE); | 
 |  | 
 | #ifdef Q_TREE_DEBUG | 
 |     q_tree_node_check(tree->root); | 
 | #endif | 
 |  | 
 |     return node; | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_replace: | 
 |  * @tree: a #QTree | 
 |  * @key: the key to insert | 
 |  * @value: the value corresponding to the key | 
 |  * | 
 |  * Inserts a new key and value into a #QTree as q_tree_replace_node() does, | 
 |  * only this function does not return the inserted or set node. | 
 |  */ | 
 | void | 
 | q_tree_replace(QTree    *tree, | 
 |                gpointer  key, | 
 |                gpointer  value) | 
 | { | 
 |     q_tree_replace_node(tree, key, value); | 
 | } | 
 |  | 
 | /* internal insert routine */ | 
 | static QTreeNode * QEMU_DISABLE_CFI | 
 | q_tree_insert_internal(QTree    *tree, | 
 |                        gpointer  key, | 
 |                        gpointer  value, | 
 |                        gboolean  replace) | 
 | { | 
 |     QTreeNode *node, *retnode; | 
 |     QTreeNode *path[MAX_GTREE_HEIGHT]; | 
 |     int idx; | 
 |  | 
 |     g_return_val_if_fail(tree != NULL, NULL); | 
 |  | 
 |     if (!tree->root) { | 
 |         tree->root = q_tree_node_new(key, value); | 
 |         tree->nnodes++; | 
 |         return tree->root; | 
 |     } | 
 |  | 
 |     idx = 0; | 
 |     path[idx++] = NULL; | 
 |     node = tree->root; | 
 |  | 
 |     while (1) { | 
 |         int cmp = tree->key_compare(key, node->key, tree->key_compare_data); | 
 |  | 
 |         if (cmp == 0) { | 
 |             if (tree->value_destroy_func) { | 
 |                 tree->value_destroy_func(node->value); | 
 |             } | 
 |  | 
 |             node->value = value; | 
 |  | 
 |             if (replace) { | 
 |                 if (tree->key_destroy_func) { | 
 |                     tree->key_destroy_func(node->key); | 
 |                 } | 
 |  | 
 |                 node->key = key; | 
 |             } else { | 
 |                 /* free the passed key */ | 
 |                 if (tree->key_destroy_func) { | 
 |                     tree->key_destroy_func(key); | 
 |                 } | 
 |             } | 
 |  | 
 |             return node; | 
 |         } else if (cmp < 0) { | 
 |             if (node->left_child) { | 
 |                 path[idx++] = node; | 
 |                 node = node->left; | 
 |             } else { | 
 |                 QTreeNode *child = q_tree_node_new(key, value); | 
 |  | 
 |                 child->left = node->left; | 
 |                 child->right = node; | 
 |                 node->left = child; | 
 |                 node->left_child = TRUE; | 
 |                 node->balance -= 1; | 
 |  | 
 |                 tree->nnodes++; | 
 |  | 
 |                 retnode = child; | 
 |                 break; | 
 |             } | 
 |         } else { | 
 |             if (node->right_child) { | 
 |                 path[idx++] = node; | 
 |                 node = node->right; | 
 |             } else { | 
 |                 QTreeNode *child = q_tree_node_new(key, value); | 
 |  | 
 |                 child->right = node->right; | 
 |                 child->left = node; | 
 |                 node->right = child; | 
 |                 node->right_child = TRUE; | 
 |                 node->balance += 1; | 
 |  | 
 |                 tree->nnodes++; | 
 |  | 
 |                 retnode = child; | 
 |                 break; | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     /* | 
 |      * Restore balance. This is the goodness of a non-recursive | 
 |      * implementation, when we are done with balancing we 'break' | 
 |      * the loop and we are done. | 
 |      */ | 
 |     while (1) { | 
 |         QTreeNode *bparent = path[--idx]; | 
 |         gboolean left_node = (bparent && node == bparent->left); | 
 |         g_assert(!bparent || bparent->left == node || bparent->right == node); | 
 |  | 
 |         if (node->balance < -1 || node->balance > 1) { | 
 |             node = q_tree_node_balance(node); | 
 |             if (bparent == NULL) { | 
 |                 tree->root = node; | 
 |             } else if (left_node) { | 
 |                 bparent->left = node; | 
 |             } else { | 
 |                 bparent->right = node; | 
 |             } | 
 |         } | 
 |  | 
 |         if (node->balance == 0 || bparent == NULL) { | 
 |             break; | 
 |         } | 
 |  | 
 |         if (left_node) { | 
 |             bparent->balance -= 1; | 
 |         } else { | 
 |             bparent->balance += 1; | 
 |         } | 
 |  | 
 |         node = bparent; | 
 |     } | 
 |  | 
 |     return retnode; | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_remove: | 
 |  * @tree: a #QTree | 
 |  * @key: the key to remove | 
 |  * | 
 |  * Removes a key/value pair from a #QTree. | 
 |  * | 
 |  * If the #QTree was created using q_tree_new_full(), the key and value | 
 |  * are freed using the supplied destroy functions, otherwise you have to | 
 |  * make sure that any dynamically allocated values are freed yourself. | 
 |  * If the key does not exist in the #QTree, the function does nothing. | 
 |  * | 
 |  * The cost of maintaining a balanced tree while removing a key/value | 
 |  * result in a O(n log(n)) operation where most of the other operations | 
 |  * are O(log(n)). | 
 |  * | 
 |  * Returns: %TRUE if the key was found (prior to 2.8, this function | 
 |  *     returned nothing) | 
 |  */ | 
 | gboolean | 
 | q_tree_remove(QTree         *tree, | 
 |               gconstpointer  key) | 
 | { | 
 |     gboolean removed; | 
 |  | 
 |     g_return_val_if_fail(tree != NULL, FALSE); | 
 |  | 
 |     removed = q_tree_remove_internal(tree, key, FALSE); | 
 |  | 
 | #ifdef Q_TREE_DEBUG | 
 |     q_tree_node_check(tree->root); | 
 | #endif | 
 |  | 
 |     return removed; | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_steal: | 
 |  * @tree: a #QTree | 
 |  * @key: the key to remove | 
 |  * | 
 |  * Removes a key and its associated value from a #QTree without calling | 
 |  * the key and value destroy functions. | 
 |  * | 
 |  * If the key does not exist in the #QTree, the function does nothing. | 
 |  * | 
 |  * Returns: %TRUE if the key was found (prior to 2.8, this function | 
 |  *     returned nothing) | 
 |  */ | 
 | gboolean | 
 | q_tree_steal(QTree         *tree, | 
 |              gconstpointer  key) | 
 | { | 
 |     gboolean removed; | 
 |  | 
 |     g_return_val_if_fail(tree != NULL, FALSE); | 
 |  | 
 |     removed = q_tree_remove_internal(tree, key, TRUE); | 
 |  | 
 | #ifdef Q_TREE_DEBUG | 
 |     q_tree_node_check(tree->root); | 
 | #endif | 
 |  | 
 |     return removed; | 
 | } | 
 |  | 
 | /* internal remove routine */ | 
 | static gboolean QEMU_DISABLE_CFI | 
 | q_tree_remove_internal(QTree         *tree, | 
 |                        gconstpointer  key, | 
 |                        gboolean       steal) | 
 | { | 
 |     QTreeNode *node, *parent, *balance; | 
 |     QTreeNode *path[MAX_GTREE_HEIGHT]; | 
 |     int idx; | 
 |     gboolean left_node; | 
 |  | 
 |     g_return_val_if_fail(tree != NULL, FALSE); | 
 |  | 
 |     if (!tree->root) { | 
 |         return FALSE; | 
 |     } | 
 |  | 
 |     idx = 0; | 
 |     path[idx++] = NULL; | 
 |     node = tree->root; | 
 |  | 
 |     while (1) { | 
 |         int cmp = tree->key_compare(key, node->key, tree->key_compare_data); | 
 |  | 
 |         if (cmp == 0) { | 
 |             break; | 
 |         } else if (cmp < 0) { | 
 |             if (!node->left_child) { | 
 |                 return FALSE; | 
 |             } | 
 |  | 
 |             path[idx++] = node; | 
 |             node = node->left; | 
 |         } else { | 
 |             if (!node->right_child) { | 
 |                 return FALSE; | 
 |             } | 
 |  | 
 |             path[idx++] = node; | 
 |             node = node->right; | 
 |         } | 
 |     } | 
 |  | 
 |     /* | 
 |      * The following code is almost equal to q_tree_remove_node, | 
 |      * except that we do not have to call q_tree_node_parent. | 
 |      */ | 
 |     balance = parent = path[--idx]; | 
 |     g_assert(!parent || parent->left == node || parent->right == node); | 
 |     left_node = (parent && node == parent->left); | 
 |  | 
 |     if (!node->left_child) { | 
 |         if (!node->right_child) { | 
 |             if (!parent) { | 
 |                 tree->root = NULL; | 
 |             } else if (left_node) { | 
 |                 parent->left_child = FALSE; | 
 |                 parent->left = node->left; | 
 |                 parent->balance += 1; | 
 |             } else { | 
 |                 parent->right_child = FALSE; | 
 |                 parent->right = node->right; | 
 |                 parent->balance -= 1; | 
 |             } | 
 |         } else { | 
 |             /* node has a right child */ | 
 |             QTreeNode *tmp = q_tree_node_next(node); | 
 |             tmp->left = node->left; | 
 |  | 
 |             if (!parent) { | 
 |                 tree->root = node->right; | 
 |             } else if (left_node) { | 
 |                 parent->left = node->right; | 
 |                 parent->balance += 1; | 
 |             } else { | 
 |                 parent->right = node->right; | 
 |                 parent->balance -= 1; | 
 |             } | 
 |         } | 
 |     } else { | 
 |         /* node has a left child */ | 
 |         if (!node->right_child) { | 
 |             QTreeNode *tmp = q_tree_node_previous(node); | 
 |             tmp->right = node->right; | 
 |  | 
 |             if (parent == NULL) { | 
 |                 tree->root = node->left; | 
 |             } else if (left_node) { | 
 |                 parent->left = node->left; | 
 |                 parent->balance += 1; | 
 |             } else { | 
 |                 parent->right = node->left; | 
 |                 parent->balance -= 1; | 
 |             } | 
 |         } else { | 
 |             /* node has a both children (pant, pant!) */ | 
 |             QTreeNode *prev = node->left; | 
 |             QTreeNode *next = node->right; | 
 |             QTreeNode *nextp = node; | 
 |             int old_idx = idx + 1; | 
 |             idx++; | 
 |  | 
 |             /* path[idx] == parent */ | 
 |             /* find the immediately next node (and its parent) */ | 
 |             while (next->left_child) { | 
 |                 path[++idx] = nextp = next; | 
 |                 next = next->left; | 
 |             } | 
 |  | 
 |             path[old_idx] = next; | 
 |             balance = path[idx]; | 
 |  | 
 |             /* remove 'next' from the tree */ | 
 |             if (nextp != node) { | 
 |                 if (next->right_child) { | 
 |                     nextp->left = next->right; | 
 |                 } else { | 
 |                     nextp->left_child = FALSE; | 
 |                 } | 
 |                 nextp->balance += 1; | 
 |  | 
 |                 next->right_child = TRUE; | 
 |                 next->right = node->right; | 
 |             } else { | 
 |                 node->balance -= 1; | 
 |             } | 
 |  | 
 |             /* set the prev to point to the right place */ | 
 |             while (prev->right_child) { | 
 |                 prev = prev->right; | 
 |             } | 
 |             prev->right = next; | 
 |  | 
 |             /* prepare 'next' to replace 'node' */ | 
 |             next->left_child = TRUE; | 
 |             next->left = node->left; | 
 |             next->balance = node->balance; | 
 |  | 
 |             if (!parent) { | 
 |                 tree->root = next; | 
 |             } else if (left_node) { | 
 |                 parent->left = next; | 
 |             } else { | 
 |                 parent->right = next; | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     /* restore balance */ | 
 |     if (balance) { | 
 |         while (1) { | 
 |             QTreeNode *bparent = path[--idx]; | 
 |             g_assert(!bparent || | 
 |                      bparent->left == balance || | 
 |                      bparent->right == balance); | 
 |             left_node = (bparent && balance == bparent->left); | 
 |  | 
 |             if (balance->balance < -1 || balance->balance > 1) { | 
 |                 balance = q_tree_node_balance(balance); | 
 |                 if (!bparent) { | 
 |                     tree->root = balance; | 
 |                 } else if (left_node) { | 
 |                     bparent->left = balance; | 
 |                 } else { | 
 |                     bparent->right = balance; | 
 |                 } | 
 |             } | 
 |  | 
 |             if (balance->balance != 0 || !bparent) { | 
 |                 break; | 
 |             } | 
 |  | 
 |             if (left_node) { | 
 |                 bparent->balance += 1; | 
 |             } else { | 
 |                 bparent->balance -= 1; | 
 |             } | 
 |  | 
 |             balance = bparent; | 
 |         } | 
 |     } | 
 |  | 
 |     if (!steal) { | 
 |         if (tree->key_destroy_func) { | 
 |             tree->key_destroy_func(node->key); | 
 |         } | 
 |         if (tree->value_destroy_func) { | 
 |             tree->value_destroy_func(node->value); | 
 |         } | 
 |     } | 
 |  | 
 |     g_free(node); | 
 |  | 
 |     tree->nnodes--; | 
 |  | 
 |     return TRUE; | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_lookup_node: | 
 |  * @tree: a #QTree | 
 |  * @key: the key to look up | 
 |  * | 
 |  * Gets the tree node corresponding to the given key. Since a #QTree is | 
 |  * automatically balanced as key/value pairs are added, key lookup | 
 |  * is O(log n) (where n is the number of key/value pairs in the tree). | 
 |  * | 
 |  * Returns: (nullable) (transfer none): the tree node corresponding to | 
 |  *          the key, or %NULL if the key was not found | 
 |  * | 
 |  * Since: 2.68 in GLib. Internal in Qtree, i.e. not in the public API. | 
 |  */ | 
 | static QTreeNode * | 
 | q_tree_lookup_node(QTree         *tree, | 
 |                    gconstpointer  key) | 
 | { | 
 |     g_return_val_if_fail(tree != NULL, NULL); | 
 |  | 
 |     return q_tree_find_node(tree, key); | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_lookup: | 
 |  * @tree: a #QTree | 
 |  * @key: the key to look up | 
 |  * | 
 |  * Gets the value corresponding to the given key. Since a #QTree is | 
 |  * automatically balanced as key/value pairs are added, key lookup | 
 |  * is O(log n) (where n is the number of key/value pairs in the tree). | 
 |  * | 
 |  * Returns: the value corresponding to the key, or %NULL | 
 |  *     if the key was not found | 
 |  */ | 
 | gpointer | 
 | q_tree_lookup(QTree         *tree, | 
 |               gconstpointer  key) | 
 | { | 
 |     QTreeNode *node; | 
 |  | 
 |     node = q_tree_lookup_node(tree, key); | 
 |  | 
 |     return node ? node->value : NULL; | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_lookup_extended: | 
 |  * @tree: a #QTree | 
 |  * @lookup_key: the key to look up | 
 |  * @orig_key: (out) (optional) (nullable): returns the original key | 
 |  * @value: (out) (optional) (nullable): returns the value associated with | 
 |  *         the key | 
 |  * | 
 |  * Looks up a key in the #QTree, returning the original key and the | 
 |  * associated value. This is useful if you need to free the memory | 
 |  * allocated for the original key, for example before calling | 
 |  * q_tree_remove(). | 
 |  * | 
 |  * Returns: %TRUE if the key was found in the #QTree | 
 |  */ | 
 | gboolean | 
 | q_tree_lookup_extended(QTree         *tree, | 
 |                        gconstpointer  lookup_key, | 
 |                        gpointer      *orig_key, | 
 |                        gpointer      *value) | 
 | { | 
 |     QTreeNode *node; | 
 |  | 
 |     g_return_val_if_fail(tree != NULL, FALSE); | 
 |  | 
 |     node = q_tree_find_node(tree, lookup_key); | 
 |  | 
 |     if (node) { | 
 |         if (orig_key) { | 
 |             *orig_key = node->key; | 
 |         } | 
 |         if (value) { | 
 |             *value = node->value; | 
 |         } | 
 |         return TRUE; | 
 |     } else { | 
 |         return FALSE; | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_foreach: | 
 |  * @tree: a #QTree | 
 |  * @func: the function to call for each node visited. | 
 |  *     If this function returns %TRUE, the traversal is stopped. | 
 |  * @user_data: user data to pass to the function | 
 |  * | 
 |  * Calls the given function for each of the key/value pairs in the #QTree. | 
 |  * The function is passed the key and value of each pair, and the given | 
 |  * @data parameter. The tree is traversed in sorted order. | 
 |  * | 
 |  * The tree may not be modified while iterating over it (you can't | 
 |  * add/remove items). To remove all items matching a predicate, you need | 
 |  * to add each item to a list in your #GTraverseFunc as you walk over | 
 |  * the tree, then walk the list and remove each item. | 
 |  */ | 
 | void | 
 | q_tree_foreach(QTree         *tree, | 
 |                GTraverseFunc  func, | 
 |                gpointer       user_data) | 
 | { | 
 |     QTreeNode *node; | 
 |  | 
 |     g_return_if_fail(tree != NULL); | 
 |  | 
 |     if (!tree->root) { | 
 |         return; | 
 |     } | 
 |  | 
 |     node = q_tree_node_first(tree); | 
 |  | 
 |     while (node) { | 
 |         if ((*func)(node->key, node->value, user_data)) { | 
 |             break; | 
 |         } | 
 |  | 
 |         node = q_tree_node_next(node); | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_search_node: | 
 |  * @tree: a #QTree | 
 |  * @search_func: a function used to search the #QTree | 
 |  * @user_data: the data passed as the second argument to @search_func | 
 |  * | 
 |  * Searches a #QTree using @search_func. | 
 |  * | 
 |  * The @search_func is called with a pointer to the key of a key/value | 
 |  * pair in the tree, and the passed in @user_data. If @search_func returns | 
 |  * 0 for a key/value pair, then the corresponding node is returned as | 
 |  * the result of q_tree_search(). If @search_func returns -1, searching | 
 |  * will proceed among the key/value pairs that have a smaller key; if | 
 |  * @search_func returns 1, searching will proceed among the key/value | 
 |  * pairs that have a larger key. | 
 |  * | 
 |  * Returns: (nullable) (transfer none): the node corresponding to the | 
 |  *          found key, or %NULL if the key was not found | 
 |  * | 
 |  * Since: 2.68 in GLib. Internal in Qtree, i.e. not in the public API. | 
 |  */ | 
 | static QTreeNode * | 
 | q_tree_search_node(QTree         *tree, | 
 |                    GCompareFunc   search_func, | 
 |                    gconstpointer  user_data) | 
 | { | 
 |     g_return_val_if_fail(tree != NULL, NULL); | 
 |  | 
 |     if (!tree->root) { | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     return q_tree_node_search(tree->root, search_func, user_data); | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_search: | 
 |  * @tree: a #QTree | 
 |  * @search_func: a function used to search the #QTree | 
 |  * @user_data: the data passed as the second argument to @search_func | 
 |  * | 
 |  * Searches a #QTree using @search_func. | 
 |  * | 
 |  * The @search_func is called with a pointer to the key of a key/value | 
 |  * pair in the tree, and the passed in @user_data. If @search_func returns | 
 |  * 0 for a key/value pair, then the corresponding value is returned as | 
 |  * the result of q_tree_search(). If @search_func returns -1, searching | 
 |  * will proceed among the key/value pairs that have a smaller key; if | 
 |  * @search_func returns 1, searching will proceed among the key/value | 
 |  * pairs that have a larger key. | 
 |  * | 
 |  * Returns: the value corresponding to the found key, or %NULL | 
 |  *     if the key was not found | 
 |  */ | 
 | gpointer | 
 | q_tree_search(QTree         *tree, | 
 |               GCompareFunc   search_func, | 
 |               gconstpointer  user_data) | 
 | { | 
 |     QTreeNode *node; | 
 |  | 
 |     node = q_tree_search_node(tree, search_func, user_data); | 
 |  | 
 |     return node ? node->value : NULL; | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_height: | 
 |  * @tree: a #QTree | 
 |  * | 
 |  * Gets the height of a #QTree. | 
 |  * | 
 |  * If the #QTree contains no nodes, the height is 0. | 
 |  * If the #QTree contains only one root node the height is 1. | 
 |  * If the root node has children the height is 2, etc. | 
 |  * | 
 |  * Returns: the height of @tree | 
 |  */ | 
 | gint | 
 | q_tree_height(QTree *tree) | 
 | { | 
 |     QTreeNode *node; | 
 |     gint height; | 
 |  | 
 |     g_return_val_if_fail(tree != NULL, 0); | 
 |  | 
 |     if (!tree->root) { | 
 |         return 0; | 
 |     } | 
 |  | 
 |     height = 0; | 
 |     node = tree->root; | 
 |  | 
 |     while (1) { | 
 |         height += 1 + MAX(node->balance, 0); | 
 |  | 
 |         if (!node->left_child) { | 
 |             return height; | 
 |         } | 
 |  | 
 |         node = node->left; | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * q_tree_nnodes: | 
 |  * @tree: a #QTree | 
 |  * | 
 |  * Gets the number of nodes in a #QTree. | 
 |  * | 
 |  * Returns: the number of nodes in @tree | 
 |  */ | 
 | gint | 
 | q_tree_nnodes(QTree *tree) | 
 | { | 
 |     g_return_val_if_fail(tree != NULL, 0); | 
 |  | 
 |     return tree->nnodes; | 
 | } | 
 |  | 
 | static QTreeNode * | 
 | q_tree_node_balance(QTreeNode *node) | 
 | { | 
 |     if (node->balance < -1) { | 
 |         if (node->left->balance > 0) { | 
 |             node->left = q_tree_node_rotate_left(node->left); | 
 |         } | 
 |         node = q_tree_node_rotate_right(node); | 
 |     } else if (node->balance > 1) { | 
 |         if (node->right->balance < 0) { | 
 |             node->right = q_tree_node_rotate_right(node->right); | 
 |         } | 
 |         node = q_tree_node_rotate_left(node); | 
 |     } | 
 |  | 
 |     return node; | 
 | } | 
 |  | 
 | static QTreeNode * QEMU_DISABLE_CFI | 
 | q_tree_find_node(QTree        *tree, | 
 |                  gconstpointer key) | 
 | { | 
 |     QTreeNode *node; | 
 |     gint cmp; | 
 |  | 
 |     node = tree->root; | 
 |     if (!node) { | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     while (1) { | 
 |         cmp = tree->key_compare(key, node->key, tree->key_compare_data); | 
 |         if (cmp == 0) { | 
 |             return node; | 
 |         } else if (cmp < 0) { | 
 |             if (!node->left_child) { | 
 |                 return NULL; | 
 |             } | 
 |  | 
 |             node = node->left; | 
 |         } else { | 
 |             if (!node->right_child) { | 
 |                 return NULL; | 
 |             } | 
 |  | 
 |             node = node->right; | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | static QTreeNode * | 
 | q_tree_node_search(QTreeNode     *node, | 
 |                    GCompareFunc   search_func, | 
 |                    gconstpointer  data) | 
 | { | 
 |     gint dir; | 
 |  | 
 |     if (!node) { | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     while (1) { | 
 |         dir = (*search_func)(node->key, data); | 
 |         if (dir == 0) { | 
 |             return node; | 
 |         } else if (dir < 0) { | 
 |             if (!node->left_child) { | 
 |                 return NULL; | 
 |             } | 
 |  | 
 |             node = node->left; | 
 |         } else { | 
 |             if (!node->right_child) { | 
 |                 return NULL; | 
 |             } | 
 |  | 
 |             node = node->right; | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | static QTreeNode * | 
 | q_tree_node_rotate_left(QTreeNode *node) | 
 | { | 
 |     QTreeNode *right; | 
 |     gint a_bal; | 
 |     gint b_bal; | 
 |  | 
 |     right = node->right; | 
 |  | 
 |     if (right->left_child) { | 
 |         node->right = right->left; | 
 |     } else { | 
 |         node->right_child = FALSE; | 
 |         right->left_child = TRUE; | 
 |     } | 
 |     right->left = node; | 
 |  | 
 |     a_bal = node->balance; | 
 |     b_bal = right->balance; | 
 |  | 
 |     if (b_bal <= 0) { | 
 |         if (a_bal >= 1) { | 
 |             right->balance = b_bal - 1; | 
 |         } else { | 
 |             right->balance = a_bal + b_bal - 2; | 
 |         } | 
 |         node->balance = a_bal - 1; | 
 |     } else { | 
 |         if (a_bal <= b_bal) { | 
 |             right->balance = a_bal - 2; | 
 |         } else { | 
 |             right->balance = b_bal - 1; | 
 |         } | 
 |         node->balance = a_bal - b_bal - 1; | 
 |     } | 
 |  | 
 |     return right; | 
 | } | 
 |  | 
 | static QTreeNode * | 
 | q_tree_node_rotate_right(QTreeNode *node) | 
 | { | 
 |     QTreeNode *left; | 
 |     gint a_bal; | 
 |     gint b_bal; | 
 |  | 
 |     left = node->left; | 
 |  | 
 |     if (left->right_child) { | 
 |         node->left = left->right; | 
 |     } else { | 
 |         node->left_child = FALSE; | 
 |         left->right_child = TRUE; | 
 |     } | 
 |     left->right = node; | 
 |  | 
 |     a_bal = node->balance; | 
 |     b_bal = left->balance; | 
 |  | 
 |     if (b_bal <= 0) { | 
 |         if (b_bal > a_bal) { | 
 |             left->balance = b_bal + 1; | 
 |         } else { | 
 |             left->balance = a_bal + 2; | 
 |         } | 
 |         node->balance = a_bal - b_bal + 1; | 
 |     } else { | 
 |         if (a_bal <= -1) { | 
 |             left->balance = b_bal + 1; | 
 |         } else { | 
 |             left->balance = a_bal + b_bal + 2; | 
 |         } | 
 |         node->balance = a_bal + 1; | 
 |     } | 
 |  | 
 |     return left; | 
 | } | 
 |  | 
 | #ifdef Q_TREE_DEBUG | 
 | static gint | 
 | q_tree_node_height(QTreeNode *node) | 
 | { | 
 |     gint left_height; | 
 |     gint right_height; | 
 |  | 
 |     if (node) { | 
 |         left_height = 0; | 
 |         right_height = 0; | 
 |  | 
 |         if (node->left_child) { | 
 |             left_height = q_tree_node_height(node->left); | 
 |         } | 
 |  | 
 |         if (node->right_child) { | 
 |             right_height = q_tree_node_height(node->right); | 
 |         } | 
 |  | 
 |         return MAX(left_height, right_height) + 1; | 
 |     } | 
 |  | 
 |     return 0; | 
 | } | 
 |  | 
 | static void q_tree_node_check(QTreeNode *node) | 
 | { | 
 |     gint left_height; | 
 |     gint right_height; | 
 |     gint balance; | 
 |     QTreeNode *tmp; | 
 |  | 
 |     if (node) { | 
 |         if (node->left_child) { | 
 |             tmp = q_tree_node_previous(node); | 
 |             g_assert(tmp->right == node); | 
 |         } | 
 |  | 
 |         if (node->right_child) { | 
 |             tmp = q_tree_node_next(node); | 
 |             g_assert(tmp->left == node); | 
 |         } | 
 |  | 
 |         left_height = 0; | 
 |         right_height = 0; | 
 |  | 
 |         if (node->left_child) { | 
 |             left_height = q_tree_node_height(node->left); | 
 |         } | 
 |         if (node->right_child) { | 
 |             right_height = q_tree_node_height(node->right); | 
 |         } | 
 |  | 
 |         balance = right_height - left_height; | 
 |         g_assert(balance == node->balance); | 
 |  | 
 |         if (node->left_child) { | 
 |             q_tree_node_check(node->left); | 
 |         } | 
 |         if (node->right_child) { | 
 |             q_tree_node_check(node->right); | 
 |         } | 
 |     } | 
 | } | 
 | #endif |