Updated Macedonian Translation <arangela@cvs.gnome.org>
[rhythmbox.git] / rhythmdb / gsequence.c
blob3a53abbdd1c97b1646ba5e5b61ba21e7aea67440
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);
84 /* GSequence */
85 GSequence *
86 g_sequence_new (GDestroyNotify data_destroy)
88 GSequence *seq = g_new (GSequence, 1);
89 seq->data_destroy_notify = data_destroy;
91 seq->node = g_sequence_node_new (NULL);
92 seq->node->is_end = TRUE;
93 seq->node->sequence = seq;
95 return seq;
98 void
99 g_sequence_free (GSequence *seq)
101 g_return_if_fail (seq != NULL);
103 g_sequence_node_free (seq->node, seq->data_destroy_notify);
105 g_free (seq);
108 #if 0
109 static void
110 flatten_nodes (GSequenceNode *node, GList **list)
112 g_print ("flatten %p\n", node);
113 if (!node)
114 return;
115 else if (g_sequence_node_is_singleton (node))
116 *list = g_list_prepend (*list, node);
117 else
119 GSequenceNode *left;
120 GSequenceNode *right;
122 g_sequence_node_split (node, &left, &right);
124 flatten_nodes (left, list);
125 flatten_nodes (right, list);
128 #endif
130 typedef struct SortInfo SortInfo;
131 struct SortInfo {
132 GCompareDataFunc cmp;
133 gpointer data;
136 static gint
137 node_compare (gconstpointer n1, gconstpointer n2, gpointer data)
139 SortInfo *info = data;
140 const GSequenceNode *node1 = n1;
141 const GSequenceNode *node2 = n2;
143 if (node1->is_end)
144 return 1;
145 else if (node2->is_end)
146 return -1;
147 else
148 return (* info->cmp) (node1->data, node2->data, info->data);
151 void
152 g_sequence_append (GSequence *seq,
153 gpointer data)
155 GSequenceNode *node, *last;
157 g_return_if_fail (seq != NULL);
159 node = g_sequence_node_new (data);
160 node->sequence = seq;
161 last = g_sequence_node_find_last (seq->node);
162 g_sequence_node_insert_before (last, node);
165 void
166 g_sequence_prepend (GSequence *seq,
167 gpointer data)
169 GSequenceNode *node, *second;
171 g_return_if_fail (seq != NULL);
173 node = g_sequence_node_new (data);
174 node->sequence = seq;
175 second = g_sequence_node_next (g_sequence_node_find_first (seq->node));
177 g_sequence_node_insert_before (second, node);
180 void
181 g_sequence_insert (GSequencePtr ptr,
182 gpointer data)
184 GSequenceNode *node;
186 g_return_if_fail (ptr != NULL);
188 node = g_sequence_node_new (data);
189 node->sequence = ptr->sequence;
191 g_sequence_node_insert_before (ptr, node);
194 static void
195 g_sequence_unlink (GSequence *seq,
196 GSequenceNode *node)
198 g_assert (!node->is_end);
200 seq->node = g_sequence_node_next (node);
202 g_assert (seq->node);
203 g_assert (seq->node != node);
205 g_sequence_node_remove (node);
208 void
209 g_sequence_remove (GSequencePtr ptr)
211 GSequence *seq;
213 g_return_if_fail (ptr != NULL);
214 g_return_if_fail (!ptr->is_end);
216 seq = g_sequence_node_get_sequence (ptr);
217 g_sequence_unlink (seq, ptr);
218 g_sequence_node_free (ptr, seq->data_destroy_notify);
221 void
222 g_sequence_sort (GSequence *seq,
223 GCompareDataFunc cmp_func,
224 gpointer cmp_data)
226 GSequence *tmp;
227 GSequenceNode *begin, *end;
229 g_return_if_fail (seq != NULL);
230 g_return_if_fail (cmp_func != NULL);
232 begin = g_sequence_get_begin_ptr (seq);
233 end = g_sequence_get_end_ptr (seq);
235 g_sequence_remove_range (begin, end, &tmp);
237 while (g_sequence_get_length (tmp) > 0)
239 GSequenceNode *node = g_sequence_get_begin_ptr (tmp);
240 g_sequence_unlink (tmp, node);
242 g_sequence_node_insert_sorted (seq->node, node, cmp_func, cmp_data);
245 g_sequence_free (tmp);
248 gpointer
249 g_sequence_ptr_get_data (GSequencePtr ptr)
251 g_return_val_if_fail (ptr != NULL, NULL);
252 g_return_val_if_fail (!ptr->is_end, NULL);
254 return ptr->data;
257 GSequencePtr
258 g_sequence_insert_sorted (GSequence *seq,
259 gpointer data,
260 GCompareDataFunc cmp_func,
261 gpointer cmp_data)
263 GSequenceNode *new_node = g_sequence_node_new (data);
264 new_node->sequence = seq;
265 g_sequence_node_insert_sorted (seq->node, new_node, cmp_func, cmp_data);
266 return new_node;
269 void
270 g_sequence_insert_sequence (GSequencePtr ptr,
271 GSequence *other_seq)
273 GSequenceNode *last;
275 g_return_if_fail (other_seq != NULL);
276 g_return_if_fail (ptr != NULL);
278 last = g_sequence_node_find_last (other_seq->node);
279 g_sequence_node_insert_before (ptr, last);
280 g_sequence_node_remove (last);
281 g_sequence_node_free (last, NULL);
282 other_seq->node = NULL;
283 g_sequence_free (other_seq);
286 void
287 g_sequence_concatenate (GSequence *seq1,
288 GSequence *seq2)
290 GSequenceNode *last;
292 g_return_if_fail (seq1 != NULL);
293 g_return_if_fail (seq2 != NULL);
295 last = g_sequence_node_find_last (seq1->node);
296 g_sequence_insert_sequence (last, seq2);
300 * The new sequence inherits the destroy notify from the sequence that
301 * beign and end comes from
303 void
304 g_sequence_remove_range (GSequencePtr begin,
305 GSequencePtr end,
306 GSequence **removed)
308 GSequence *seq;
309 GSequenceNode *s1, *s2, *s3;
311 seq = g_sequence_node_get_sequence (begin);
313 g_assert (end != NULL);
315 g_return_if_fail (seq == g_sequence_node_get_sequence (end));
317 g_sequence_node_split (begin, &s1, &s2);
318 g_sequence_node_split (end, NULL, &s3);
320 if (s1)
321 g_sequence_node_insert_before (s3, s1);
323 seq->node = s3;
325 if (removed)
327 *removed = g_sequence_new (seq->data_destroy_notify);
328 g_sequence_node_insert_before ((*removed)->node, s2);
330 else
332 g_sequence_node_free (s2, seq->data_destroy_notify);
336 gint
337 g_sequence_get_length (GSequence *seq)
339 return g_sequence_node_get_length (seq->node) - 1;
342 GSequencePtr
343 g_sequence_get_end_ptr (GSequence *seq)
345 g_return_val_if_fail (seq != NULL, NULL);
346 return g_sequence_node_find_last (seq->node);
349 GSequencePtr
350 g_sequence_get_begin_ptr (GSequence *seq)
352 g_return_val_if_fail (seq != NULL, NULL);
353 return g_sequence_node_find_first (seq->node);
357 * if pos > number of items or -1, will return end pointer
359 GSequencePtr
360 g_sequence_get_ptr_at_pos (GSequence *seq,
361 gint pos)
363 gint len;
365 g_return_val_if_fail (seq != NULL, NULL);
367 len = g_sequence_get_length (seq);
369 if (pos > len || pos == -1)
370 pos = len;
372 return g_sequence_node_find_by_pos (seq->node, pos);
376 /* GSequencePtr */
377 gboolean
378 g_sequence_ptr_is_end (GSequencePtr ptr)
380 g_return_val_if_fail (ptr != NULL, FALSE);
381 return ptr->is_end;
384 gboolean
385 g_sequence_ptr_is_begin (GSequencePtr ptr)
387 return (g_sequence_node_prev (ptr) == ptr);
390 gint
391 g_sequence_ptr_get_position (GSequencePtr ptr)
393 g_return_val_if_fail (ptr != NULL, -1);
395 return g_sequence_node_get_pos (ptr);
398 GSequencePtr
399 g_sequence_ptr_next (GSequencePtr ptr)
401 g_return_val_if_fail (ptr != NULL, NULL);
403 return g_sequence_node_next (ptr);
406 GSequencePtr
407 g_sequence_ptr_prev (GSequencePtr ptr)
409 g_return_val_if_fail (ptr != NULL, NULL);
411 return g_sequence_node_prev (ptr);
414 GSequencePtr
415 g_sequence_ptr_move (GSequencePtr ptr,
416 guint delta)
418 gint new_pos;
420 g_return_val_if_fail (ptr != NULL, NULL);
422 new_pos = g_sequence_node_get_pos (ptr) + delta;
424 return g_sequence_node_find_by_pos (ptr, new_pos);
427 void
428 g_sequence_ptr_sort_changed (GSequencePtr ptr,
429 GCompareDataFunc cmp_func,
430 gpointer cmp_data)
432 GSequence *seq;
434 g_return_if_fail (!ptr->is_end);
436 seq = g_sequence_node_get_sequence (ptr);
437 g_sequence_unlink (seq, ptr);
438 g_sequence_node_insert_sorted (seq->node, ptr, cmp_func, cmp_data);
441 /* search
443 * The only restriction on the search function is that it
444 * must not delete any nodes. It is permitted to insert new nodes,
445 * but the caller should "know what he is doing"
447 void
448 g_sequence_search (GSequence *seq,
449 GSequenceSearchFunc f,
450 gpointer data)
452 GQueue *intervals = g_queue_new ();
454 g_queue_push_tail (intervals, g_sequence_node_find_first (seq->node));
455 g_queue_push_tail (intervals, g_sequence_node_find_last (seq->node));
457 while (!g_queue_is_empty (intervals))
459 GSequenceNode *begin = g_queue_pop_head (intervals);
460 GSequenceNode *end = g_queue_pop_head (intervals);
462 if (f (begin, end, data))
464 gint begin_pos = g_sequence_node_get_pos (begin);
465 gint end_pos = g_sequence_node_get_pos (end);
467 if (end_pos - begin_pos > 1)
469 GSequenceNode *mid;
470 gint mid_pos;
472 mid_pos = begin_pos + (end_pos - begin_pos) / 2;
473 mid = g_sequence_node_find_by_pos (begin, mid_pos);
475 g_queue_push_tail (intervals, begin);
476 g_queue_push_tail (intervals, mid);
478 g_queue_push_tail (intervals, mid);
479 g_queue_push_tail (intervals, end);
484 g_queue_free (intervals);
489 #if 0
490 /* aggregates */
491 void
492 g_sequence_add_aggregate (GSequence *seq,
493 const gchar *aggregate,
494 GSequenceAggregateFunc f,
495 gpointer data,
496 GDestroyNotify destroy)
498 /* FIXME */
501 void
502 g_sequence_remove_aggregate (GSequence *seq,
503 const gchar aggregate)
505 /* FIXME */
509 void
510 g_sequence_set_aggregate_data (GSequencePtr ptr,
511 const gchar *aggregate,
512 gpointer data)
514 /* FIXME */
518 gpointer
519 g_sequence_get_aggregate_data (GSequencePtr begin,
520 GSequencePtr end,
521 const gchar *aggregate)
523 g_assert_not_reached();
524 return NULL;
526 #endif
529 /* Nodes
531 static void
532 g_sequence_node_update_fields (GSequenceNode *node)
534 g_assert (node != NULL);
536 node->n_nodes = 1;
538 if (node->left)
539 node->n_nodes += node->left->n_nodes;
541 if (node->right)
542 node->n_nodes += node->right->n_nodes;
544 #if 0
545 if (node->left || node->right)
546 g_assert (node->n_nodes > 1);
547 #endif
550 #define NODE_LEFT_CHILD(n) (((n)->parent) && ((n)->parent->left) == (n))
551 #define NODE_RIGHT_CHILD(n) (((n)->parent) && ((n)->parent->right) == (n))
553 static void
554 g_sequence_node_rotate (GSequenceNode *node)
556 GSequenceNode *tmp, *old;
558 g_assert (node->parent);
559 g_assert (node->parent != node);
561 if (NODE_LEFT_CHILD (node))
563 /* rotate right */
564 tmp = node->right;
566 node->right = node->parent;
567 node->parent = node->parent->parent;
568 if (node->parent)
570 if (node->parent->left == node->right)
571 node->parent->left = node;
572 else
573 node->parent->right = node;
576 g_assert (node->right);
578 node->right->parent = node;
579 node->right->left = tmp;
581 if (node->right->left)
582 node->right->left->parent = node->right;
584 old = node->right;
586 else
588 /* rotate left */
589 tmp = node->left;
591 node->left = node->parent;
592 node->parent = node->parent->parent;
593 if (node->parent)
595 if (node->parent->right == node->left)
596 node->parent->right = node;
597 else
598 node->parent->left = node;
601 g_assert (node->left);
603 node->left->parent = node;
604 node->left->right = tmp;
606 if (node->left->right)
607 node->left->right->parent = node->left;
609 old = node->left;
612 g_sequence_node_update_fields (old);
613 g_sequence_node_update_fields (node);
616 static GSequenceNode *
617 splay (GSequenceNode *node)
619 while (node->parent)
621 if (!node->parent->parent)
623 /* zig */
624 g_sequence_node_rotate (node);
626 else if ((NODE_LEFT_CHILD (node) && NODE_LEFT_CHILD (node->parent)) ||
627 (NODE_RIGHT_CHILD (node) && NODE_RIGHT_CHILD (node->parent)))
629 /* zig-zig */
630 g_sequence_node_rotate (node->parent);
631 g_sequence_node_rotate (node);
633 else
635 /* zig-zag */
636 g_sequence_node_rotate (node);
637 g_sequence_node_rotate (node);
641 return node;
644 static GSequenceNode *
645 g_sequence_node_new (gpointer data)
647 GSequenceNode *node = g_slice_new0 (GSequenceNode);
649 node->parent = NULL;
650 node->left = NULL;
651 node->right = NULL;
653 node->data = data;
654 node->is_end = FALSE;
655 node->n_nodes = 1;
657 return node;
660 static GSequenceNode *
661 find_min (GSequenceNode *node)
663 splay (node);
665 while (node->left)
666 node = node->left;
668 return node;
671 static GSequenceNode *
672 find_max (GSequenceNode *node)
674 splay (node);
676 while (node->right)
677 node = node->right;
679 return node;
682 static GSequenceNode *
683 g_sequence_node_find_first (GSequenceNode *node)
685 return splay (find_min (node));
688 static GSequenceNode *
689 g_sequence_node_find_last (GSequenceNode *node)
691 return splay (find_max (node));
694 static gint
695 get_n_nodes (GSequenceNode *node)
697 if (node)
698 return node->n_nodes;
699 else
700 return 0;
703 static GSequenceNode *
704 g_sequence_node_find_by_pos (GSequenceNode *node,
705 gint pos)
707 gint i;
709 g_assert (node != NULL);
711 splay (node);
713 while ((i = get_n_nodes (node->left)) != pos)
715 if (i < pos)
717 node = node->right;
718 pos -= (i + 1);
720 else
722 node = node->left;
723 g_assert (node->parent != NULL);
727 return splay (node);
730 static GSequenceNode *
731 g_sequence_node_prev (GSequenceNode *node)
733 splay (node);
735 if (node->left)
737 node = node->left;
738 while (node->right)
739 node = node->right;
742 return splay (node);
745 static GSequenceNode *
746 g_sequence_node_next (GSequenceNode *node)
748 splay (node);
750 if (node->right)
752 node = node->right;
753 while (node->left)
754 node = node->left;
757 return splay (node);
760 static gint
761 g_sequence_node_get_pos (GSequenceNode *node)
763 splay (node);
765 return get_n_nodes (node->left);
768 static GSequence *
769 g_sequence_node_get_sequence (GSequenceNode *node)
771 splay (node);
773 return node->sequence;
776 static GSequenceNode *
777 g_sequence_node_find_closest (GSequenceNode *node,
778 GSequenceNode *other,
779 GCompareDataFunc cmp,
780 gpointer data)
782 GSequenceNode *best;
783 gint c;
785 splay (node);
789 best = node;
791 if ((c = cmp (node, other, data)) != 0)
793 if (c < 0)
794 node = node->right;
795 else
796 node = node->left;
799 while (c != 0 && node != NULL);
801 return best;
804 static void
805 g_sequence_node_free (GSequenceNode *node,
806 GDestroyNotify destroy)
808 /* FIXME:
810 * This is to avoid excessively deep recursions. A splay tree is not necessarily
811 * balanced at all.
813 * I _think_ this is still linear in the number of nodes, but I'd like to
814 * do something more efficient.
817 while (node)
819 GSequenceNode *next;
821 node = splay (find_min (node));
822 next = node->right;
823 if (next)
824 next->parent = NULL;
826 if (destroy && !node->is_end)
827 destroy (node->data);
828 g_slice_free (GSequenceNode, node);
830 node = next;
834 #if 0
835 static gboolean
836 g_sequence_node_is_singleton (GSequenceNode *node)
838 splay (node);
840 if (node->left || node->right)
841 return FALSE;
843 return TRUE;
845 #endif
847 static void
848 g_sequence_node_split (GSequenceNode *node,
849 GSequenceNode **left,
850 GSequenceNode **right)
852 GSequenceNode *left_tree;
854 splay (node);
856 left_tree = node->left;
857 if (left_tree)
859 left_tree->parent = NULL;
860 g_sequence_node_update_fields (left_tree);
863 node->left = NULL;
864 g_sequence_node_update_fields (node);
866 if (left)
867 *left = left_tree;
869 if (right)
870 *right = node;
873 static void
874 g_sequence_node_insert_before (GSequenceNode *node,
875 GSequenceNode *new)
877 g_assert (node != NULL);
878 g_assert (new != NULL);
880 splay (node);
882 new = splay (find_min (new));
883 g_assert (new->left == NULL);
885 if (node->left)
886 node->left->parent = new;
888 new->left = node->left;
889 new->parent = node;
891 node->left = new;
893 g_sequence_node_update_fields (new);
894 g_sequence_node_update_fields (node);
897 static gint
898 g_sequence_node_get_length (GSequenceNode *node)
900 g_assert (node != NULL);
902 splay (node);
903 return node->n_nodes;
906 static void
907 g_sequence_node_remove (GSequenceNode *node)
909 GSequenceNode *right, *left;
911 splay (node);
913 left = node->left;
914 right = node->right;
916 node->left = node->right = NULL;
918 if (right)
920 right->parent = NULL;
922 right = g_sequence_node_find_first (right);
923 g_assert (right->left == NULL);
925 right->left = left;
926 if (left)
928 left->parent = right;
929 g_sequence_node_update_fields (right);
932 else if (left)
933 left->parent = NULL;
936 #if 0
937 /* debug func */
938 static gint
939 g_sequence_node_calc_height (GSequenceNode *node)
941 /* breadth first traversal */
942 gint height = 0;
943 GQueue *nodes = g_queue_new ();
945 g_queue_push_tail (nodes, node);
947 while (!g_queue_is_empty (nodes))
949 GQueue *tmp = g_queue_new ();
951 height++;
952 while (!g_queue_is_empty (nodes))
954 GSequenceNode *node = g_queue_pop_head (nodes);
955 if (node->left)
956 g_queue_push_tail (tmp, node->left);
957 if (node->right)
958 g_queue_push_tail (tmp, node->right);
961 g_queue_free (nodes);
963 nodes = tmp;
965 g_queue_free (nodes);
967 return height;
969 #endif
971 static void
972 g_sequence_node_insert_sorted (GSequenceNode *node,
973 GSequenceNode *new,
974 GCompareDataFunc cmp_func,
975 gpointer cmp_data)
977 SortInfo info;
978 GSequenceNode *closest;
979 info.cmp = cmp_func;
980 info.data = cmp_data;
982 closest =
983 g_sequence_node_find_closest (node, new, node_compare, &info);
985 if (node_compare (new, closest, &info) > 0)
986 closest = g_sequence_node_next (closest);
988 /* this can never fail since we have a bigger-than-everything
989 * end-node
991 g_assert (node_compare (new, closest, &info) <= 0);
992 g_sequence_node_insert_before (closest, new);
995 static gint
996 g_sequence_node_calc_height (GSequenceNode *node)
998 gint left_height;
999 gint right_height;
1001 if (node)
1003 left_height = 0;
1004 right_height = 0;
1006 if (node->left)
1007 left_height = g_sequence_node_calc_height (node->left);
1009 if (node->right)
1010 right_height = g_sequence_node_calc_height (node->right);
1012 return MAX (left_height, right_height) + 1;
1015 return 0;
1018 gint
1019 g_sequence_calc_tree_height (GSequence *seq)
1021 GSequenceNode *node = seq->node;
1022 gint r, l;
1023 while (node->parent)
1024 node = node->parent;
1026 if (node)
1028 r = g_sequence_node_calc_height (node->right);
1029 l = g_sequence_node_calc_height (node->left);
1031 return MAX (r, l) + 1;
1033 else
1034 return 0;