1
/* GLIB - Library of useful routines for C programming
2
* Copyright (C) 2002 Soeren Sandmann (sandmann@daimi.au.dk)
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the
16
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17
* Boston, MA 02111-1307, USA.
22
#include "gtksequence.h"
25
typedef struct _GtkSequenceNode GtkSequenceNode;
28
GtkSequenceNode *node; /* does not necessarily point to the root.
29
* You can splay it if you want it to
31
GDestroyNotify data_destroy_notify;
34
struct _GtkSequenceNode {
36
gint n_nodes : 31; /* number of nodes below this node,
39
GtkSequenceNode *parent;
40
GtkSequenceNode *left;
41
GtkSequenceNode *right;
43
GtkSequence *sequence;
48
static GtkSequenceNode *_gtk_sequence_node_new (gpointer data);
49
static GtkSequenceNode *_gtk_sequence_node_find_first (GtkSequenceNode *node);
50
static GtkSequenceNode *_gtk_sequence_node_find_last (GtkSequenceNode *node);
51
static GtkSequenceNode *_gtk_sequence_node_find_by_pos (GtkSequenceNode *node,
53
static GtkSequenceNode *_gtk_sequence_node_prev (GtkSequenceNode *node);
54
static GtkSequenceNode *_gtk_sequence_node_next (GtkSequenceNode *node);
55
static gint _gtk_sequence_node_get_pos (GtkSequenceNode *node);
56
static GtkSequence *_gtk_sequence_node_get_sequence (GtkSequenceNode *node);
57
static GtkSequenceNode *_gtk_sequence_node_find_closest (GtkSequenceNode *node,
58
GtkSequenceNode *other,
61
static gint _gtk_sequence_node_get_length (GtkSequenceNode *node);
62
static void _gtk_sequence_node_free (GtkSequenceNode *node,
63
GDestroyNotify destroy);
65
static gboolean _gtk_sequence_node_is_singleton (GtkSequenceNode *node);
67
static void _gtk_sequence_node_split (GtkSequenceNode *node,
68
GtkSequenceNode **left,
69
GtkSequenceNode **right);
70
static void _gtk_sequence_node_insert_before (GtkSequenceNode *node,
71
GtkSequenceNode *new);
72
static void _gtk_sequence_node_remove (GtkSequenceNode *node);
73
static void _gtk_sequence_node_insert_sorted (GtkSequenceNode *node,
75
GCompareDataFunc cmp_func,
80
_gtk_sequence_new (GDestroyNotify data_destroy)
82
GtkSequence *seq = g_new (GtkSequence, 1);
83
seq->data_destroy_notify = data_destroy;
85
seq->node = _gtk_sequence_node_new (NULL);
86
seq->node->is_end = TRUE;
87
seq->node->sequence = seq;
93
_gtk_sequence_foreach (GtkSequence *seq,
99
g_return_if_fail (seq != NULL);
100
g_return_if_fail (func != NULL);
102
ptr = _gtk_sequence_get_begin_ptr (seq);
104
while (!_gtk_sequence_ptr_is_end (ptr))
106
GtkSequenceNode *node = ptr;
108
func (node->data, data);
110
ptr = _gtk_sequence_ptr_next (ptr);
116
_gtk_sequence_free (GtkSequence *seq)
118
g_return_if_fail (seq != NULL);
120
_gtk_sequence_node_free (seq->node, seq->data_destroy_notify);
127
flatten_nodes (GtkSequenceNode *node, GList **list)
129
g_print ("flatten %p\n", node);
132
else if (_gtk_sequence_node_is_singleton (node))
133
*list = g_list_prepend (*list, node);
136
GtkSequenceNode *left;
137
GtkSequenceNode *right;
139
_gtk_sequence_node_split (node, &left, &right);
141
flatten_nodes (left, list);
142
flatten_nodes (right, list);
147
typedef struct SortInfo SortInfo;
149
GCompareDataFunc cmp;
154
node_compare (gconstpointer n1, gconstpointer n2, gpointer data)
156
const SortInfo *info = data;
157
const GtkSequenceNode *node1 = n1;
158
const GtkSequenceNode *node2 = n2;
167
retval = (* info->cmp) (node1, node2, info->data);
169
/* If the nodes are different, but the user-supplied compare function
170
* compares them equal, then force an arbitrary (but consistent) order
171
* on them, so that our sorts will be stable
173
if (retval != 0 || n1 == n2)
183
_gtk_sequence_append (GtkSequence *seq,
186
GtkSequenceNode *node, *last;
188
g_return_if_fail (seq != NULL);
190
node = _gtk_sequence_node_new (data);
191
node->sequence = seq;
192
last = _gtk_sequence_node_find_last (seq->node);
193
_gtk_sequence_node_insert_before (last, node);
198
_gtk_sequence_prepend (GtkSequence *seq,
201
GtkSequenceNode *node, *second;
203
g_return_if_fail (seq != NULL);
205
node = _gtk_sequence_node_new (data);
206
node->sequence = seq;
207
second = _gtk_sequence_node_next (_gtk_sequence_node_find_first (seq->node));
209
_gtk_sequence_node_insert_before (second, node);
214
_gtk_sequence_insert (GtkSequencePtr ptr,
217
GtkSequenceNode *node;
219
g_return_val_if_fail (ptr != NULL, NULL);
221
node = _gtk_sequence_node_new (data);
222
node->sequence = ptr->sequence;
224
_gtk_sequence_node_insert_before (ptr, node);
230
_gtk_sequence_unlink (GtkSequence *seq,
231
GtkSequenceNode *node)
233
g_assert (!node->is_end);
235
seq->node = _gtk_sequence_node_next (node);
237
g_assert (seq->node);
238
g_assert (seq->node != node);
240
_gtk_sequence_node_remove (node);
244
_gtk_sequence_remove (GtkSequencePtr ptr)
248
g_return_if_fail (ptr != NULL);
249
g_return_if_fail (!ptr->is_end);
251
seq = _gtk_sequence_node_get_sequence (ptr);
252
_gtk_sequence_unlink (seq, ptr);
253
_gtk_sequence_node_free (ptr, seq->data_destroy_notify);
257
_gtk_sequence_sort (GtkSequence *seq,
258
GCompareDataFunc cmp_func,
262
GtkSequenceNode *begin, *end;
264
g_return_if_fail (seq != NULL);
265
g_return_if_fail (cmp_func != NULL);
267
begin = _gtk_sequence_get_begin_ptr (seq);
268
end = _gtk_sequence_get_end_ptr (seq);
270
_gtk_sequence_remove_range (begin, end, &tmp);
272
while (_gtk_sequence_get_length (tmp) > 0)
274
GtkSequenceNode *node = _gtk_sequence_get_begin_ptr (tmp);
275
_gtk_sequence_unlink (tmp, node);
277
_gtk_sequence_node_insert_sorted (seq->node, node, cmp_func, cmp_data);
280
_gtk_sequence_free (tmp);
284
_gtk_sequence_ptr_get_data (GtkSequencePtr ptr)
286
g_return_val_if_fail (ptr != NULL, NULL);
287
g_return_val_if_fail (!ptr->is_end, NULL);
293
_gtk_sequence_insert_sorted (GtkSequence *seq,
295
GCompareDataFunc cmp_func,
298
GtkSequenceNode *new_node = _gtk_sequence_node_new (data);
299
new_node->sequence = seq;
300
_gtk_sequence_node_insert_sorted (seq->node, new_node, cmp_func, cmp_data);
305
_gtk_sequence_insert_sequence (GtkSequencePtr ptr,
306
GtkSequence *other_seq)
308
GtkSequenceNode *last;
310
g_return_if_fail (other_seq != NULL);
311
g_return_if_fail (ptr != NULL);
313
last = _gtk_sequence_node_find_last (other_seq->node);
314
_gtk_sequence_node_insert_before (ptr, last);
315
_gtk_sequence_node_remove (last);
316
_gtk_sequence_node_free (last, NULL);
317
other_seq->node = NULL;
318
_gtk_sequence_free (other_seq);
322
_gtk_sequence_concatenate (GtkSequence *seq1,
325
GtkSequenceNode *last;
327
g_return_if_fail (seq1 != NULL);
328
g_return_if_fail (seq2 != NULL);
330
last = _gtk_sequence_node_find_last (seq1->node);
331
_gtk_sequence_insert_sequence (last, seq2);
335
* The new sequence inherits the destroy notify from the sequence that
336
* beign and end comes from
339
_gtk_sequence_remove_range (GtkSequencePtr begin,
341
GtkSequence **removed)
344
GtkSequenceNode *s1, *s2, *s3;
346
seq = _gtk_sequence_node_get_sequence (begin);
348
g_assert (end != NULL);
350
g_return_if_fail (seq == _gtk_sequence_node_get_sequence (end));
352
_gtk_sequence_node_split (begin, &s1, &s2);
353
_gtk_sequence_node_split (end, NULL, &s3);
356
_gtk_sequence_node_insert_before (s3, s1);
362
*removed = _gtk_sequence_new (seq->data_destroy_notify);
363
_gtk_sequence_node_insert_before ((*removed)->node, s2);
367
_gtk_sequence_node_free (s2, seq->data_destroy_notify);
372
_gtk_sequence_get_length (GtkSequence *seq)
374
return _gtk_sequence_node_get_length (seq->node) - 1;
378
_gtk_sequence_get_end_ptr (GtkSequence *seq)
380
g_return_val_if_fail (seq != NULL, NULL);
381
return _gtk_sequence_node_find_last (seq->node);
385
_gtk_sequence_get_begin_ptr (GtkSequence *seq)
387
g_return_val_if_fail (seq != NULL, NULL);
388
return _gtk_sequence_node_find_first (seq->node);
392
* if pos > number of items or -1, will return end pointer
395
_gtk_sequence_get_ptr_at_pos (GtkSequence *seq,
400
g_return_val_if_fail (seq != NULL, NULL);
402
len = _gtk_sequence_get_length (seq);
404
if (pos > len || pos == -1)
407
return _gtk_sequence_node_find_by_pos (seq->node, pos);
413
_gtk_sequence_ptr_is_end (GtkSequencePtr ptr)
415
g_return_val_if_fail (ptr != NULL, FALSE);
420
_gtk_sequence_ptr_is_begin (GtkSequencePtr ptr)
422
return (_gtk_sequence_node_prev (ptr) == ptr);
425
/* If you call this on an end pointer you'll get
426
* the length of the sequence
429
_gtk_sequence_ptr_get_position (GtkSequencePtr ptr)
431
g_return_val_if_fail (ptr != NULL, -1);
433
return _gtk_sequence_node_get_pos (ptr);
437
_gtk_sequence_ptr_next (GtkSequencePtr ptr)
439
g_return_val_if_fail (ptr != NULL, NULL);
441
return _gtk_sequence_node_next (ptr);
445
_gtk_sequence_ptr_prev (GtkSequencePtr ptr)
447
g_return_val_if_fail (ptr != NULL, NULL);
449
return _gtk_sequence_node_prev (ptr);
453
_gtk_sequence_ptr_move (GtkSequencePtr ptr,
458
g_return_val_if_fail (ptr != NULL, NULL);
460
new_pos = _gtk_sequence_node_get_pos (ptr) + delta;
462
return _gtk_sequence_node_find_by_pos (ptr, new_pos);
466
_gtk_sequence_sort_changed (GtkSequencePtr ptr,
467
GCompareDataFunc cmp_func,
473
g_return_if_fail (ptr != NULL);
474
g_return_if_fail (!ptr->is_end);
476
seq = _gtk_sequence_node_get_sequence (ptr);
477
_gtk_sequence_unlink (seq, ptr);
478
_gtk_sequence_node_insert_sorted (seq->node, ptr, cmp_func, cmp_data);
483
* The only restriction on the search function is that it
484
* must not delete any nodes. It is permitted to insert new nodes,
485
* but the caller should "know what he is doing"
488
_gtk_sequence_search (GtkSequence *seq,
489
GtkSequenceSearchFunc f,
492
GQueue *intervals = g_queue_new ();
494
g_queue_push_tail (intervals, _gtk_sequence_node_find_first (seq->node));
495
g_queue_push_tail (intervals, _gtk_sequence_node_find_last (seq->node));
497
while (!g_queue_is_empty (intervals))
499
GtkSequenceNode *begin = g_queue_pop_head (intervals);
500
GtkSequenceNode *end = g_queue_pop_head (intervals);
502
if (f (begin, end, data))
504
gint begin_pos = _gtk_sequence_node_get_pos (begin);
505
gint end_pos = _gtk_sequence_node_get_pos (end);
507
if (end_pos - begin_pos > 1)
509
GtkSequenceNode *mid;
512
mid_pos = begin_pos + (end_pos - begin_pos) / 2;
513
mid = _gtk_sequence_node_find_by_pos (begin, mid_pos);
515
g_queue_push_tail (intervals, begin);
516
g_queue_push_tail (intervals, mid);
518
g_queue_push_tail (intervals, mid);
519
g_queue_push_tail (intervals, end);
524
g_queue_free (intervals);
530
_gtk_sequence_add_aggregate (GtkSequence *seq,
531
const gchar *aggregate,
532
GtkSequenceAggregateFunc f,
534
GDestroyNotify destroy)
540
_gtk_sequence_remove_aggregate (GtkSequence *seq,
541
const gchar aggregate)
548
_gtk_sequence_set_aggregate_data (GtkSequencePtr ptr,
549
const gchar *aggregate,
557
_gtk_sequence_get_aggregate_data (GtkSequencePtr begin,
559
const gchar *aggregate)
561
g_assert_not_reached();
570
_gtk_sequence_node_update_fields (GtkSequenceNode *node)
572
g_assert (node != NULL);
577
node->n_nodes += node->left->n_nodes;
580
node->n_nodes += node->right->n_nodes;
583
if (node->left || node->right)
584
g_assert (node->n_nodes > 1);
588
#define NODE_LEFT_CHILD(n) (((n)->parent) && ((n)->parent->left) == (n))
589
#define NODE_RIGHT_CHILD(n) (((n)->parent) && ((n)->parent->right) == (n))
592
_gtk_sequence_node_rotate (GtkSequenceNode *node)
594
GtkSequenceNode *tmp, *old;
596
g_assert (node->parent);
597
g_assert (node->parent != node);
599
if (NODE_LEFT_CHILD (node))
604
node->right = node->parent;
605
node->parent = node->parent->parent;
608
if (node->parent->left == node->right)
609
node->parent->left = node;
611
node->parent->right = node;
614
g_assert (node->right);
616
node->right->parent = node;
617
node->right->left = tmp;
619
if (node->right->left)
620
node->right->left->parent = node->right;
629
node->left = node->parent;
630
node->parent = node->parent->parent;
633
if (node->parent->right == node->left)
634
node->parent->right = node;
636
node->parent->left = node;
639
g_assert (node->left);
641
node->left->parent = node;
642
node->left->right = tmp;
644
if (node->left->right)
645
node->left->right->parent = node->left;
650
_gtk_sequence_node_update_fields (old);
651
_gtk_sequence_node_update_fields (node);
654
static GtkSequenceNode *
655
splay (GtkSequenceNode *node)
659
if (!node->parent->parent)
662
_gtk_sequence_node_rotate (node);
664
else if ((NODE_LEFT_CHILD (node) && NODE_LEFT_CHILD (node->parent)) ||
665
(NODE_RIGHT_CHILD (node) && NODE_RIGHT_CHILD (node->parent)))
668
_gtk_sequence_node_rotate (node->parent);
669
_gtk_sequence_node_rotate (node);
674
_gtk_sequence_node_rotate (node);
675
_gtk_sequence_node_rotate (node);
682
static GtkSequenceNode *
683
_gtk_sequence_node_new (gpointer data)
685
GtkSequenceNode *node = g_new0 (GtkSequenceNode, 1);
692
node->is_end = FALSE;
698
static GtkSequenceNode *
699
find_min (GtkSequenceNode *node)
709
static GtkSequenceNode *
710
find_max (GtkSequenceNode *node)
720
static GtkSequenceNode *
721
_gtk_sequence_node_find_first (GtkSequenceNode *node)
723
return splay (find_min (node));
726
static GtkSequenceNode *
727
_gtk_sequence_node_find_last (GtkSequenceNode *node)
729
return splay (find_max (node));
733
get_n_nodes (GtkSequenceNode *node)
736
return node->n_nodes;
741
static GtkSequenceNode *
742
_gtk_sequence_node_find_by_pos (GtkSequenceNode *node,
747
g_assert (node != NULL);
751
while ((i = get_n_nodes (node->left)) != pos)
761
g_assert (node->parent != NULL);
768
static GtkSequenceNode *
769
_gtk_sequence_node_prev (GtkSequenceNode *node)
783
static GtkSequenceNode *
784
_gtk_sequence_node_next (GtkSequenceNode *node)
799
_gtk_sequence_node_get_pos (GtkSequenceNode *node)
803
return get_n_nodes (node->left);
807
_gtk_sequence_node_get_sequence (GtkSequenceNode *node)
811
return node->sequence;
814
static GtkSequenceNode *
815
_gtk_sequence_node_find_closest (GtkSequenceNode *node,
816
GtkSequenceNode *other,
817
GCompareDataFunc cmp,
820
GtkSequenceNode *best;
829
if ((c = cmp (node, other, data)) != 0)
837
while (c != 0 && node != NULL);
843
_gtk_sequence_node_free (GtkSequenceNode *node,
844
GDestroyNotify destroy)
848
* This is to avoid excessively deep recursions. A splay tree is not necessarily
851
* I _think_ this is still linear in the number of nodes, but I'd like to
852
* do something more efficient.
857
GtkSequenceNode *next;
859
node = splay (find_min (node));
864
if (destroy && !node->is_end)
865
destroy (node->data);
874
_gtk_sequence_node_is_singleton (GtkSequenceNode *node)
878
if (node->left || node->right)
886
_gtk_sequence_node_split (GtkSequenceNode *node,
887
GtkSequenceNode **left,
888
GtkSequenceNode **right)
890
GtkSequenceNode *left_tree;
894
left_tree = node->left;
897
left_tree->parent = NULL;
898
_gtk_sequence_node_update_fields (left_tree);
902
_gtk_sequence_node_update_fields (node);
912
_gtk_sequence_node_insert_before (GtkSequenceNode *node,
913
GtkSequenceNode *new)
915
g_assert (node != NULL);
916
g_assert (new != NULL);
920
new = splay (find_min (new));
921
g_assert (new->left == NULL);
924
node->left->parent = new;
926
new->left = node->left;
931
_gtk_sequence_node_update_fields (new);
932
_gtk_sequence_node_update_fields (node);
936
_gtk_sequence_node_get_length (GtkSequenceNode *node)
938
g_assert (node != NULL);
941
return node->n_nodes;
945
_gtk_sequence_node_remove (GtkSequenceNode *node)
947
GtkSequenceNode *right, *left;
954
node->left = node->right = NULL;
958
right->parent = NULL;
960
right = _gtk_sequence_node_find_first (right);
961
g_assert (right->left == NULL);
966
left->parent = right;
967
_gtk_sequence_node_update_fields (right);
977
_gtk_sequence_node_calc_height (GtkSequenceNode *node)
979
/* breadth first traversal */
981
GQueue *nodes = g_queue_new ();
983
g_queue_push_tail (nodes, node);
985
while (!g_queue_is_empty (nodes))
987
GQueue *tmp = g_queue_new ();
990
while (!g_queue_is_empty (nodes))
992
GtkSequenceNode *node = g_queue_pop_head (nodes);
994
g_queue_push_tail (tmp, node->left);
996
g_queue_push_tail (tmp, node->right);
999
g_queue_free (nodes);
1003
g_queue_free (nodes);
1010
_gtk_sequence_node_insert_sorted (GtkSequenceNode *node,
1011
GtkSequenceNode *new,
1012
GCompareDataFunc cmp_func,
1016
GtkSequenceNode *closest;
1017
info.cmp = cmp_func;
1018
info.data = cmp_data;
1021
_gtk_sequence_node_find_closest (node, new, node_compare, &info);
1023
g_assert (closest != new);
1025
if (node_compare (new, closest, &info) > 0)
1026
closest = _gtk_sequence_node_next (closest);
1028
_gtk_sequence_node_insert_before (closest, new);
1032
_gtk_sequence_node_calc_height (GtkSequenceNode *node)
1043
left_height = _gtk_sequence_node_calc_height (node->left);
1046
right_height = _gtk_sequence_node_calc_height (node->right);
1048
return MAX (left_height, right_height) + 1;
1055
_gtk_sequence_calc_tree_height (GtkSequence *seq)
1057
GtkSequenceNode *node = seq->node;
1059
while (node->parent)
1060
node = node->parent;
1064
r = _gtk_sequence_node_calc_height (node->right);
1065
l = _gtk_sequence_node_calc_height (node->left);
1067
return MAX (r, l) + 1;
1074
_gtk_sequence_ptr_get_sequence (GtkSequencePtr ptr)
1076
GtkSequenceNode *node = ptr;
1078
return node->sequence;
1082
_gtk_sequence_swap (GtkSequencePtr a,
1085
GtkSequenceNode *leftmost, *rightmost, *rightmost_next;
1088
g_return_if_fail (!_gtk_sequence_ptr_is_end (a));
1089
g_return_if_fail (!_gtk_sequence_ptr_is_end (b));
1094
a_pos = _gtk_sequence_ptr_get_position (a);
1095
b_pos = _gtk_sequence_ptr_get_position (b);
1108
rightmost_next = _gtk_sequence_node_next (rightmost);
1110
/* Situation now: ..., leftmost, ......., rightmost, rightmost_next, ... */
1112
_gtk_sequence_move (rightmost, leftmost);
1113
_gtk_sequence_move (leftmost, rightmost_next);
1117
_gtk_sequence_move (GtkSequencePtr ptr,
1118
GtkSequencePtr new_pos)
1120
g_return_if_fail (ptr != NULL);
1121
g_return_if_fail (new_pos != NULL);
1126
_gtk_sequence_unlink (ptr->sequence, ptr);
1127
_gtk_sequence_node_insert_before (new_pos, ptr);
1130
/* Overwrites the existing pointer. */
1132
_gtk_sequence_set (GtkSequencePtr ptr,
1137
g_return_if_fail (!_gtk_sequence_ptr_is_end (ptr));
1139
seq = _gtk_sequence_node_get_sequence (ptr);
1140
if (seq->data_destroy_notify)
1141
seq->data_destroy_notify (ptr->data);