udapted vi.po
[rhythmbox.git] / rhythmdb / gsequence.c
blob361193e21407c1aae32d9f89942683cf67bc6a00
1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 2002 Soeren Sandmann (sandmann@daimi.au.dk)
4 * arch-tag: Implementation of GSequence - a fast ordered-sequence
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301 USA.
21 #include <glib.h>
23 #include "gsequence.h"
25 #ifndef g_slice_new0
26 #define g_slice_new0(a) g_new0(a, 1)
27 #define g_slice_free(a, b) g_free(b)
28 #endif
30 typedef struct _GSequenceNode GSequenceNode;
32 struct _GSequence {
33 GSequenceNode *node; /* does not necessarily point to the root.
34 * You can splay it if you want it to
36 GDestroyNotify data_destroy_notify;
39 struct _GSequenceNode {
40 guint is_end : 1;
41 gint n_nodes : 31; /* number of nodes below this node,
42 * including this node
44 GSequenceNode *parent;
45 GSequenceNode *left;
46 GSequenceNode *right;
48 GSequence *sequence;
50 gpointer data;
53 static GSequenceNode *g_sequence_node_new (gpointer data);
54 static GSequenceNode *g_sequence_node_find_first (GSequenceNode *node);
55 static GSequenceNode *g_sequence_node_find_last (GSequenceNode *node);
56 static GSequenceNode *g_sequence_node_find_by_pos (GSequenceNode *node,
57 gint pos);
58 static GSequenceNode *g_sequence_node_prev (GSequenceNode *node);
59 static GSequenceNode *g_sequence_node_next (GSequenceNode *node);
60 static gint g_sequence_node_get_pos (GSequenceNode *node);
61 static GSequence *g_sequence_node_get_sequence (GSequenceNode *node);
62 static GSequenceNode *g_sequence_node_find_closest (GSequenceNode *node,
63 GSequenceNode *other,
64 GCompareDataFunc cmp,
65 gpointer data);
66 static gint g_sequence_node_get_length (GSequenceNode *node);
67 static void g_sequence_node_free (GSequenceNode *node,
68 GDestroyNotify destroy);
69 #if 0
70 static gboolean g_sequence_node_is_singleton (GSequenceNode *node);
71 #endif
72 static void g_sequence_node_split (GSequenceNode *node,
73 GSequenceNode **left,
74 GSequenceNode **right);
75 static void g_sequence_node_insert_before (GSequenceNode *node,
76 GSequenceNode *new);
77 static void g_sequence_node_remove (GSequenceNode *node);
78 static void g_sequence_node_insert_sorted (GSequenceNode *node,
79 GSequenceNode *new,
80 GCompareDataFunc cmp_func,
81 gpointer cmp_data);
83 /* GSequence */
84 GSequence *
85 g_sequence_new (GDestroyNotify data_destroy)
87 GSequence *seq = g_new (GSequence, 1);
88 seq->data_destroy_notify = data_destroy;
90 seq->node = g_sequence_node_new (NULL);
91 seq->node->is_end = TRUE;
92 seq->node->sequence = seq;
94 return seq;
97 void
98 g_sequence_free (GSequence *seq)
100 g_return_if_fail (seq != NULL);
102 g_sequence_node_free (seq->node, seq->data_destroy_notify);
104 g_free (seq);
107 #if 0
108 static void
109 flatten_nodes (GSequenceNode *node, GList **list)
111 g_print ("flatten %p\n", node);
112 if (!node)
113 return;
114 else if (g_sequence_node_is_singleton (node))
115 *list = g_list_prepend (*list, node);
116 else
118 GSequenceNode *left;
119 GSequenceNode *right;
121 g_sequence_node_split (node, &left, &right);
123 flatten_nodes (left, list);
124 flatten_nodes (right, list);
127 #endif
129 typedef struct SortInfo SortInfo;
130 struct SortInfo {
131 GCompareDataFunc cmp;
132 gpointer data;
135 static gint
136 node_compare (gconstpointer n1, gconstpointer n2, gpointer data)
138 SortInfo *info = data;
139 const GSequenceNode *node1 = n1;
140 const GSequenceNode *node2 = n2;
142 if (node1->is_end)
143 return 1;
144 else if (node2->is_end)
145 return -1;
146 else
147 return (* info->cmp) (node1->data, node2->data, info->data);
150 void
151 g_sequence_append (GSequence *seq,
152 gpointer data)
154 GSequenceNode *node, *last;
156 g_return_if_fail (seq != NULL);
158 node = g_sequence_node_new (data);
159 node->sequence = seq;
160 last = g_sequence_node_find_last (seq->node);
161 g_sequence_node_insert_before (last, node);
164 void
165 g_sequence_prepend (GSequence *seq,
166 gpointer data)
168 GSequenceNode *node, *second;
170 g_return_if_fail (seq != NULL);
172 node = g_sequence_node_new (data);
173 node->sequence = seq;
174 second = g_sequence_node_next (g_sequence_node_find_first (seq->node));
176 g_sequence_node_insert_before (second, node);
179 void
180 g_sequence_insert (GSequencePtr ptr,
181 gpointer data)
183 GSequenceNode *node;
185 g_return_if_fail (ptr != NULL);
187 node = g_sequence_node_new (data);
188 node->sequence = ptr->sequence;
190 g_sequence_node_insert_before (ptr, node);
193 static void
194 g_sequence_unlink (GSequence *seq,
195 GSequenceNode *node)
197 g_assert (!node->is_end);
199 seq->node = g_sequence_node_next (node);
201 g_assert (seq->node);
202 g_assert (seq->node != node);
204 g_sequence_node_remove (node);
207 void
208 g_sequence_remove (GSequencePtr ptr)
210 GSequence *seq;
212 g_return_if_fail (ptr != NULL);
213 g_return_if_fail (!ptr->is_end);
215 seq = g_sequence_node_get_sequence (ptr);
216 g_sequence_unlink (seq, ptr);
217 g_sequence_node_free (ptr, seq->data_destroy_notify);
220 void
221 g_sequence_sort (GSequence *seq,
222 GCompareDataFunc cmp_func,
223 gpointer cmp_data)
225 GSequence *tmp;
226 GSequenceNode *begin, *end;
228 g_return_if_fail (seq != NULL);
229 g_return_if_fail (cmp_func != NULL);
231 begin = g_sequence_get_begin_ptr (seq);
232 end = g_sequence_get_end_ptr (seq);
234 g_sequence_remove_range (begin, end, &tmp);
236 while (g_sequence_get_length (tmp) > 0)
238 GSequenceNode *node = g_sequence_get_begin_ptr (tmp);
239 g_sequence_unlink (tmp, node);
241 g_sequence_node_insert_sorted (seq->node, node, cmp_func, cmp_data);
244 g_sequence_free (tmp);
247 gpointer
248 g_sequence_ptr_get_data (GSequencePtr ptr)
250 g_return_val_if_fail (ptr != NULL, NULL);
251 g_return_val_if_fail (!ptr->is_end, NULL);
253 return ptr->data;
256 GSequencePtr
257 g_sequence_insert_sorted (GSequence *seq,
258 gpointer data,
259 GCompareDataFunc cmp_func,
260 gpointer cmp_data)
262 GSequenceNode *new_node = g_sequence_node_new (data);
263 new_node->sequence = seq;
264 g_sequence_node_insert_sorted (seq->node, new_node, cmp_func, cmp_data);
265 return new_node;
268 void
269 g_sequence_insert_sequence (GSequencePtr ptr,
270 GSequence *other_seq)
272 GSequenceNode *last;
274 g_return_if_fail (other_seq != NULL);
275 g_return_if_fail (ptr != NULL);
277 last = g_sequence_node_find_last (other_seq->node);
278 g_sequence_node_insert_before (ptr, last);
279 g_sequence_node_remove (last);
280 g_sequence_node_free (last, NULL);
281 other_seq->node = NULL;
282 g_sequence_free (other_seq);
285 void
286 g_sequence_concatenate (GSequence *seq1,
287 GSequence *seq2)
289 GSequenceNode *last;
291 g_return_if_fail (seq1 != NULL);
292 g_return_if_fail (seq2 != NULL);
294 last = g_sequence_node_find_last (seq1->node);
295 g_sequence_insert_sequence (last, seq2);
299 * The new sequence inherits the destroy notify from the sequence that
300 * beign and end comes from
302 void
303 g_sequence_remove_range (GSequencePtr begin,
304 GSequencePtr end,
305 GSequence **removed)
307 GSequence *seq;
308 GSequenceNode *s1, *s2, *s3;
310 seq = g_sequence_node_get_sequence (begin);
312 g_assert (end != NULL);
314 g_return_if_fail (seq == g_sequence_node_get_sequence (end));
316 g_sequence_node_split (begin, &s1, &s2);
317 g_sequence_node_split (end, NULL, &s3);
319 if (s1)
320 g_sequence_node_insert_before (s3, s1);
322 seq->node = s3;
324 if (removed)
326 *removed = g_sequence_new (seq->data_destroy_notify);
327 g_sequence_node_insert_before ((*removed)->node, s2);
329 else
331 g_sequence_node_free (s2, seq->data_destroy_notify);
335 gint
336 g_sequence_get_length (GSequence *seq)
338 return g_sequence_node_get_length (seq->node) - 1;
341 GSequencePtr
342 g_sequence_get_end_ptr (GSequence *seq)
344 g_return_val_if_fail (seq != NULL, NULL);
345 return g_sequence_node_find_last (seq->node);
348 GSequencePtr
349 g_sequence_get_begin_ptr (GSequence *seq)
351 g_return_val_if_fail (seq != NULL, NULL);
352 return g_sequence_node_find_first (seq->node);
356 * if pos > number of items or -1, will return end pointer
358 GSequencePtr
359 g_sequence_get_ptr_at_pos (GSequence *seq,
360 gint pos)
362 gint len;
364 g_return_val_if_fail (seq != NULL, NULL);
366 len = g_sequence_get_length (seq);
368 if (pos > len || pos == -1)
369 pos = len;
371 return g_sequence_node_find_by_pos (seq->node, pos);
374 /* GSequencePtr */
375 gboolean
376 g_sequence_ptr_is_end (GSequencePtr ptr)
378 g_return_val_if_fail (ptr != NULL, FALSE);
379 return ptr->is_end;
382 gboolean
383 g_sequence_ptr_is_begin (GSequencePtr ptr)
385 return (g_sequence_node_prev (ptr) == ptr);
388 gint
389 g_sequence_ptr_get_position (GSequencePtr ptr)
391 g_return_val_if_fail (ptr != NULL, -1);
393 return g_sequence_node_get_pos (ptr);
396 GSequencePtr
397 g_sequence_ptr_next (GSequencePtr ptr)
399 g_return_val_if_fail (ptr != NULL, NULL);
401 return g_sequence_node_next (ptr);
404 GSequencePtr
405 g_sequence_ptr_prev (GSequencePtr ptr)
407 g_return_val_if_fail (ptr != NULL, NULL);
409 return g_sequence_node_prev (ptr);
412 GSequencePtr
413 g_sequence_ptr_move (GSequencePtr ptr,
414 guint delta)
416 gint new_pos;
418 g_return_val_if_fail (ptr != NULL, NULL);
420 new_pos = g_sequence_node_get_pos (ptr) + delta;
422 return g_sequence_node_find_by_pos (ptr, new_pos);
425 void
426 g_sequence_ptr_sort_changed (GSequencePtr ptr,
427 GCompareDataFunc cmp_func,
428 gpointer cmp_data)
430 GSequence *seq;
432 g_return_if_fail (!ptr->is_end);
434 seq = g_sequence_node_get_sequence (ptr);
435 g_sequence_unlink (seq, ptr);
436 g_sequence_node_insert_sorted (seq->node, ptr, cmp_func, cmp_data);
439 /* search
441 * The only restriction on the search function is that it
442 * must not delete any nodes. It is permitted to insert new nodes,
443 * but the caller should "know what he is doing"
445 void
446 g_sequence_search (GSequence *seq,
447 GSequenceSearchFunc f,
448 gpointer data)
450 GQueue *intervals = g_queue_new ();
452 g_queue_push_tail (intervals, g_sequence_node_find_first (seq->node));
453 g_queue_push_tail (intervals, g_sequence_node_find_last (seq->node));
455 while (!g_queue_is_empty (intervals))
457 GSequenceNode *begin = g_queue_pop_head (intervals);
458 GSequenceNode *end = g_queue_pop_head (intervals);
460 if (f (begin, end, data))
462 gint begin_pos = g_sequence_node_get_pos (begin);
463 gint end_pos = g_sequence_node_get_pos (end);
465 if (end_pos - begin_pos > 1)
467 GSequenceNode *mid;
468 gint mid_pos;
470 mid_pos = begin_pos + (end_pos - begin_pos) / 2;
471 mid = g_sequence_node_find_by_pos (begin, mid_pos);
473 g_queue_push_tail (intervals, begin);
474 g_queue_push_tail (intervals, mid);
476 g_queue_push_tail (intervals, mid);
477 g_queue_push_tail (intervals, end);
482 g_queue_free (intervals);
485 #if 0
486 /* aggregates */
487 void
488 g_sequence_add_aggregate (GSequence *seq,
489 const gchar *aggregate,
490 GSequenceAggregateFunc f,
491 gpointer data,
492 GDestroyNotify destroy)
494 /* FIXME */
497 void
498 g_sequence_remove_aggregate (GSequence *seq,
499 const gchar aggregate)
501 /* FIXME */
505 void
506 g_sequence_set_aggregate_data (GSequencePtr ptr,
507 const gchar *aggregate,
508 gpointer data)
510 /* FIXME */
514 gpointer
515 g_sequence_get_aggregate_data (GSequencePtr begin,
516 GSequencePtr end,
517 const gchar *aggregate)
519 g_assert_not_reached();
520 return NULL;
522 #endif
524 /* Nodes
526 static void
527 g_sequence_node_update_fields (GSequenceNode *node)
529 g_assert (node != NULL);
531 node->n_nodes = 1;
533 if (node->left)
534 node->n_nodes += node->left->n_nodes;
536 if (node->right)
537 node->n_nodes += node->right->n_nodes;
539 #if 0
540 if (node->left || node->right)
541 g_assert (node->n_nodes > 1);
542 #endif
545 #define NODE_LEFT_CHILD(n) (((n)->parent) && ((n)->parent->left) == (n))
546 #define NODE_RIGHT_CHILD(n) (((n)->parent) && ((n)->parent->right) == (n))
548 static void
549 g_sequence_node_rotate (GSequenceNode *node)
551 GSequenceNode *tmp, *old;
553 g_assert (node->parent);
554 g_assert (node->parent != node);
556 if (NODE_LEFT_CHILD (node))
558 /* rotate right */
559 tmp = node->right;
561 node->right = node->parent;
562 node->parent = node->parent->parent;
563 if (node->parent)
565 if (node->parent->left == node->right)
566 node->parent->left = node;
567 else
568 node->parent->right = node;
571 g_assert (node->right);
573 node->right->parent = node;
574 node->right->left = tmp;
576 if (node->right->left)
577 node->right->left->parent = node->right;
579 old = node->right;
581 else
583 /* rotate left */
584 tmp = node->left;
586 node->left = node->parent;
587 node->parent = node->parent->parent;
588 if (node->parent)
590 if (node->parent->right == node->left)
591 node->parent->right = node;
592 else
593 node->parent->left = node;
596 g_assert (node->left);
598 node->left->parent = node;
599 node->left->right = tmp;
601 if (node->left->right)
602 node->left->right->parent = node->left;
604 old = node->left;
607 g_sequence_node_update_fields (old);
608 g_sequence_node_update_fields (node);
611 static GSequenceNode *
612 splay (GSequenceNode *node)
614 while (node->parent)
616 if (!node->parent->parent)
618 /* zig */
619 g_sequence_node_rotate (node);
621 else if ((NODE_LEFT_CHILD (node) && NODE_LEFT_CHILD (node->parent)) ||
622 (NODE_RIGHT_CHILD (node) && NODE_RIGHT_CHILD (node->parent)))
624 /* zig-zig */
625 g_sequence_node_rotate (node->parent);
626 g_sequence_node_rotate (node);
628 else
630 /* zig-zag */
631 g_sequence_node_rotate (node);
632 g_sequence_node_rotate (node);
636 return node;
639 static GSequenceNode *
640 g_sequence_node_new (gpointer data)
642 GSequenceNode *node = g_slice_new0 (GSequenceNode);
644 node->parent = NULL;
645 node->left = NULL;
646 node->right = NULL;
648 node->data = data;
649 node->is_end = FALSE;
650 node->n_nodes = 1;
652 return node;
655 static GSequenceNode *
656 find_min (GSequenceNode *node)
658 splay (node);
660 while (node->left)
661 node = node->left;
663 return node;
666 static GSequenceNode *
667 find_max (GSequenceNode *node)
669 splay (node);
671 while (node->right)
672 node = node->right;
674 return node;
677 static GSequenceNode *
678 g_sequence_node_find_first (GSequenceNode *node)
680 return splay (find_min (node));
683 static GSequenceNode *
684 g_sequence_node_find_last (GSequenceNode *node)
686 return splay (find_max (node));
689 static gint
690 get_n_nodes (GSequenceNode *node)
692 if (node)
693 return node->n_nodes;
694 else
695 return 0;
698 static GSequenceNode *
699 g_sequence_node_find_by_pos (GSequenceNode *node,
700 gint pos)
702 gint i;
704 g_assert (node != NULL);
706 splay (node);
708 while ((i = get_n_nodes (node->left)) != pos)
710 if (i < pos)
712 node = node->right;
713 pos -= (i + 1);
715 else
717 node = node->left;
718 g_assert (node->parent != NULL);
722 return splay (node);
725 static GSequenceNode *
726 g_sequence_node_prev (GSequenceNode *node)
728 splay (node);
730 if (node->left)
732 node = node->left;
733 while (node->right)
734 node = node->right;
737 return splay (node);
740 static GSequenceNode *
741 g_sequence_node_next (GSequenceNode *node)
743 splay (node);
745 if (node->right)
747 node = node->right;
748 while (node->left)
749 node = node->left;
752 return splay (node);
755 static gint
756 g_sequence_node_get_pos (GSequenceNode *node)
758 splay (node);
760 return get_n_nodes (node->left);
763 static GSequence *
764 g_sequence_node_get_sequence (GSequenceNode *node)
766 splay (node);
768 return node->sequence;
771 static GSequenceNode *
772 g_sequence_node_find_closest (GSequenceNode *node,
773 GSequenceNode *other,
774 GCompareDataFunc cmp,
775 gpointer data)
777 GSequenceNode *best;
778 gint c;
780 splay (node);
784 best = node;
786 if ((c = cmp (node, other, data)) != 0)
788 if (c < 0)
789 node = node->right;
790 else
791 node = node->left;
794 while (c != 0 && node != NULL);
796 return best;
799 static void
800 g_sequence_node_free (GSequenceNode *node,
801 GDestroyNotify destroy)
803 /* FIXME:
805 * This is to avoid excessively deep recursions. A splay tree is not necessarily
806 * balanced at all.
808 * I _think_ this is still linear in the number of nodes, but I'd like to
809 * do something more efficient.
812 while (node)
814 GSequenceNode *next;
816 node = splay (find_min (node));
817 next = node->right;
818 if (next)
819 next->parent = NULL;
821 if (destroy && !node->is_end)
822 destroy (node->data);
823 g_slice_free (GSequenceNode, node);
825 node = next;
829 #if 0
830 static gboolean
831 g_sequence_node_is_singleton (GSequenceNode *node)
833 splay (node);
835 if (node->left || node->right)
836 return FALSE;
838 return TRUE;
840 #endif
842 static void
843 g_sequence_node_split (GSequenceNode *node,
844 GSequenceNode **left,
845 GSequenceNode **right)
847 GSequenceNode *left_tree;
849 splay (node);
851 left_tree = node->left;
852 if (left_tree)
854 left_tree->parent = NULL;
855 g_sequence_node_update_fields (left_tree);
858 node->left = NULL;
859 g_sequence_node_update_fields (node);
861 if (left)
862 *left = left_tree;
864 if (right)
865 *right = node;
868 static void
869 g_sequence_node_insert_before (GSequenceNode *node,
870 GSequenceNode *new)
872 g_assert (node != NULL);
873 g_assert (new != NULL);
875 splay (node);
877 new = splay (find_min (new));
878 g_assert (new->left == NULL);
880 if (node->left)
881 node->left->parent = new;
883 new->left = node->left;
884 new->parent = node;
886 node->left = new;
888 g_sequence_node_update_fields (new);
889 g_sequence_node_update_fields (node);
892 static gint
893 g_sequence_node_get_length (GSequenceNode *node)
895 g_assert (node != NULL);
897 splay (node);
898 return node->n_nodes;
901 static void
902 g_sequence_node_remove (GSequenceNode *node)
904 GSequenceNode *right, *left;
906 splay (node);
908 left = node->left;
909 right = node->right;
911 node->left = node->right = NULL;
913 if (right)
915 right->parent = NULL;
917 right = g_sequence_node_find_first (right);
918 g_assert (right->left == NULL);
920 right->left = left;
921 if (left)
923 left->parent = right;
924 g_sequence_node_update_fields (right);
927 else if (left)
928 left->parent = NULL;
931 #if 0
932 /* debug func */
933 static gint
934 g_sequence_node_calc_height (GSequenceNode *node)
936 /* breadth first traversal */
937 gint height = 0;
938 GQueue *nodes = g_queue_new ();
940 g_queue_push_tail (nodes, node);
942 while (!g_queue_is_empty (nodes))
944 GQueue *tmp = g_queue_new ();
946 height++;
947 while (!g_queue_is_empty (nodes))
949 GSequenceNode *node = g_queue_pop_head (nodes);
950 if (node->left)
951 g_queue_push_tail (tmp, node->left);
952 if (node->right)
953 g_queue_push_tail (tmp, node->right);
956 g_queue_free (nodes);
958 nodes = tmp;
960 g_queue_free (nodes);
962 return height;
964 #endif
966 static void
967 g_sequence_node_insert_sorted (GSequenceNode *node,
968 GSequenceNode *new,
969 GCompareDataFunc cmp_func,
970 gpointer cmp_data)
972 SortInfo info;
973 GSequenceNode *closest;
974 info.cmp = cmp_func;
975 info.data = cmp_data;
977 closest =
978 g_sequence_node_find_closest (node, new, node_compare, &info);
980 if (node_compare (new, closest, &info) > 0)
981 closest = g_sequence_node_next (closest);
983 /* this can never fail since we have a bigger-than-everything
984 * end-node
986 g_assert (node_compare (new, closest, &info) <= 0);
987 g_sequence_node_insert_before (closest, new);
990 static gint
991 g_sequence_node_calc_height (GSequenceNode *node)
993 gint left_height;
994 gint right_height;
996 if (node)
998 left_height = 0;
999 right_height = 0;
1001 if (node->left)
1002 left_height = g_sequence_node_calc_height (node->left);
1004 if (node->right)
1005 right_height = g_sequence_node_calc_height (node->right);
1007 return MAX (left_height, right_height) + 1;
1010 return 0;
1013 gint
1014 g_sequence_calc_tree_height (GSequence *seq)
1016 GSequenceNode *node = seq->node;
1017 gint r, l;
1018 while (node->parent)
1019 node = node->parent;
1021 if (node)
1023 r = g_sequence_node_calc_height (node->right);
1024 l = g_sequence_node_calc_height (node->left);
1026 return MAX (r, l) + 1;
1028 else
1029 return 0;