qemu
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 4068
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 {77QTreeNode *root;78GCompareDataFunc key_compare;79GDestroyNotify key_destroy_func;80GDestroyNotify value_destroy_func;81gpointer key_compare_data;82guint nnodes;83gint ref_count;84};85
86struct _QTreeNode {87gpointer key; /* key for this node */88gpointer value; /* value stored at this node */89QTreeNode *left; /* left subtree */90QTreeNode *right; /* right subtree */91gint8 balance; /* height (right) - height (left) */92guint8 left_child;93guint8 right_child;94};95
96
97static QTreeNode *q_tree_node_new(gpointer key,98gpointer value);99static QTreeNode *q_tree_insert_internal(QTree *tree,100gpointer key,101gpointer value,102gboolean replace);103static gboolean q_tree_remove_internal(QTree *tree,104gconstpointer key,105gboolean steal);106static QTreeNode *q_tree_node_balance(QTreeNode *node);107static QTreeNode *q_tree_find_node(QTree *tree,108gconstpointer key);109static QTreeNode *q_tree_node_search(QTreeNode *node,110GCompareFunc search_func,111gconstpointer data);112static QTreeNode *q_tree_node_rotate_left(QTreeNode *node);113static QTreeNode *q_tree_node_rotate_right(QTreeNode *node);114#ifdef Q_TREE_DEBUG115static void q_tree_node_check(QTreeNode *node);116#endif117
118static QTreeNode*119q_tree_node_new(gpointer key,120gpointer value)121{
122QTreeNode *node = g_new(QTreeNode, 1);123
124node->balance = 0;125node->left = NULL;126node->right = NULL;127node->left_child = FALSE;128node->right_child = FALSE;129node->key = key;130node->value = value;131
132return 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{
150g_return_val_if_fail(key_compare_func != NULL, NULL);151
152return q_tree_new_full((GCompareDataFunc) key_compare_func, NULL,153NULL, 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,168gpointer key_compare_data)169{
170g_return_val_if_fail(key_compare_func != NULL, NULL);171
172return q_tree_new_full(key_compare_func, key_compare_data,173NULL, 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,195gpointer key_compare_data,196GDestroyNotify key_destroy_func,197GDestroyNotify value_destroy_func)198{
199QTree *tree;200
201g_return_val_if_fail(key_compare_func != NULL, NULL);202
203tree = g_new(QTree, 1);204tree->root = NULL;205tree->key_compare = key_compare_func;206tree->key_destroy_func = key_destroy_func;207tree->value_destroy_func = value_destroy_func;208tree->key_compare_data = key_compare_data;209tree->nnodes = 0;210tree->ref_count = 1;211
212return 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{
229QTreeNode *tmp;230
231g_return_val_if_fail(tree != NULL, NULL);232
233if (!tree->root) {234return NULL;235}236
237tmp = tree->root;238
239while (tmp->left_child) {240tmp = tmp->left;241}242
243return 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{
260QTreeNode *tmp;261
262g_return_val_if_fail(node != NULL, NULL);263
264tmp = node->left;265
266if (node->left_child) {267while (tmp->right_child) {268tmp = tmp->right;269}270}271
272return 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{
289QTreeNode *tmp;290
291g_return_val_if_fail(node != NULL, NULL);292
293tmp = node->right;294
295if (node->right_child) {296while (tmp->left_child) {297tmp = tmp->left;298}299}300
301return 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_CFI314q_tree_remove_all(QTree *tree)315{
316QTreeNode *node;317QTreeNode *next;318
319g_return_if_fail(tree != NULL);320
321node = q_tree_node_first(tree);322
323while (node) {324next = q_tree_node_next(node);325
326if (tree->key_destroy_func) {327tree->key_destroy_func(node->key);328}329if (tree->value_destroy_func) {330tree->value_destroy_func(node->value);331}332g_free(node);333
334#ifdef Q_TREE_DEBUG335g_assert(tree->nnodes > 0);336tree->nnodes--;337#endif338
339node = next;340}341
342#ifdef Q_TREE_DEBUG343g_assert(tree->nnodes == 0);344#endif345
346tree->root = NULL;347#ifndef Q_TREE_DEBUG348tree->nnodes = 0;349#endif350}
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{
367g_return_val_if_fail(tree != NULL, NULL);368
369g_atomic_int_inc(&tree->ref_count);370
371return 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{
390g_return_if_fail(tree != NULL);391
392if (g_atomic_int_dec_and_test(&tree->ref_count)) {393q_tree_remove_all(tree);394g_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{
412g_return_if_fail(tree != NULL);413
414q_tree_remove_all(tree);415q_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,444gpointer key,445gpointer value)446{
447QTreeNode *node;448
449g_return_val_if_fail(tree != NULL, NULL);450
451node = q_tree_insert_internal(tree, key, value, FALSE);452
453#ifdef Q_TREE_DEBUG454q_tree_node_check(tree->root);455#endif456
457return 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,473gpointer key,474gpointer value)475{
476q_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,501gpointer key,502gpointer value)503{
504QTreeNode *node;505
506g_return_val_if_fail(tree != NULL, NULL);507
508node = q_tree_insert_internal(tree, key, value, TRUE);509
510#ifdef Q_TREE_DEBUG511q_tree_node_check(tree->root);512#endif513
514return 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,528gpointer key,529gpointer value)530{
531q_tree_replace_node(tree, key, value);532}
533
534/* internal insert routine */
535static QTreeNode * QEMU_DISABLE_CFI536q_tree_insert_internal(QTree *tree,537gpointer key,538gpointer value,539gboolean replace)540{
541QTreeNode *node, *retnode;542QTreeNode *path[MAX_GTREE_HEIGHT];543int idx;544
545g_return_val_if_fail(tree != NULL, NULL);546
547if (!tree->root) {548tree->root = q_tree_node_new(key, value);549tree->nnodes++;550return tree->root;551}552
553idx = 0;554path[idx++] = NULL;555node = tree->root;556
557while (1) {558int cmp = tree->key_compare(key, node->key, tree->key_compare_data);559
560if (cmp == 0) {561if (tree->value_destroy_func) {562tree->value_destroy_func(node->value);563}564
565node->value = value;566
567if (replace) {568if (tree->key_destroy_func) {569tree->key_destroy_func(node->key);570}571
572node->key = key;573} else {574/* free the passed key */575if (tree->key_destroy_func) {576tree->key_destroy_func(key);577}578}579
580return node;581} else if (cmp < 0) {582if (node->left_child) {583path[idx++] = node;584node = node->left;585} else {586QTreeNode *child = q_tree_node_new(key, value);587
588child->left = node->left;589child->right = node;590node->left = child;591node->left_child = TRUE;592node->balance -= 1;593
594tree->nnodes++;595
596retnode = child;597break;598}599} else {600if (node->right_child) {601path[idx++] = node;602node = node->right;603} else {604QTreeNode *child = q_tree_node_new(key, value);605
606child->right = node->right;607child->left = node;608node->right = child;609node->right_child = TRUE;610node->balance += 1;611
612tree->nnodes++;613
614retnode = child;615break;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*/
625while (1) {626QTreeNode *bparent = path[--idx];627gboolean left_node = (bparent && node == bparent->left);628g_assert(!bparent || bparent->left == node || bparent->right == node);629
630if (node->balance < -1 || node->balance > 1) {631node = q_tree_node_balance(node);632if (bparent == NULL) {633tree->root = node;634} else if (left_node) {635bparent->left = node;636} else {637bparent->right = node;638}639}640
641if (node->balance == 0 || bparent == NULL) {642break;643}644
645if (left_node) {646bparent->balance -= 1;647} else {648bparent->balance += 1;649}650
651node = bparent;652}653
654return 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,678gconstpointer key)679{
680gboolean removed;681
682g_return_val_if_fail(tree != NULL, FALSE);683
684removed = q_tree_remove_internal(tree, key, FALSE);685
686#ifdef Q_TREE_DEBUG687q_tree_node_check(tree->root);688#endif689
690return 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,708gconstpointer key)709{
710gboolean removed;711
712g_return_val_if_fail(tree != NULL, FALSE);713
714removed = q_tree_remove_internal(tree, key, TRUE);715
716#ifdef Q_TREE_DEBUG717q_tree_node_check(tree->root);718#endif719
720return removed;721}
722
723/* internal remove routine */
724static gboolean QEMU_DISABLE_CFI725q_tree_remove_internal(QTree *tree,726gconstpointer key,727gboolean steal)728{
729QTreeNode *node, *parent, *balance;730QTreeNode *path[MAX_GTREE_HEIGHT];731int idx;732gboolean left_node;733
734g_return_val_if_fail(tree != NULL, FALSE);735
736if (!tree->root) {737return FALSE;738}739
740idx = 0;741path[idx++] = NULL;742node = tree->root;743
744while (1) {745int cmp = tree->key_compare(key, node->key, tree->key_compare_data);746
747if (cmp == 0) {748break;749} else if (cmp < 0) {750if (!node->left_child) {751return FALSE;752}753
754path[idx++] = node;755node = node->left;756} else {757if (!node->right_child) {758return FALSE;759}760
761path[idx++] = node;762node = 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*/
770balance = parent = path[--idx];771g_assert(!parent || parent->left == node || parent->right == node);772left_node = (parent && node == parent->left);773
774if (!node->left_child) {775if (!node->right_child) {776if (!parent) {777tree->root = NULL;778} else if (left_node) {779parent->left_child = FALSE;780parent->left = node->left;781parent->balance += 1;782} else {783parent->right_child = FALSE;784parent->right = node->right;785parent->balance -= 1;786}787} else {788/* node has a right child */789QTreeNode *tmp = q_tree_node_next(node);790tmp->left = node->left;791
792if (!parent) {793tree->root = node->right;794} else if (left_node) {795parent->left = node->right;796parent->balance += 1;797} else {798parent->right = node->right;799parent->balance -= 1;800}801}802} else {803/* node has a left child */804if (!node->right_child) {805QTreeNode *tmp = q_tree_node_previous(node);806tmp->right = node->right;807
808if (parent == NULL) {809tree->root = node->left;810} else if (left_node) {811parent->left = node->left;812parent->balance += 1;813} else {814parent->right = node->left;815parent->balance -= 1;816}817} else {818/* node has a both children (pant, pant!) */819QTreeNode *prev = node->left;820QTreeNode *next = node->right;821QTreeNode *nextp = node;822int old_idx = idx + 1;823idx++;824
825/* path[idx] == parent */826/* find the immediately next node (and its parent) */827while (next->left_child) {828path[++idx] = nextp = next;829next = next->left;830}831
832path[old_idx] = next;833balance = path[idx];834
835/* remove 'next' from the tree */836if (nextp != node) {837if (next->right_child) {838nextp->left = next->right;839} else {840nextp->left_child = FALSE;841}842nextp->balance += 1;843
844next->right_child = TRUE;845next->right = node->right;846} else {847node->balance -= 1;848}849
850/* set the prev to point to the right place */851while (prev->right_child) {852prev = prev->right;853}854prev->right = next;855
856/* prepare 'next' to replace 'node' */857next->left_child = TRUE;858next->left = node->left;859next->balance = node->balance;860
861if (!parent) {862tree->root = next;863} else if (left_node) {864parent->left = next;865} else {866parent->right = next;867}868}869}870
871/* restore balance */872if (balance) {873while (1) {874QTreeNode *bparent = path[--idx];875g_assert(!bparent ||876bparent->left == balance ||877bparent->right == balance);878left_node = (bparent && balance == bparent->left);879
880if (balance->balance < -1 || balance->balance > 1) {881balance = q_tree_node_balance(balance);882if (!bparent) {883tree->root = balance;884} else if (left_node) {885bparent->left = balance;886} else {887bparent->right = balance;888}889}890
891if (balance->balance != 0 || !bparent) {892break;893}894
895if (left_node) {896bparent->balance += 1;897} else {898bparent->balance -= 1;899}900
901balance = bparent;902}903}904
905if (!steal) {906if (tree->key_destroy_func) {907tree->key_destroy_func(node->key);908}909if (tree->value_destroy_func) {910tree->value_destroy_func(node->value);911}912}913
914g_free(node);915
916tree->nnodes--;917
918return 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,937gconstpointer key)938{
939g_return_val_if_fail(tree != NULL, NULL);940
941return 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,958gconstpointer key)959{
960QTreeNode *node;961
962node = q_tree_lookup_node(tree, key);963
964return 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,984gconstpointer lookup_key,985gpointer *orig_key,986gpointer *value)987{
988QTreeNode *node;989
990g_return_val_if_fail(tree != NULL, FALSE);991
992node = q_tree_find_node(tree, lookup_key);993
994if (node) {995if (orig_key) {996*orig_key = node->key;997}998if (value) {999*value = node->value;1000}1001return TRUE;1002} else {1003return 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,1025GTraverseFunc func,1026gpointer user_data)1027{
1028QTreeNode *node;1029
1030g_return_if_fail(tree != NULL);1031
1032if (!tree->root) {1033return;1034}1035
1036node = q_tree_node_first(tree);1037
1038while (node) {1039if ((*func)(node->key, node->value, user_data)) {1040break;1041}1042
1043node = 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,1070GCompareFunc search_func,1071gconstpointer user_data)1072{
1073g_return_val_if_fail(tree != NULL, NULL);1074
1075if (!tree->root) {1076return NULL;1077}1078
1079return 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,1103GCompareFunc search_func,1104gconstpointer user_data)1105{
1106QTreeNode *node;1107
1108node = q_tree_search_node(tree, search_func, user_data);1109
1110return 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{
1128QTreeNode *node;1129gint height;1130
1131g_return_val_if_fail(tree != NULL, 0);1132
1133if (!tree->root) {1134return 0;1135}1136
1137height = 0;1138node = tree->root;1139
1140while (1) {1141height += 1 + MAX(node->balance, 0);1142
1143if (!node->left_child) {1144return height;1145}1146
1147node = 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{
1162g_return_val_if_fail(tree != NULL, 0);1163
1164return tree->nnodes;1165}
1166
1167static QTreeNode *1168q_tree_node_balance(QTreeNode *node)1169{
1170if (node->balance < -1) {1171if (node->left->balance > 0) {1172node->left = q_tree_node_rotate_left(node->left);1173}1174node = q_tree_node_rotate_right(node);1175} else if (node->balance > 1) {1176if (node->right->balance < 0) {1177node->right = q_tree_node_rotate_right(node->right);1178}1179node = q_tree_node_rotate_left(node);1180}1181
1182return node;1183}
1184
1185static QTreeNode * QEMU_DISABLE_CFI1186q_tree_find_node(QTree *tree,1187gconstpointer key)1188{
1189QTreeNode *node;1190gint cmp;1191
1192node = tree->root;1193if (!node) {1194return NULL;1195}1196
1197while (1) {1198cmp = tree->key_compare(key, node->key, tree->key_compare_data);1199if (cmp == 0) {1200return node;1201} else if (cmp < 0) {1202if (!node->left_child) {1203return NULL;1204}1205
1206node = node->left;1207} else {1208if (!node->right_child) {1209return NULL;1210}1211
1212node = node->right;1213}1214}1215}
1216
1217static QTreeNode *1218q_tree_node_search(QTreeNode *node,1219GCompareFunc search_func,1220gconstpointer data)1221{
1222gint dir;1223
1224if (!node) {1225return NULL;1226}1227
1228while (1) {1229dir = (*search_func)(node->key, data);1230if (dir == 0) {1231return node;1232} else if (dir < 0) {1233if (!node->left_child) {1234return NULL;1235}1236
1237node = node->left;1238} else {1239if (!node->right_child) {1240return NULL;1241}1242
1243node = node->right;1244}1245}1246}
1247
1248static QTreeNode *1249q_tree_node_rotate_left(QTreeNode *node)1250{
1251QTreeNode *right;1252gint a_bal;1253gint b_bal;1254
1255right = node->right;1256
1257if (right->left_child) {1258node->right = right->left;1259} else {1260node->right_child = FALSE;1261right->left_child = TRUE;1262}1263right->left = node;1264
1265a_bal = node->balance;1266b_bal = right->balance;1267
1268if (b_bal <= 0) {1269if (a_bal >= 1) {1270right->balance = b_bal - 1;1271} else {1272right->balance = a_bal + b_bal - 2;1273}1274node->balance = a_bal - 1;1275} else {1276if (a_bal <= b_bal) {1277right->balance = a_bal - 2;1278} else {1279right->balance = b_bal - 1;1280}1281node->balance = a_bal - b_bal - 1;1282}1283
1284return right;1285}
1286
1287static QTreeNode *1288q_tree_node_rotate_right(QTreeNode *node)1289{
1290QTreeNode *left;1291gint a_bal;1292gint b_bal;1293
1294left = node->left;1295
1296if (left->right_child) {1297node->left = left->right;1298} else {1299node->left_child = FALSE;1300left->right_child = TRUE;1301}1302left->right = node;1303
1304a_bal = node->balance;1305b_bal = left->balance;1306
1307if (b_bal <= 0) {1308if (b_bal > a_bal) {1309left->balance = b_bal + 1;1310} else {1311left->balance = a_bal + 2;1312}1313node->balance = a_bal - b_bal + 1;1314} else {1315if (a_bal <= -1) {1316left->balance = b_bal + 1;1317} else {1318left->balance = a_bal + b_bal + 2;1319}1320node->balance = a_bal + 1;1321}1322
1323return left;1324}
1325
1326#ifdef Q_TREE_DEBUG1327static gint1328q_tree_node_height(QTreeNode *node)1329{
1330gint left_height;1331gint right_height;1332
1333if (node) {1334left_height = 0;1335right_height = 0;1336
1337if (node->left_child) {1338left_height = q_tree_node_height(node->left);1339}1340
1341if (node->right_child) {1342right_height = q_tree_node_height(node->right);1343}1344
1345return MAX(left_height, right_height) + 1;1346}1347
1348return 0;1349}
1350
1351static void q_tree_node_check(QTreeNode *node)1352{
1353gint left_height;1354gint right_height;1355gint balance;1356QTreeNode *tmp;1357
1358if (node) {1359if (node->left_child) {1360tmp = q_tree_node_previous(node);1361g_assert(tmp->right == node);1362}1363
1364if (node->right_child) {1365tmp = q_tree_node_next(node);1366g_assert(tmp->left == node);1367}1368
1369left_height = 0;1370right_height = 0;1371
1372if (node->left_child) {1373left_height = q_tree_node_height(node->left);1374}1375if (node->right_child) {1376right_height = q_tree_node_height(node->right);1377}1378
1379balance = right_height - left_height;1380g_assert(balance == node->balance);1381
1382if (node->left_child) {1383q_tree_node_check(node->left);1384}1385if (node->right_child) {1386q_tree_node_check(node->right);1387}1388}1389}
1390#endif1391