Coverage Report

Created: 2025-07-12 06:30

/src/tinysparql/subprojects/glib-2.80.3/glib/gtree.c
Line
Count
Source (jump to first uncovered line)
1
/* GLIB - Library of useful routines for C programming
2
 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
20
/*
21
 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22
 * file for a list of people on the GLib Team.  See the ChangeLog
23
 * files for a list of changes.  These files are distributed with
24
 * GLib at ftp://ftp.gtk.org/pub/gtk/. 
25
 */
26
27
/* 
28
 * MT safe
29
 */
30
31
#include "config.h"
32
33
#include "gtree.h"
34
35
#include "gatomic.h"
36
#include "gtestutils.h"
37
#include "gslice.h"
38
39
#define MAX_GTREE_HEIGHT 40
40
/* G_MAXUINT nodes will be covered by tree height of log2(G_MAXUINT) + 2. */
41
G_STATIC_ASSERT ((G_GUINT64_CONSTANT (1) << (MAX_GTREE_HEIGHT - 2)) >= G_MAXUINT);
42
43
/**
44
 * GTree:
45
 *
46
 * The GTree struct is an opaque data structure representing a
47
 * [balanced binary tree][glib-Balanced-Binary-Trees]. It should be
48
 * accessed only by using the following functions.
49
 */
50
struct _GTree
51
{
52
  GTreeNode        *root;
53
  GCompareDataFunc  key_compare;
54
  GDestroyNotify    key_destroy_func;
55
  GDestroyNotify    value_destroy_func;
56
  gpointer          key_compare_data;
57
  guint             nnodes;
58
  gint              ref_count;
59
};
60
61
struct _GTreeNode
62
{
63
  gpointer   key;         /* key for this node */
64
  gpointer   value;       /* value stored at this node */
65
  GTreeNode *left;        /* left subtree */
66
  GTreeNode *right;       /* right subtree */
67
  gint8      balance;     /* height (right) - height (left) */
68
  guint8     left_child;
69
  guint8     right_child;
70
};
71
72
73
static GTreeNode* g_tree_node_new                   (gpointer       key,
74
                                                     gpointer       value);
75
static GTreeNode *g_tree_insert_internal (GTree *tree,
76
                                          gpointer key,
77
                                          gpointer value,
78
                                          gboolean replace,
79
                                          gboolean null_ret_ok);
80
static gboolean   g_tree_remove_internal            (GTree         *tree,
81
                                                     gconstpointer  key,
82
                                                     gboolean       steal);
83
static GTreeNode* g_tree_node_balance               (GTreeNode     *node);
84
static GTreeNode *g_tree_find_node                  (GTree         *tree,
85
                                                     gconstpointer  key);
86
static gint       g_tree_node_pre_order             (GTreeNode     *node,
87
                                                     GTraverseFunc  traverse_func,
88
                                                     gpointer       data);
89
static gint       g_tree_node_in_order              (GTreeNode     *node,
90
                                                     GTraverseFunc  traverse_func,
91
                                                     gpointer       data);
92
static gint       g_tree_node_post_order            (GTreeNode     *node,
93
                                                     GTraverseFunc  traverse_func,
94
                                                     gpointer       data);
95
static GTreeNode *g_tree_node_search (GTreeNode *node,
96
                                      GCompareFunc search_func,
97
                                      gconstpointer data);
98
static GTreeNode* g_tree_node_rotate_left           (GTreeNode     *node);
99
static GTreeNode* g_tree_node_rotate_right          (GTreeNode     *node);
100
#ifdef G_TREE_DEBUG
101
static void       g_tree_node_check                 (GTreeNode     *node);
102
#endif
103
104
105
static GTreeNode*
106
g_tree_node_new (gpointer key,
107
                 gpointer value)
108
0
{
109
0
  GTreeNode *node = g_slice_new (GTreeNode);
110
111
0
  node->balance = 0;
112
0
  node->left = NULL;
113
0
  node->right = NULL;
114
0
  node->left_child = FALSE;
115
0
  node->right_child = FALSE;
116
0
  node->key = key;
117
0
  node->value = value;
118
119
0
  return node;
120
0
}
121
122
/**
123
 * g_tree_new: (constructor)
124
 * @key_compare_func: the function used to order the nodes in the #GTree.
125
 *   It should return values similar to the standard strcmp() function -
126
 *   0 if the two arguments are equal, a negative value if the first argument 
127
 *   comes before the second, or a positive value if the first argument comes 
128
 *   after the second.
129
 * 
130
 * Creates a new #GTree.
131
 * 
132
 * Returns: a newly allocated #GTree
133
 */
134
GTree *
135
g_tree_new (GCompareFunc key_compare_func)
136
0
{
137
0
  g_return_val_if_fail (key_compare_func != NULL, NULL);
138
139
0
  return g_tree_new_full ((GCompareDataFunc) key_compare_func, NULL,
140
0
                          NULL, NULL);
141
0
}
142
143
/**
144
 * g_tree_new_with_data:
145
 * @key_compare_func: qsort()-style comparison function
146
 * @key_compare_data: data to pass to comparison function
147
 * 
148
 * Creates a new #GTree with a comparison function that accepts user data.
149
 * See g_tree_new() for more details.
150
 * 
151
 * Returns: a newly allocated #GTree
152
 */
153
GTree *
154
g_tree_new_with_data (GCompareDataFunc key_compare_func,
155
                      gpointer         key_compare_data)
156
0
{
157
0
  g_return_val_if_fail (key_compare_func != NULL, NULL);
158
  
159
0
  return g_tree_new_full (key_compare_func, key_compare_data, 
160
0
                          NULL, NULL);
161
0
}
162
163
/**
164
 * g_tree_new_full:
165
 * @key_compare_func: qsort()-style comparison function
166
 * @key_compare_data: data to pass to comparison function
167
 * @key_destroy_func: a function to free the memory allocated for the key 
168
 *   used when removing the entry from the #GTree or %NULL if you don't
169
 *   want to supply such a function
170
 * @value_destroy_func: a function to free the memory allocated for the 
171
 *   value used when removing the entry from the #GTree or %NULL if you 
172
 *   don't want to supply such a function
173
 * 
174
 * Creates a new #GTree like g_tree_new() and allows to specify functions 
175
 * to free the memory allocated for the key and value that get called when 
176
 * removing the entry from the #GTree.
177
 * 
178
 * Returns: a newly allocated #GTree
179
 */
180
GTree *
181
g_tree_new_full (GCompareDataFunc key_compare_func,
182
                 gpointer         key_compare_data,
183
                 GDestroyNotify   key_destroy_func,
184
                 GDestroyNotify   value_destroy_func)
185
0
{
186
0
  GTree *tree;
187
  
188
0
  g_return_val_if_fail (key_compare_func != NULL, NULL);
189
  
190
0
  tree = g_slice_new (GTree);
191
0
  tree->root               = NULL;
192
0
  tree->key_compare        = key_compare_func;
193
0
  tree->key_destroy_func   = key_destroy_func;
194
0
  tree->value_destroy_func = value_destroy_func;
195
0
  tree->key_compare_data   = key_compare_data;
196
0
  tree->nnodes             = 0;
197
0
  tree->ref_count          = 1;
198
  
199
0
  return tree;
200
0
}
201
202
/**
203
 * g_tree_node_first:
204
 * @tree: a #GTree
205
 *
206
 * Returns the first in-order node of the tree, or %NULL
207
 * for an empty tree.
208
 *
209
 * Returns: (nullable) (transfer none): the first node in the tree
210
 *
211
 * Since: 2.68
212
 */
213
GTreeNode *
214
g_tree_node_first (GTree *tree)
215
0
{
216
0
  GTreeNode *tmp;
217
218
0
  g_return_val_if_fail (tree != NULL, NULL);
219
220
0
  if (!tree->root)
221
0
    return NULL;
222
223
0
  tmp = tree->root;
224
225
0
  while (tmp->left_child)
226
0
    tmp = tmp->left;
227
228
0
  return tmp;
229
0
}
230
231
/**
232
 * g_tree_node_last:
233
 * @tree: a #GTree
234
 *
235
 * Returns the last in-order node of the tree, or %NULL
236
 * for an empty tree.
237
 *
238
 * Returns: (nullable) (transfer none): the last node in the tree
239
 *
240
 * Since: 2.68
241
 */
242
GTreeNode *
243
g_tree_node_last (GTree *tree)
244
0
{
245
0
  GTreeNode *tmp;
246
247
0
  g_return_val_if_fail (tree != NULL, NULL);
248
249
0
  if (!tree->root)
250
0
    return NULL;
251
252
0
  tmp = tree->root;
253
254
0
  while (tmp->right_child)
255
0
    tmp = tmp->right;
256
257
0
  return tmp;
258
0
}
259
260
/**
261
 * g_tree_node_previous
262
 * @node: a #GTree node
263
 *
264
 * Returns the previous in-order node of the tree, or %NULL
265
 * if the passed node was already the first one.
266
 *
267
 * Returns: (nullable) (transfer none): the previous node in the tree
268
 *
269
 * Since: 2.68
270
 */
271
GTreeNode *
272
g_tree_node_previous (GTreeNode *node)
273
0
{
274
0
  GTreeNode *tmp;
275
276
0
  g_return_val_if_fail (node != NULL, NULL);
277
278
0
  tmp = node->left;
279
280
0
  if (node->left_child)
281
0
    while (tmp->right_child)
282
0
      tmp = tmp->right;
283
284
0
  return tmp;
285
0
}
286
287
/**
288
 * g_tree_node_next
289
 * @node: a #GTree node
290
 *
291
 * Returns the next in-order node of the tree, or %NULL
292
 * if the passed node was already the last one.
293
 *
294
 * Returns: (nullable) (transfer none): the next node in the tree
295
 *
296
 * Since: 2.68
297
 */
298
GTreeNode *
299
g_tree_node_next (GTreeNode *node)
300
0
{
301
0
  GTreeNode *tmp;
302
303
0
  g_return_val_if_fail (node != NULL, NULL);
304
305
0
  tmp = node->right;
306
307
0
  if (node->right_child)
308
0
    while (tmp->left_child)
309
0
      tmp = tmp->left;
310
311
0
  return tmp;
312
0
}
313
314
/**
315
 * g_tree_remove_all:
316
 * @tree: a #GTree
317
 *
318
 * Removes all nodes from a #GTree and destroys their keys and values,
319
 * then resets the #GTree’s root to %NULL.
320
 *
321
 * Since: 2.70
322
 */
323
void
324
g_tree_remove_all (GTree *tree)
325
0
{
326
0
  GTreeNode *node;
327
0
  GTreeNode *next;
328
329
0
  g_return_if_fail (tree != NULL);
330
331
0
  node = g_tree_node_first (tree);
332
333
0
  while (node)
334
0
    {
335
0
      next = g_tree_node_next (node);
336
337
0
      if (tree->key_destroy_func)
338
0
        tree->key_destroy_func (node->key);
339
0
      if (tree->value_destroy_func)
340
0
        tree->value_destroy_func (node->value);
341
0
      g_slice_free (GTreeNode, node);
342
343
#ifdef G_TREE_DEBUG
344
      g_assert (tree->nnodes > 0);
345
      tree->nnodes--;
346
#endif
347
348
0
      node = next;
349
0
    }
350
351
#ifdef G_TREE_DEBUG
352
  g_assert (tree->nnodes == 0);
353
#endif
354
355
0
  tree->root = NULL;
356
0
#ifndef G_TREE_DEBUG
357
0
  tree->nnodes = 0;
358
0
#endif
359
0
}
360
361
/**
362
 * g_tree_ref:
363
 * @tree: a #GTree
364
 *
365
 * Increments the reference count of @tree by one.
366
 *
367
 * It is safe to call this function from any thread.
368
 *
369
 * Returns: the passed in #GTree
370
 *
371
 * Since: 2.22
372
 */
373
GTree *
374
g_tree_ref (GTree *tree)
375
0
{
376
0
  g_return_val_if_fail (tree != NULL, NULL);
377
378
0
  g_atomic_int_inc (&tree->ref_count);
379
380
0
  return tree;
381
0
}
382
383
/**
384
 * g_tree_unref:
385
 * @tree: a #GTree
386
 *
387
 * Decrements the reference count of @tree by one.
388
 * If the reference count drops to 0, all keys and values will
389
 * be destroyed (if destroy functions were specified) and all
390
 * memory allocated by @tree will be released.
391
 *
392
 * It is safe to call this function from any thread.
393
 *
394
 * Since: 2.22
395
 */
396
void
397
g_tree_unref (GTree *tree)
398
0
{
399
0
  g_return_if_fail (tree != NULL);
400
401
0
  if (g_atomic_int_dec_and_test (&tree->ref_count))
402
0
    {
403
0
      g_tree_remove_all (tree);
404
0
      g_slice_free (GTree, tree);
405
0
    }
406
0
}
407
408
/**
409
 * g_tree_destroy:
410
 * @tree: a #GTree
411
 * 
412
 * Removes all keys and values from the #GTree and decreases its
413
 * reference count by one. If keys and/or values are dynamically
414
 * allocated, you should either free them first or create the #GTree
415
 * using g_tree_new_full(). In the latter case the destroy functions
416
 * you supplied will be called on all keys and values before destroying
417
 * the #GTree.
418
 */
419
void
420
g_tree_destroy (GTree *tree)
421
0
{
422
0
  g_return_if_fail (tree != NULL);
423
424
0
  g_tree_remove_all (tree);
425
0
  g_tree_unref (tree);
426
0
}
427
428
static GTreeNode *
429
g_tree_insert_replace_node_internal (GTree *tree,
430
                                     gpointer key,
431
                                     gpointer value,
432
                                     gboolean replace,
433
                                     gboolean null_ret_ok)
434
0
{
435
0
  GTreeNode *node;
436
437
0
  g_return_val_if_fail (tree != NULL, NULL);
438
439
0
  node = g_tree_insert_internal (tree, key, value, replace, null_ret_ok);
440
441
#ifdef G_TREE_DEBUG
442
  g_tree_node_check (tree->root);
443
#endif
444
445
0
  return node;
446
0
}
447
448
/**
449
 * g_tree_insert_node:
450
 * @tree: a #GTree
451
 * @key: the key to insert
452
 * @value: the value corresponding to the key
453
 * 
454
 * Inserts a key/value pair into a #GTree.
455
 *
456
 * If the given key already exists in the #GTree its corresponding value
457
 * is set to the new value. If you supplied a @value_destroy_func when
458
 * creating the #GTree, the old value is freed using that function. If
459
 * you supplied a @key_destroy_func when creating the #GTree, the passed
460
 * key is freed using that function.
461
 *
462
 * The tree is automatically 'balanced' as new key/value pairs are added,
463
 * so that the distance from the root to every leaf is as small as possible.
464
 * The cost of maintaining a balanced tree while inserting new key/value
465
 * result in a O(n log(n)) operation where most of the other operations
466
 * are O(log(n)).
467
 *
468
 * Returns: (transfer none) (nullable): the inserted (or set) node or %NULL
469
 * if insertion would overflow the tree node counter.
470
 *
471
 * Since: 2.68
472
 */
473
GTreeNode *
474
g_tree_insert_node (GTree    *tree,
475
                    gpointer  key,
476
                    gpointer  value)
477
0
{
478
0
  return g_tree_insert_replace_node_internal (tree, key, value, FALSE, TRUE);
479
0
}
480
481
/**
482
 * g_tree_insert:
483
 * @tree: a #GTree
484
 * @key: the key to insert
485
 * @value: the value corresponding to the key
486
 * 
487
 * Inserts a key/value pair into a #GTree.
488
 *
489
 * Inserts a new key and value into a #GTree as g_tree_insert_node() does,
490
 * only this function does not return the inserted or set node.
491
 */
492
void
493
g_tree_insert (GTree    *tree,
494
               gpointer  key,
495
               gpointer  value)
496
0
{
497
0
  g_tree_insert_replace_node_internal (tree, key, value, FALSE, FALSE);
498
0
}
499
500
/**
501
 * g_tree_replace_node:
502
 * @tree: a #GTree
503
 * @key: the key to insert
504
 * @value: the value corresponding to the key
505
 *
506
 * Inserts a new key and value into a #GTree similar to g_tree_insert_node().
507
 * The difference is that if the key already exists in the #GTree, it gets 
508
 * replaced by the new key. If you supplied a @value_destroy_func when 
509
 * creating the #GTree, the old value is freed using that function. If you 
510
 * supplied a @key_destroy_func when creating the #GTree, the old key is 
511
 * freed using that function. 
512
 *
513
 * The tree is automatically 'balanced' as new key/value pairs are added,
514
 * so that the distance from the root to every leaf is as small as possible.
515
 *
516
 * Returns: (transfer none) (nullable): the inserted (or set) node or %NULL
517
 * if insertion would overflow the tree node counter.
518
 *
519
 * Since: 2.68
520
 */
521
GTreeNode *
522
g_tree_replace_node (GTree    *tree,
523
                     gpointer  key,
524
                     gpointer  value)
525
0
{
526
0
  return g_tree_insert_replace_node_internal (tree, key, value, TRUE, TRUE);
527
0
}
528
529
/**
530
 * g_tree_replace:
531
 * @tree: a #GTree
532
 * @key: the key to insert
533
 * @value: the value corresponding to the key
534
 *
535
 * Inserts a new key and value into a #GTree as g_tree_replace_node() does,
536
 * only this function does not return the inserted or set node.
537
 */
538
void
539
g_tree_replace (GTree    *tree,
540
                gpointer  key,
541
                gpointer  value)
542
0
{
543
0
  g_tree_insert_replace_node_internal (tree, key, value, TRUE, FALSE);
544
0
}
545
546
/* internal checked nnodes increment routine */
547
static gboolean
548
g_tree_nnodes_inc_checked (GTree *tree, gboolean overflow_fatal)
549
0
{
550
0
  if (G_UNLIKELY (tree->nnodes == G_MAXUINT))
551
0
    {
552
0
      if (overflow_fatal)
553
0
        {
554
0
          g_error ("Incrementing GTree nnodes counter would overflow");
555
0
        }
556
557
0
      return FALSE;
558
0
    }
559
560
0
  tree->nnodes++;
561
562
0
  return TRUE;
563
0
}
564
565
/* internal insert routine */
566
static GTreeNode *
567
g_tree_insert_internal (GTree    *tree,
568
                        gpointer  key,
569
                        gpointer  value,
570
                        gboolean  replace,
571
                        gboolean  null_ret_ok)
572
0
{
573
0
  GTreeNode *node, *retnode;
574
0
  GTreeNode *path[MAX_GTREE_HEIGHT];
575
0
  int idx;
576
577
0
  g_return_val_if_fail (tree != NULL, NULL);
578
579
0
  if (!tree->root)
580
0
    {
581
0
      tree->root = g_tree_node_new (key, value);
582
583
#ifdef G_TREE_DEBUG
584
      g_assert (tree->nnodes == 0);
585
#endif
586
0
      tree->nnodes++;
587
588
0
      return tree->root;
589
0
    }
590
591
0
  idx = 0;
592
0
  path[idx++] = NULL;
593
0
  node = tree->root;
594
595
0
  while (1)
596
0
    {
597
0
      int cmp = tree->key_compare (key, node->key, tree->key_compare_data);
598
      
599
0
      if (cmp == 0)
600
0
        {
601
0
          if (tree->value_destroy_func)
602
0
            tree->value_destroy_func (node->value);
603
604
0
          node->value = value;
605
606
0
          if (replace)
607
0
            {
608
0
              if (tree->key_destroy_func)
609
0
                tree->key_destroy_func (node->key);
610
611
0
              node->key = key;
612
0
            }
613
0
          else
614
0
            {
615
              /* free the passed key */
616
0
              if (tree->key_destroy_func)
617
0
                tree->key_destroy_func (key);
618
0
            }
619
620
0
          return node;
621
0
        }
622
0
      else if (cmp < 0)
623
0
        {
624
0
          if (node->left_child)
625
0
            {
626
0
              path[idx++] = node;
627
0
              node = node->left;
628
0
            }
629
0
          else
630
0
            {
631
0
              GTreeNode *child;
632
633
0
              if (!g_tree_nnodes_inc_checked (tree, !null_ret_ok))
634
0
                {
635
0
                  return NULL;
636
0
                }
637
638
0
              child = g_tree_node_new (key, value);
639
0
              child->left = node->left;
640
0
              child->right = node;
641
0
              node->left = child;
642
0
              node->left_child = TRUE;
643
0
              node->balance -= 1;
644
645
0
              retnode = child;
646
0
              break;
647
0
            }
648
0
        }
649
0
      else
650
0
        {
651
0
          if (node->right_child)
652
0
            {
653
0
              path[idx++] = node;
654
0
              node = node->right;
655
0
            }
656
0
          else
657
0
            {
658
0
              GTreeNode *child;
659
660
0
              if (!g_tree_nnodes_inc_checked (tree, !null_ret_ok))
661
0
                {
662
0
                  return NULL;
663
0
                }
664
665
0
              child = g_tree_node_new (key, value);
666
0
              child->right = node->right;
667
0
              child->left = node;
668
0
              node->right = child;
669
0
              node->right_child = TRUE;
670
0
              node->balance += 1;
671
672
0
              retnode = child;
673
0
              break;
674
0
            }
675
0
        }
676
0
    }
677
678
  /* Restore balance. This is the goodness of a non-recursive
679
   * implementation, when we are done with balancing we 'break'
680
   * the loop and we are done.
681
   */
682
0
  while (1)
683
0
    {
684
0
      GTreeNode *bparent = path[--idx];
685
0
      gboolean left_node = (bparent && node == bparent->left);
686
0
      g_assert (!bparent || bparent->left == node || bparent->right == node);
687
688
0
      if (node->balance < -1 || node->balance > 1)
689
0
        {
690
0
          node = g_tree_node_balance (node);
691
0
          if (bparent == NULL)
692
0
            tree->root = node;
693
0
          else if (left_node)
694
0
            bparent->left = node;
695
0
          else
696
0
            bparent->right = node;
697
0
        }
698
699
0
      if (node->balance == 0 || bparent == NULL)
700
0
        break;
701
      
702
0
      if (left_node)
703
0
        bparent->balance -= 1;
704
0
      else
705
0
        bparent->balance += 1;
706
707
0
      node = bparent;
708
0
    }
709
710
0
  return retnode;
711
0
}
712
713
/**
714
 * g_tree_remove:
715
 * @tree: a #GTree
716
 * @key: the key to remove
717
 * 
718
 * Removes a key/value pair from a #GTree.
719
 *
720
 * If the #GTree was created using g_tree_new_full(), the key and value 
721
 * are freed using the supplied destroy functions, otherwise you have to 
722
 * make sure that any dynamically allocated values are freed yourself.
723
 * If the key does not exist in the #GTree, the function does nothing.
724
 *
725
 * The cost of maintaining a balanced tree while removing a key/value
726
 * result in a O(n log(n)) operation where most of the other operations
727
 * are O(log(n)).
728
 *
729
 * Returns: %TRUE if the key was found (prior to 2.8, this function
730
 *     returned nothing)
731
 */
732
gboolean
733
g_tree_remove (GTree         *tree,
734
               gconstpointer  key)
735
0
{
736
0
  gboolean removed;
737
738
0
  g_return_val_if_fail (tree != NULL, FALSE);
739
740
0
  removed = g_tree_remove_internal (tree, key, FALSE);
741
742
#ifdef G_TREE_DEBUG
743
  g_tree_node_check (tree->root);
744
#endif
745
746
0
  return removed;
747
0
}
748
749
/**
750
 * g_tree_steal:
751
 * @tree: a #GTree
752
 * @key: the key to remove
753
 * 
754
 * Removes a key and its associated value from a #GTree without calling 
755
 * the key and value destroy functions.
756
 *
757
 * If the key does not exist in the #GTree, the function does nothing.
758
 *
759
 * Returns: %TRUE if the key was found (prior to 2.8, this function
760
 *     returned nothing)
761
 */
762
gboolean
763
g_tree_steal (GTree         *tree,
764
              gconstpointer  key)
765
0
{
766
0
  gboolean removed;
767
768
0
  g_return_val_if_fail (tree != NULL, FALSE);
769
770
0
  removed = g_tree_remove_internal (tree, key, TRUE);
771
772
#ifdef G_TREE_DEBUG
773
  g_tree_node_check (tree->root);
774
#endif
775
776
0
  return removed;
777
0
}
778
779
/* internal remove routine */
780
static gboolean
781
g_tree_remove_internal (GTree         *tree,
782
                        gconstpointer  key,
783
                        gboolean       steal)
784
0
{
785
0
  GTreeNode *node, *parent, *balance;
786
0
  GTreeNode *path[MAX_GTREE_HEIGHT];
787
0
  int idx;
788
0
  gboolean left_node;
789
790
0
  g_return_val_if_fail (tree != NULL, FALSE);
791
792
0
  if (!tree->root)
793
0
    return FALSE;
794
795
0
  idx = 0;
796
0
  path[idx++] = NULL;
797
0
  node = tree->root;
798
799
0
  while (1)
800
0
    {
801
0
      int cmp = tree->key_compare (key, node->key, tree->key_compare_data);
802
803
0
      if (cmp == 0)
804
0
        break;
805
0
      else if (cmp < 0)
806
0
        {
807
0
          if (!node->left_child)
808
0
            return FALSE;
809
810
0
          path[idx++] = node;
811
0
          node = node->left;
812
0
        }
813
0
      else
814
0
        {
815
0
          if (!node->right_child)
816
0
            return FALSE;
817
818
0
          path[idx++] = node;
819
0
          node = node->right;
820
0
        }
821
0
    }
822
823
  /* The following code is almost equal to g_tree_remove_node,
824
   * except that we do not have to call g_tree_node_parent.
825
   */
826
0
  balance = parent = path[--idx];
827
0
  g_assert (!parent || parent->left == node || parent->right == node);
828
0
  left_node = (parent && node == parent->left);
829
830
0
  if (!node->left_child)
831
0
    {
832
0
      if (!node->right_child)
833
0
        {
834
0
          if (!parent)
835
0
            tree->root = NULL;
836
0
          else if (left_node)
837
0
            {
838
0
              parent->left_child = FALSE;
839
0
              parent->left = node->left;
840
0
              parent->balance += 1;
841
0
            }
842
0
          else
843
0
            {
844
0
              parent->right_child = FALSE;
845
0
              parent->right = node->right;
846
0
              parent->balance -= 1;
847
0
            }
848
0
        }
849
0
      else /* node has a right child */
850
0
        {
851
0
          GTreeNode *tmp = g_tree_node_next (node);
852
0
          tmp->left = node->left;
853
854
0
          if (!parent)
855
0
            tree->root = node->right;
856
0
          else if (left_node)
857
0
            {
858
0
              parent->left = node->right;
859
0
              parent->balance += 1;
860
0
            }
861
0
          else
862
0
            {
863
0
              parent->right = node->right;
864
0
              parent->balance -= 1;
865
0
            }
866
0
        }
867
0
    }
868
0
  else /* node has a left child */
869
0
    {
870
0
      if (!node->right_child)
871
0
        {
872
0
          GTreeNode *tmp = g_tree_node_previous (node);
873
0
          tmp->right = node->right;
874
875
0
          if (parent == NULL)
876
0
            tree->root = node->left;
877
0
          else if (left_node)
878
0
            {
879
0
              parent->left = node->left;
880
0
              parent->balance += 1;
881
0
            }
882
0
          else
883
0
            {
884
0
              parent->right = node->left;
885
0
              parent->balance -= 1;
886
0
            }
887
0
        }
888
0
      else /* node has a both children (pant, pant!) */
889
0
        {
890
0
          GTreeNode *prev = node->left;
891
0
          GTreeNode *next = node->right;
892
0
          GTreeNode *nextp = node;
893
0
          int old_idx = idx + 1;
894
0
          idx++;
895
896
          /* path[idx] == parent */
897
          /* find the immediately next node (and its parent) */
898
0
          while (next->left_child)
899
0
            {
900
0
              path[++idx] = nextp = next;
901
0
              next = next->left;
902
0
            }
903
904
0
          path[old_idx] = next;
905
0
          balance = path[idx];
906
907
          /* remove 'next' from the tree */
908
0
          if (nextp != node)
909
0
            {
910
0
              if (next->right_child)
911
0
                nextp->left = next->right;
912
0
              else
913
0
                nextp->left_child = FALSE;
914
0
              nextp->balance += 1;
915
916
0
              next->right_child = TRUE;
917
0
              next->right = node->right;
918
0
            }
919
0
          else
920
0
            node->balance -= 1;
921
922
          /* set the prev to point to the right place */
923
0
          while (prev->right_child)
924
0
            prev = prev->right;
925
0
          prev->right = next;
926
927
          /* prepare 'next' to replace 'node' */
928
0
          next->left_child = TRUE;
929
0
          next->left = node->left;
930
0
          next->balance = node->balance;
931
932
0
          if (!parent)
933
0
            tree->root = next;
934
0
          else if (left_node)
935
0
            parent->left = next;
936
0
          else
937
0
            parent->right = next;
938
0
        }
939
0
    }
940
941
  /* restore balance */
942
0
  if (balance)
943
0
    while (1)
944
0
      {
945
0
        GTreeNode *bparent = path[--idx];
946
0
        g_assert (!bparent || bparent->left == balance || bparent->right == balance);
947
0
        left_node = (bparent && balance == bparent->left);
948
949
0
        if(balance->balance < -1 || balance->balance > 1)
950
0
          {
951
0
            balance = g_tree_node_balance (balance);
952
0
            if (!bparent)
953
0
              tree->root = balance;
954
0
            else if (left_node)
955
0
              bparent->left = balance;
956
0
            else
957
0
              bparent->right = balance;
958
0
          }
959
960
0
        if (balance->balance != 0 || !bparent)
961
0
          break;
962
963
0
        if (left_node)
964
0
          bparent->balance += 1;
965
0
        else
966
0
          bparent->balance -= 1;
967
968
0
        balance = bparent;
969
0
      }
970
971
0
  if (!steal)
972
0
    {
973
0
      if (tree->key_destroy_func)
974
0
        tree->key_destroy_func (node->key);
975
0
      if (tree->value_destroy_func)
976
0
        tree->value_destroy_func (node->value);
977
0
    }
978
979
0
  g_slice_free (GTreeNode, node);
980
981
0
  tree->nnodes--;
982
983
0
  return TRUE;
984
0
}
985
986
/**
987
 * g_tree_node_key:
988
 * @node: a #GTree node
989
 *
990
 * Gets the key stored at a particular tree node.
991
 *
992
 * Returns: (nullable) (transfer none): the key at the node.
993
 *
994
 * Since: 2.68
995
 */
996
gpointer
997
g_tree_node_key (GTreeNode *node)
998
0
{
999
0
  g_return_val_if_fail (node != NULL, NULL);
1000
1001
0
  return node->key;
1002
0
}
1003
1004
/**
1005
 * g_tree_node_value:
1006
 * @node: a #GTree node
1007
 *
1008
 * Gets the value stored at a particular tree node.
1009
 *
1010
 * Returns: (nullable) (transfer none): the value at the node.
1011
 *
1012
 * Since: 2.68
1013
 */
1014
gpointer
1015
g_tree_node_value (GTreeNode *node)
1016
0
{
1017
0
  g_return_val_if_fail (node != NULL, NULL);
1018
1019
0
  return node->value;
1020
0
}
1021
1022
/**
1023
 * g_tree_lookup_node:
1024
 * @tree: a #GTree
1025
 * @key: the key to look up
1026
 *
1027
 * Gets the tree node corresponding to the given key. Since a #GTree is
1028
 * automatically balanced as key/value pairs are added, key lookup
1029
 * is O(log n) (where n is the number of key/value pairs in the tree).
1030
 *
1031
 * Returns: (nullable) (transfer none): the tree node corresponding to
1032
 *          the key, or %NULL if the key was not found
1033
 *
1034
 * Since: 2.68
1035
 */
1036
GTreeNode *
1037
g_tree_lookup_node (GTree         *tree,
1038
                    gconstpointer  key)
1039
0
{
1040
0
  g_return_val_if_fail (tree != NULL, NULL);
1041
1042
0
  return g_tree_find_node (tree, key);
1043
0
}
1044
1045
/**
1046
 * g_tree_lookup:
1047
 * @tree: a #GTree
1048
 * @key: the key to look up
1049
 * 
1050
 * Gets the value corresponding to the given key. Since a #GTree is 
1051
 * automatically balanced as key/value pairs are added, key lookup
1052
 * is O(log n) (where n is the number of key/value pairs in the tree).
1053
 *
1054
 * Returns: the value corresponding to the key, or %NULL
1055
 *     if the key was not found
1056
 */
1057
gpointer
1058
g_tree_lookup (GTree         *tree,
1059
               gconstpointer  key)
1060
0
{
1061
0
  GTreeNode *node;
1062
1063
0
  node = g_tree_lookup_node (tree, key);
1064
1065
0
  return node ? node->value : NULL;
1066
0
}
1067
1068
/**
1069
 * g_tree_lookup_extended:
1070
 * @tree: a #GTree
1071
 * @lookup_key: the key to look up
1072
 * @orig_key: (out) (optional) (nullable): returns the original key
1073
 * @value: (out) (optional) (nullable): returns the value associated with the key
1074
 * 
1075
 * Looks up a key in the #GTree, returning the original key and the
1076
 * associated value. This is useful if you need to free the memory
1077
 * allocated for the original key, for example before calling
1078
 * g_tree_remove().
1079
 * 
1080
 * Returns: %TRUE if the key was found in the #GTree
1081
 */
1082
gboolean
1083
g_tree_lookup_extended (GTree         *tree,
1084
                        gconstpointer  lookup_key,
1085
                        gpointer      *orig_key,
1086
                        gpointer      *value)
1087
0
{
1088
0
  GTreeNode *node;
1089
  
1090
0
  g_return_val_if_fail (tree != NULL, FALSE);
1091
  
1092
0
  node = g_tree_find_node (tree, lookup_key);
1093
  
1094
0
  if (node)
1095
0
    {
1096
0
      if (orig_key)
1097
0
        *orig_key = node->key;
1098
0
      if (value)
1099
0
        *value = node->value;
1100
0
      return TRUE;
1101
0
    }
1102
0
  else
1103
0
    return FALSE;
1104
0
}
1105
1106
/**
1107
 * g_tree_foreach:
1108
 * @tree: a #GTree
1109
 * @func: (scope call): the function to call for each node visited.
1110
 *     If this function returns %TRUE, the traversal is stopped.
1111
 * @user_data: user data to pass to the function
1112
 *
1113
 * Calls the given function for each of the key/value pairs in the #GTree.
1114
 * The function is passed the key and value of each pair, and the given
1115
 * @data parameter. The tree is traversed in sorted order.
1116
 *
1117
 * The tree may not be modified while iterating over it (you can't 
1118
 * add/remove items). To remove all items matching a predicate, you need 
1119
 * to add each item to a list in your #GTraverseFunc as you walk over 
1120
 * the tree, then walk the list and remove each item.
1121
 */
1122
void
1123
g_tree_foreach (GTree         *tree,
1124
                GTraverseFunc  func,
1125
                gpointer       user_data)
1126
0
{
1127
0
  GTreeNode *node;
1128
1129
0
  g_return_if_fail (tree != NULL);
1130
  
1131
0
  if (!tree->root)
1132
0
    return;
1133
1134
0
  node = g_tree_node_first (tree);
1135
1136
0
  while (node)
1137
0
    {
1138
0
      if ((*func) (node->key, node->value, user_data))
1139
0
        break;
1140
      
1141
0
      node = g_tree_node_next (node);
1142
0
    }
1143
0
}
1144
1145
/**
1146
 * g_tree_foreach_node:
1147
 * @tree: a #GTree
1148
 * @func: (scope call): the function to call for each node visited.
1149
 *     If this function returns %TRUE, the traversal is stopped.
1150
 * @user_data: user data to pass to the function
1151
 *
1152
 * Calls the given function for each of the nodes in the #GTree.
1153
 * The function is passed the pointer to the particular node, and the given
1154
 * @data parameter. The tree traversal happens in-order.
1155
 *
1156
 * The tree may not be modified while iterating over it (you can't
1157
 * add/remove items). To remove all items matching a predicate, you need
1158
 * to add each item to a list in your #GTraverseFunc as you walk over
1159
 * the tree, then walk the list and remove each item.
1160
 *
1161
 * Since: 2.68
1162
 */
1163
void
1164
g_tree_foreach_node (GTree             *tree,
1165
                     GTraverseNodeFunc  func,
1166
                     gpointer           user_data)
1167
0
{
1168
0
  GTreeNode *node;
1169
1170
0
  g_return_if_fail (tree != NULL);
1171
1172
0
  if (!tree->root)
1173
0
    return;
1174
1175
0
  node = g_tree_node_first (tree);
1176
1177
0
  while (node)
1178
0
    {
1179
0
      if ((*func) (node, user_data))
1180
0
        break;
1181
1182
0
      node = g_tree_node_next (node);
1183
0
    }
1184
0
}
1185
1186
/**
1187
 * g_tree_traverse:
1188
 * @tree: a #GTree
1189
 * @traverse_func: (scope call): the function to call for each node visited. If this
1190
 *   function returns %TRUE, the traversal is stopped.
1191
 * @traverse_type: the order in which nodes are visited, one of %G_IN_ORDER,
1192
 *   %G_PRE_ORDER and %G_POST_ORDER
1193
 * @user_data: user data to pass to the function
1194
 * 
1195
 * Calls the given function for each node in the #GTree. 
1196
 *
1197
 * Deprecated:2.2: The order of a balanced tree is somewhat arbitrary.
1198
 *     If you just want to visit all nodes in sorted order, use
1199
 *     g_tree_foreach() instead. If you really need to visit nodes in
1200
 *     a different order, consider using an [n-ary tree][glib-N-ary-Trees].
1201
 */
1202
/**
1203
 * GTraverseFunc:
1204
 * @key: a key of a #GTree node
1205
 * @value: the value corresponding to the key
1206
 * @data: user data passed to g_tree_traverse()
1207
 *
1208
 * Specifies the type of function passed to g_tree_traverse(). It is
1209
 * passed the key and value of each node, together with the @user_data
1210
 * parameter passed to g_tree_traverse(). If the function returns
1211
 * %TRUE, the traversal is stopped.
1212
 *
1213
 * Returns: %TRUE to stop the traversal
1214
 */
1215
void
1216
g_tree_traverse (GTree         *tree,
1217
                 GTraverseFunc  traverse_func,
1218
                 GTraverseType  traverse_type,
1219
                 gpointer       user_data)
1220
0
{
1221
0
  g_return_if_fail (tree != NULL);
1222
1223
0
  if (!tree->root)
1224
0
    return;
1225
1226
0
  switch (traverse_type)
1227
0
    {
1228
0
    case G_PRE_ORDER:
1229
0
      g_tree_node_pre_order (tree->root, traverse_func, user_data);
1230
0
      break;
1231
1232
0
    case G_IN_ORDER:
1233
0
      g_tree_node_in_order (tree->root, traverse_func, user_data);
1234
0
      break;
1235
1236
0
    case G_POST_ORDER:
1237
0
      g_tree_node_post_order (tree->root, traverse_func, user_data);
1238
0
      break;
1239
    
1240
0
    case G_LEVEL_ORDER:
1241
0
      g_warning ("g_tree_traverse(): traverse type G_LEVEL_ORDER isn't implemented.");
1242
0
      break;
1243
0
    }
1244
0
}
1245
1246
/**
1247
 * g_tree_search_node:
1248
 * @tree: a #GTree
1249
 * @search_func: (scope call): a function used to search the #GTree
1250
 * @user_data: the data passed as the second argument to @search_func
1251
 *
1252
 * Searches a #GTree using @search_func.
1253
 *
1254
 * The @search_func is called with a pointer to the key of a key/value
1255
 * pair in the tree, and the passed in @user_data. If @search_func returns
1256
 * 0 for a key/value pair, then the corresponding node is returned as
1257
 * the result of g_tree_search(). If @search_func returns -1, searching
1258
 * will proceed among the key/value pairs that have a smaller key; if
1259
 * @search_func returns 1, searching will proceed among the key/value
1260
 * pairs that have a larger key.
1261
 *
1262
 * Returns: (nullable) (transfer none): the node corresponding to the
1263
 *          found key, or %NULL if the key was not found
1264
 *
1265
 * Since: 2.68
1266
 */
1267
GTreeNode *
1268
g_tree_search_node (GTree         *tree,
1269
                    GCompareFunc   search_func,
1270
                    gconstpointer  user_data)
1271
0
{
1272
0
  g_return_val_if_fail (tree != NULL, NULL);
1273
1274
0
  if (!tree->root)
1275
0
    return NULL;
1276
1277
0
  return g_tree_node_search (tree->root, search_func, user_data);
1278
0
}
1279
1280
/**
1281
 * g_tree_search:
1282
 * @tree: a #GTree
1283
 * @search_func: (scope call): a function used to search the #GTree
1284
 * @user_data: the data passed as the second argument to @search_func
1285
 *
1286
 * Searches a #GTree using @search_func.
1287
 *
1288
 * The @search_func is called with a pointer to the key of a key/value
1289
 * pair in the tree, and the passed in @user_data. If @search_func returns
1290
 * 0 for a key/value pair, then the corresponding value is returned as
1291
 * the result of g_tree_search(). If @search_func returns -1, searching
1292
 * will proceed among the key/value pairs that have a smaller key; if
1293
 * @search_func returns 1, searching will proceed among the key/value
1294
 * pairs that have a larger key.
1295
 *
1296
 * Returns: the value corresponding to the found key, or %NULL
1297
 *     if the key was not found
1298
 */
1299
gpointer
1300
g_tree_search (GTree         *tree,
1301
               GCompareFunc   search_func,
1302
               gconstpointer  user_data)
1303
0
{
1304
0
  GTreeNode *node;
1305
1306
0
  node = g_tree_search_node (tree, search_func, user_data);
1307
1308
0
  return node ? node->value : NULL;
1309
0
}
1310
1311
/**
1312
 * g_tree_lower_bound:
1313
 * @tree: a #GTree
1314
 * @key: the key to calculate the lower bound for
1315
 *
1316
 * Gets the lower bound node corresponding to the given key,
1317
 * or %NULL if the tree is empty or all the nodes in the tree
1318
 * have keys that are strictly lower than the searched key.
1319
 *
1320
 * The lower bound is the first node that has its key greater
1321
 * than or equal to the searched key.
1322
 *
1323
 * Returns: (nullable) (transfer none): the tree node corresponding to
1324
 *          the lower bound, or %NULL if the tree is empty or has only
1325
 *          keys strictly lower than the searched key.
1326
 *
1327
 * Since: 2.68
1328
 */
1329
GTreeNode *
1330
g_tree_lower_bound (GTree         *tree,
1331
                    gconstpointer  key)
1332
0
{
1333
0
  GTreeNode *node, *result;
1334
0
  gint cmp;
1335
1336
0
  g_return_val_if_fail (tree != NULL, NULL);
1337
1338
0
  node = tree->root;
1339
0
  if (!node)
1340
0
    return NULL;
1341
1342
0
  result = NULL;
1343
0
  while (1)
1344
0
    {
1345
0
      cmp = tree->key_compare (key, node->key, tree->key_compare_data);
1346
0
      if (cmp <= 0)
1347
0
        {
1348
0
          result = node;
1349
1350
0
          if (!node->left_child)
1351
0
            return result;
1352
1353
0
          node = node->left;
1354
0
        }
1355
0
      else
1356
0
        {
1357
0
          if (!node->right_child)
1358
0
            return result;
1359
1360
0
          node = node->right;
1361
0
        }
1362
0
    }
1363
0
}
1364
1365
/**
1366
 * g_tree_upper_bound:
1367
 * @tree: a #GTree
1368
 * @key: the key to calculate the upper bound for
1369
 *
1370
 * Gets the upper bound node corresponding to the given key,
1371
 * or %NULL if the tree is empty or all the nodes in the tree
1372
 * have keys that are lower than or equal to the searched key.
1373
 *
1374
 * The upper bound is the first node that has its key strictly greater
1375
 * than the searched key.
1376
 *
1377
 * Returns: (nullable) (transfer none): the tree node corresponding to the
1378
 *          upper bound, or %NULL if the tree is empty or has only keys
1379
 *          lower than or equal to the searched key.
1380
 *
1381
 * Since: 2.68
1382
 */
1383
GTreeNode *
1384
g_tree_upper_bound (GTree         *tree,
1385
                    gconstpointer  key)
1386
0
{
1387
0
  GTreeNode *node, *result;
1388
0
  gint cmp;
1389
1390
0
  g_return_val_if_fail (tree != NULL, NULL);
1391
1392
0
  node = tree->root;
1393
0
  if (!node)
1394
0
    return NULL;
1395
1396
0
  result = NULL;
1397
0
  while (1)
1398
0
    {
1399
0
      cmp = tree->key_compare (key, node->key, tree->key_compare_data);
1400
0
      if (cmp < 0)
1401
0
        {
1402
0
          result = node;
1403
1404
0
          if (!node->left_child)
1405
0
            return result;
1406
1407
0
          node = node->left;
1408
0
        }
1409
0
      else
1410
0
        {
1411
0
          if (!node->right_child)
1412
0
            return result;
1413
1414
0
          node = node->right;
1415
0
        }
1416
0
    }
1417
0
}
1418
1419
/**
1420
 * g_tree_height:
1421
 * @tree: a #GTree
1422
 * 
1423
 * Gets the height of a #GTree.
1424
 *
1425
 * If the #GTree contains no nodes, the height is 0.
1426
 * If the #GTree contains only one root node the height is 1.
1427
 * If the root node has children the height is 2, etc.
1428
 * 
1429
 * Returns: the height of @tree
1430
 */
1431
gint
1432
g_tree_height (GTree *tree)
1433
0
{
1434
0
  GTreeNode *node;
1435
0
  gint height;
1436
1437
0
  g_return_val_if_fail (tree != NULL, 0);
1438
1439
0
  if (!tree->root)
1440
0
    return 0;
1441
1442
0
  height = 0;
1443
0
  node = tree->root;
1444
1445
0
  while (1)
1446
0
    {
1447
0
      height += 1 + MAX(node->balance, 0);
1448
1449
0
      if (!node->left_child)
1450
0
        return height;
1451
      
1452
0
      node = node->left;
1453
0
    }
1454
0
}
1455
1456
/**
1457
 * g_tree_nnodes:
1458
 * @tree: a #GTree
1459
 * 
1460
 * Gets the number of nodes in a #GTree.
1461
 * 
1462
 * Returns: the number of nodes in @tree
1463
 *
1464
 * The node counter value type is really a #guint,
1465
 * but it is returned as a #gint due to backward
1466
 * compatibility issues (can be cast back to #guint to
1467
 * support its full range of values).
1468
 */
1469
gint
1470
g_tree_nnodes (GTree *tree)
1471
0
{
1472
0
  g_return_val_if_fail (tree != NULL, 0);
1473
1474
0
  return tree->nnodes;
1475
0
}
1476
1477
static GTreeNode *
1478
g_tree_node_balance (GTreeNode *node)
1479
0
{
1480
0
  if (node->balance < -1)
1481
0
    {
1482
0
      if (node->left->balance > 0)
1483
0
        node->left = g_tree_node_rotate_left (node->left);
1484
0
      node = g_tree_node_rotate_right (node);
1485
0
    }
1486
0
  else if (node->balance > 1)
1487
0
    {
1488
0
      if (node->right->balance < 0)
1489
0
        node->right = g_tree_node_rotate_right (node->right);
1490
0
      node = g_tree_node_rotate_left (node);
1491
0
    }
1492
1493
0
  return node;
1494
0
}
1495
1496
static GTreeNode *
1497
g_tree_find_node (GTree        *tree,
1498
                  gconstpointer key)
1499
0
{
1500
0
  GTreeNode *node;
1501
0
  gint cmp;
1502
1503
0
  node = tree->root;
1504
0
  if (!node)
1505
0
    return NULL;
1506
1507
0
  while (1)
1508
0
    {
1509
0
      cmp = tree->key_compare (key, node->key, tree->key_compare_data);
1510
0
      if (cmp == 0)
1511
0
        return node;
1512
0
      else if (cmp < 0)
1513
0
        {
1514
0
          if (!node->left_child)
1515
0
            return NULL;
1516
1517
0
          node = node->left;
1518
0
        }
1519
0
      else
1520
0
        {
1521
0
          if (!node->right_child)
1522
0
            return NULL;
1523
1524
0
          node = node->right;
1525
0
        }
1526
0
    }
1527
0
}
1528
1529
static gint
1530
g_tree_node_pre_order (GTreeNode     *node,
1531
                       GTraverseFunc  traverse_func,
1532
                       gpointer       data)
1533
0
{
1534
0
  if ((*traverse_func) (node->key, node->value, data))
1535
0
    return TRUE;
1536
1537
0
  if (node->left_child)
1538
0
    {
1539
0
      if (g_tree_node_pre_order (node->left, traverse_func, data))
1540
0
        return TRUE;
1541
0
    }
1542
1543
0
  if (node->right_child)
1544
0
    {
1545
0
      if (g_tree_node_pre_order (node->right, traverse_func, data))
1546
0
        return TRUE;
1547
0
    }
1548
1549
0
  return FALSE;
1550
0
}
1551
1552
static gint
1553
g_tree_node_in_order (GTreeNode     *node,
1554
                      GTraverseFunc  traverse_func,
1555
                      gpointer       data)
1556
0
{
1557
0
  if (node->left_child)
1558
0
    {
1559
0
      if (g_tree_node_in_order (node->left, traverse_func, data))
1560
0
        return TRUE;
1561
0
    }
1562
1563
0
  if ((*traverse_func) (node->key, node->value, data))
1564
0
    return TRUE;
1565
1566
0
  if (node->right_child)
1567
0
    {
1568
0
      if (g_tree_node_in_order (node->right, traverse_func, data))
1569
0
        return TRUE;
1570
0
    }
1571
  
1572
0
  return FALSE;
1573
0
}
1574
1575
static gint
1576
g_tree_node_post_order (GTreeNode     *node,
1577
                        GTraverseFunc  traverse_func,
1578
                        gpointer       data)
1579
0
{
1580
0
  if (node->left_child)
1581
0
    {
1582
0
      if (g_tree_node_post_order (node->left, traverse_func, data))
1583
0
        return TRUE;
1584
0
    }
1585
1586
0
  if (node->right_child)
1587
0
    {
1588
0
      if (g_tree_node_post_order (node->right, traverse_func, data))
1589
0
        return TRUE;
1590
0
    }
1591
1592
0
  if ((*traverse_func) (node->key, node->value, data))
1593
0
    return TRUE;
1594
1595
0
  return FALSE;
1596
0
}
1597
1598
static GTreeNode *
1599
g_tree_node_search (GTreeNode     *node,
1600
                    GCompareFunc   search_func,
1601
                    gconstpointer  data)
1602
0
{
1603
0
  gint dir;
1604
1605
0
  if (!node)
1606
0
    return NULL;
1607
1608
0
  while (1) 
1609
0
    {
1610
0
      dir = (* search_func) (node->key, data);
1611
0
      if (dir == 0)
1612
0
        return node;
1613
0
      else if (dir < 0) 
1614
0
        {
1615
0
          if (!node->left_child)
1616
0
            return NULL;
1617
1618
0
          node = node->left;
1619
0
        }
1620
0
      else
1621
0
        {
1622
0
          if (!node->right_child)
1623
0
            return NULL;
1624
1625
0
          node = node->right;
1626
0
        }
1627
0
    }
1628
0
}
1629
1630
static GTreeNode *
1631
g_tree_node_rotate_left (GTreeNode *node)
1632
0
{
1633
0
  GTreeNode *right;
1634
0
  gint a_bal;
1635
0
  gint b_bal;
1636
1637
0
  right = node->right;
1638
1639
0
  if (right->left_child)
1640
0
    node->right = right->left;
1641
0
  else
1642
0
    {
1643
0
      node->right_child = FALSE;
1644
0
      right->left_child = TRUE;
1645
0
    }
1646
0
  right->left = node;
1647
1648
0
  a_bal = node->balance;
1649
0
  b_bal = right->balance;
1650
1651
0
  if (b_bal <= 0)
1652
0
    {
1653
0
      if (a_bal >= 1)
1654
0
        right->balance = b_bal - 1;
1655
0
      else
1656
0
        right->balance = a_bal + b_bal - 2;
1657
0
      node->balance = a_bal - 1;
1658
0
    }
1659
0
  else
1660
0
    {
1661
0
      if (a_bal <= b_bal)
1662
0
        right->balance = a_bal - 2;
1663
0
      else
1664
0
        right->balance = b_bal - 1;
1665
0
      node->balance = a_bal - b_bal - 1;
1666
0
    }
1667
1668
0
  return right;
1669
0
}
1670
1671
static GTreeNode *
1672
g_tree_node_rotate_right (GTreeNode *node)
1673
0
{
1674
0
  GTreeNode *left;
1675
0
  gint a_bal;
1676
0
  gint b_bal;
1677
1678
0
  left = node->left;
1679
1680
0
  if (left->right_child)
1681
0
    node->left = left->right;
1682
0
  else
1683
0
    {
1684
0
      node->left_child = FALSE;
1685
0
      left->right_child = TRUE;
1686
0
    }
1687
0
  left->right = node;
1688
1689
0
  a_bal = node->balance;
1690
0
  b_bal = left->balance;
1691
1692
0
  if (b_bal <= 0)
1693
0
    {
1694
0
      if (b_bal > a_bal)
1695
0
        left->balance = b_bal + 1;
1696
0
      else
1697
0
        left->balance = a_bal + 2;
1698
0
      node->balance = a_bal - b_bal + 1;
1699
0
    }
1700
0
  else
1701
0
    {
1702
0
      if (a_bal <= -1)
1703
0
        left->balance = b_bal + 1;
1704
0
      else
1705
0
        left->balance = a_bal + b_bal + 2;
1706
0
      node->balance = a_bal + 1;
1707
0
    }
1708
1709
0
  return left;
1710
0
}
1711
1712
#ifdef G_TREE_DEBUG
1713
static gint
1714
g_tree_node_height (GTreeNode *node)
1715
{
1716
  gint left_height;
1717
  gint right_height;
1718
1719
  if (node)
1720
    {
1721
      left_height = 0;
1722
      right_height = 0;
1723
1724
      if (node->left_child)
1725
        left_height = g_tree_node_height (node->left);
1726
1727
      if (node->right_child)
1728
        right_height = g_tree_node_height (node->right);
1729
1730
      return MAX (left_height, right_height) + 1;
1731
    }
1732
1733
  return 0;
1734
}
1735
1736
static void
1737
g_tree_node_check (GTreeNode *node)
1738
{
1739
  gint left_height;
1740
  gint right_height;
1741
  gint balance;
1742
  GTreeNode *tmp;
1743
1744
  if (node)
1745
    {
1746
      if (node->left_child)
1747
        {
1748
          tmp = g_tree_node_previous (node);
1749
          g_assert (tmp->right == node);
1750
        }
1751
1752
      if (node->right_child)
1753
        {
1754
          tmp = g_tree_node_next (node);
1755
          g_assert (tmp->left == node);
1756
        }
1757
1758
      left_height = 0;
1759
      right_height = 0;
1760
      
1761
      if (node->left_child)
1762
        left_height = g_tree_node_height (node->left);
1763
      if (node->right_child)
1764
        right_height = g_tree_node_height (node->right);
1765
      
1766
      balance = right_height - left_height;
1767
      g_assert (balance == node->balance);
1768
      
1769
      if (node->left_child)
1770
        g_tree_node_check (node->left);
1771
      if (node->right_child)
1772
        g_tree_node_check (node->right);
1773
    }
1774
}
1775
1776
static void
1777
g_tree_node_dump (GTreeNode *node, 
1778
                  gint       indent)
1779
{
1780
  g_print ("%*s%c\n", indent, "", *(char *)node->key);
1781
1782
  if (node->left_child)
1783
    {
1784
      g_print ("%*sLEFT\n", indent, "");
1785
      g_tree_node_dump (node->left, indent + 2);
1786
    }
1787
  else if (node->left)
1788
    g_print ("%*s<%c\n", indent + 2, "", *(char *)node->left->key);
1789
1790
  if (node->right_child)
1791
    {
1792
      g_print ("%*sRIGHT\n", indent, "");
1793
      g_tree_node_dump (node->right, indent + 2);
1794
    }
1795
  else if (node->right)
1796
    g_print ("%*s>%c\n", indent + 2, "", *(char *)node->right->key);
1797
}
1798
1799
void
1800
g_tree_dump (GTree *tree)
1801
{
1802
  if (tree->root)
1803
    g_tree_node_dump (tree->root, 0);
1804
}
1805
#endif