• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
4  *
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.1 of the License, or (at your option) any later version.
9  *
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.
14  *
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/>.
17  */
18 
19 #include "config.h"
20 
21 #include "gsequence.h"
22 
23 #include "gmem.h"
24 #include "gtestutils.h"
25 #include "gslice.h"
26 /**
27  * SECTION:sequence
28  * @title: Sequences
29  * @short_description: scalable lists
30  *
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.
37  *
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.
45  *
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
51  * sequence.
52  *
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.
56  *
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.
64  *
65  * To sort the data, either use g_sequence_insert_sorted() or
66  * g_sequence_insert_sorted_iter() to add data to the #GSequence or, if
67  * you want to add a large amount of data, it is more efficient to call
68  * g_sequence_sort() or g_sequence_sort_iter() after doing unsorted
69  * insertions.
70  */
71 
72 /**
73  * GSequenceIter:
74  *
75  * The #GSequenceIter struct is an opaque data type representing an
76  * iterator pointing into a #GSequence.
77  */
78 
79 /**
80  * GSequenceIterCompareFunc:
81  * @a: a #GSequenceIter
82  * @b: a #GSequenceIter
83  * @data: user data
84  *
85  * A #GSequenceIterCompareFunc is a function used to compare iterators.
86  * It must return zero if the iterators compare equal, a negative value
87  * if @a comes before @b, and a positive value if @b comes before @a.
88  *
89  * Returns: zero if the iterators are equal, a negative value if @a
90  *     comes before @b, and a positive value if @b comes before @a.
91  */
92 
93 typedef struct _GSequenceNode GSequenceNode;
94 
95 /**
96  * GSequence:
97  *
98  * The #GSequence struct is an opaque data type representing a
99  * [sequence][glib-Sequences] data type.
100  */
101 struct _GSequence
102 {
103   GSequenceNode *       end_node;
104   GDestroyNotify        data_destroy_notify;
105   gboolean              access_prohibited;
106 
107   /* The 'real_sequence' is used when temporary sequences are created
108    * to hold nodes that are being rearranged. The 'real_sequence' of such
109    * a temporary sequence points to the sequence that is actually being
110    * manipulated. The only reason we need this is so that when the
111    * sort/sort_changed/search_iter() functions call out to the application
112    * g_sequence_iter_get_sequence() will return the correct sequence.
113    */
114   GSequence *           real_sequence;
115 };
116 
117 struct _GSequenceNode
118 {
119   gint                  n_nodes;
120   GSequenceNode *       parent;
121   GSequenceNode *       left;
122   GSequenceNode *       right;
123   gpointer              data;   /* For the end node, this field points
124                                  * to the sequence
125                                  */
126 };
127 
128 /*
129  * Declaration of GSequenceNode methods
130  */
131 static GSequenceNode *node_new           (gpointer                  data);
132 static GSequenceNode *node_get_first     (GSequenceNode            *node);
133 static GSequenceNode *node_get_last      (GSequenceNode            *node);
134 static GSequenceNode *node_get_prev      (GSequenceNode            *node);
135 static GSequenceNode *node_get_next      (GSequenceNode            *node);
136 static gint           node_get_pos       (GSequenceNode            *node);
137 static GSequenceNode *node_get_by_pos    (GSequenceNode            *node,
138                                           gint                      pos);
139 static GSequenceNode *node_find          (GSequenceNode            *haystack,
140                                           GSequenceNode            *needle,
141                                           GSequenceNode            *end,
142                                           GSequenceIterCompareFunc  cmp,
143                                           gpointer                  user_data);
144 static GSequenceNode *node_find_closest  (GSequenceNode            *haystack,
145                                           GSequenceNode            *needle,
146                                           GSequenceNode            *end,
147                                           GSequenceIterCompareFunc  cmp,
148                                           gpointer                  user_data);
149 static gint           node_get_length    (GSequenceNode            *node);
150 static void           node_free          (GSequenceNode            *node,
151                                           GSequence                *seq);
152 static void           node_cut           (GSequenceNode            *split);
153 static void           node_insert_before (GSequenceNode            *node,
154                                           GSequenceNode            *new);
155 static void           node_unlink        (GSequenceNode            *node);
156 static void           node_join          (GSequenceNode            *left,
157                                           GSequenceNode            *right);
158 static void           node_insert_sorted (GSequenceNode            *node,
159                                           GSequenceNode            *new,
160                                           GSequenceNode            *end,
161                                           GSequenceIterCompareFunc  cmp_func,
162                                           gpointer                  cmp_data);
163 
164 
165 /*
166  * Various helper functions
167  */
168 static void
check_seq_access(GSequence * seq)169 check_seq_access (GSequence *seq)
170 {
171   if (G_UNLIKELY (seq->access_prohibited))
172     {
173       g_warning ("Accessing a sequence while it is "
174                  "being sorted or searched is not allowed");
175     }
176 }
177 
178 static GSequence *
get_sequence(GSequenceNode * node)179 get_sequence (GSequenceNode *node)
180 {
181   return (GSequence *)node_get_last (node)->data;
182 }
183 
184 static gboolean
seq_is_end(GSequence * seq,GSequenceIter * iter)185 seq_is_end (GSequence     *seq,
186             GSequenceIter *iter)
187 {
188   return seq->end_node == iter;
189 }
190 
191 static gboolean
is_end(GSequenceIter * iter)192 is_end (GSequenceIter *iter)
193 {
194   GSequenceIter *parent = iter->parent;
195 
196   if (iter->right)
197     return FALSE;
198 
199   if (!parent)
200     return TRUE;
201 
202   while (parent->right == iter)
203     {
204       iter = parent;
205       parent = iter->parent;
206 
207       if (!parent)
208         return TRUE;
209     }
210 
211   return FALSE;
212 }
213 
214 typedef struct
215 {
216   GCompareDataFunc  cmp_func;
217   gpointer          cmp_data;
218   GSequenceNode    *end_node;
219 } SortInfo;
220 
221 /* This function compares two iters using a normal compare
222  * function and user_data passed in in a SortInfo struct
223  */
224 static gint
iter_compare(GSequenceIter * node1,GSequenceIter * node2,gpointer data)225 iter_compare (GSequenceIter *node1,
226               GSequenceIter *node2,
227               gpointer       data)
228 {
229   const SortInfo *info = data;
230   gint retval;
231 
232   if (node1 == info->end_node)
233     return 1;
234 
235   if (node2 == info->end_node)
236     return -1;
237 
238   retval = info->cmp_func (node1->data, node2->data, info->cmp_data);
239 
240   return retval;
241 }
242 
243 /*
244  * Public API
245  */
246 
247 /**
248  * g_sequence_new:
249  * @data_destroy: (nullable): a #GDestroyNotify function, or %NULL
250  *
251  * Creates a new GSequence. The @data_destroy function, if non-%NULL will
252  * be called on all items when the sequence is destroyed and on items that
253  * are removed from the sequence.
254  *
255  * Returns: (transfer full): a new #GSequence
256  *
257  * Since: 2.14
258  **/
259 GSequence *
g_sequence_new(GDestroyNotify data_destroy)260 g_sequence_new (GDestroyNotify data_destroy)
261 {
262   GSequence *seq = g_new (GSequence, 1);
263   seq->data_destroy_notify = data_destroy;
264 
265   seq->end_node = node_new (seq);
266 
267   seq->access_prohibited = FALSE;
268 
269   seq->real_sequence = seq;
270 
271   return seq;
272 }
273 
274 /**
275  * g_sequence_free:
276  * @seq: a #GSequence
277  *
278  * Frees the memory allocated for @seq. If @seq has a data destroy
279  * function associated with it, that function is called on all items
280  * in @seq.
281  *
282  * Since: 2.14
283  */
284 void
g_sequence_free(GSequence * seq)285 g_sequence_free (GSequence *seq)
286 {
287   g_return_if_fail (seq != NULL);
288 
289   check_seq_access (seq);
290 
291   node_free (seq->end_node, seq);
292 
293   g_free (seq);
294 }
295 
296 /**
297  * g_sequence_foreach_range:
298  * @begin: a #GSequenceIter
299  * @end: a #GSequenceIter
300  * @func: a #GFunc
301  * @user_data: user data passed to @func
302  *
303  * Calls @func for each item in the range (@begin, @end) passing
304  * @user_data to the function. @func must not modify the sequence
305  * itself.
306  *
307  * Since: 2.14
308  */
309 void
g_sequence_foreach_range(GSequenceIter * begin,GSequenceIter * end,GFunc func,gpointer user_data)310 g_sequence_foreach_range (GSequenceIter *begin,
311                           GSequenceIter *end,
312                           GFunc          func,
313                           gpointer       user_data)
314 {
315   GSequence *seq;
316   GSequenceIter *iter;
317 
318   g_return_if_fail (func != NULL);
319   g_return_if_fail (begin != NULL);
320   g_return_if_fail (end != NULL);
321 
322   seq = get_sequence (begin);
323 
324   seq->access_prohibited = TRUE;
325 
326   iter = begin;
327   while (iter != end)
328     {
329       GSequenceIter *next = node_get_next (iter);
330 
331       func (iter->data, user_data);
332 
333       iter = next;
334     }
335 
336   seq->access_prohibited = FALSE;
337 }
338 
339 /**
340  * g_sequence_foreach:
341  * @seq: a #GSequence
342  * @func: the function to call for each item in @seq
343  * @user_data: user data passed to @func
344  *
345  * Calls @func for each item in the sequence passing @user_data
346  * to the function. @func must not modify the sequence itself.
347  *
348  * Since: 2.14
349  */
350 void
g_sequence_foreach(GSequence * seq,GFunc func,gpointer user_data)351 g_sequence_foreach (GSequence *seq,
352                     GFunc      func,
353                     gpointer   user_data)
354 {
355   GSequenceIter *begin, *end;
356 
357   check_seq_access (seq);
358 
359   begin = g_sequence_get_begin_iter (seq);
360   end   = g_sequence_get_end_iter (seq);
361 
362   g_sequence_foreach_range (begin, end, func, user_data);
363 }
364 
365 /**
366  * g_sequence_range_get_midpoint:
367  * @begin: a #GSequenceIter
368  * @end: a #GSequenceIter
369  *
370  * Finds an iterator somewhere in the range (@begin, @end). This
371  * iterator will be close to the middle of the range, but is not
372  * guaranteed to be exactly in the middle.
373  *
374  * The @begin and @end iterators must both point to the same sequence
375  * and @begin must come before or be equal to @end in the sequence.
376  *
377  * Returns: (transfer none): a #GSequenceIter pointing somewhere in the
378  *    (@begin, @end) range
379  *
380  * Since: 2.14
381  */
382 GSequenceIter *
g_sequence_range_get_midpoint(GSequenceIter * begin,GSequenceIter * end)383 g_sequence_range_get_midpoint (GSequenceIter *begin,
384                                GSequenceIter *end)
385 {
386   int begin_pos, end_pos, mid_pos;
387 
388   g_return_val_if_fail (begin != NULL, NULL);
389   g_return_val_if_fail (end != NULL, NULL);
390   g_return_val_if_fail (get_sequence (begin) == get_sequence (end), NULL);
391 
392   begin_pos = node_get_pos (begin);
393   end_pos = node_get_pos (end);
394 
395   g_return_val_if_fail (end_pos >= begin_pos, NULL);
396 
397   mid_pos = begin_pos + (end_pos - begin_pos) / 2;
398 
399   return node_get_by_pos (begin, mid_pos);
400 }
401 
402 /**
403  * g_sequence_iter_compare:
404  * @a: a #GSequenceIter
405  * @b: a #GSequenceIter
406  *
407  * Returns a negative number if @a comes before @b, 0 if they are equal,
408  * and a positive number if @a comes after @b.
409  *
410  * The @a and @b iterators must point into the same sequence.
411  *
412  * Returns: a negative number if @a comes before @b, 0 if they are
413  *     equal, and a positive number if @a comes after @b
414  *
415  * Since: 2.14
416  */
417 gint
g_sequence_iter_compare(GSequenceIter * a,GSequenceIter * b)418 g_sequence_iter_compare (GSequenceIter *a,
419                          GSequenceIter *b)
420 {
421   gint a_pos, b_pos;
422   GSequence *seq_a, *seq_b;
423 
424   g_return_val_if_fail (a != NULL, 0);
425   g_return_val_if_fail (b != NULL, 0);
426 
427   seq_a = get_sequence (a);
428   seq_b = get_sequence (b);
429   g_return_val_if_fail (seq_a == seq_b, 0);
430 
431   check_seq_access (seq_a);
432   check_seq_access (seq_b);
433 
434   a_pos = node_get_pos (a);
435   b_pos = node_get_pos (b);
436 
437   if (a_pos == b_pos)
438     return 0;
439   else if (a_pos > b_pos)
440     return 1;
441   else
442     return -1;
443 }
444 
445 /**
446  * g_sequence_append:
447  * @seq: a #GSequence
448  * @data: the data for the new item
449  *
450  * Adds a new item to the end of @seq.
451  *
452  * Returns: (transfer none): an iterator pointing to the new item
453  *
454  * Since: 2.14
455  */
456 GSequenceIter *
g_sequence_append(GSequence * seq,gpointer data)457 g_sequence_append (GSequence *seq,
458                    gpointer   data)
459 {
460   GSequenceNode *node;
461 
462   g_return_val_if_fail (seq != NULL, NULL);
463 
464   check_seq_access (seq);
465 
466   node = node_new (data);
467   node_insert_before (seq->end_node, node);
468 
469   return node;
470 }
471 
472 /**
473  * g_sequence_prepend:
474  * @seq: a #GSequence
475  * @data: the data for the new item
476  *
477  * Adds a new item to the front of @seq
478  *
479  * Returns: (transfer none): an iterator pointing to the new item
480  *
481  * Since: 2.14
482  */
483 GSequenceIter *
g_sequence_prepend(GSequence * seq,gpointer data)484 g_sequence_prepend (GSequence *seq,
485                     gpointer   data)
486 {
487   GSequenceNode *node, *first;
488 
489   g_return_val_if_fail (seq != NULL, NULL);
490 
491   check_seq_access (seq);
492 
493   node = node_new (data);
494   first = node_get_first (seq->end_node);
495 
496   node_insert_before (first, node);
497 
498   return node;
499 }
500 
501 /**
502  * g_sequence_insert_before:
503  * @iter: a #GSequenceIter
504  * @data: the data for the new item
505  *
506  * Inserts a new item just before the item pointed to by @iter.
507  *
508  * Returns: (transfer none): an iterator pointing to the new item
509  *
510  * Since: 2.14
511  */
512 GSequenceIter *
g_sequence_insert_before(GSequenceIter * iter,gpointer data)513 g_sequence_insert_before (GSequenceIter *iter,
514                           gpointer       data)
515 {
516   GSequence *seq;
517   GSequenceNode *node;
518 
519   g_return_val_if_fail (iter != NULL, NULL);
520 
521   seq = get_sequence (iter);
522   check_seq_access (seq);
523 
524   node = node_new (data);
525 
526   node_insert_before (iter, node);
527 
528   return node;
529 }
530 
531 /**
532  * g_sequence_remove:
533  * @iter: a #GSequenceIter
534  *
535  * Removes the item pointed to by @iter. It is an error to pass the
536  * end iterator to this function.
537  *
538  * If the sequence has a data destroy function associated with it, this
539  * function is called on the data for the removed item.
540  *
541  * Since: 2.14
542  */
543 void
g_sequence_remove(GSequenceIter * iter)544 g_sequence_remove (GSequenceIter *iter)
545 {
546   GSequence *seq;
547 
548   g_return_if_fail (iter != NULL);
549 
550   seq = get_sequence (iter);
551   g_return_if_fail (!seq_is_end (seq, iter));
552 
553   check_seq_access (seq);
554 
555   node_unlink (iter);
556   node_free (iter, seq);
557 }
558 
559 /**
560  * g_sequence_remove_range:
561  * @begin: a #GSequenceIter
562  * @end: a #GSequenceIter
563  *
564  * Removes all items in the (@begin, @end) range.
565  *
566  * If the sequence has a data destroy function associated with it, this
567  * function is called on the data for the removed items.
568  *
569  * Since: 2.14
570  */
571 void
g_sequence_remove_range(GSequenceIter * begin,GSequenceIter * end)572 g_sequence_remove_range (GSequenceIter *begin,
573                          GSequenceIter *end)
574 {
575   GSequence *seq_begin, *seq_end;
576 
577   seq_begin = get_sequence (begin);
578   seq_end = get_sequence (end);
579   g_return_if_fail (seq_begin == seq_end);
580   /* check_seq_access() calls are done by g_sequence_move_range() */
581 
582   g_sequence_move_range (NULL, begin, end);
583 }
584 
585 /**
586  * g_sequence_move_range:
587  * @dest: a #GSequenceIter
588  * @begin: a #GSequenceIter
589  * @end: a #GSequenceIter
590  *
591  * Inserts the (@begin, @end) range at the destination pointed to by @dest.
592  * The @begin and @end iters must point into the same sequence. It is
593  * allowed for @dest to point to a different sequence than the one pointed
594  * into by @begin and @end.
595  *
596  * If @dest is %NULL, the range indicated by @begin and @end is
597  * removed from the sequence. If @dest points to a place within
598  * the (@begin, @end) range, the range does not move.
599  *
600  * Since: 2.14
601  */
602 void
g_sequence_move_range(GSequenceIter * dest,GSequenceIter * begin,GSequenceIter * end)603 g_sequence_move_range (GSequenceIter *dest,
604                        GSequenceIter *begin,
605                        GSequenceIter *end)
606 {
607   GSequence *src_seq, *end_seq, *dest_seq;
608   GSequenceNode *first;
609 
610   g_return_if_fail (begin != NULL);
611   g_return_if_fail (end != NULL);
612 
613   src_seq = get_sequence (begin);
614   check_seq_access (src_seq);
615 
616   end_seq = get_sequence (end);
617   check_seq_access (end_seq);
618 
619   if (dest)
620     {
621       dest_seq = get_sequence (dest);
622       check_seq_access (dest_seq);
623     }
624 
625   g_return_if_fail (src_seq == end_seq);
626 
627   /* Dest points to begin or end? */
628   if (dest == begin || dest == end)
629     return;
630 
631   /* begin comes after end? */
632   if (g_sequence_iter_compare (begin, end) >= 0)
633     return;
634 
635   /* dest points somewhere in the (begin, end) range? */
636   if (dest && dest_seq == src_seq &&
637       g_sequence_iter_compare (dest, begin) > 0 &&
638       g_sequence_iter_compare (dest, end) < 0)
639     {
640       return;
641     }
642 
643   first = node_get_first (begin);
644 
645   node_cut (begin);
646 
647   node_cut (end);
648 
649   if (first != begin)
650     node_join (first, end);
651 
652   if (dest)
653     {
654       first = node_get_first (dest);
655 
656       node_cut (dest);
657 
658       node_join (begin, dest);
659 
660       if (dest != first)
661         node_join (first, begin);
662     }
663   else
664     {
665       node_free (begin, src_seq);
666     }
667 }
668 
669 /**
670  * g_sequence_sort:
671  * @seq: a #GSequence
672  * @cmp_func: the function used to sort the sequence
673  * @cmp_data: user data passed to @cmp_func
674  *
675  * Sorts @seq using @cmp_func.
676  *
677  * @cmp_func is passed two items of @seq and should
678  * return 0 if they are equal, a negative value if the
679  * first comes before the second, and a positive value
680  * if the second comes before the first.
681  *
682  * Since: 2.14
683  */
684 void
g_sequence_sort(GSequence * seq,GCompareDataFunc cmp_func,gpointer cmp_data)685 g_sequence_sort (GSequence        *seq,
686                  GCompareDataFunc  cmp_func,
687                  gpointer          cmp_data)
688 {
689   SortInfo info;
690 
691   info.cmp_func = cmp_func;
692   info.cmp_data = cmp_data;
693   info.end_node = seq->end_node;
694 
695   check_seq_access (seq);
696 
697   g_sequence_sort_iter (seq, iter_compare, &info);
698 }
699 
700 /**
701  * g_sequence_insert_sorted:
702  * @seq: a #GSequence
703  * @data: the data to insert
704  * @cmp_func: the function used to compare items in the sequence
705  * @cmp_data: user data passed to @cmp_func.
706  *
707  * Inserts @data into @seq using @cmp_func to determine the new
708  * position. The sequence must already be sorted according to @cmp_func;
709  * otherwise the new position of @data is undefined.
710  *
711  * @cmp_func is called with two items of the @seq, and @cmp_data.
712  * It should return 0 if the items are equal, a negative value
713  * if the first item comes before the second, and a positive value
714  * if the second item comes before the first.
715  *
716  * Note that when adding a large amount of data to a #GSequence,
717  * it is more efficient to do unsorted insertions and then call
718  * g_sequence_sort() or g_sequence_sort_iter().
719  *
720  * Returns: (transfer none): a #GSequenceIter pointing to the new item.
721  *
722  * Since: 2.14
723  */
724 GSequenceIter *
g_sequence_insert_sorted(GSequence * seq,gpointer data,GCompareDataFunc cmp_func,gpointer cmp_data)725 g_sequence_insert_sorted (GSequence        *seq,
726                           gpointer          data,
727                           GCompareDataFunc  cmp_func,
728                           gpointer          cmp_data)
729 {
730   SortInfo info;
731 
732   g_return_val_if_fail (seq != NULL, NULL);
733   g_return_val_if_fail (cmp_func != NULL, NULL);
734 
735   info.cmp_func = cmp_func;
736   info.cmp_data = cmp_data;
737   info.end_node = seq->end_node;
738   check_seq_access (seq);
739 
740   return g_sequence_insert_sorted_iter (seq, data, iter_compare, &info);
741 }
742 
743 /**
744  * g_sequence_sort_changed:
745  * @iter: A #GSequenceIter
746  * @cmp_func: the function used to compare items in the sequence
747  * @cmp_data: user data passed to @cmp_func.
748  *
749  * Moves the data pointed to by @iter to a new position as indicated by
750  * @cmp_func. This
751  * function should be called for items in a sequence already sorted according
752  * to @cmp_func whenever some aspect of an item changes so that @cmp_func
753  * may return different values for that item.
754  *
755  * @cmp_func is called with two items of the @seq, and @cmp_data.
756  * It should return 0 if the items are equal, a negative value if
757  * the first item comes before the second, and a positive value if
758  * the second item comes before the first.
759  *
760  * Since: 2.14
761  */
762 void
g_sequence_sort_changed(GSequenceIter * iter,GCompareDataFunc cmp_func,gpointer cmp_data)763 g_sequence_sort_changed (GSequenceIter    *iter,
764                          GCompareDataFunc  cmp_func,
765                          gpointer          cmp_data)
766 {
767   GSequence *seq;
768   SortInfo info;
769 
770   g_return_if_fail (iter != NULL);
771 
772   seq = get_sequence (iter);
773   /* check_seq_access() call is done by g_sequence_sort_changed_iter() */
774   g_return_if_fail (!seq_is_end (seq, iter));
775 
776   info.cmp_func = cmp_func;
777   info.cmp_data = cmp_data;
778   info.end_node = seq->end_node;
779 
780   g_sequence_sort_changed_iter (iter, iter_compare, &info);
781 }
782 
783 /**
784  * g_sequence_search:
785  * @seq: a #GSequence
786  * @data: data for the new item
787  * @cmp_func: the function used to compare items in the sequence
788  * @cmp_data: user data passed to @cmp_func
789  *
790  * Returns an iterator pointing to the position where @data would
791  * be inserted according to @cmp_func and @cmp_data.
792  *
793  * @cmp_func is called with two items of the @seq, and @cmp_data.
794  * It should return 0 if the items are equal, a negative value if
795  * the first item comes before the second, and a positive value if
796  * the second item comes before the first.
797  *
798  * If you are simply searching for an existing element of the sequence,
799  * consider using g_sequence_lookup().
800  *
801  * This function will fail if the data contained in the sequence is
802  * unsorted.
803  *
804  * Returns: (transfer none): an #GSequenceIter pointing to the position where @data
805  *     would have been inserted according to @cmp_func and @cmp_data
806  *
807  * Since: 2.14
808  */
809 GSequenceIter *
g_sequence_search(GSequence * seq,gpointer data,GCompareDataFunc cmp_func,gpointer cmp_data)810 g_sequence_search (GSequence        *seq,
811                    gpointer          data,
812                    GCompareDataFunc  cmp_func,
813                    gpointer          cmp_data)
814 {
815   SortInfo info;
816 
817   g_return_val_if_fail (seq != NULL, NULL);
818 
819   info.cmp_func = cmp_func;
820   info.cmp_data = cmp_data;
821   info.end_node = seq->end_node;
822   check_seq_access (seq);
823 
824   return g_sequence_search_iter (seq, data, iter_compare, &info);
825 }
826 
827 /**
828  * g_sequence_lookup:
829  * @seq: a #GSequence
830  * @data: data to look up
831  * @cmp_func: the function used to compare items in the sequence
832  * @cmp_data: user data passed to @cmp_func
833  *
834  * Returns an iterator pointing to the position of the first item found
835  * equal to @data according to @cmp_func and @cmp_data. If more than one
836  * item is equal, it is not guaranteed that it is the first which is
837  * returned. In that case, you can use g_sequence_iter_next() and
838  * g_sequence_iter_prev() to get others.
839  *
840  * @cmp_func is called with two items of the @seq, and @cmp_data.
841  * It should return 0 if the items are equal, a negative value if
842  * the first item comes before the second, and a positive value if
843  * the second item comes before the first.
844  *
845  * This function will fail if the data contained in the sequence is
846  * unsorted.
847  *
848  * Returns: (transfer none) (nullable): an #GSequenceIter pointing to the position of the
849  *     first item found equal to @data according to @cmp_func and
850  *     @cmp_data, or %NULL if no such item exists
851  *
852  * Since: 2.28
853  */
854 GSequenceIter *
g_sequence_lookup(GSequence * seq,gpointer data,GCompareDataFunc cmp_func,gpointer cmp_data)855 g_sequence_lookup (GSequence        *seq,
856                    gpointer          data,
857                    GCompareDataFunc  cmp_func,
858                    gpointer          cmp_data)
859 {
860   SortInfo info;
861 
862   g_return_val_if_fail (seq != NULL, NULL);
863 
864   info.cmp_func = cmp_func;
865   info.cmp_data = cmp_data;
866   info.end_node = seq->end_node;
867   check_seq_access (seq);
868 
869   return g_sequence_lookup_iter (seq, data, iter_compare, &info);
870 }
871 
872 /**
873  * g_sequence_sort_iter:
874  * @seq: a #GSequence
875  * @cmp_func: the function used to compare iterators in the sequence
876  * @cmp_data: user data passed to @cmp_func
877  *
878  * Like g_sequence_sort(), but uses a #GSequenceIterCompareFunc instead
879  * of a #GCompareDataFunc as the compare function
880  *
881  * @cmp_func is called with two iterators pointing into @seq. It should
882  * return 0 if the iterators are equal, a negative value if the first
883  * iterator comes before the second, and a positive value if the second
884  * iterator comes before the first.
885  *
886  * Since: 2.14
887  */
888 void
g_sequence_sort_iter(GSequence * seq,GSequenceIterCompareFunc cmp_func,gpointer cmp_data)889 g_sequence_sort_iter (GSequence                *seq,
890                       GSequenceIterCompareFunc  cmp_func,
891                       gpointer                  cmp_data)
892 {
893   GSequence *tmp;
894   GSequenceNode *begin, *end;
895 
896   g_return_if_fail (seq != NULL);
897   g_return_if_fail (cmp_func != NULL);
898 
899   check_seq_access (seq);
900 
901   begin = g_sequence_get_begin_iter (seq);
902   end   = g_sequence_get_end_iter (seq);
903 
904   tmp = g_sequence_new (NULL);
905   tmp->real_sequence = seq;
906 
907   g_sequence_move_range (g_sequence_get_begin_iter (tmp), begin, end);
908 
909   seq->access_prohibited = TRUE;
910   tmp->access_prohibited = TRUE;
911 
912   while (!g_sequence_is_empty (tmp))
913     {
914       GSequenceNode *node = g_sequence_get_begin_iter (tmp);
915 
916       node_insert_sorted (seq->end_node, node, seq->end_node,
917                           cmp_func, cmp_data);
918     }
919 
920   tmp->access_prohibited = FALSE;
921   seq->access_prohibited = FALSE;
922 
923   g_sequence_free (tmp);
924 }
925 
926 /**
927  * g_sequence_sort_changed_iter:
928  * @iter: a #GSequenceIter
929  * @iter_cmp: the function used to compare iterators in the sequence
930  * @cmp_data: user data passed to @cmp_func
931  *
932  * Like g_sequence_sort_changed(), but uses
933  * a #GSequenceIterCompareFunc instead of a #GCompareDataFunc as
934  * the compare function.
935  *
936  * @iter_cmp is called with two iterators pointing into the #GSequence that
937  * @iter points into. It should
938  * return 0 if the iterators are equal, a negative value if the first
939  * iterator comes before the second, and a positive value if the second
940  * iterator comes before the first.
941  *
942  * Since: 2.14
943  */
944 void
g_sequence_sort_changed_iter(GSequenceIter * iter,GSequenceIterCompareFunc iter_cmp,gpointer cmp_data)945 g_sequence_sort_changed_iter (GSequenceIter            *iter,
946                               GSequenceIterCompareFunc  iter_cmp,
947                               gpointer                  cmp_data)
948 {
949   GSequence *seq, *tmp_seq;
950   GSequenceIter *next, *prev;
951 
952   g_return_if_fail (iter != NULL);
953   g_return_if_fail (iter_cmp != NULL);
954 
955   seq = get_sequence (iter);
956   g_return_if_fail (!seq_is_end (seq, iter));
957 
958   check_seq_access (seq);
959 
960   /* If one of the neighbours is equal to iter, then
961    * don't move it. This ensures that sort_changed() is
962    * a stable operation.
963    */
964 
965   next = node_get_next (iter);
966   prev = node_get_prev (iter);
967 
968   if (prev != iter && iter_cmp (prev, iter, cmp_data) == 0)
969     return;
970 
971   if (!is_end (next) && iter_cmp (next, iter, cmp_data) == 0)
972     return;
973 
974   seq->access_prohibited = TRUE;
975 
976   tmp_seq = g_sequence_new (NULL);
977   tmp_seq->real_sequence = seq;
978 
979   node_unlink (iter);
980   node_insert_before (tmp_seq->end_node, iter);
981 
982   node_insert_sorted (seq->end_node, iter, seq->end_node,
983                       iter_cmp, cmp_data);
984 
985   g_sequence_free (tmp_seq);
986 
987   seq->access_prohibited = FALSE;
988 }
989 
990 /**
991  * g_sequence_insert_sorted_iter:
992  * @seq: a #GSequence
993  * @data: data for the new item
994  * @iter_cmp: the function used to compare iterators in the sequence
995  * @cmp_data: user data passed to @iter_cmp
996  *
997  * Like g_sequence_insert_sorted(), but uses
998  * a #GSequenceIterCompareFunc instead of a #GCompareDataFunc as
999  * the compare function.
1000  *
1001  * @iter_cmp is called with two iterators pointing into @seq.
1002  * It should return 0 if the iterators are equal, a negative
1003  * value if the first iterator comes before the second, and a
1004  * positive value if the second iterator comes before the first.
1005  *
1006  * Note that when adding a large amount of data to a #GSequence,
1007  * it is more efficient to do unsorted insertions and then call
1008  * g_sequence_sort() or g_sequence_sort_iter().
1009  *
1010  * Returns: (transfer none): a #GSequenceIter pointing to the new item
1011  *
1012  * Since: 2.14
1013  */
1014 GSequenceIter *
g_sequence_insert_sorted_iter(GSequence * seq,gpointer data,GSequenceIterCompareFunc iter_cmp,gpointer cmp_data)1015 g_sequence_insert_sorted_iter (GSequence                *seq,
1016                                gpointer                  data,
1017                                GSequenceIterCompareFunc  iter_cmp,
1018                                gpointer                  cmp_data)
1019 {
1020   GSequenceNode *new_node;
1021   GSequence *tmp_seq;
1022 
1023   g_return_val_if_fail (seq != NULL, NULL);
1024   g_return_val_if_fail (iter_cmp != NULL, NULL);
1025 
1026   check_seq_access (seq);
1027 
1028   seq->access_prohibited = TRUE;
1029 
1030   /* Create a new temporary sequence and put the new node into
1031    * that. The reason for this is that the user compare function
1032    * will be called with the new node, and if it dereferences,
1033    * "is_end" will be called on it. But that will crash if the
1034    * node is not actually in a sequence.
1035    *
1036    * node_insert_sorted() makes sure the node is unlinked before
1037    * it is inserted.
1038    *
1039    * The reason we need the "iter" versions at all is that that
1040    * is the only kind of compare functions GtkTreeView can use.
1041    */
1042   tmp_seq = g_sequence_new (NULL);
1043   tmp_seq->real_sequence = seq;
1044 
1045   new_node = g_sequence_append (tmp_seq, data);
1046 
1047   node_insert_sorted (seq->end_node, new_node,
1048                       seq->end_node, iter_cmp, cmp_data);
1049 
1050   g_sequence_free (tmp_seq);
1051 
1052   seq->access_prohibited = FALSE;
1053 
1054   return new_node;
1055 }
1056 
1057 /**
1058  * g_sequence_search_iter:
1059  * @seq: a #GSequence
1060  * @data: data for the new item
1061  * @iter_cmp: the function used to compare iterators in the sequence
1062  * @cmp_data: user data passed to @iter_cmp
1063  *
1064  * Like g_sequence_search(), but uses a #GSequenceIterCompareFunc
1065  * instead of a #GCompareDataFunc as the compare function.
1066  *
1067  * @iter_cmp is called with two iterators pointing into @seq.
1068  * It should return 0 if the iterators are equal, a negative value
1069  * if the first iterator comes before the second, and a positive
1070  * value if the second iterator comes before the first.
1071  *
1072  * If you are simply searching for an existing element of the sequence,
1073  * consider using g_sequence_lookup_iter().
1074  *
1075  * This function will fail if the data contained in the sequence is
1076  * unsorted.
1077  *
1078  * Returns: (transfer none): a #GSequenceIter pointing to the position in @seq
1079  *     where @data would have been inserted according to @iter_cmp
1080  *     and @cmp_data
1081  *
1082  * Since: 2.14
1083  */
1084 GSequenceIter *
g_sequence_search_iter(GSequence * seq,gpointer data,GSequenceIterCompareFunc iter_cmp,gpointer cmp_data)1085 g_sequence_search_iter (GSequence                *seq,
1086                         gpointer                  data,
1087                         GSequenceIterCompareFunc  iter_cmp,
1088                         gpointer                  cmp_data)
1089 {
1090   GSequenceNode *node;
1091   GSequenceNode *dummy;
1092   GSequence *tmp_seq;
1093 
1094   g_return_val_if_fail (seq != NULL, NULL);
1095 
1096   check_seq_access (seq);
1097 
1098   seq->access_prohibited = TRUE;
1099 
1100   tmp_seq = g_sequence_new (NULL);
1101   tmp_seq->real_sequence = seq;
1102 
1103   dummy = g_sequence_append (tmp_seq, data);
1104 
1105   node = node_find_closest (seq->end_node, dummy,
1106                             seq->end_node, iter_cmp, cmp_data);
1107 
1108   g_sequence_free (tmp_seq);
1109 
1110   seq->access_prohibited = FALSE;
1111 
1112   return node;
1113 }
1114 
1115 /**
1116  * g_sequence_lookup_iter:
1117  * @seq: a #GSequence
1118  * @data: data to look up
1119  * @iter_cmp: the function used to compare iterators in the sequence
1120  * @cmp_data: user data passed to @iter_cmp
1121  *
1122  * Like g_sequence_lookup(), but uses a #GSequenceIterCompareFunc
1123  * instead of a #GCompareDataFunc as the compare function.
1124  *
1125  * @iter_cmp is called with two iterators pointing into @seq.
1126  * It should return 0 if the iterators are equal, a negative value
1127  * if the first iterator comes before the second, and a positive
1128  * value if the second iterator comes before the first.
1129  *
1130  * This function will fail if the data contained in the sequence is
1131  * unsorted.
1132  *
1133  * Returns: (transfer none) (nullable): an #GSequenceIter pointing to the position of
1134  *     the first item found equal to @data according to @iter_cmp
1135  *     and @cmp_data, or %NULL if no such item exists
1136  *
1137  * Since: 2.28
1138  */
1139 GSequenceIter *
g_sequence_lookup_iter(GSequence * seq,gpointer data,GSequenceIterCompareFunc iter_cmp,gpointer cmp_data)1140 g_sequence_lookup_iter (GSequence                *seq,
1141                         gpointer                  data,
1142                         GSequenceIterCompareFunc  iter_cmp,
1143                         gpointer                  cmp_data)
1144 {
1145   GSequenceNode *node;
1146   GSequenceNode *dummy;
1147   GSequence *tmp_seq;
1148 
1149   g_return_val_if_fail (seq != NULL, NULL);
1150 
1151   check_seq_access (seq);
1152 
1153   seq->access_prohibited = TRUE;
1154 
1155   tmp_seq = g_sequence_new (NULL);
1156   tmp_seq->real_sequence = seq;
1157 
1158   dummy = g_sequence_append (tmp_seq, data);
1159 
1160   node = node_find (seq->end_node, dummy,
1161                     seq->end_node, iter_cmp, cmp_data);
1162 
1163   g_sequence_free (tmp_seq);
1164 
1165   seq->access_prohibited = FALSE;
1166 
1167   return node;
1168 }
1169 
1170 /**
1171  * g_sequence_iter_get_sequence:
1172  * @iter: a #GSequenceIter
1173  *
1174  * Returns the #GSequence that @iter points into.
1175  *
1176  * Returns: (transfer none): the #GSequence that @iter points into
1177  *
1178  * Since: 2.14
1179  */
1180 GSequence *
g_sequence_iter_get_sequence(GSequenceIter * iter)1181 g_sequence_iter_get_sequence (GSequenceIter *iter)
1182 {
1183   GSequence *seq;
1184 
1185   g_return_val_if_fail (iter != NULL, NULL);
1186 
1187   seq = get_sequence (iter);
1188 
1189   /* For temporary sequences, this points to the sequence that
1190    * is actually being manipulated
1191    */
1192   return seq->real_sequence;
1193 }
1194 
1195 /**
1196  * g_sequence_get:
1197  * @iter: a #GSequenceIter
1198  *
1199  * Returns the data that @iter points to.
1200  *
1201  * Returns: (transfer none): the data that @iter points to
1202  *
1203  * Since: 2.14
1204  */
1205 gpointer
g_sequence_get(GSequenceIter * iter)1206 g_sequence_get (GSequenceIter *iter)
1207 {
1208   g_return_val_if_fail (iter != NULL, NULL);
1209   g_return_val_if_fail (!is_end (iter), NULL);
1210 
1211   return iter->data;
1212 }
1213 
1214 /**
1215  * g_sequence_set:
1216  * @iter: a #GSequenceIter
1217  * @data: new data for the item
1218  *
1219  * Changes the data for the item pointed to by @iter to be @data. If
1220  * the sequence has a data destroy function associated with it, that
1221  * function is called on the existing data that @iter pointed to.
1222  *
1223  * Since: 2.14
1224  */
1225 void
g_sequence_set(GSequenceIter * iter,gpointer data)1226 g_sequence_set (GSequenceIter *iter,
1227                 gpointer       data)
1228 {
1229   GSequence *seq;
1230 
1231   g_return_if_fail (iter != NULL);
1232 
1233   seq = get_sequence (iter);
1234   g_return_if_fail (!seq_is_end (seq, iter));
1235 
1236   /* If @data is identical to iter->data, it is destroyed
1237    * here. This will work right in case of ref-counted objects. Also
1238    * it is similar to what ghashtables do.
1239    *
1240    * For non-refcounted data it's a little less convenient, but
1241    * code relying on self-setting not destroying would be
1242    * pretty dubious anyway ...
1243    */
1244 
1245   if (seq->data_destroy_notify)
1246     seq->data_destroy_notify (iter->data);
1247 
1248   iter->data = data;
1249 }
1250 
1251 /**
1252  * g_sequence_get_length:
1253  * @seq: a #GSequence
1254  *
1255  * Returns the length of @seq. Note that this method is O(h) where `h' is the
1256  * height of the tree. It is thus more efficient to use g_sequence_is_empty()
1257  * when comparing the length to zero.
1258  *
1259  * Returns: the length of @seq
1260  *
1261  * Since: 2.14
1262  */
1263 gint
g_sequence_get_length(GSequence * seq)1264 g_sequence_get_length (GSequence *seq)
1265 {
1266   return node_get_length (seq->end_node) - 1;
1267 }
1268 
1269 /**
1270  * g_sequence_is_empty:
1271  * @seq: a #GSequence
1272  *
1273  * Returns %TRUE if the sequence contains zero items.
1274  *
1275  * This function is functionally identical to checking the result of
1276  * g_sequence_get_length() being equal to zero. However this function is
1277  * implemented in O(1) running time.
1278  *
1279  * Returns: %TRUE if the sequence is empty, otherwise %FALSE.
1280  *
1281  * Since: 2.48
1282  */
1283 gboolean
g_sequence_is_empty(GSequence * seq)1284 g_sequence_is_empty (GSequence *seq)
1285 {
1286   return (seq->end_node->parent == NULL) && (seq->end_node->left == NULL);
1287 }
1288 
1289 /**
1290  * g_sequence_get_end_iter:
1291  * @seq: a #GSequence
1292  *
1293  * Returns the end iterator for @seg
1294  *
1295  * Returns: (transfer none): the end iterator for @seq
1296  *
1297  * Since: 2.14
1298  */
1299 GSequenceIter *
g_sequence_get_end_iter(GSequence * seq)1300 g_sequence_get_end_iter (GSequence *seq)
1301 {
1302   g_return_val_if_fail (seq != NULL, NULL);
1303 
1304   return seq->end_node;
1305 }
1306 
1307 /**
1308  * g_sequence_get_begin_iter:
1309  * @seq: a #GSequence
1310  *
1311  * Returns the begin iterator for @seq.
1312  *
1313  * Returns: (transfer none): the begin iterator for @seq.
1314  *
1315  * Since: 2.14
1316  */
1317 GSequenceIter *
g_sequence_get_begin_iter(GSequence * seq)1318 g_sequence_get_begin_iter (GSequence *seq)
1319 {
1320   g_return_val_if_fail (seq != NULL, NULL);
1321 
1322   return node_get_first (seq->end_node);
1323 }
1324 
1325 static int
clamp_position(GSequence * seq,int pos)1326 clamp_position (GSequence *seq,
1327                 int        pos)
1328 {
1329   gint len = g_sequence_get_length (seq);
1330 
1331   if (pos > len || pos < 0)
1332     pos = len;
1333 
1334   return pos;
1335 }
1336 
1337 /**
1338  * g_sequence_get_iter_at_pos:
1339  * @seq: a #GSequence
1340  * @pos: a position in @seq, or -1 for the end
1341  *
1342  * Returns the iterator at position @pos. If @pos is negative or larger
1343  * than the number of items in @seq, the end iterator is returned.
1344  *
1345  * Returns: (transfer none): The #GSequenceIter at position @pos
1346  *
1347  * Since: 2.14
1348  */
1349 GSequenceIter *
g_sequence_get_iter_at_pos(GSequence * seq,gint pos)1350 g_sequence_get_iter_at_pos (GSequence *seq,
1351                             gint       pos)
1352 {
1353   g_return_val_if_fail (seq != NULL, NULL);
1354 
1355   pos = clamp_position (seq, pos);
1356 
1357   return node_get_by_pos (seq->end_node, pos);
1358 }
1359 
1360 /**
1361  * g_sequence_move:
1362  * @src: a #GSequenceIter pointing to the item to move
1363  * @dest: a #GSequenceIter pointing to the position to which
1364  *     the item is moved
1365  *
1366  * Moves the item pointed to by @src to the position indicated by @dest.
1367  * After calling this function @dest will point to the position immediately
1368  * after @src. It is allowed for @src and @dest to point into different
1369  * sequences.
1370  *
1371  * Since: 2.14
1372  **/
1373 void
g_sequence_move(GSequenceIter * src,GSequenceIter * dest)1374 g_sequence_move (GSequenceIter *src,
1375                  GSequenceIter *dest)
1376 {
1377   g_return_if_fail (src != NULL);
1378   g_return_if_fail (dest != NULL);
1379   g_return_if_fail (!is_end (src));
1380 
1381   if (src == dest)
1382     return;
1383 
1384   node_unlink (src);
1385   node_insert_before (dest, src);
1386 }
1387 
1388 /* GSequenceIter */
1389 
1390 /**
1391  * g_sequence_iter_is_end:
1392  * @iter: a #GSequenceIter
1393  *
1394  * Returns whether @iter is the end iterator
1395  *
1396  * Returns: Whether @iter is the end iterator
1397  *
1398  * Since: 2.14
1399  */
1400 gboolean
g_sequence_iter_is_end(GSequenceIter * iter)1401 g_sequence_iter_is_end (GSequenceIter *iter)
1402 {
1403   g_return_val_if_fail (iter != NULL, FALSE);
1404 
1405   return is_end (iter);
1406 }
1407 
1408 /**
1409  * g_sequence_iter_is_begin:
1410  * @iter: a #GSequenceIter
1411  *
1412  * Returns whether @iter is the begin iterator
1413  *
1414  * Returns: whether @iter is the begin iterator
1415  *
1416  * Since: 2.14
1417  */
1418 gboolean
g_sequence_iter_is_begin(GSequenceIter * iter)1419 g_sequence_iter_is_begin (GSequenceIter *iter)
1420 {
1421   g_return_val_if_fail (iter != NULL, FALSE);
1422 
1423   return (node_get_prev (iter) == iter);
1424 }
1425 
1426 /**
1427  * g_sequence_iter_get_position:
1428  * @iter: a #GSequenceIter
1429  *
1430  * Returns the position of @iter
1431  *
1432  * Returns: the position of @iter
1433  *
1434  * Since: 2.14
1435  */
1436 gint
g_sequence_iter_get_position(GSequenceIter * iter)1437 g_sequence_iter_get_position (GSequenceIter *iter)
1438 {
1439   g_return_val_if_fail (iter != NULL, -1);
1440 
1441   return node_get_pos (iter);
1442 }
1443 
1444 /**
1445  * g_sequence_iter_next:
1446  * @iter: a #GSequenceIter
1447  *
1448  * Returns an iterator pointing to the next position after @iter.
1449  * If @iter is the end iterator, the end iterator is returned.
1450  *
1451  * Returns: (transfer none): a #GSequenceIter pointing to the next position after @iter
1452  *
1453  * Since: 2.14
1454  */
1455 GSequenceIter *
g_sequence_iter_next(GSequenceIter * iter)1456 g_sequence_iter_next (GSequenceIter *iter)
1457 {
1458   g_return_val_if_fail (iter != NULL, NULL);
1459 
1460   return node_get_next (iter);
1461 }
1462 
1463 /**
1464  * g_sequence_iter_prev:
1465  * @iter: a #GSequenceIter
1466  *
1467  * Returns an iterator pointing to the previous position before @iter.
1468  * If @iter is the begin iterator, the begin iterator is returned.
1469  *
1470  * Returns: (transfer none): a #GSequenceIter pointing to the previous position
1471  *     before @iter
1472  *
1473  * Since: 2.14
1474  */
1475 GSequenceIter *
g_sequence_iter_prev(GSequenceIter * iter)1476 g_sequence_iter_prev (GSequenceIter *iter)
1477 {
1478   g_return_val_if_fail (iter != NULL, NULL);
1479 
1480   return node_get_prev (iter);
1481 }
1482 
1483 /**
1484  * g_sequence_iter_move:
1485  * @iter: a #GSequenceIter
1486  * @delta: A positive or negative number indicating how many positions away
1487  *    from @iter the returned #GSequenceIter will be
1488  *
1489  * Returns the #GSequenceIter which is @delta positions away from @iter.
1490  * If @iter is closer than -@delta positions to the beginning of the sequence,
1491  * the begin iterator is returned. If @iter is closer than @delta positions
1492  * to the end of the sequence, the end iterator is returned.
1493  *
1494  * Returns: (transfer none): a #GSequenceIter which is @delta positions away from @iter
1495  *
1496  * Since: 2.14
1497  */
1498 GSequenceIter *
g_sequence_iter_move(GSequenceIter * iter,gint delta)1499 g_sequence_iter_move (GSequenceIter *iter,
1500                       gint           delta)
1501 {
1502   gint new_pos;
1503   gint len;
1504 
1505   g_return_val_if_fail (iter != NULL, NULL);
1506 
1507   len = g_sequence_get_length (get_sequence (iter));
1508 
1509   new_pos = node_get_pos (iter) + delta;
1510 
1511   if (new_pos < 0)
1512     new_pos = 0;
1513   else if (new_pos > len)
1514     new_pos = len;
1515 
1516   return node_get_by_pos (iter, new_pos);
1517 }
1518 
1519 /**
1520  * g_sequence_swap:
1521  * @a: a #GSequenceIter
1522  * @b: a #GSequenceIter
1523  *
1524  * Swaps the items pointed to by @a and @b. It is allowed for @a and @b
1525  * to point into difference sequences.
1526  *
1527  * Since: 2.14
1528  */
1529 void
g_sequence_swap(GSequenceIter * a,GSequenceIter * b)1530 g_sequence_swap (GSequenceIter *a,
1531                  GSequenceIter *b)
1532 {
1533   GSequenceNode *leftmost, *rightmost, *rightmost_next;
1534   int a_pos, b_pos;
1535 
1536   g_return_if_fail (!g_sequence_iter_is_end (a));
1537   g_return_if_fail (!g_sequence_iter_is_end (b));
1538 
1539   if (a == b)
1540     return;
1541 
1542   a_pos = g_sequence_iter_get_position (a);
1543   b_pos = g_sequence_iter_get_position (b);
1544 
1545   if (a_pos > b_pos)
1546     {
1547       leftmost = b;
1548       rightmost = a;
1549     }
1550   else
1551     {
1552       leftmost = a;
1553       rightmost = b;
1554     }
1555 
1556   rightmost_next = node_get_next (rightmost);
1557 
1558   /* The situation is now like this:
1559    *
1560    *     ..., leftmost, ......., rightmost, rightmost_next, ...
1561    *
1562    */
1563   g_sequence_move (rightmost, leftmost);
1564   g_sequence_move (leftmost, rightmost_next);
1565 }
1566 
1567 /*
1568  * Implementation of a treap
1569  *
1570  *
1571  */
1572 static guint
get_priority(GSequenceNode * node)1573 get_priority (GSequenceNode *node)
1574 {
1575   guint key = GPOINTER_TO_UINT (node);
1576 
1577   /* This hash function is based on one found on Thomas Wang's
1578    * web page at
1579    *
1580    *    http://www.concentric.net/~Ttwang/tech/inthash.htm
1581    *
1582    */
1583   key = (key << 15) - key - 1;
1584   key = key ^ (key >> 12);
1585   key = key + (key << 2);
1586   key = key ^ (key >> 4);
1587   key = key + (key << 3) + (key << 11);
1588   key = key ^ (key >> 16);
1589 
1590   /* We rely on 0 being less than all other priorities */
1591   return key? key : 1;
1592 }
1593 
1594 static GSequenceNode *
find_root(GSequenceNode * node)1595 find_root (GSequenceNode *node)
1596 {
1597   while (node->parent)
1598     node = node->parent;
1599 
1600   return node;
1601 }
1602 
1603 static GSequenceNode *
node_new(gpointer data)1604 node_new (gpointer data)
1605 {
1606   GSequenceNode *node = g_slice_new0 (GSequenceNode);
1607 
1608   node->n_nodes = 1;
1609   node->data = data;
1610   node->left = NULL;
1611   node->right = NULL;
1612   node->parent = NULL;
1613 
1614   return node;
1615 }
1616 
1617 static GSequenceNode *
node_get_first(GSequenceNode * node)1618 node_get_first (GSequenceNode *node)
1619 {
1620   node = find_root (node);
1621 
1622   while (node->left)
1623     node = node->left;
1624 
1625   return node;
1626 }
1627 
1628 static GSequenceNode *
node_get_last(GSequenceNode * node)1629 node_get_last (GSequenceNode *node)
1630 {
1631   node = find_root (node);
1632 
1633   while (node->right)
1634     node = node->right;
1635 
1636   return node;
1637 }
1638 
1639 #define NODE_LEFT_CHILD(n)  (((n)->parent) && ((n)->parent->left) == (n))
1640 #define NODE_RIGHT_CHILD(n) (((n)->parent) && ((n)->parent->right) == (n))
1641 
1642 static GSequenceNode *
node_get_next(GSequenceNode * node)1643 node_get_next (GSequenceNode *node)
1644 {
1645   GSequenceNode *n = node;
1646 
1647   if (n->right)
1648     {
1649       n = n->right;
1650       while (n->left)
1651         n = n->left;
1652     }
1653   else
1654     {
1655       while (NODE_RIGHT_CHILD (n))
1656         n = n->parent;
1657 
1658       if (n->parent)
1659         n = n->parent;
1660       else
1661         n = node;
1662     }
1663 
1664   return n;
1665 }
1666 
1667 static GSequenceNode *
node_get_prev(GSequenceNode * node)1668 node_get_prev (GSequenceNode *node)
1669 {
1670   GSequenceNode *n = node;
1671 
1672   if (n->left)
1673     {
1674       n = n->left;
1675       while (n->right)
1676         n = n->right;
1677     }
1678   else
1679     {
1680       while (NODE_LEFT_CHILD (n))
1681         n = n->parent;
1682 
1683       if (n->parent)
1684         n = n->parent;
1685       else
1686         n = node;
1687     }
1688 
1689   return n;
1690 }
1691 
1692 #define N_NODES(n) ((n)? (n)->n_nodes : 0)
1693 
1694 static gint
node_get_pos(GSequenceNode * node)1695 node_get_pos (GSequenceNode *node)
1696 {
1697   int n_smaller = 0;
1698 
1699   if (node->left)
1700     n_smaller = node->left->n_nodes;
1701 
1702   while (node)
1703     {
1704       if (NODE_RIGHT_CHILD (node))
1705         n_smaller += N_NODES (node->parent->left) + 1;
1706 
1707       node = node->parent;
1708     }
1709 
1710   return n_smaller;
1711 }
1712 
1713 static GSequenceNode *
node_get_by_pos(GSequenceNode * node,gint pos)1714 node_get_by_pos (GSequenceNode *node,
1715                  gint           pos)
1716 {
1717   int i;
1718 
1719   node = find_root (node);
1720 
1721   while ((i = N_NODES (node->left)) != pos)
1722     {
1723       if (i < pos)
1724         {
1725           node = node->right;
1726           pos -= (i + 1);
1727         }
1728       else
1729         {
1730           node = node->left;
1731         }
1732     }
1733 
1734   return node;
1735 }
1736 
1737 static GSequenceNode *
node_find(GSequenceNode * haystack,GSequenceNode * needle,GSequenceNode * end,GSequenceIterCompareFunc iter_cmp,gpointer cmp_data)1738 node_find (GSequenceNode            *haystack,
1739            GSequenceNode            *needle,
1740            GSequenceNode            *end,
1741            GSequenceIterCompareFunc  iter_cmp,
1742            gpointer                  cmp_data)
1743 {
1744   gint c;
1745 
1746   haystack = find_root (haystack);
1747 
1748   do
1749     {
1750       /* iter_cmp can't be passed the end node, since the function may
1751        * be user-supplied
1752        */
1753       if (haystack == end)
1754         c = 1;
1755       else
1756         c = iter_cmp (haystack, needle, cmp_data);
1757 
1758       if (c == 0)
1759         break;
1760 
1761       if (c > 0)
1762         haystack = haystack->left;
1763       else
1764         haystack = haystack->right;
1765     }
1766   while (haystack != NULL);
1767 
1768   return haystack;
1769 }
1770 
1771 static GSequenceNode *
node_find_closest(GSequenceNode * haystack,GSequenceNode * needle,GSequenceNode * end,GSequenceIterCompareFunc iter_cmp,gpointer cmp_data)1772 node_find_closest (GSequenceNode            *haystack,
1773                    GSequenceNode            *needle,
1774                    GSequenceNode            *end,
1775                    GSequenceIterCompareFunc  iter_cmp,
1776                    gpointer                  cmp_data)
1777 {
1778   GSequenceNode *best;
1779   gint c;
1780 
1781   haystack = find_root (haystack);
1782 
1783   do
1784     {
1785       best = haystack;
1786 
1787       /* iter_cmp can't be passed the end node, since the function may
1788        * be user-supplied
1789        */
1790       if (haystack == end)
1791         c = 1;
1792       else
1793         c = iter_cmp (haystack, needle, cmp_data);
1794 
1795       /* In the following we don't break even if c == 0. Instead we go on
1796        * searching along the 'bigger' nodes, so that we find the last one
1797        * that is equal to the needle.
1798        */
1799       if (c > 0)
1800         haystack = haystack->left;
1801       else
1802         haystack = haystack->right;
1803     }
1804   while (haystack != NULL);
1805 
1806   /* If the best node is smaller or equal to the data, then move one step
1807    * to the right to make sure the best one is strictly bigger than the data
1808    */
1809   if (best != end && c <= 0)
1810     best = node_get_next (best);
1811 
1812   return best;
1813 }
1814 
1815 static gint
node_get_length(GSequenceNode * node)1816 node_get_length    (GSequenceNode            *node)
1817 {
1818   node = find_root (node);
1819 
1820   return node->n_nodes;
1821 }
1822 
1823 static void
real_node_free(GSequenceNode * node,GSequence * seq)1824 real_node_free (GSequenceNode *node,
1825                 GSequence     *seq)
1826 {
1827   if (node)
1828     {
1829       real_node_free (node->left, seq);
1830       real_node_free (node->right, seq);
1831 
1832       if (seq && seq->data_destroy_notify && node != seq->end_node)
1833         seq->data_destroy_notify (node->data);
1834 
1835       g_slice_free (GSequenceNode, node);
1836     }
1837 }
1838 
1839 static void
node_free(GSequenceNode * node,GSequence * seq)1840 node_free (GSequenceNode *node,
1841            GSequence *seq)
1842 {
1843   node = find_root (node);
1844 
1845   real_node_free (node, seq);
1846 }
1847 
1848 static void
node_update_fields(GSequenceNode * node)1849 node_update_fields (GSequenceNode *node)
1850 {
1851   int n_nodes = 1;
1852 
1853   n_nodes += N_NODES (node->left);
1854   n_nodes += N_NODES (node->right);
1855 
1856   node->n_nodes = n_nodes;
1857 }
1858 
1859 static void
node_rotate(GSequenceNode * node)1860 node_rotate (GSequenceNode *node)
1861 {
1862   GSequenceNode *tmp, *old;
1863 
1864   g_assert (node->parent);
1865   g_assert (node->parent != node);
1866 
1867   if (NODE_LEFT_CHILD (node))
1868     {
1869       /* rotate right */
1870       tmp = node->right;
1871 
1872       node->right = node->parent;
1873       node->parent = node->parent->parent;
1874       if (node->parent)
1875         {
1876           if (node->parent->left == node->right)
1877             node->parent->left = node;
1878           else
1879             node->parent->right = node;
1880         }
1881 
1882       g_assert (node->right);
1883 
1884       node->right->parent = node;
1885       node->right->left = tmp;
1886 
1887       if (node->right->left)
1888         node->right->left->parent = node->right;
1889 
1890       old = node->right;
1891     }
1892   else
1893     {
1894       /* rotate left */
1895       tmp = node->left;
1896 
1897       node->left = node->parent;
1898       node->parent = node->parent->parent;
1899       if (node->parent)
1900         {
1901           if (node->parent->right == node->left)
1902             node->parent->right = node;
1903           else
1904             node->parent->left = node;
1905         }
1906 
1907       g_assert (node->left);
1908 
1909       node->left->parent = node;
1910       node->left->right = tmp;
1911 
1912       if (node->left->right)
1913         node->left->right->parent = node->left;
1914 
1915       old = node->left;
1916     }
1917 
1918   node_update_fields (old);
1919   node_update_fields (node);
1920 }
1921 
1922 static void
node_update_fields_deep(GSequenceNode * node)1923 node_update_fields_deep (GSequenceNode *node)
1924 {
1925   if (node)
1926     {
1927       node_update_fields (node);
1928 
1929       node_update_fields_deep (node->parent);
1930     }
1931 }
1932 
1933 static void
rotate_down(GSequenceNode * node,guint priority)1934 rotate_down (GSequenceNode *node,
1935              guint          priority)
1936 {
1937   guint left, right;
1938 
1939   left = node->left ? get_priority (node->left)  : 0;
1940   right = node->right ? get_priority (node->right) : 0;
1941 
1942   while (priority < left || priority < right)
1943     {
1944       if (left > right)
1945         node_rotate (node->left);
1946       else
1947         node_rotate (node->right);
1948 
1949       left = node->left ? get_priority (node->left)  : 0;
1950       right = node->right ? get_priority (node->right) : 0;
1951     }
1952 }
1953 
1954 static void
node_cut(GSequenceNode * node)1955 node_cut (GSequenceNode *node)
1956 {
1957   while (node->parent)
1958     node_rotate (node);
1959 
1960   if (node->left)
1961     node->left->parent = NULL;
1962 
1963   node->left = NULL;
1964   node_update_fields (node);
1965 
1966   rotate_down (node, get_priority (node));
1967 }
1968 
1969 static void
node_join(GSequenceNode * left,GSequenceNode * right)1970 node_join (GSequenceNode *left,
1971            GSequenceNode *right)
1972 {
1973   GSequenceNode *fake = node_new (NULL);
1974 
1975   fake->left = find_root (left);
1976   fake->right = find_root (right);
1977   fake->left->parent = fake;
1978   fake->right->parent = fake;
1979 
1980   node_update_fields (fake);
1981 
1982   node_unlink (fake);
1983 
1984   node_free (fake, NULL);
1985 }
1986 
1987 static void
node_insert_before(GSequenceNode * node,GSequenceNode * new)1988 node_insert_before (GSequenceNode *node,
1989                     GSequenceNode *new)
1990 {
1991   new->left = node->left;
1992   if (new->left)
1993     new->left->parent = new;
1994 
1995   new->parent = node;
1996   node->left = new;
1997 
1998   node_update_fields_deep (new);
1999 
2000   while (new->parent && get_priority (new) > get_priority (new->parent))
2001     node_rotate (new);
2002 
2003   rotate_down (new, get_priority (new));
2004 }
2005 
2006 static void
node_unlink(GSequenceNode * node)2007 node_unlink (GSequenceNode *node)
2008 {
2009   rotate_down (node, 0);
2010 
2011   if (NODE_RIGHT_CHILD (node))
2012     node->parent->right = NULL;
2013   else if (NODE_LEFT_CHILD (node))
2014     node->parent->left = NULL;
2015 
2016   if (node->parent)
2017     node_update_fields_deep (node->parent);
2018 
2019   node->parent = NULL;
2020 }
2021 
2022 static void
node_insert_sorted(GSequenceNode * node,GSequenceNode * new,GSequenceNode * end,GSequenceIterCompareFunc iter_cmp,gpointer cmp_data)2023 node_insert_sorted (GSequenceNode            *node,
2024                     GSequenceNode            *new,
2025                     GSequenceNode            *end,
2026                     GSequenceIterCompareFunc  iter_cmp,
2027                     gpointer                  cmp_data)
2028 {
2029   GSequenceNode *closest;
2030 
2031   closest = node_find_closest (node, new, end, iter_cmp, cmp_data);
2032 
2033   node_unlink (new);
2034 
2035   node_insert_before (closest, new);
2036 }
2037