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"
24 typedef struct _GtkSequenceNode GtkSequenceNode;
27 GtkSequenceNode *node; /* does not necessarily point to the root.
28 * You can splay it if you want it to
30 GDestroyNotify data_destroy_notify;
33 struct _GtkSequenceNode {
35 gint n_nodes : 31; /* number of nodes below this node,
38 GtkSequenceNode *parent;
39 GtkSequenceNode *left;
40 GtkSequenceNode *right;
42 GtkSequence *sequence;
47 static GtkSequenceNode *_gtk_sequence_node_new (gpointer data);
48 static GtkSequenceNode *_gtk_sequence_node_find_first (GtkSequenceNode *node);
49 static GtkSequenceNode *_gtk_sequence_node_find_last (GtkSequenceNode *node);
50 static GtkSequenceNode *_gtk_sequence_node_find_by_pos (GtkSequenceNode *node,
52 static GtkSequenceNode *_gtk_sequence_node_prev (GtkSequenceNode *node);
53 static GtkSequenceNode *_gtk_sequence_node_next (GtkSequenceNode *node);
54 static gint _gtk_sequence_node_get_pos (GtkSequenceNode *node);
55 static GtkSequence *_gtk_sequence_node_get_sequence (GtkSequenceNode *node);
56 static GtkSequenceNode *_gtk_sequence_node_find_closest (GtkSequenceNode *node,
57 GtkSequenceNode *other,
60 static gint _gtk_sequence_node_get_length (GtkSequenceNode *node);
61 static void _gtk_sequence_node_free (GtkSequenceNode *node,
62 GDestroyNotify destroy);
64 static gboolean _gtk_sequence_node_is_singleton (GtkSequenceNode *node);
66 static void _gtk_sequence_node_split (GtkSequenceNode *node,
67 GtkSequenceNode **left,
68 GtkSequenceNode **right);
69 static void _gtk_sequence_node_insert_before (GtkSequenceNode *node,
70 GtkSequenceNode *new);
71 static void _gtk_sequence_node_remove (GtkSequenceNode *node);
72 static void _gtk_sequence_node_insert_sorted (GtkSequenceNode *node,
74 GCompareDataFunc cmp_func,
79 _gtk_sequence_new (GDestroyNotify data_destroy)
81 GtkSequence *seq = g_new (GtkSequence, 1);
82 seq->data_destroy_notify = data_destroy;
84 seq->node = _gtk_sequence_node_new (NULL);
85 seq->node->is_end = TRUE;
86 seq->node->sequence = seq;
92 _gtk_sequence_foreach (GtkSequence *seq,
98 g_return_if_fail (seq != NULL);
99 g_return_if_fail (func != NULL);
101 ptr = _gtk_sequence_get_begin_ptr (seq);
103 while (!_gtk_sequence_ptr_is_end (ptr))
105 GtkSequenceNode *node = ptr;
107 func (node->data, data);
109 ptr = _gtk_sequence_ptr_next (ptr);
115 _gtk_sequence_free (GtkSequence *seq)
117 g_return_if_fail (seq != NULL);
119 _gtk_sequence_node_free (seq->node, seq->data_destroy_notify);
126 flatten_nodes (GtkSequenceNode *node, GList **list)
128 g_print ("flatten %p\n", node);
131 else if (_gtk_sequence_node_is_singleton (node))
132 *list = g_list_prepend (*list, node);
135 GtkSequenceNode *left;
136 GtkSequenceNode *right;
138 _gtk_sequence_node_split (node, &left, &right);
140 flatten_nodes (left, list);
141 flatten_nodes (right, list);
146 typedef struct SortInfo SortInfo;
148 GCompareDataFunc cmp;
153 node_compare (gconstpointer n1, gconstpointer n2, gpointer data)
155 const SortInfo *info = data;
156 const GtkSequenceNode *node1 = n1;
157 const GtkSequenceNode *node2 = n2;
166 retval = (* info->cmp) (node1, node2, info->data);
168 /* If the nodes are different, but the user-supplied compare function
169 * compares them equal, then force an arbitrary (but consistent) order
170 * on them, so that our sorts will be stable
172 if (retval != 0 || n1 == n2)
182 _gtk_sequence_append (GtkSequence *seq,
185 GtkSequenceNode *node, *last;
187 g_return_if_fail (seq != NULL);
189 node = _gtk_sequence_node_new (data);
190 node->sequence = seq;
191 last = _gtk_sequence_node_find_last (seq->node);
192 _gtk_sequence_node_insert_before (last, node);
197 _gtk_sequence_prepend (GtkSequence *seq,
200 GtkSequenceNode *node, *second;
202 g_return_if_fail (seq != NULL);
204 node = _gtk_sequence_node_new (data);
205 node->sequence = seq;
206 second = _gtk_sequence_node_next (_gtk_sequence_node_find_first (seq->node));
208 _gtk_sequence_node_insert_before (second, node);
213 _gtk_sequence_insert (GtkSequencePtr ptr,
216 GtkSequenceNode *node;
218 g_return_val_if_fail (ptr != NULL, NULL);
220 node = _gtk_sequence_node_new (data);
221 node->sequence = ptr->sequence;
223 _gtk_sequence_node_insert_before (ptr, node);
229 _gtk_sequence_unlink (GtkSequence *seq,
230 GtkSequenceNode *node)
232 g_assert (!node->is_end);
234 seq->node = _gtk_sequence_node_next (node);
236 g_assert (seq->node);
237 g_assert (seq->node != node);
239 _gtk_sequence_node_remove (node);
243 _gtk_sequence_remove (GtkSequencePtr ptr)
247 g_return_if_fail (ptr != NULL);
248 g_return_if_fail (!ptr->is_end);
250 seq = _gtk_sequence_node_get_sequence (ptr);
251 _gtk_sequence_unlink (seq, ptr);
252 _gtk_sequence_node_free (ptr, seq->data_destroy_notify);
256 _gtk_sequence_sort (GtkSequence *seq,
257 GCompareDataFunc cmp_func,
261 GtkSequenceNode *begin, *end;
263 g_return_if_fail (seq != NULL);
264 g_return_if_fail (cmp_func != NULL);
266 begin = _gtk_sequence_get_begin_ptr (seq);
267 end = _gtk_sequence_get_end_ptr (seq);
269 _gtk_sequence_remove_range (begin, end, &tmp);
271 while (_gtk_sequence_get_length (tmp) > 0)
273 GtkSequenceNode *node = _gtk_sequence_get_begin_ptr (tmp);
274 _gtk_sequence_unlink (tmp, node);
276 _gtk_sequence_node_insert_sorted (seq->node, node, cmp_func, cmp_data);
279 _gtk_sequence_free (tmp);
283 _gtk_sequence_ptr_get_data (GtkSequencePtr ptr)
285 g_return_val_if_fail (ptr != NULL, NULL);
286 g_return_val_if_fail (!ptr->is_end, NULL);
292 _gtk_sequence_insert_sorted (GtkSequence *seq,
294 GCompareDataFunc cmp_func,
297 GtkSequenceNode *new_node = _gtk_sequence_node_new (data);
298 new_node->sequence = seq;
299 _gtk_sequence_node_insert_sorted (seq->node, new_node, cmp_func, cmp_data);
304 _gtk_sequence_insert_sequence (GtkSequencePtr ptr,
305 GtkSequence *other_seq)
307 GtkSequenceNode *last;
309 g_return_if_fail (other_seq != NULL);
310 g_return_if_fail (ptr != NULL);
312 last = _gtk_sequence_node_find_last (other_seq->node);
313 _gtk_sequence_node_insert_before (ptr, last);
314 _gtk_sequence_node_remove (last);
315 _gtk_sequence_node_free (last, NULL);
316 other_seq->node = NULL;
317 _gtk_sequence_free (other_seq);
321 _gtk_sequence_concatenate (GtkSequence *seq1,
324 GtkSequenceNode *last;
326 g_return_if_fail (seq1 != NULL);
327 g_return_if_fail (seq2 != NULL);
329 last = _gtk_sequence_node_find_last (seq1->node);
330 _gtk_sequence_insert_sequence (last, seq2);
334 * The new sequence inherits the destroy notify from the sequence that
335 * beign and end comes from
338 _gtk_sequence_remove_range (GtkSequencePtr begin,
340 GtkSequence **removed)
343 GtkSequenceNode *s1, *s2, *s3;
345 seq = _gtk_sequence_node_get_sequence (begin);
347 g_assert (end != NULL);
349 g_return_if_fail (seq == _gtk_sequence_node_get_sequence (end));
351 _gtk_sequence_node_split (begin, &s1, &s2);
352 _gtk_sequence_node_split (end, NULL, &s3);
355 _gtk_sequence_node_insert_before (s3, s1);
361 *removed = _gtk_sequence_new (seq->data_destroy_notify);
362 _gtk_sequence_node_insert_before ((*removed)->node, s2);
366 _gtk_sequence_node_free (s2, seq->data_destroy_notify);
371 _gtk_sequence_get_length (GtkSequence *seq)
373 return _gtk_sequence_node_get_length (seq->node) - 1;
377 _gtk_sequence_get_end_ptr (GtkSequence *seq)
379 g_return_val_if_fail (seq != NULL, NULL);
380 return _gtk_sequence_node_find_last (seq->node);
384 _gtk_sequence_get_begin_ptr (GtkSequence *seq)
386 g_return_val_if_fail (seq != NULL, NULL);
387 return _gtk_sequence_node_find_first (seq->node);
391 * if pos > number of items or -1, will return end pointer
394 _gtk_sequence_get_ptr_at_pos (GtkSequence *seq,
399 g_return_val_if_fail (seq != NULL, NULL);
401 len = _gtk_sequence_get_length (seq);
403 if (pos > len || pos == -1)
406 return _gtk_sequence_node_find_by_pos (seq->node, pos);
412 _gtk_sequence_ptr_is_end (GtkSequencePtr ptr)
414 g_return_val_if_fail (ptr != NULL, FALSE);
419 _gtk_sequence_ptr_is_begin (GtkSequencePtr ptr)
421 return (_gtk_sequence_node_prev (ptr) == ptr);
424 /* If you call this on an end pointer you'll get
425 * the length of the sequence
428 _gtk_sequence_ptr_get_position (GtkSequencePtr ptr)
430 g_return_val_if_fail (ptr != NULL, -1);
432 return _gtk_sequence_node_get_pos (ptr);
436 _gtk_sequence_ptr_next (GtkSequencePtr ptr)
438 g_return_val_if_fail (ptr != NULL, NULL);
440 return _gtk_sequence_node_next (ptr);
444 _gtk_sequence_ptr_prev (GtkSequencePtr ptr)
446 g_return_val_if_fail (ptr != NULL, NULL);
448 return _gtk_sequence_node_prev (ptr);
452 _gtk_sequence_ptr_move (GtkSequencePtr ptr,
457 g_return_val_if_fail (ptr != NULL, NULL);
459 new_pos = _gtk_sequence_node_get_pos (ptr) + delta;
461 return _gtk_sequence_node_find_by_pos (ptr, new_pos);
465 _gtk_sequence_sort_changed (GtkSequencePtr ptr,
466 GCompareDataFunc cmp_func,
472 g_return_if_fail (ptr != NULL);
473 g_return_if_fail (!ptr->is_end);
475 seq = _gtk_sequence_node_get_sequence (ptr);
476 _gtk_sequence_unlink (seq, ptr);
477 _gtk_sequence_node_insert_sorted (seq->node, ptr, cmp_func, cmp_data);
482 * The only restriction on the search function is that it
483 * must not delete any nodes. It is permitted to insert new nodes,
484 * but the caller should "know what he is doing"
487 _gtk_sequence_search (GtkSequence *seq,
488 GtkSequenceSearchFunc f,
491 GQueue *intervals = g_queue_new ();
493 g_queue_push_tail (intervals, _gtk_sequence_node_find_first (seq->node));
494 g_queue_push_tail (intervals, _gtk_sequence_node_find_last (seq->node));
496 while (!g_queue_is_empty (intervals))
498 GtkSequenceNode *begin = g_queue_pop_head (intervals);
499 GtkSequenceNode *end = g_queue_pop_head (intervals);
501 if (f (begin, end, data))
503 gint begin_pos = _gtk_sequence_node_get_pos (begin);
504 gint end_pos = _gtk_sequence_node_get_pos (end);
506 if (end_pos - begin_pos > 1)
508 GtkSequenceNode *mid;
511 mid_pos = begin_pos + (end_pos - begin_pos) / 2;
512 mid = _gtk_sequence_node_find_by_pos (begin, mid_pos);
514 g_queue_push_tail (intervals, begin);
515 g_queue_push_tail (intervals, mid);
517 g_queue_push_tail (intervals, mid);
518 g_queue_push_tail (intervals, end);
523 g_queue_free (intervals);
529 _gtk_sequence_add_aggregate (GtkSequence *seq,
530 const gchar *aggregate,
531 GtkSequenceAggregateFunc f,
533 GDestroyNotify destroy)
539 _gtk_sequence_remove_aggregate (GtkSequence *seq,
540 const gchar aggregate)
547 _gtk_sequence_set_aggregate_data (GtkSequencePtr ptr,
548 const gchar *aggregate,
556 _gtk_sequence_get_aggregate_data (GtkSequencePtr begin,
558 const gchar *aggregate)
560 g_assert_not_reached();
569 _gtk_sequence_node_update_fields (GtkSequenceNode *node)
571 g_assert (node != NULL);
576 node->n_nodes += node->left->n_nodes;
579 node->n_nodes += node->right->n_nodes;
582 if (node->left || node->right)
583 g_assert (node->n_nodes > 1);
587 #define NODE_LEFT_CHILD(n) (((n)->parent) && ((n)->parent->left) == (n))
588 #define NODE_RIGHT_CHILD(n) (((n)->parent) && ((n)->parent->right) == (n))
591 _gtk_sequence_node_rotate (GtkSequenceNode *node)
593 GtkSequenceNode *tmp, *old;
595 g_assert (node->parent);
596 g_assert (node->parent != node);
598 if (NODE_LEFT_CHILD (node))
603 node->right = node->parent;
604 node->parent = node->parent->parent;
607 if (node->parent->left == node->right)
608 node->parent->left = node;
610 node->parent->right = node;
613 g_assert (node->right);
615 node->right->parent = node;
616 node->right->left = tmp;
618 if (node->right->left)
619 node->right->left->parent = node->right;
628 node->left = node->parent;
629 node->parent = node->parent->parent;
632 if (node->parent->right == node->left)
633 node->parent->right = node;
635 node->parent->left = node;
638 g_assert (node->left);
640 node->left->parent = node;
641 node->left->right = tmp;
643 if (node->left->right)
644 node->left->right->parent = node->left;
649 _gtk_sequence_node_update_fields (old);
650 _gtk_sequence_node_update_fields (node);
653 static GtkSequenceNode *
654 splay (GtkSequenceNode *node)
658 if (!node->parent->parent)
661 _gtk_sequence_node_rotate (node);
663 else if ((NODE_LEFT_CHILD (node) && NODE_LEFT_CHILD (node->parent)) ||
664 (NODE_RIGHT_CHILD (node) && NODE_RIGHT_CHILD (node->parent)))
667 _gtk_sequence_node_rotate (node->parent);
668 _gtk_sequence_node_rotate (node);
673 _gtk_sequence_node_rotate (node);
674 _gtk_sequence_node_rotate (node);
681 static GtkSequenceNode *
682 _gtk_sequence_node_new (gpointer data)
684 GtkSequenceNode *node = g_new0 (GtkSequenceNode, 1);
691 node->is_end = FALSE;
697 static GtkSequenceNode *
698 find_min (GtkSequenceNode *node)
708 static GtkSequenceNode *
709 find_max (GtkSequenceNode *node)
719 static GtkSequenceNode *
720 _gtk_sequence_node_find_first (GtkSequenceNode *node)
722 return splay (find_min (node));
725 static GtkSequenceNode *
726 _gtk_sequence_node_find_last (GtkSequenceNode *node)
728 return splay (find_max (node));
732 get_n_nodes (GtkSequenceNode *node)
735 return node->n_nodes;
740 static GtkSequenceNode *
741 _gtk_sequence_node_find_by_pos (GtkSequenceNode *node,
746 g_assert (node != NULL);
750 while ((i = get_n_nodes (node->left)) != pos)
760 g_assert (node->parent != NULL);
767 static GtkSequenceNode *
768 _gtk_sequence_node_prev (GtkSequenceNode *node)
782 static GtkSequenceNode *
783 _gtk_sequence_node_next (GtkSequenceNode *node)
798 _gtk_sequence_node_get_pos (GtkSequenceNode *node)
802 return get_n_nodes (node->left);
806 _gtk_sequence_node_get_sequence (GtkSequenceNode *node)
810 return node->sequence;
813 static GtkSequenceNode *
814 _gtk_sequence_node_find_closest (GtkSequenceNode *node,
815 GtkSequenceNode *other,
816 GCompareDataFunc cmp,
819 GtkSequenceNode *best;
828 if ((c = cmp (node, other, data)) != 0)
836 while (c != 0 && node != NULL);
842 _gtk_sequence_node_free (GtkSequenceNode *node,
843 GDestroyNotify destroy)
847 * This is to avoid excessively deep recursions. A splay tree is not necessarily
850 * I _think_ this is still linear in the number of nodes, but I'd like to
851 * do something more efficient.
856 GtkSequenceNode *next;
858 node = splay (find_min (node));
863 if (destroy && !node->is_end)
864 destroy (node->data);
873 _gtk_sequence_node_is_singleton (GtkSequenceNode *node)
877 if (node->left || node->right)
885 _gtk_sequence_node_split (GtkSequenceNode *node,
886 GtkSequenceNode **left,
887 GtkSequenceNode **right)
889 GtkSequenceNode *left_tree;
893 left_tree = node->left;
896 left_tree->parent = NULL;
897 _gtk_sequence_node_update_fields (left_tree);
901 _gtk_sequence_node_update_fields (node);
911 _gtk_sequence_node_insert_before (GtkSequenceNode *node,
912 GtkSequenceNode *new)
914 g_assert (node != NULL);
915 g_assert (new != NULL);
919 new = splay (find_min (new));
920 g_assert (new->left == NULL);
923 node->left->parent = new;
925 new->left = node->left;
930 _gtk_sequence_node_update_fields (new);
931 _gtk_sequence_node_update_fields (node);
935 _gtk_sequence_node_get_length (GtkSequenceNode *node)
937 g_assert (node != NULL);
940 return node->n_nodes;
944 _gtk_sequence_node_remove (GtkSequenceNode *node)
946 GtkSequenceNode *right, *left;
953 node->left = node->right = NULL;
957 right->parent = NULL;
959 right = _gtk_sequence_node_find_first (right);
960 g_assert (right->left == NULL);
965 left->parent = right;
966 _gtk_sequence_node_update_fields (right);
976 _gtk_sequence_node_calc_height (GtkSequenceNode *node)
978 /* breadth first traversal */
980 GQueue *nodes = g_queue_new ();
982 g_queue_push_tail (nodes, node);
984 while (!g_queue_is_empty (nodes))
986 GQueue *tmp = g_queue_new ();
989 while (!g_queue_is_empty (nodes))
991 GtkSequenceNode *node = g_queue_pop_head (nodes);
993 g_queue_push_tail (tmp, node->left);
995 g_queue_push_tail (tmp, node->right);
998 g_queue_free (nodes);
1002 g_queue_free (nodes);
1009 _gtk_sequence_node_insert_sorted (GtkSequenceNode *node,
1010 GtkSequenceNode *new,
1011 GCompareDataFunc cmp_func,
1015 GtkSequenceNode *closest;
1016 info.cmp = cmp_func;
1017 info.data = cmp_data;
1020 _gtk_sequence_node_find_closest (node, new, node_compare, &info);
1022 g_assert (closest != new);
1024 if (node_compare (new, closest, &info) > 0)
1025 closest = _gtk_sequence_node_next (closest);
1027 _gtk_sequence_node_insert_before (closest, new);
1031 _gtk_sequence_node_calc_height (GtkSequenceNode *node)
1042 left_height = _gtk_sequence_node_calc_height (node->left);
1045 right_height = _gtk_sequence_node_calc_height (node->right);
1047 return MAX (left_height, right_height) + 1;
1054 _gtk_sequence_calc_tree_height (GtkSequence *seq)
1056 GtkSequenceNode *node = seq->node;
1058 while (node->parent)
1059 node = node->parent;
1063 r = _gtk_sequence_node_calc_height (node->right);
1064 l = _gtk_sequence_node_calc_height (node->left);
1066 return MAX (r, l) + 1;
1073 _gtk_sequence_ptr_get_sequence (GtkSequencePtr ptr)
1075 GtkSequenceNode *node = ptr;
1077 return node->sequence;
1081 _gtk_sequence_swap (GtkSequencePtr a,
1084 GtkSequenceNode *leftmost, *rightmost, *rightmost_next;
1087 g_return_if_fail (!_gtk_sequence_ptr_is_end (a));
1088 g_return_if_fail (!_gtk_sequence_ptr_is_end (b));
1093 a_pos = _gtk_sequence_ptr_get_position (a);
1094 b_pos = _gtk_sequence_ptr_get_position (b);
1107 rightmost_next = _gtk_sequence_node_next (rightmost);
1109 /* Situation now: ..., leftmost, ......., rightmost, rightmost_next, ... */
1111 _gtk_sequence_move (rightmost, leftmost);
1112 _gtk_sequence_move (leftmost, rightmost_next);
1116 _gtk_sequence_move (GtkSequencePtr ptr,
1117 GtkSequencePtr new_pos)
1119 g_return_if_fail (ptr != NULL);
1120 g_return_if_fail (new_pos != NULL);
1125 _gtk_sequence_unlink (ptr->sequence, ptr);
1126 _gtk_sequence_node_insert_before (new_pos, ptr);
1129 /* Overwrites the existing pointer. */
1131 _gtk_sequence_set (GtkSequencePtr ptr,
1136 g_return_if_fail (!_gtk_sequence_ptr_is_end (ptr));
1138 seq = _gtk_sequence_node_get_sequence (ptr);
1139 if (seq->data_destroy_notify)
1140 seq->data_destroy_notify (ptr->data);