1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
3 * Soeren Sandmann (sandmann@daimi.au.dk)
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, see <http://www.gnu.org/licenses/>.
21 #include "gsequence.h"
24 #include "gtestutils.h"
29 * @short_description: scalable lists
31 * The #GSequence data structure has the API of a list, but is
32 * implemented internally with a balanced binary tree. This means that
33 * it is possible to maintain a sorted list of n elements in time O(n log n).
34 * The data contained in each element can be either integer values, by using
35 * of the [Type Conversion Macros][glib-Type-Conversion-Macros], or simply
36 * pointers to any type of data.
38 * A #GSequence is accessed through "iterators", represented by a
39 * #GSequenceIter. An iterator represents a position between two
40 * elements of the sequence. For example, the "begin" iterator
41 * represents the gap immediately before the first element of the
42 * sequence, and the "end" iterator represents the gap immediately
43 * after the last element. In an empty sequence, the begin and end
44 * iterators are the same.
46 * Some methods on #GSequence operate on ranges of items. For example
47 * g_sequence_foreach_range() will call a user-specified function on
48 * each element with the given range. The range is delimited by the
49 * gaps represented by the passed-in iterators, so if you pass in the
50 * begin and end iterators, the range in question is the entire
53 * The function g_sequence_get() is used with an iterator to access the
54 * element immediately following the gap that the iterator represents.
55 * The iterator is said to "point" to that element.
57 * Iterators are stable across most operations on a #GSequence. For
58 * example an iterator pointing to some element of a sequence will
59 * continue to point to that element even after the sequence is sorted.
60 * Even moving an element to another sequence using for example
61 * g_sequence_move_range() will not invalidate the iterators pointing
62 * to it. The only operation that will invalidate an iterator is when
63 * the element it points to is removed from any sequence.
69 * The #GSequenceIter struct is an opaque data type representing an
70 * iterator pointing into a #GSequence.
74 * GSequenceIterCompareFunc:
75 * @a: a #GSequenceIter
76 * @b: a #GSequenceIter
79 * A #GSequenceIterCompareFunc is a function used to compare iterators.
80 * It must return zero if the iterators compare equal, a negative value
81 * if @a comes before @b, and a positive value if @b comes before @a.
83 * Returns: zero if the iterators are equal, a negative value if @a
84 * comes before @b, and a positive value if @b comes before @a.
87 typedef struct _GSequenceNode GSequenceNode
;
92 * The #GSequence struct is an opaque data type representing a
93 * [sequence][glib-Sequences] data type.
97 GSequenceNode
* end_node
;
98 GDestroyNotify data_destroy_notify
;
99 gboolean access_prohibited
;
101 /* The 'real_sequence' is used when temporary sequences are created
102 * to hold nodes that are being rearranged. The 'real_sequence' of such
103 * a temporary sequence points to the sequence that is actually being
104 * manipulated. The only reason we need this is so that when the
105 * sort/sort_changed/search_iter() functions call out to the application
106 * g_sequence_iter_get_sequence() will return the correct sequence.
108 GSequence
* real_sequence
;
111 struct _GSequenceNode
114 GSequenceNode
* parent
;
115 GSequenceNode
* left
;
116 GSequenceNode
* right
;
117 gpointer data
; /* For the end node, this field points
123 * Declaration of GSequenceNode methods
125 static GSequenceNode
*node_new (gpointer data
);
126 static GSequenceNode
*node_get_first (GSequenceNode
*node
);
127 static GSequenceNode
*node_get_last (GSequenceNode
*node
);
128 static GSequenceNode
*node_get_prev (GSequenceNode
*node
);
129 static GSequenceNode
*node_get_next (GSequenceNode
*node
);
130 static gint
node_get_pos (GSequenceNode
*node
);
131 static GSequenceNode
*node_get_by_pos (GSequenceNode
*node
,
133 static GSequenceNode
*node_find (GSequenceNode
*haystack
,
134 GSequenceNode
*needle
,
136 GSequenceIterCompareFunc cmp
,
138 static GSequenceNode
*node_find_closest (GSequenceNode
*haystack
,
139 GSequenceNode
*needle
,
141 GSequenceIterCompareFunc cmp
,
143 static gint
node_get_length (GSequenceNode
*node
);
144 static void node_free (GSequenceNode
*node
,
146 static void node_cut (GSequenceNode
*split
);
147 static void node_insert_before (GSequenceNode
*node
,
149 static void node_unlink (GSequenceNode
*node
);
150 static void node_join (GSequenceNode
*left
,
151 GSequenceNode
*right
);
152 static void node_insert_sorted (GSequenceNode
*node
,
155 GSequenceIterCompareFunc cmp_func
,
160 * Various helper functions
163 check_seq_access (GSequence
*seq
)
165 if (G_UNLIKELY (seq
->access_prohibited
))
167 g_warning ("Accessing a sequence while it is "
168 "being sorted or searched is not allowed");
173 get_sequence (GSequenceNode
*node
)
175 return (GSequence
*)node_get_last (node
)->data
;
179 check_iter_access (GSequenceIter
*iter
)
181 check_seq_access (get_sequence (iter
));
185 is_end (GSequenceIter
*iter
)
187 GSequenceIter
*parent
= iter
->parent
;
195 while (parent
->right
== iter
)
198 parent
= iter
->parent
;
209 GCompareDataFunc cmp_func
;
211 GSequenceNode
*end_node
;
214 /* This function compares two iters using a normal compare
215 * function and user_data passed in in a SortInfo struct
218 iter_compare (GSequenceIter
*node1
,
219 GSequenceIter
*node2
,
222 const SortInfo
*info
= data
;
225 if (node1
== info
->end_node
)
228 if (node2
== info
->end_node
)
231 retval
= info
->cmp_func (node1
->data
, node2
->data
, info
->cmp_data
);
242 * @data_destroy: (nullable): a #GDestroyNotify function, or %NULL
244 * Creates a new GSequence. The @data_destroy function, if non-%NULL will
245 * be called on all items when the sequence is destroyed and on items that
246 * are removed from the sequence.
248 * Returns: a new #GSequence
253 g_sequence_new (GDestroyNotify data_destroy
)
255 GSequence
*seq
= g_new (GSequence
, 1);
256 seq
->data_destroy_notify
= data_destroy
;
258 seq
->end_node
= node_new (seq
);
260 seq
->access_prohibited
= FALSE
;
262 seq
->real_sequence
= seq
;
271 * Frees the memory allocated for @seq. If @seq has a data destroy
272 * function associated with it, that function is called on all items
278 g_sequence_free (GSequence
*seq
)
280 g_return_if_fail (seq
!= NULL
);
282 check_seq_access (seq
);
284 node_free (seq
->end_node
, seq
);
290 * g_sequence_foreach_range:
291 * @begin: a #GSequenceIter
292 * @end: a #GSequenceIter
294 * @user_data: user data passed to @func
296 * Calls @func for each item in the range (@begin, @end) passing
297 * @user_data to the function.
302 g_sequence_foreach_range (GSequenceIter
*begin
,
310 g_return_if_fail (func
!= NULL
);
311 g_return_if_fail (begin
!= NULL
);
312 g_return_if_fail (end
!= NULL
);
314 seq
= get_sequence (begin
);
316 seq
->access_prohibited
= TRUE
;
321 GSequenceIter
*next
= node_get_next (iter
);
323 func (iter
->data
, user_data
);
328 seq
->access_prohibited
= FALSE
;
332 * g_sequence_foreach:
334 * @func: the function to call for each item in @seq
335 * @user_data: user data passed to @func
337 * Calls @func for each item in the sequence passing @user_data
343 g_sequence_foreach (GSequence
*seq
,
347 GSequenceIter
*begin
, *end
;
349 check_seq_access (seq
);
351 begin
= g_sequence_get_begin_iter (seq
);
352 end
= g_sequence_get_end_iter (seq
);
354 g_sequence_foreach_range (begin
, end
, func
, user_data
);
358 * g_sequence_range_get_midpoint:
359 * @begin: a #GSequenceIter
360 * @end: a #GSequenceIter
362 * Finds an iterator somewhere in the range (@begin, @end). This
363 * iterator will be close to the middle of the range, but is not
364 * guaranteed to be exactly in the middle.
366 * The @begin and @end iterators must both point to the same sequence
367 * and @begin must come before or be equal to @end in the sequence.
369 * Returns: a #GSequenceIter pointing somewhere in the
370 * (@begin, @end) range
375 g_sequence_range_get_midpoint (GSequenceIter
*begin
,
378 int begin_pos
, end_pos
, mid_pos
;
380 g_return_val_if_fail (begin
!= NULL
, NULL
);
381 g_return_val_if_fail (end
!= NULL
, NULL
);
382 g_return_val_if_fail (get_sequence (begin
) == get_sequence (end
), NULL
);
384 begin_pos
= node_get_pos (begin
);
385 end_pos
= node_get_pos (end
);
387 g_return_val_if_fail (end_pos
>= begin_pos
, NULL
);
389 mid_pos
= begin_pos
+ (end_pos
- begin_pos
) / 2;
391 return node_get_by_pos (begin
, mid_pos
);
395 * g_sequence_iter_compare:
396 * @a: a #GSequenceIter
397 * @b: a #GSequenceIter
399 * Returns a negative number if @a comes before @b, 0 if they are equal,
400 * and a positive number if @a comes after @b.
402 * The @a and @b iterators must point into the same sequence.
404 * Returns: a negative number if @a comes before @b, 0 if they are
405 * equal, and a positive number if @a comes after @b
410 g_sequence_iter_compare (GSequenceIter
*a
,
415 g_return_val_if_fail (a
!= NULL
, 0);
416 g_return_val_if_fail (b
!= NULL
, 0);
417 g_return_val_if_fail (get_sequence (a
) == get_sequence (b
), 0);
419 check_iter_access (a
);
420 check_iter_access (b
);
422 a_pos
= node_get_pos (a
);
423 b_pos
= node_get_pos (b
);
427 else if (a_pos
> b_pos
)
436 * @data: the data for the new item
438 * Adds a new item to the end of @seq.
440 * Returns: an iterator pointing to the new item
445 g_sequence_append (GSequence
*seq
,
450 g_return_val_if_fail (seq
!= NULL
, NULL
);
452 check_seq_access (seq
);
454 node
= node_new (data
);
455 node_insert_before (seq
->end_node
, node
);
461 * g_sequence_prepend:
463 * @data: the data for the new item
465 * Adds a new item to the front of @seq
467 * Returns: an iterator pointing to the new item
472 g_sequence_prepend (GSequence
*seq
,
475 GSequenceNode
*node
, *first
;
477 g_return_val_if_fail (seq
!= NULL
, NULL
);
479 check_seq_access (seq
);
481 node
= node_new (data
);
482 first
= node_get_first (seq
->end_node
);
484 node_insert_before (first
, node
);
490 * g_sequence_insert_before:
491 * @iter: a #GSequenceIter
492 * @data: the data for the new item
494 * Inserts a new item just before the item pointed to by @iter.
496 * Returns: an iterator pointing to the new item
501 g_sequence_insert_before (GSequenceIter
*iter
,
506 g_return_val_if_fail (iter
!= NULL
, NULL
);
508 check_iter_access (iter
);
510 node
= node_new (data
);
512 node_insert_before (iter
, node
);
519 * @iter: a #GSequenceIter
521 * Removes the item pointed to by @iter. It is an error to pass the
522 * end iterator to this function.
524 * If the sequence has a data destroy function associated with it, this
525 * function is called on the data for the removed item.
530 g_sequence_remove (GSequenceIter
*iter
)
534 g_return_if_fail (iter
!= NULL
);
535 g_return_if_fail (!is_end (iter
));
537 check_iter_access (iter
);
539 seq
= get_sequence (iter
);
542 node_free (iter
, seq
);
546 * g_sequence_remove_range:
547 * @begin: a #GSequenceIter
548 * @end: a #GSequenceIter
550 * Removes all items in the (@begin, @end) range.
552 * If the sequence has a data destroy function associated with it, this
553 * function is called on the data for the removed items.
558 g_sequence_remove_range (GSequenceIter
*begin
,
561 g_return_if_fail (get_sequence (begin
) == get_sequence (end
));
563 check_iter_access (begin
);
564 check_iter_access (end
);
566 g_sequence_move_range (NULL
, begin
, end
);
570 * g_sequence_move_range:
571 * @dest: a #GSequenceIter
572 * @begin: a #GSequenceIter
573 * @end: a #GSequenceIter
575 * Inserts the (@begin, @end) range at the destination pointed to by ptr.
576 * The @begin and @end iters must point into the same sequence. It is
577 * allowed for @dest to point to a different sequence than the one pointed
578 * into by @begin and @end.
580 * If @dest is NULL, the range indicated by @begin and @end is
581 * removed from the sequence. If @dest iter points to a place within
582 * the (@begin, @end) range, the range does not move.
587 g_sequence_move_range (GSequenceIter
*dest
,
588 GSequenceIter
*begin
,
592 GSequenceNode
*first
;
594 g_return_if_fail (begin
!= NULL
);
595 g_return_if_fail (end
!= NULL
);
597 check_iter_access (begin
);
598 check_iter_access (end
);
600 check_iter_access (dest
);
602 src_seq
= get_sequence (begin
);
604 g_return_if_fail (src_seq
== get_sequence (end
));
606 /* Dest points to begin or end? */
607 if (dest
== begin
|| dest
== end
)
610 /* begin comes after end? */
611 if (g_sequence_iter_compare (begin
, end
) >= 0)
614 /* dest points somewhere in the (begin, end) range? */
615 if (dest
&& get_sequence (dest
) == src_seq
&&
616 g_sequence_iter_compare (dest
, begin
) > 0 &&
617 g_sequence_iter_compare (dest
, end
) < 0)
622 src_seq
= get_sequence (begin
);
624 first
= node_get_first (begin
);
631 node_join (first
, end
);
635 first
= node_get_first (dest
);
639 node_join (begin
, dest
);
642 node_join (first
, begin
);
646 node_free (begin
, src_seq
);
653 * @cmp_func: the function used to sort the sequence
654 * @cmp_data: user data passed to @cmp_func
656 * Sorts @seq using @cmp_func.
658 * @cmp_func is passed two items of @seq and should
659 * return 0 if they are equal, a negative value if the
660 * first comes before the second, and a positive value
661 * if the second comes before the first.
666 g_sequence_sort (GSequence
*seq
,
667 GCompareDataFunc cmp_func
,
672 info
.cmp_func
= cmp_func
;
673 info
.cmp_data
= cmp_data
;
674 info
.end_node
= seq
->end_node
;
676 check_seq_access (seq
);
678 g_sequence_sort_iter (seq
, iter_compare
, &info
);
682 * g_sequence_insert_sorted:
684 * @data: the data to insert
685 * @cmp_func: the function used to compare items in the sequence
686 * @cmp_data: user data passed to @cmp_func.
688 * Inserts @data into @sequence using @func to determine the new
689 * position. The sequence must already be sorted according to @cmp_func;
690 * otherwise the new position of @data is undefined.
692 * @cmp_func is called with two items of the @seq and @user_data.
693 * It should return 0 if the items are equal, a negative value
694 * if the first item comes before the second, and a positive value
695 * if the second item comes before the first.
697 * Returns: a #GSequenceIter pointing to the new item.
702 g_sequence_insert_sorted (GSequence
*seq
,
704 GCompareDataFunc cmp_func
,
709 g_return_val_if_fail (seq
!= NULL
, NULL
);
710 g_return_val_if_fail (cmp_func
!= NULL
, NULL
);
712 info
.cmp_func
= cmp_func
;
713 info
.cmp_data
= cmp_data
;
714 info
.end_node
= seq
->end_node
;
715 check_seq_access (seq
);
717 return g_sequence_insert_sorted_iter (seq
, data
, iter_compare
, &info
);
721 * g_sequence_sort_changed:
722 * @iter: A #GSequenceIter
723 * @cmp_func: the function used to compare items in the sequence
724 * @cmp_data: user data passed to @cmp_func.
726 * Moves the data pointed to a new position as indicated by @cmp_func. This
727 * function should be called for items in a sequence already sorted according
728 * to @cmp_func whenever some aspect of an item changes so that @cmp_func
729 * may return different values for that item.
731 * @cmp_func is called with two items of the @seq and @user_data.
732 * It should return 0 if the items are equal, a negative value if
733 * the first item comes before the second, and a positive value if
734 * the second item comes before the first.
739 g_sequence_sort_changed (GSequenceIter
*iter
,
740 GCompareDataFunc cmp_func
,
745 g_return_if_fail (!is_end (iter
));
747 info
.cmp_func
= cmp_func
;
748 info
.cmp_data
= cmp_data
;
749 info
.end_node
= get_sequence (iter
)->end_node
;
750 check_iter_access (iter
);
752 g_sequence_sort_changed_iter (iter
, iter_compare
, &info
);
758 * @data: data for the new item
759 * @cmp_func: the function used to compare items in the sequence
760 * @cmp_data: user data passed to @cmp_func
762 * Returns an iterator pointing to the position where @data would
763 * be inserted according to @cmp_func and @cmp_data.
765 * @cmp_func is called with two items of the @seq and @user_data.
766 * It should return 0 if the items are equal, a negative value if
767 * the first item comes before the second, and a positive value if
768 * the second item comes before the first.
770 * If you are simply searching for an existing element of the sequence,
771 * consider using g_sequence_lookup().
773 * This function will fail if the data contained in the sequence is
774 * unsorted. Use g_sequence_insert_sorted() or
775 * g_sequence_insert_sorted_iter() to add data to your sequence or, if
776 * you want to add a large amount of data, call g_sequence_sort() after
777 * doing unsorted insertions.
779 * Returns: an #GSequenceIter pointing to the position where @data
780 * would have been inserted according to @cmp_func and @cmp_data
785 g_sequence_search (GSequence
*seq
,
787 GCompareDataFunc cmp_func
,
792 g_return_val_if_fail (seq
!= NULL
, NULL
);
794 info
.cmp_func
= cmp_func
;
795 info
.cmp_data
= cmp_data
;
796 info
.end_node
= seq
->end_node
;
797 check_seq_access (seq
);
799 return g_sequence_search_iter (seq
, data
, iter_compare
, &info
);
805 * @data: data to lookup
806 * @cmp_func: the function used to compare items in the sequence
807 * @cmp_data: user data passed to @cmp_func
809 * Returns an iterator pointing to the position of the first item found
810 * equal to @data according to @cmp_func and @cmp_data. If more than one
811 * item is equal, it is not guaranteed that it is the first which is
812 * returned. In that case, you can use g_sequence_iter_next() and
813 * g_sequence_iter_prev() to get others.
815 * @cmp_func is called with two items of the @seq and @user_data.
816 * It should return 0 if the items are equal, a negative value if
817 * the first item comes before the second, and a positive value if
818 * the second item comes before the first.
820 * This function will fail if the data contained in the sequence is
821 * unsorted. Use g_sequence_insert_sorted() or
822 * g_sequence_insert_sorted_iter() to add data to your sequence or, if
823 * you want to add a large amount of data, call g_sequence_sort() after
824 * doing unsorted insertions.
826 * Returns: an #GSequenceIter pointing to the position of the
827 * first item found equal to @data according to @cmp_func and
828 * @cmp_data, or %NULL if no such item exists
833 g_sequence_lookup (GSequence
*seq
,
835 GCompareDataFunc cmp_func
,
840 g_return_val_if_fail (seq
!= NULL
, NULL
);
842 info
.cmp_func
= cmp_func
;
843 info
.cmp_data
= cmp_data
;
844 info
.end_node
= seq
->end_node
;
845 check_seq_access (seq
);
847 return g_sequence_lookup_iter (seq
, data
, iter_compare
, &info
);
851 * g_sequence_sort_iter:
853 * @cmp_func: the function used to compare iterators in the sequence
854 * @cmp_data: user data passed to @cmp_func
856 * Like g_sequence_sort(), but uses a #GSequenceIterCompareFunc instead
857 * of a GCompareDataFunc as the compare function
859 * @cmp_func is called with two iterators pointing into @seq. It should
860 * return 0 if the iterators are equal, a negative value if the first
861 * iterator comes before the second, and a positive value if the second
862 * iterator comes before the first.
867 g_sequence_sort_iter (GSequence
*seq
,
868 GSequenceIterCompareFunc cmp_func
,
872 GSequenceNode
*begin
, *end
;
874 g_return_if_fail (seq
!= NULL
);
875 g_return_if_fail (cmp_func
!= NULL
);
877 check_seq_access (seq
);
879 begin
= g_sequence_get_begin_iter (seq
);
880 end
= g_sequence_get_end_iter (seq
);
882 tmp
= g_sequence_new (NULL
);
883 tmp
->real_sequence
= seq
;
885 g_sequence_move_range (g_sequence_get_begin_iter (tmp
), begin
, end
);
887 seq
->access_prohibited
= TRUE
;
888 tmp
->access_prohibited
= TRUE
;
890 while (!g_sequence_is_empty (tmp
))
892 GSequenceNode
*node
= g_sequence_get_begin_iter (tmp
);
894 node_insert_sorted (seq
->end_node
, node
, seq
->end_node
,
898 tmp
->access_prohibited
= FALSE
;
899 seq
->access_prohibited
= FALSE
;
901 g_sequence_free (tmp
);
905 * g_sequence_sort_changed_iter:
906 * @iter: a #GSequenceIter
907 * @iter_cmp: the function used to compare iterators in the sequence
908 * @cmp_data: user data passed to @cmp_func
910 * Like g_sequence_sort_changed(), but uses
911 * a #GSequenceIterCompareFunc instead of a #GCompareDataFunc as
912 * the compare function.
914 * @iter_cmp is called with two iterators pointing into @seq. It should
915 * return 0 if the iterators are equal, a negative value if the first
916 * iterator comes before the second, and a positive value if the second
917 * iterator comes before the first.
922 g_sequence_sort_changed_iter (GSequenceIter
*iter
,
923 GSequenceIterCompareFunc iter_cmp
,
926 GSequence
*seq
, *tmp_seq
;
927 GSequenceIter
*next
, *prev
;
929 g_return_if_fail (iter
!= NULL
);
930 g_return_if_fail (!is_end (iter
));
931 g_return_if_fail (iter_cmp
!= NULL
);
932 check_iter_access (iter
);
934 /* If one of the neighbours is equal to iter, then
935 * don't move it. This ensures that sort_changed() is
936 * a stable operation.
939 next
= node_get_next (iter
);
940 prev
= node_get_prev (iter
);
942 if (prev
!= iter
&& iter_cmp (prev
, iter
, cmp_data
) == 0)
945 if (!is_end (next
) && iter_cmp (next
, iter
, cmp_data
) == 0)
948 seq
= get_sequence (iter
);
950 seq
->access_prohibited
= TRUE
;
952 tmp_seq
= g_sequence_new (NULL
);
953 tmp_seq
->real_sequence
= seq
;
956 node_insert_before (tmp_seq
->end_node
, iter
);
958 node_insert_sorted (seq
->end_node
, iter
, seq
->end_node
,
961 g_sequence_free (tmp_seq
);
963 seq
->access_prohibited
= FALSE
;
967 * g_sequence_insert_sorted_iter:
969 * @data: data for the new item
970 * @iter_cmp: the function used to compare iterators in the sequence
971 * @cmp_data: user data passed to @cmp_func
973 * Like g_sequence_insert_sorted(), but uses
974 * a #GSequenceIterCompareFunc instead of a #GCompareDataFunc as
975 * the compare function.
977 * @iter_cmp is called with two iterators pointing into @seq.
978 * It should return 0 if the iterators are equal, a negative
979 * value if the first iterator comes before the second, and a
980 * positive value if the second iterator comes before the first.
982 * It is called with two iterators pointing into @seq. It should
983 * return 0 if the iterators are equal, a negative value if the
984 * first iterator comes before the second, and a positive value
985 * if the second iterator comes before the first.
987 * Returns: a #GSequenceIter pointing to the new item
992 g_sequence_insert_sorted_iter (GSequence
*seq
,
994 GSequenceIterCompareFunc iter_cmp
,
997 GSequenceNode
*new_node
;
1000 g_return_val_if_fail (seq
!= NULL
, NULL
);
1001 g_return_val_if_fail (iter_cmp
!= NULL
, NULL
);
1003 check_seq_access (seq
);
1005 seq
->access_prohibited
= TRUE
;
1007 /* Create a new temporary sequence and put the new node into
1008 * that. The reason for this is that the user compare function
1009 * will be called with the new node, and if it dereferences,
1010 * "is_end" will be called on it. But that will crash if the
1011 * node is not actually in a sequence.
1013 * node_insert_sorted() makes sure the node is unlinked before
1016 * The reason we need the "iter" versions at all is that that
1017 * is the only kind of compare functions GtkTreeView can use.
1019 tmp_seq
= g_sequence_new (NULL
);
1020 tmp_seq
->real_sequence
= seq
;
1022 new_node
= g_sequence_append (tmp_seq
, data
);
1024 node_insert_sorted (seq
->end_node
, new_node
,
1025 seq
->end_node
, iter_cmp
, cmp_data
);
1027 g_sequence_free (tmp_seq
);
1029 seq
->access_prohibited
= FALSE
;
1035 * g_sequence_search_iter:
1036 * @seq: a #GSequence
1037 * @data: data for the new item
1038 * @iter_cmp: the function used to compare iterators in the sequence
1039 * @cmp_data: user data passed to @iter_cmp
1041 * Like g_sequence_search(), but uses a #GSequenceIterCompareFunc
1042 * instead of a #GCompareDataFunc as the compare function.
1044 * @iter_cmp is called with two iterators pointing into @seq.
1045 * It should return 0 if the iterators are equal, a negative value
1046 * if the first iterator comes before the second, and a positive
1047 * value if the second iterator comes before the first.
1049 * If you are simply searching for an existing element of the sequence,
1050 * consider using g_sequence_lookup_iter().
1052 * This function will fail if the data contained in the sequence is
1053 * unsorted. Use g_sequence_insert_sorted() or
1054 * g_sequence_insert_sorted_iter() to add data to your sequence or, if
1055 * you want to add a large amount of data, call g_sequence_sort() after
1056 * doing unsorted insertions.
1058 * Returns: a #GSequenceIter pointing to the position in @seq
1059 * where @data would have been inserted according to @iter_cmp
1065 g_sequence_search_iter (GSequence
*seq
,
1067 GSequenceIterCompareFunc iter_cmp
,
1070 GSequenceNode
*node
;
1071 GSequenceNode
*dummy
;
1074 g_return_val_if_fail (seq
!= NULL
, NULL
);
1076 check_seq_access (seq
);
1078 seq
->access_prohibited
= TRUE
;
1080 tmp_seq
= g_sequence_new (NULL
);
1081 tmp_seq
->real_sequence
= seq
;
1083 dummy
= g_sequence_append (tmp_seq
, data
);
1085 node
= node_find_closest (seq
->end_node
, dummy
,
1086 seq
->end_node
, iter_cmp
, cmp_data
);
1088 g_sequence_free (tmp_seq
);
1090 seq
->access_prohibited
= FALSE
;
1096 * g_sequence_lookup_iter:
1097 * @seq: a #GSequence
1098 * @data: data to lookup
1099 * @iter_cmp: the function used to compare iterators in the sequence
1100 * @cmp_data: user data passed to @iter_cmp
1102 * Like g_sequence_lookup(), but uses a #GSequenceIterCompareFunc
1103 * instead of a #GCompareDataFunc as the compare function.
1105 * @iter_cmp is called with two iterators pointing into @seq.
1106 * It should return 0 if the iterators are equal, a negative value
1107 * if the first iterator comes before the second, and a positive
1108 * value if the second iterator comes before the first.
1110 * This function will fail if the data contained in the sequence is
1111 * unsorted. Use g_sequence_insert_sorted() or
1112 * g_sequence_insert_sorted_iter() to add data to your sequence or, if
1113 * you want to add a large amount of data, call g_sequence_sort() after
1114 * doing unsorted insertions.
1116 * Returns: an #GSequenceIter pointing to the position of
1117 * the first item found equal to @data according to @cmp_func
1118 * and @cmp_data, or %NULL if no such item exists
1123 g_sequence_lookup_iter (GSequence
*seq
,
1125 GSequenceIterCompareFunc iter_cmp
,
1128 GSequenceNode
*node
;
1129 GSequenceNode
*dummy
;
1132 g_return_val_if_fail (seq
!= NULL
, NULL
);
1134 check_seq_access (seq
);
1136 seq
->access_prohibited
= TRUE
;
1138 tmp_seq
= g_sequence_new (NULL
);
1139 tmp_seq
->real_sequence
= seq
;
1141 dummy
= g_sequence_append (tmp_seq
, data
);
1143 node
= node_find (seq
->end_node
, dummy
,
1144 seq
->end_node
, iter_cmp
, cmp_data
);
1146 g_sequence_free (tmp_seq
);
1148 seq
->access_prohibited
= FALSE
;
1154 * g_sequence_iter_get_sequence:
1155 * @iter: a #GSequenceIter
1157 * Returns the #GSequence that @iter points into.
1159 * Returns: the #GSequence that @iter points into
1164 g_sequence_iter_get_sequence (GSequenceIter
*iter
)
1168 g_return_val_if_fail (iter
!= NULL
, NULL
);
1170 seq
= get_sequence (iter
);
1172 /* For temporary sequences, this points to the sequence that
1173 * is actually being manipulated
1175 return seq
->real_sequence
;
1180 * @iter: a #GSequenceIter
1182 * Returns the data that @iter points to.
1184 * Returns: the data that @iter points to
1189 g_sequence_get (GSequenceIter
*iter
)
1191 g_return_val_if_fail (iter
!= NULL
, NULL
);
1192 g_return_val_if_fail (!is_end (iter
), NULL
);
1199 * @iter: a #GSequenceIter
1200 * @data: new data for the item
1202 * Changes the data for the item pointed to by @iter to be @data. If
1203 * the sequence has a data destroy function associated with it, that
1204 * function is called on the existing data that @iter pointed to.
1209 g_sequence_set (GSequenceIter
*iter
,
1214 g_return_if_fail (iter
!= NULL
);
1215 g_return_if_fail (!is_end (iter
));
1217 seq
= get_sequence (iter
);
1219 /* If @data is identical to iter->data, it is destroyed
1220 * here. This will work right in case of ref-counted objects. Also
1221 * it is similar to what ghashtables do.
1223 * For non-refcounted data it's a little less convenient, but
1224 * code relying on self-setting not destroying would be
1225 * pretty dubious anyway ...
1228 if (seq
->data_destroy_notify
)
1229 seq
->data_destroy_notify (iter
->data
);
1235 * g_sequence_get_length:
1236 * @seq: a #GSequence
1238 * Returns the length of @seq. Note that this method is O(h) where `h' is the
1239 * height of the tree. It is thus more efficient to use g_sequence_is_empty()
1240 * when comparing the length to zero.
1242 * Returns: the length of @seq
1247 g_sequence_get_length (GSequence
*seq
)
1249 return node_get_length (seq
->end_node
) - 1;
1253 * g_sequence_is_empty:
1254 * @seq: a #GSequence
1256 * Returns %TRUE if the sequence contains zero items.
1258 * This function is functionally identical to checking the result of
1259 * g_sequence_get_length() being equal to zero. However this function is
1260 * implemented in O(1) running time.
1262 * Returns: %TRUE if the sequence is empty, otherwise %FALSE.
1267 g_sequence_is_empty (GSequence
*seq
)
1269 return (seq
->end_node
->parent
== NULL
) && (seq
->end_node
->left
== NULL
);
1273 * g_sequence_get_end_iter:
1274 * @seq: a #GSequence
1276 * Returns the end iterator for @seg
1278 * Returns: the end iterator for @seq
1283 g_sequence_get_end_iter (GSequence
*seq
)
1285 g_return_val_if_fail (seq
!= NULL
, NULL
);
1287 return seq
->end_node
;
1291 * g_sequence_get_begin_iter:
1292 * @seq: a #GSequence
1294 * Returns the begin iterator for @seq.
1296 * Returns: the begin iterator for @seq.
1301 g_sequence_get_begin_iter (GSequence
*seq
)
1303 g_return_val_if_fail (seq
!= NULL
, NULL
);
1305 return node_get_first (seq
->end_node
);
1309 clamp_position (GSequence
*seq
,
1312 gint len
= g_sequence_get_length (seq
);
1314 if (pos
> len
|| pos
< 0)
1321 * if pos > number of items or -1, will return end pointer
1324 * g_sequence_get_iter_at_pos:
1325 * @seq: a #GSequence
1326 * @pos: a position in @seq, or -1 for the end
1328 * Returns the iterator at position @pos. If @pos is negative or larger
1329 * than the number of items in @seq, the end iterator is returned.
1331 * Returns: The #GSequenceIter at position @pos
1336 g_sequence_get_iter_at_pos (GSequence
*seq
,
1339 g_return_val_if_fail (seq
!= NULL
, NULL
);
1341 pos
= clamp_position (seq
, pos
);
1343 return node_get_by_pos (seq
->end_node
, pos
);
1348 * @src: a #GSequenceIter pointing to the item to move
1349 * @dest: a #GSequenceIter pointing to the position to which
1352 * Moves the item pointed to by @src to the position indicated by @dest.
1353 * After calling this function @dest will point to the position immediately
1354 * after @src. It is allowed for @src and @dest to point into different
1360 g_sequence_move (GSequenceIter
*src
,
1361 GSequenceIter
*dest
)
1363 g_return_if_fail (src
!= NULL
);
1364 g_return_if_fail (dest
!= NULL
);
1365 g_return_if_fail (!is_end (src
));
1371 node_insert_before (dest
, src
);
1377 * g_sequence_iter_is_end:
1378 * @iter: a #GSequenceIter
1380 * Returns whether @iter is the end iterator
1382 * Returns: Whether @iter is the end iterator
1387 g_sequence_iter_is_end (GSequenceIter
*iter
)
1389 g_return_val_if_fail (iter
!= NULL
, FALSE
);
1391 return is_end (iter
);
1395 * g_sequence_iter_is_begin:
1396 * @iter: a #GSequenceIter
1398 * Returns whether @iter is the begin iterator
1400 * Returns: whether @iter is the begin iterator
1405 g_sequence_iter_is_begin (GSequenceIter
*iter
)
1407 g_return_val_if_fail (iter
!= NULL
, FALSE
);
1409 return (node_get_prev (iter
) == iter
);
1413 * g_sequence_iter_get_position:
1414 * @iter: a #GSequenceIter
1416 * Returns the position of @iter
1418 * Returns: the position of @iter
1423 g_sequence_iter_get_position (GSequenceIter
*iter
)
1425 g_return_val_if_fail (iter
!= NULL
, -1);
1427 return node_get_pos (iter
);
1431 * g_sequence_iter_next:
1432 * @iter: a #GSequenceIter
1434 * Returns an iterator pointing to the next position after @iter.
1435 * If @iter is the end iterator, the end iterator is returned.
1437 * Returns: a #GSequenceIter pointing to the next position after @iter
1442 g_sequence_iter_next (GSequenceIter
*iter
)
1444 g_return_val_if_fail (iter
!= NULL
, NULL
);
1446 return node_get_next (iter
);
1450 * g_sequence_iter_prev:
1451 * @iter: a #GSequenceIter
1453 * Returns an iterator pointing to the previous position before @iter.
1454 * If @iter is the begin iterator, the begin iterator is returned.
1456 * Returns: a #GSequenceIter pointing to the previous position
1462 g_sequence_iter_prev (GSequenceIter
*iter
)
1464 g_return_val_if_fail (iter
!= NULL
, NULL
);
1466 return node_get_prev (iter
);
1470 * g_sequence_iter_move:
1471 * @iter: a #GSequenceIter
1472 * @delta: A positive or negative number indicating how many positions away
1473 * from @iter the returned #GSequenceIter will be
1475 * Returns the #GSequenceIter which is @delta positions away from @iter.
1476 * If @iter is closer than -@delta positions to the beginning of the sequence,
1477 * the begin iterator is returned. If @iter is closer than @delta positions
1478 * to the end of the sequence, the end iterator is returned.
1480 * Returns: a #GSequenceIter which is @delta positions away from @iter
1485 g_sequence_iter_move (GSequenceIter
*iter
,
1491 g_return_val_if_fail (iter
!= NULL
, NULL
);
1493 len
= g_sequence_get_length (get_sequence (iter
));
1495 new_pos
= node_get_pos (iter
) + delta
;
1499 else if (new_pos
> len
)
1502 return node_get_by_pos (iter
, new_pos
);
1507 * @a: a #GSequenceIter
1508 * @b: a #GSequenceIter
1510 * Swaps the items pointed to by @a and @b. It is allowed for @a and @b
1511 * to point into difference sequences.
1516 g_sequence_swap (GSequenceIter
*a
,
1519 GSequenceNode
*leftmost
, *rightmost
, *rightmost_next
;
1522 g_return_if_fail (!g_sequence_iter_is_end (a
));
1523 g_return_if_fail (!g_sequence_iter_is_end (b
));
1528 a_pos
= g_sequence_iter_get_position (a
);
1529 b_pos
= g_sequence_iter_get_position (b
);
1542 rightmost_next
= node_get_next (rightmost
);
1544 /* The situation is now like this:
1546 * ..., leftmost, ......., rightmost, rightmost_next, ...
1549 g_sequence_move (rightmost
, leftmost
);
1550 g_sequence_move (leftmost
, rightmost_next
);
1554 * Implementation of a treap
1559 get_priority (GSequenceNode
*node
)
1561 guint key
= GPOINTER_TO_UINT (node
);
1563 /* This hash function is based on one found on Thomas Wang's
1566 * http://www.concentric.net/~Ttwang/tech/inthash.htm
1569 key
= (key
<< 15) - key
- 1;
1570 key
= key
^ (key
>> 12);
1571 key
= key
+ (key
<< 2);
1572 key
= key
^ (key
>> 4);
1573 key
= key
+ (key
<< 3) + (key
<< 11);
1574 key
= key
^ (key
>> 16);
1576 /* We rely on 0 being less than all other priorities */
1577 return key
? key
: 1;
1580 static GSequenceNode
*
1581 find_root (GSequenceNode
*node
)
1583 while (node
->parent
)
1584 node
= node
->parent
;
1589 static GSequenceNode
*
1590 node_new (gpointer data
)
1592 GSequenceNode
*node
= g_slice_new0 (GSequenceNode
);
1598 node
->parent
= NULL
;
1603 static GSequenceNode
*
1604 node_get_first (GSequenceNode
*node
)
1606 node
= find_root (node
);
1614 static GSequenceNode
*
1615 node_get_last (GSequenceNode
*node
)
1617 node
= find_root (node
);
1625 #define NODE_LEFT_CHILD(n) (((n)->parent) && ((n)->parent->left) == (n))
1626 #define NODE_RIGHT_CHILD(n) (((n)->parent) && ((n)->parent->right) == (n))
1628 static GSequenceNode
*
1629 node_get_next (GSequenceNode
*node
)
1631 GSequenceNode
*n
= node
;
1641 while (NODE_RIGHT_CHILD (n
))
1653 static GSequenceNode
*
1654 node_get_prev (GSequenceNode
*node
)
1656 GSequenceNode
*n
= node
;
1666 while (NODE_LEFT_CHILD (n
))
1678 #define N_NODES(n) ((n)? (n)->n_nodes : 0)
1681 node_get_pos (GSequenceNode
*node
)
1686 n_smaller
= node
->left
->n_nodes
;
1690 if (NODE_RIGHT_CHILD (node
))
1691 n_smaller
+= N_NODES (node
->parent
->left
) + 1;
1693 node
= node
->parent
;
1699 static GSequenceNode
*
1700 node_get_by_pos (GSequenceNode
*node
,
1705 node
= find_root (node
);
1707 while ((i
= N_NODES (node
->left
)) != pos
)
1723 static GSequenceNode
*
1724 node_find (GSequenceNode
*haystack
,
1725 GSequenceNode
*needle
,
1727 GSequenceIterCompareFunc iter_cmp
,
1732 haystack
= find_root (haystack
);
1736 /* iter_cmp can't be passed the end node, since the function may
1739 if (haystack
== end
)
1742 c
= iter_cmp (haystack
, needle
, cmp_data
);
1748 haystack
= haystack
->left
;
1750 haystack
= haystack
->right
;
1752 while (haystack
!= NULL
);
1757 static GSequenceNode
*
1758 node_find_closest (GSequenceNode
*haystack
,
1759 GSequenceNode
*needle
,
1761 GSequenceIterCompareFunc iter_cmp
,
1764 GSequenceNode
*best
;
1767 haystack
= find_root (haystack
);
1773 /* iter_cmp can't be passed the end node, since the function may
1776 if (haystack
== end
)
1779 c
= iter_cmp (haystack
, needle
, cmp_data
);
1781 /* In the following we don't break even if c == 0. Instead we go on
1782 * searching along the 'bigger' nodes, so that we find the last one
1783 * that is equal to the needle.
1786 haystack
= haystack
->left
;
1788 haystack
= haystack
->right
;
1790 while (haystack
!= NULL
);
1792 /* If the best node is smaller or equal to the data, then move one step
1793 * to the right to make sure the best one is strictly bigger than the data
1795 if (best
!= end
&& c
<= 0)
1796 best
= node_get_next (best
);
1802 node_get_length (GSequenceNode
*node
)
1804 node
= find_root (node
);
1806 return node
->n_nodes
;
1810 real_node_free (GSequenceNode
*node
,
1815 real_node_free (node
->left
, seq
);
1816 real_node_free (node
->right
, seq
);
1818 if (seq
&& seq
->data_destroy_notify
&& node
!= seq
->end_node
)
1819 seq
->data_destroy_notify (node
->data
);
1821 g_slice_free (GSequenceNode
, node
);
1826 node_free (GSequenceNode
*node
,
1829 node
= find_root (node
);
1831 real_node_free (node
, seq
);
1835 node_update_fields (GSequenceNode
*node
)
1839 n_nodes
+= N_NODES (node
->left
);
1840 n_nodes
+= N_NODES (node
->right
);
1842 node
->n_nodes
= n_nodes
;
1846 node_rotate (GSequenceNode
*node
)
1848 GSequenceNode
*tmp
, *old
;
1850 g_assert (node
->parent
);
1851 g_assert (node
->parent
!= node
);
1853 if (NODE_LEFT_CHILD (node
))
1858 node
->right
= node
->parent
;
1859 node
->parent
= node
->parent
->parent
;
1862 if (node
->parent
->left
== node
->right
)
1863 node
->parent
->left
= node
;
1865 node
->parent
->right
= node
;
1868 g_assert (node
->right
);
1870 node
->right
->parent
= node
;
1871 node
->right
->left
= tmp
;
1873 if (node
->right
->left
)
1874 node
->right
->left
->parent
= node
->right
;
1883 node
->left
= node
->parent
;
1884 node
->parent
= node
->parent
->parent
;
1887 if (node
->parent
->right
== node
->left
)
1888 node
->parent
->right
= node
;
1890 node
->parent
->left
= node
;
1893 g_assert (node
->left
);
1895 node
->left
->parent
= node
;
1896 node
->left
->right
= tmp
;
1898 if (node
->left
->right
)
1899 node
->left
->right
->parent
= node
->left
;
1904 node_update_fields (old
);
1905 node_update_fields (node
);
1909 node_update_fields_deep (GSequenceNode
*node
)
1913 node_update_fields (node
);
1915 node_update_fields_deep (node
->parent
);
1920 rotate_down (GSequenceNode
*node
,
1925 left
= node
->left
? get_priority (node
->left
) : 0;
1926 right
= node
->right
? get_priority (node
->right
) : 0;
1928 while (priority
< left
|| priority
< right
)
1931 node_rotate (node
->left
);
1933 node_rotate (node
->right
);
1935 left
= node
->left
? get_priority (node
->left
) : 0;
1936 right
= node
->right
? get_priority (node
->right
) : 0;
1941 node_cut (GSequenceNode
*node
)
1943 while (node
->parent
)
1947 node
->left
->parent
= NULL
;
1950 node_update_fields (node
);
1952 rotate_down (node
, get_priority (node
));
1956 node_join (GSequenceNode
*left
,
1957 GSequenceNode
*right
)
1959 GSequenceNode
*fake
= node_new (NULL
);
1961 fake
->left
= find_root (left
);
1962 fake
->right
= find_root (right
);
1963 fake
->left
->parent
= fake
;
1964 fake
->right
->parent
= fake
;
1966 node_update_fields (fake
);
1970 node_free (fake
, NULL
);
1974 node_insert_before (GSequenceNode
*node
,
1977 new->left
= node
->left
;
1979 new->left
->parent
= new;
1984 node_update_fields_deep (new);
1986 while (new->parent
&& get_priority (new) > get_priority (new->parent
))
1989 rotate_down (new, get_priority (new));
1993 node_unlink (GSequenceNode
*node
)
1995 rotate_down (node
, 0);
1997 if (NODE_RIGHT_CHILD (node
))
1998 node
->parent
->right
= NULL
;
1999 else if (NODE_LEFT_CHILD (node
))
2000 node
->parent
->left
= NULL
;
2003 node_update_fields_deep (node
->parent
);
2005 node
->parent
= NULL
;
2009 node_insert_sorted (GSequenceNode
*node
,
2012 GSequenceIterCompareFunc iter_cmp
,
2015 GSequenceNode
*closest
;
2017 closest
= node_find_closest (node
, new, end
, iter_cmp
, cmp_data
);
2021 node_insert_before (closest
, new);