mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-11-04 10:08:56 +01:00 
			
		
		
		
	For move, test moving between two sequences. Add test for swap.
2007-02-16 Soren Sandmann <sandmann@redhat.com> * tests/sequence-test.c: For move, test moving between two sequences. Add test for swap. * glib/gsequence.c: Replace splay tree with a treap. (check_node): Add checks for the treap invariants. svn path=/trunk/; revision=5337
This commit is contained in:
		
				
					committed by
					
						
						Søren Sandmann Pedersen
					
				
			
			
				
	
			
			
			
						parent
						
							c6efde4f62
						
					
				
				
					commit
					f13d070e20
				
			@@ -1,3 +1,11 @@
 | 
			
		||||
2007-02-16  Soren Sandmann <sandmann@redhat.com>
 | 
			
		||||
 | 
			
		||||
	* tests/sequence-test.c: For move, test moving between two
 | 
			
		||||
	sequences. Add test for swap.
 | 
			
		||||
 | 
			
		||||
	* glib/gsequence.c: Replace splay tree with a treap.
 | 
			
		||||
	(check_node): Add checks for the treap invariants.
 | 
			
		||||
 | 
			
		||||
2007-02-10  Hans Breuer  <hans@breuer.org>
 | 
			
		||||
 | 
			
		||||
	* glib/makefile.msc.in : added gsequence.obj
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										734
									
								
								glib/gsequence.c
									
									
									
									
									
								
							
							
						
						
									
										734
									
								
								glib/gsequence.c
									
									
									
									
									
								
							@@ -72,17 +72,18 @@ static gint           node_get_length    (GSequenceNode            *node);
 | 
			
		||||
static void           node_free          (GSequenceNode            *node,
 | 
			
		||||
                                          GSequence                *seq);
 | 
			
		||||
static void           node_cut           (GSequenceNode            *split);
 | 
			
		||||
static void           node_insert_after  (GSequenceNode            *node,
 | 
			
		||||
                                          GSequenceNode            *second);
 | 
			
		||||
static void           node_insert_before (GSequenceNode            *node,
 | 
			
		||||
                                          GSequenceNode            *new);
 | 
			
		||||
static void           node_unlink        (GSequenceNode            *node);
 | 
			
		||||
static void           node_join          (GSequenceNode            *left,
 | 
			
		||||
					  GSequenceNode            *right);
 | 
			
		||||
static void           node_insert_sorted (GSequenceNode            *node,
 | 
			
		||||
                                          GSequenceNode            *new,
 | 
			
		||||
                                          GSequenceNode            *end,
 | 
			
		||||
                                          GSequenceIterCompareFunc  cmp_func,
 | 
			
		||||
                                          gpointer                  cmp_data);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Various helper functions
 | 
			
		||||
 */
 | 
			
		||||
@@ -551,12 +552,23 @@ g_sequence_move_range (GSequenceIter *dest,
 | 
			
		||||
  node_cut (end);
 | 
			
		||||
  
 | 
			
		||||
  if (first != begin)
 | 
			
		||||
    node_insert_after (node_get_last (first), end);
 | 
			
		||||
    node_join (first, end);
 | 
			
		||||
  
 | 
			
		||||
  if (dest)
 | 
			
		||||
    node_insert_before (dest, begin);
 | 
			
		||||
    {
 | 
			
		||||
      first = node_get_first (dest);
 | 
			
		||||
      
 | 
			
		||||
      node_cut (dest);
 | 
			
		||||
      
 | 
			
		||||
      node_join (begin, dest);
 | 
			
		||||
      
 | 
			
		||||
      if (dest != first)
 | 
			
		||||
	node_join (first, begin);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      node_free (begin, src_seq);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -899,18 +911,6 @@ g_sequence_search_iter (GSequence                *seq,
 | 
			
		||||
  
 | 
			
		||||
  seq->access_prohibited = TRUE;
 | 
			
		||||
 | 
			
		||||
  /* Create a new temporary sequence and put the dummy node into
 | 
			
		||||
   * that. The reason for this is that the user compare function
 | 
			
		||||
   * will be called with the new node, and if it dereferences, 
 | 
			
		||||
   * "is_end" will be called on it. But that will crash if the
 | 
			
		||||
   * node is not actually in a sequence.
 | 
			
		||||
   *
 | 
			
		||||
   * node_insert_sorted() makes sure the node is unlinked before
 | 
			
		||||
   * is is inserted.
 | 
			
		||||
   *
 | 
			
		||||
   * The reason we need the "iter" versions at all is that that
 | 
			
		||||
   * is the only kind of compare functions GtkTreeView can use.
 | 
			
		||||
   */
 | 
			
		||||
  tmp_seq = g_sequence_new (NULL);
 | 
			
		||||
  tmp_seq->real_sequence = seq;
 | 
			
		||||
  
 | 
			
		||||
@@ -1055,6 +1055,7 @@ GSequenceIter *
 | 
			
		||||
g_sequence_get_begin_iter (GSequence *seq)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (seq != NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  return node_get_first (seq->end_node);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1104,7 +1105,8 @@ g_sequence_get_iter_at_pos (GSequence *seq,
 | 
			
		||||
 *
 | 
			
		||||
 * Moves the item pointed to by @src to the position indicated by @dest.
 | 
			
		||||
 * After calling this function @dest will point to the position immediately
 | 
			
		||||
 * after @src.
 | 
			
		||||
 * after @src. It is allowed for @src and @dest to point into different
 | 
			
		||||
 * sequences.
 | 
			
		||||
 * 
 | 
			
		||||
 * Since: 2.14
 | 
			
		||||
 **/
 | 
			
		||||
@@ -1253,7 +1255,8 @@ g_sequence_iter_move (GSequenceIter *iter,
 | 
			
		||||
 * @a: a #GSequenceIter
 | 
			
		||||
 * @b: a #GSequenceIter
 | 
			
		||||
 * 
 | 
			
		||||
 * Swaps the items pointed to by @a and @b
 | 
			
		||||
 * Swaps the items pointed to by @a and @b. It is allowed for @a and @b
 | 
			
		||||
 * to point into difference sequences.
 | 
			
		||||
 * 
 | 
			
		||||
 * Since: 2.14
 | 
			
		||||
 **/
 | 
			
		||||
@@ -1296,71 +1299,263 @@ g_sequence_swap (GSequenceIter *a,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Implementation of the splay tree. 
 | 
			
		||||
 * Implementation of a treap
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
static guint
 | 
			
		||||
get_priority (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  guint key = GPOINTER_TO_UINT (node);
 | 
			
		||||
 | 
			
		||||
/* Splay Tree vs. Other Kinds of Trees
 | 
			
		||||
  /* This hash function is based on one found on Thomas Wang's
 | 
			
		||||
   * web page at
 | 
			
		||||
   *
 | 
			
		||||
 * There are both advantages and disadvantages to using a splay tree vs. some other
 | 
			
		||||
 * kind of tree such as a red/black tree or a btree.
 | 
			
		||||
 *
 | 
			
		||||
 * Advantages of splay trees
 | 
			
		||||
 *
 | 
			
		||||
 * - They are very simple to implement, especially things like move_range or concatenate
 | 
			
		||||
 *   are easy to do for splay trees. The algorithm to split a red/black tree, while still O(log n),
 | 
			
		||||
 *   is much more complicated
 | 
			
		||||
 *
 | 
			
		||||
 * - If we add aggregates at some point, splay trees make it easy to compute the aggregate
 | 
			
		||||
 *   for an arbitrary range of the tree. In a red/black tree you would have to pick out
 | 
			
		||||
 *   the correct subtrees, then call out to the aggregator function to compute them.
 | 
			
		||||
 *      On the other hand, for a splay tree, aggregates would be invalidated on lookups, so you
 | 
			
		||||
 *   would call the aggregator much more often. The aggregates could be invalidated lazily though.
 | 
			
		||||
 *      In both cases, the aggregator function would be called O(log n) times as a side-effect of
 | 
			
		||||
 *   asking for the aggregate of a range.
 | 
			
		||||
 *
 | 
			
		||||
 * - If you are only using the list API and never the insert_sorted(), the operations on a
 | 
			
		||||
 *   splay tree will actually be O(1) rather than O(log n). But this is most likely just
 | 
			
		||||
 *   not that interesting in practice since the O(log n) of a BTree is actually very fast.
 | 
			
		||||
 *
 | 
			
		||||
 * The disadvantages
 | 
			
		||||
 *
 | 
			
		||||
 * - Splay trees are only amortized O(log n) which means individual operations could take a long
 | 
			
		||||
 *   time, which is undesirable in GUI applications
 | 
			
		||||
 *
 | 
			
		||||
 * - Red/black trees are more widely known since they are tought in CS101 courses.
 | 
			
		||||
 *
 | 
			
		||||
 * - Red/black trees or btrees are more efficient. Not only is the red/black algorithm faster
 | 
			
		||||
 *   in itself, the splaying writes to nodes on lookup which causes dirty pages that the VM
 | 
			
		||||
 *   system will have to launder.
 | 
			
		||||
 *
 | 
			
		||||
 * - Splay trees are not necessarily balanced at all which means straight-forward recursive
 | 
			
		||||
 *   algorithms can use lots of stack.
 | 
			
		||||
 *
 | 
			
		||||
 * It is likely worth investigating whether a BTree would be a better choice, in particular the
 | 
			
		||||
 * algorithm to split a BTree may not be all that complicated given that split/join for nodes
 | 
			
		||||
 * will have to be implemented anyway.
 | 
			
		||||
   *    http://www.concentric.net/~Ttwang/tech/inthash.htm
 | 
			
		||||
   *
 | 
			
		||||
   */
 | 
			
		||||
  key = (key << 15) - key - 1;
 | 
			
		||||
  key = key ^ (key >> 12);
 | 
			
		||||
  key = key + (key << 2);
 | 
			
		||||
  key = key ^ (key >> 4);
 | 
			
		||||
  key = key + (key << 3) + (key << 11);
 | 
			
		||||
  key = key ^ (key >> 16);
 | 
			
		||||
 | 
			
		||||
  /* We rely on 0 being less than all other priorities */
 | 
			
		||||
  return key? key : 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
find_root (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  while (node->parent)
 | 
			
		||||
    node = node->parent;
 | 
			
		||||
  
 | 
			
		||||
  return node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
node_new (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  GSequenceNode *node = g_slice_new0 (GSequenceNode);
 | 
			
		||||
  
 | 
			
		||||
  node->n_nodes = 1;
 | 
			
		||||
  node->data = data;
 | 
			
		||||
  node->left = NULL;
 | 
			
		||||
  node->right = NULL;
 | 
			
		||||
  node->parent = NULL;
 | 
			
		||||
  
 | 
			
		||||
  return node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
node_get_first (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  node = find_root (node);
 | 
			
		||||
  
 | 
			
		||||
  while (node->left)
 | 
			
		||||
    node = node->left;
 | 
			
		||||
  
 | 
			
		||||
  return node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
node_get_last (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  node = find_root (node);
 | 
			
		||||
  
 | 
			
		||||
  while (node->right)
 | 
			
		||||
    node = node->right;
 | 
			
		||||
  
 | 
			
		||||
  return node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define NODE_LEFT_CHILD(n)  (((n)->parent) && ((n)->parent->left) == (n))
 | 
			
		||||
#define NODE_RIGHT_CHILD(n) (((n)->parent) && ((n)->parent->right) == (n))
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
node_get_next (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  GSequenceNode *n = node;
 | 
			
		||||
 | 
			
		||||
  if (n->right)
 | 
			
		||||
    {
 | 
			
		||||
      n = n->right;
 | 
			
		||||
      while (n->left)
 | 
			
		||||
	n = n->left;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      while (NODE_RIGHT_CHILD (n))
 | 
			
		||||
	n = n->parent;
 | 
			
		||||
      
 | 
			
		||||
      if (n->parent)
 | 
			
		||||
	n = n->parent;
 | 
			
		||||
      else
 | 
			
		||||
	n = node;
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
node_get_prev (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  GSequenceNode *n = node;
 | 
			
		||||
  
 | 
			
		||||
  if (n->left)
 | 
			
		||||
    {
 | 
			
		||||
      n = n->left;
 | 
			
		||||
      while (n->right)
 | 
			
		||||
	n = n->right;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      while (NODE_LEFT_CHILD (n))
 | 
			
		||||
	n = n->parent;
 | 
			
		||||
      
 | 
			
		||||
      if (n->parent)
 | 
			
		||||
	n = n->parent;
 | 
			
		||||
      else
 | 
			
		||||
	n = node;
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define N_NODES(n) ((n)? (n)->n_nodes : 0)
 | 
			
		||||
 | 
			
		||||
static gint
 | 
			
		||||
node_get_pos (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  int n_smaller = 0;
 | 
			
		||||
  
 | 
			
		||||
  if (node->left)
 | 
			
		||||
    n_smaller = node->left->n_nodes;
 | 
			
		||||
  
 | 
			
		||||
  while (node)
 | 
			
		||||
    {
 | 
			
		||||
      if (NODE_RIGHT_CHILD (node))
 | 
			
		||||
	n_smaller += N_NODES (node->parent->left) + 1;
 | 
			
		||||
      
 | 
			
		||||
      node = node->parent;
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  return n_smaller;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
node_get_by_pos (GSequenceNode *node,
 | 
			
		||||
		 gint           pos)
 | 
			
		||||
{
 | 
			
		||||
  int i;
 | 
			
		||||
  
 | 
			
		||||
  node = find_root (node);
 | 
			
		||||
  
 | 
			
		||||
  while ((i = N_NODES (node->left)) != pos)
 | 
			
		||||
    {
 | 
			
		||||
      if (i < pos)
 | 
			
		||||
        {
 | 
			
		||||
	  node = node->right;
 | 
			
		||||
	  pos -= (i + 1);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
	  node = node->left;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  return node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
node_find_closest (GSequenceNode            *haystack,
 | 
			
		||||
                   GSequenceNode            *needle,
 | 
			
		||||
                   GSequenceNode            *end,
 | 
			
		||||
                   GSequenceIterCompareFunc  iter_cmp,
 | 
			
		||||
                   gpointer                  cmp_data)
 | 
			
		||||
{
 | 
			
		||||
  GSequenceNode *best;
 | 
			
		||||
  gint c;
 | 
			
		||||
  
 | 
			
		||||
  haystack = find_root (haystack);
 | 
			
		||||
  
 | 
			
		||||
  do
 | 
			
		||||
    {
 | 
			
		||||
      best = haystack;
 | 
			
		||||
      
 | 
			
		||||
      /* iter_cmp can't be passed the end node, since the function may
 | 
			
		||||
       * be user-supplied
 | 
			
		||||
       */
 | 
			
		||||
      if (haystack == end)
 | 
			
		||||
        c = 1;
 | 
			
		||||
      else
 | 
			
		||||
        c = iter_cmp (haystack, needle, cmp_data);
 | 
			
		||||
      
 | 
			
		||||
      /* In the following we don't break even if c == 0. Instaed we go on
 | 
			
		||||
       * searching along the 'bigger' nodes, so that we find the last one
 | 
			
		||||
       * that is equal to the needle.
 | 
			
		||||
       */
 | 
			
		||||
      if (c > 0)
 | 
			
		||||
        haystack = haystack->left;
 | 
			
		||||
      else
 | 
			
		||||
        haystack = haystack->right;
 | 
			
		||||
    }
 | 
			
		||||
  while (haystack != NULL);
 | 
			
		||||
  
 | 
			
		||||
  /* If the best node is smaller or equal to the data, then move one step
 | 
			
		||||
   * to the right to make sure the best one is strictly bigger than the data
 | 
			
		||||
   */
 | 
			
		||||
  if (best != end && c <= 0)
 | 
			
		||||
    best = node_get_next (best);
 | 
			
		||||
  
 | 
			
		||||
  return best;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gint
 | 
			
		||||
node_get_length    (GSequenceNode            *node)
 | 
			
		||||
{
 | 
			
		||||
  node = find_root (node);
 | 
			
		||||
  
 | 
			
		||||
  return node->n_nodes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
real_node_free (GSequenceNode *node,
 | 
			
		||||
		GSequence     *seq)
 | 
			
		||||
{
 | 
			
		||||
  if (node)
 | 
			
		||||
    {
 | 
			
		||||
      real_node_free (node->left, seq);
 | 
			
		||||
      real_node_free (node->right, seq);
 | 
			
		||||
      
 | 
			
		||||
      if (seq && seq->data_destroy_notify && node != seq->end_node)
 | 
			
		||||
	seq->data_destroy_notify (node->data);
 | 
			
		||||
      
 | 
			
		||||
      g_slice_free (GSequenceNode, node);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
node_free (GSequenceNode *node,
 | 
			
		||||
	   GSequence *seq)
 | 
			
		||||
{
 | 
			
		||||
  node = find_root (node);
 | 
			
		||||
  
 | 
			
		||||
  real_node_free (node, seq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
node_update_fields (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  int n_nodes = 1;
 | 
			
		||||
  
 | 
			
		||||
  g_assert (node != NULL);
 | 
			
		||||
 | 
			
		||||
  if (node->left)
 | 
			
		||||
    n_nodes += node->left->n_nodes;
 | 
			
		||||
 | 
			
		||||
  if (node->right)
 | 
			
		||||
    n_nodes += node->right->n_nodes;
 | 
			
		||||
  n_nodes += N_NODES (node->left);
 | 
			
		||||
  n_nodes += N_NODES (node->right);
 | 
			
		||||
  
 | 
			
		||||
  node->n_nodes = n_nodes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define NODE_LEFT_CHILD(n)  (((n)->parent) && ((n)->parent->left) == (n))
 | 
			
		||||
#define NODE_RIGHT_CHILD(n) (((n)->parent) && ((n)->parent->right) == (n))
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
node_rotate (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
@@ -1424,342 +1619,104 @@ node_rotate (GSequenceNode *node)
 | 
			
		||||
  node_update_fields (node);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
splay (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  while (node->parent)
 | 
			
		||||
    {
 | 
			
		||||
      if (!node->parent->parent)
 | 
			
		||||
        {
 | 
			
		||||
          /* zig */
 | 
			
		||||
          node_rotate (node);
 | 
			
		||||
        }
 | 
			
		||||
      else if ((NODE_LEFT_CHILD (node) && NODE_LEFT_CHILD (node->parent)) ||
 | 
			
		||||
               (NODE_RIGHT_CHILD (node) && NODE_RIGHT_CHILD (node->parent)))
 | 
			
		||||
        {
 | 
			
		||||
          /* zig-zig */
 | 
			
		||||
          node_rotate (node->parent);
 | 
			
		||||
          node_rotate (node);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          /* zig-zag */
 | 
			
		||||
          node_rotate (node);
 | 
			
		||||
          node_rotate (node);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  return node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
node_new (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  GSequenceNode *node = g_slice_new0 (GSequenceNode);
 | 
			
		||||
  
 | 
			
		||||
  node->parent = NULL;
 | 
			
		||||
  node->parent = NULL;
 | 
			
		||||
  node->left = NULL;
 | 
			
		||||
  node->right = NULL;
 | 
			
		||||
  
 | 
			
		||||
  node->data = data;
 | 
			
		||||
  node->n_nodes = 1;
 | 
			
		||||
  
 | 
			
		||||
  return node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
find_min (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  splay (node);
 | 
			
		||||
  
 | 
			
		||||
  while (node->left)
 | 
			
		||||
    node = node->left;
 | 
			
		||||
  
 | 
			
		||||
  return node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
find_max (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  splay (node);
 | 
			
		||||
  
 | 
			
		||||
  while (node->right)
 | 
			
		||||
    node = node->right;
 | 
			
		||||
  
 | 
			
		||||
  return node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
node_get_first (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  return splay (find_min (node));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
node_get_last (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  return splay (find_max (node));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gint
 | 
			
		||||
get_n_nodes (GSequenceNode *node)
 | 
			
		||||
static void
 | 
			
		||||
node_update_fields_deep (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  if (node)
 | 
			
		||||
    return node->n_nodes;
 | 
			
		||||
  else
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
node_get_by_pos (GSequenceNode *node,
 | 
			
		||||
		 gint           pos)
 | 
			
		||||
{
 | 
			
		||||
  gint i;
 | 
			
		||||
  
 | 
			
		||||
  g_assert (node != NULL);
 | 
			
		||||
  
 | 
			
		||||
  splay (node);
 | 
			
		||||
  
 | 
			
		||||
  while ((i = get_n_nodes (node->left)) != pos)
 | 
			
		||||
    {
 | 
			
		||||
      if (i < pos)
 | 
			
		||||
        {
 | 
			
		||||
          node = node->right;
 | 
			
		||||
          pos -= (i + 1);
 | 
			
		||||
      node_update_fields (node);
 | 
			
		||||
      
 | 
			
		||||
      node_update_fields_deep (node->parent);
 | 
			
		||||
    }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          node = node->left;
 | 
			
		||||
          g_assert (node->parent != NULL);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  return splay (node);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
node_get_prev (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  splay (node);
 | 
			
		||||
  
 | 
			
		||||
  if (node->left)
 | 
			
		||||
    {
 | 
			
		||||
      node = node->left;
 | 
			
		||||
      while (node->right)
 | 
			
		||||
        node = node->right;
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  return splay (node);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
node_get_next (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  splay (node);
 | 
			
		||||
  
 | 
			
		||||
  if (node->right)
 | 
			
		||||
    {
 | 
			
		||||
      node = node->right;
 | 
			
		||||
      while (node->left)
 | 
			
		||||
        node = node->left;
 | 
			
		||||
   }
 | 
			
		||||
  
 | 
			
		||||
  return splay (node);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gint
 | 
			
		||||
node_get_pos (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  splay (node);
 | 
			
		||||
  
 | 
			
		||||
  return get_n_nodes (node->left);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Return closest node _strictly_ bigger than @needle. This node
 | 
			
		||||
 * always exists because the tree has an explicit end node).
 | 
			
		||||
 * This end node of @haystack must be passed in @end.
 | 
			
		||||
 */
 | 
			
		||||
static GSequenceNode *
 | 
			
		||||
node_find_closest (GSequenceNode            *haystack,
 | 
			
		||||
                   GSequenceNode            *needle,
 | 
			
		||||
                   GSequenceNode            *end,
 | 
			
		||||
                   GSequenceIterCompareFunc  iter_cmp,
 | 
			
		||||
                   gpointer                  cmp_data)
 | 
			
		||||
{
 | 
			
		||||
  GSequenceNode *best;
 | 
			
		||||
  gint c;
 | 
			
		||||
  
 | 
			
		||||
  g_assert (haystack);
 | 
			
		||||
  
 | 
			
		||||
  haystack = splay (haystack);
 | 
			
		||||
  
 | 
			
		||||
  do
 | 
			
		||||
    {
 | 
			
		||||
      best = haystack;
 | 
			
		||||
      
 | 
			
		||||
      /* iter_cmp can't be passed the end node, since the function may
 | 
			
		||||
       * be user-supplied
 | 
			
		||||
       */
 | 
			
		||||
      if (haystack == end)
 | 
			
		||||
        c = 1;
 | 
			
		||||
      else
 | 
			
		||||
        c = iter_cmp (haystack, needle, cmp_data);
 | 
			
		||||
      
 | 
			
		||||
      /* In the following we don't break even if c == 0. Instaed we go on
 | 
			
		||||
       * searching along the 'bigger' nodes, so that we find the last one
 | 
			
		||||
       * that is equal to the needle.
 | 
			
		||||
       */
 | 
			
		||||
      if (c > 0)
 | 
			
		||||
        haystack = haystack->left;
 | 
			
		||||
      else
 | 
			
		||||
        haystack = haystack->right;
 | 
			
		||||
    }
 | 
			
		||||
  while (haystack != NULL);
 | 
			
		||||
  
 | 
			
		||||
  /* If the best node is smaller or equal to the data, then move one step
 | 
			
		||||
   * to the right to make sure the best one is strictly bigger than the data
 | 
			
		||||
   */
 | 
			
		||||
  if (best != end && c <= 0)
 | 
			
		||||
    best = node_get_next (best);
 | 
			
		||||
  
 | 
			
		||||
  return best;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
node_free (GSequenceNode *node,
 | 
			
		||||
           GSequence     *seq)
 | 
			
		||||
rotate_down (GSequenceNode *node,
 | 
			
		||||
	     guint          priority)
 | 
			
		||||
{
 | 
			
		||||
  GPtrArray *stack = g_ptr_array_new ();
 | 
			
		||||
  guint left, right;
 | 
			
		||||
  
 | 
			
		||||
  splay (node);
 | 
			
		||||
  left = node->left ? get_priority (node->left)  : 0;
 | 
			
		||||
  right = node->right ? get_priority (node->right) : 0;
 | 
			
		||||
  
 | 
			
		||||
  g_ptr_array_add (stack, node);
 | 
			
		||||
  
 | 
			
		||||
  while (stack->len > 0)
 | 
			
		||||
  while (priority < left || priority < right)
 | 
			
		||||
    {
 | 
			
		||||
      node = g_ptr_array_remove_index (stack, stack->len - 1);
 | 
			
		||||
      if (left > right)
 | 
			
		||||
	node_rotate (node->left);
 | 
			
		||||
      else
 | 
			
		||||
	node_rotate (node->right);
 | 
			
		||||
  
 | 
			
		||||
      if (node)
 | 
			
		||||
        {
 | 
			
		||||
	  g_ptr_array_add (stack, node->right);
 | 
			
		||||
	  g_ptr_array_add (stack, node->left);
 | 
			
		||||
          
 | 
			
		||||
          if (seq && seq->data_destroy_notify && node != seq->end_node)
 | 
			
		||||
            seq->data_destroy_notify (node->data);
 | 
			
		||||
          
 | 
			
		||||
          g_slice_free (GSequenceNode, node);
 | 
			
		||||
      left = node->left ? get_priority (node->left)  : 0;
 | 
			
		||||
      right = node->right ? get_priority (node->right) : 0;
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  g_ptr_array_free (stack, TRUE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Splits into two trees. @node will be part of the right tree
 | 
			
		||||
 */
 | 
			
		||||
static void
 | 
			
		||||
node_cut (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  splay (node);
 | 
			
		||||
  
 | 
			
		||||
  g_assert (node->parent == NULL);
 | 
			
		||||
  while (node->parent)
 | 
			
		||||
    node_rotate (node);
 | 
			
		||||
  
 | 
			
		||||
  if (node->left)
 | 
			
		||||
    node->left->parent = NULL;
 | 
			
		||||
  
 | 
			
		||||
  node->left = NULL;
 | 
			
		||||
  node_update_fields (node);
 | 
			
		||||
  
 | 
			
		||||
  rotate_down (node, get_priority (node));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
node_join (GSequenceNode *left,
 | 
			
		||||
	   GSequenceNode *right)
 | 
			
		||||
{
 | 
			
		||||
  GSequenceNode *fake = node_new (NULL);
 | 
			
		||||
      
 | 
			
		||||
  fake->left = find_root (left);
 | 
			
		||||
  fake->right = find_root (right);
 | 
			
		||||
  fake->left->parent = fake;
 | 
			
		||||
  fake->right->parent = fake;
 | 
			
		||||
      
 | 
			
		||||
  node_update_fields (fake);
 | 
			
		||||
  
 | 
			
		||||
  node_unlink (fake);
 | 
			
		||||
  
 | 
			
		||||
  node_free (fake, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
node_insert_before (GSequenceNode *node,
 | 
			
		||||
		    GSequenceNode *new)
 | 
			
		||||
{
 | 
			
		||||
  g_assert (node != NULL);
 | 
			
		||||
  g_assert (new != NULL);
 | 
			
		||||
  
 | 
			
		||||
  splay (node);
 | 
			
		||||
  
 | 
			
		||||
  new = splay (find_min (new));
 | 
			
		||||
  g_assert (new->left == NULL);
 | 
			
		||||
  
 | 
			
		||||
  if (node->left)
 | 
			
		||||
    node->left->parent = new;
 | 
			
		||||
  
 | 
			
		||||
  new->left = node->left;
 | 
			
		||||
  new->parent = node;
 | 
			
		||||
  if (new->left)
 | 
			
		||||
    new->left->parent = new;
 | 
			
		||||
  
 | 
			
		||||
  new->parent = node;
 | 
			
		||||
  node->left = new;
 | 
			
		||||
  
 | 
			
		||||
  node_update_fields (new);
 | 
			
		||||
  node_update_fields (node);
 | 
			
		||||
}
 | 
			
		||||
  node_update_fields_deep (new);
 | 
			
		||||
  
 | 
			
		||||
static void
 | 
			
		||||
node_insert_after (GSequenceNode *node,
 | 
			
		||||
                   GSequenceNode *new)
 | 
			
		||||
{
 | 
			
		||||
  g_assert (node != NULL);
 | 
			
		||||
  g_assert (new != NULL);
 | 
			
		||||
  while (new->parent && get_priority (new) > get_priority (new->parent))
 | 
			
		||||
    node_rotate (new);
 | 
			
		||||
  
 | 
			
		||||
  splay (node);
 | 
			
		||||
  
 | 
			
		||||
  new = splay (find_max (new));
 | 
			
		||||
  g_assert (new->right == NULL);
 | 
			
		||||
  g_assert (node->parent == NULL);
 | 
			
		||||
  
 | 
			
		||||
  if (node->right)
 | 
			
		||||
    node->right->parent = new;
 | 
			
		||||
  
 | 
			
		||||
  new->right = node->right;
 | 
			
		||||
  new->parent = node;
 | 
			
		||||
  
 | 
			
		||||
  node->right = new;
 | 
			
		||||
  
 | 
			
		||||
  node_update_fields (new);
 | 
			
		||||
  node_update_fields (node);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gint
 | 
			
		||||
node_get_length (GSequenceNode    *node)
 | 
			
		||||
{
 | 
			
		||||
  g_assert (node != NULL);
 | 
			
		||||
  
 | 
			
		||||
  splay (node);
 | 
			
		||||
  return node->n_nodes;
 | 
			
		||||
  rotate_down (new, get_priority (new));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
node_unlink (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  GSequenceNode *right, *left;
 | 
			
		||||
  rotate_down (node, 0);
 | 
			
		||||
  
 | 
			
		||||
  splay (node);
 | 
			
		||||
  if (NODE_RIGHT_CHILD (node))
 | 
			
		||||
    node->parent->right = NULL;
 | 
			
		||||
  else if (NODE_LEFT_CHILD (node))
 | 
			
		||||
    node->parent->left = NULL;
 | 
			
		||||
  
 | 
			
		||||
  left = node->left;
 | 
			
		||||
  right = node->right;
 | 
			
		||||
  if (node->parent)
 | 
			
		||||
    node_update_fields_deep (node->parent);
 | 
			
		||||
  
 | 
			
		||||
  node->parent = node->left = node->right = NULL;
 | 
			
		||||
  node_update_fields (node);
 | 
			
		||||
  
 | 
			
		||||
  if (right)
 | 
			
		||||
    {
 | 
			
		||||
      right->parent = NULL;
 | 
			
		||||
      
 | 
			
		||||
      right = node_get_first (right);
 | 
			
		||||
      g_assert (right->left == NULL);
 | 
			
		||||
      
 | 
			
		||||
      right->left = left;
 | 
			
		||||
      if (left)
 | 
			
		||||
        {
 | 
			
		||||
          left->parent = right;
 | 
			
		||||
          node_update_fields (right);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else if (left)
 | 
			
		||||
    {
 | 
			
		||||
      left->parent = NULL;
 | 
			
		||||
    }
 | 
			
		||||
  node->parent = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -1778,49 +1735,60 @@ node_insert_sorted (GSequenceNode            *node,
 | 
			
		||||
  node_insert_before (closest, new);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gint
 | 
			
		||||
node_calc_height (GSequenceNode *node)
 | 
			
		||||
/* Self-test function */
 | 
			
		||||
static int
 | 
			
		||||
count_nodes (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  gint left_height;
 | 
			
		||||
  gint right_height;
 | 
			
		||||
  
 | 
			
		||||
  if (node)
 | 
			
		||||
    {
 | 
			
		||||
      left_height = 0;
 | 
			
		||||
      right_height = 0;
 | 
			
		||||
      
 | 
			
		||||
      if (node->left)
 | 
			
		||||
        left_height = node_calc_height (node->left);
 | 
			
		||||
      
 | 
			
		||||
      if (node->right)
 | 
			
		||||
        right_height = node_calc_height (node->right);
 | 
			
		||||
      
 | 
			
		||||
      return MAX (left_height, right_height) + 1;
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  if (!node)
 | 
			
		||||
    return 0;
 | 
			
		||||
  
 | 
			
		||||
  return count_nodes (node->left) + count_nodes (node->right) + 1;
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
/* Self-test function */
 | 
			
		||||
static void
 | 
			
		||||
check_node (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  if (node)
 | 
			
		||||
    {
 | 
			
		||||
      g_assert (node->parent != node);
 | 
			
		||||
      g_assert (node->n_nodes ==
 | 
			
		||||
                1 + get_n_nodes (node->left) + get_n_nodes (node->right));
 | 
			
		||||
      if (node->parent)
 | 
			
		||||
	g_assert (node->parent->left == node || node->parent->right == node);
 | 
			
		||||
      g_assert (node->n_nodes == count_nodes (node));
 | 
			
		||||
      if (node->left)
 | 
			
		||||
	  g_assert (get_priority (node) >= get_priority (node->left));
 | 
			
		||||
      if (node->right)
 | 
			
		||||
	  g_assert (get_priority (node) >= get_priority (node->right));
 | 
			
		||||
      check_node (node->left);
 | 
			
		||||
      check_node (node->right);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gint
 | 
			
		||||
compute_height (GSequenceNode *node)
 | 
			
		||||
{
 | 
			
		||||
  int left, right;
 | 
			
		||||
  
 | 
			
		||||
  if (!node)
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
  left = compute_height (node->left);
 | 
			
		||||
  right = compute_height (node->right);
 | 
			
		||||
 | 
			
		||||
  return MAX (left, right) + 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
g_sequence_self_test_internal_to_glib_dont_use (GSequence *seq)
 | 
			
		||||
{
 | 
			
		||||
  GSequenceNode *node = splay (seq->end_node);
 | 
			
		||||
  GSequenceNode *node = find_root (seq->end_node);
 | 
			
		||||
  
 | 
			
		||||
  check_node (node);
 | 
			
		||||
   
 | 
			
		||||
  node = node_get_last (node);
 | 
			
		||||
  
 | 
			
		||||
  g_assert (seq->end_node == node);
 | 
			
		||||
  g_assert (node->data == seq);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define __G_SEQUENCE_C__
 | 
			
		||||
 
 | 
			
		||||
@@ -2,13 +2,12 @@
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
  {
 | 
			
		||||
enum {
 | 
			
		||||
  NEW, FREE, GET_LENGTH, FOREACH, FOREACH_RANGE, SORT, SORT_ITER,
 | 
			
		||||
  
 | 
			
		||||
  /* Getting iters */
 | 
			
		||||
  GET_BEGIN_ITER, GET_END_ITER, GET_ITER_AT_POS, APPEND, PREPEND,
 | 
			
		||||
    INSERT_BEFORE, MOVE, INSERT_SORTED, INSERT_SORTED_ITER, SORT_CHANGED,
 | 
			
		||||
  INSERT_BEFORE, MOVE, SWAP, INSERT_SORTED, INSERT_SORTED_ITER, SORT_CHANGED,
 | 
			
		||||
  SORT_CHANGED_ITER, REMOVE, REMOVE_RANGE, MOVE_RANGE, SEARCH, SEARCH_ITER,
 | 
			
		||||
  
 | 
			
		||||
  /* dereferencing */
 | 
			
		||||
@@ -21,7 +20,7 @@ enum
 | 
			
		||||
  /* search */
 | 
			
		||||
  ITER_COMPARE, RANGE_GET_MIDPOINT,
 | 
			
		||||
  N_OPS
 | 
			
		||||
  } Op;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct SequenceInfo
 | 
			
		||||
{
 | 
			
		||||
@@ -70,7 +69,10 @@ check_integrity (SequenceInfo *info)
 | 
			
		||||
  i = 0;
 | 
			
		||||
  while (iter != g_sequence_get_end_iter (info->sequence))
 | 
			
		||||
    {
 | 
			
		||||
      Item *item;
 | 
			
		||||
      g_assert (list->data == iter);
 | 
			
		||||
      item = get_item (list->data);
 | 
			
		||||
      g_assert (item->seq == info);
 | 
			
		||||
      
 | 
			
		||||
      iter = g_sequence_iter_next (iter);
 | 
			
		||||
      list = list->next;
 | 
			
		||||
@@ -312,6 +314,7 @@ run_random_tests (guint32 seed)
 | 
			
		||||
{
 | 
			
		||||
#define N_ITERATIONS 60000
 | 
			
		||||
#define N_SEQUENCES 8
 | 
			
		||||
#define N_TIMES 24
 | 
			
		||||
    
 | 
			
		||||
  SequenceInfo sequences[N_SEQUENCES];
 | 
			
		||||
  int k;
 | 
			
		||||
@@ -501,8 +504,10 @@ run_random_tests (guint32 seed)
 | 
			
		||||
 	case MOVE:
 | 
			
		||||
	  {
 | 
			
		||||
	    GList *link1, *link2;
 | 
			
		||||
	    GSequenceIter *iter1 = get_random_iter (seq, &link1);
 | 
			
		||||
	    GSequenceIter *iter2 = get_random_iter (seq, &link2);
 | 
			
		||||
	    SequenceInfo *seq1 = RANDOM_SEQUENCE();
 | 
			
		||||
	    SequenceInfo *seq2 = RANDOM_SEQUENCE();
 | 
			
		||||
	    GSequenceIter *iter1 = get_random_iter (seq1, &link1);
 | 
			
		||||
	    GSequenceIter *iter2 = get_random_iter (seq2, &link2);
 | 
			
		||||
	    
 | 
			
		||||
	    if (!g_sequence_iter_is_end (iter1))
 | 
			
		||||
	      {
 | 
			
		||||
@@ -511,9 +516,14 @@ run_random_tests (guint32 seed)
 | 
			
		||||
		if (!link2)
 | 
			
		||||
		  g_assert (g_sequence_iter_is_end (iter2));
 | 
			
		||||
		
 | 
			
		||||
		queue_insert_before (seq, link2, link1->data);
 | 
			
		||||
		queue_insert_before (seq2, link2, link1->data);
 | 
			
		||||
		
 | 
			
		||||
		g_queue_delete_link (seq->queue, link1);
 | 
			
		||||
		g_queue_delete_link (seq1->queue, link1);
 | 
			
		||||
 | 
			
		||||
		get_item (iter1)->seq = seq2;
 | 
			
		||||
		
 | 
			
		||||
		seq1->n_items--;
 | 
			
		||||
		seq2->n_items++;
 | 
			
		||||
	      }
 | 
			
		||||
	    
 | 
			
		||||
	    check_integrity (seq);
 | 
			
		||||
@@ -525,6 +535,30 @@ run_random_tests (guint32 seed)
 | 
			
		||||
	      g_sequence_move (iter1, iter1);
 | 
			
		||||
	  }
 | 
			
		||||
	  break;
 | 
			
		||||
	case SWAP:
 | 
			
		||||
	  {
 | 
			
		||||
	    GList *link1, *link2;
 | 
			
		||||
	    SequenceInfo *seq1 = RANDOM_SEQUENCE();
 | 
			
		||||
	    SequenceInfo *seq2 = RANDOM_SEQUENCE();
 | 
			
		||||
	    GSequenceIter *iter1 = get_random_iter (seq1, &link1);
 | 
			
		||||
	    GSequenceIter *iter2 = get_random_iter (seq2, &link2);
 | 
			
		||||
	    
 | 
			
		||||
	    if (!g_sequence_iter_is_end (iter1) &&
 | 
			
		||||
		!g_sequence_iter_is_end (iter2))
 | 
			
		||||
	      {
 | 
			
		||||
		gpointer tmp;
 | 
			
		||||
 | 
			
		||||
		g_sequence_swap (iter1, iter2);
 | 
			
		||||
 | 
			
		||||
		get_item (iter1)->seq = seq2;
 | 
			
		||||
		get_item (iter2)->seq = seq1;
 | 
			
		||||
		
 | 
			
		||||
		tmp = link1->data;
 | 
			
		||||
		link1->data = link2->data;
 | 
			
		||||
		link2->data = tmp;
 | 
			
		||||
	      }
 | 
			
		||||
	  }
 | 
			
		||||
	  break;
 | 
			
		||||
	case INSERT_SORTED:
 | 
			
		||||
	  {
 | 
			
		||||
	    int i;
 | 
			
		||||
@@ -535,7 +569,7 @@ run_random_tests (guint32 seed)
 | 
			
		||||
	    
 | 
			
		||||
	    check_sorted (seq);
 | 
			
		||||
	    
 | 
			
		||||
	    for (i = 0; i < 15; ++i)
 | 
			
		||||
	    for (i = 0; i < N_TIMES; ++i)
 | 
			
		||||
	      {
 | 
			
		||||
		GSequenceIter *iter =
 | 
			
		||||
		  g_sequence_insert_sorted (seq->sequence, new_item(seq), compare_items, NULL);
 | 
			
		||||
@@ -558,7 +592,7 @@ run_random_tests (guint32 seed)
 | 
			
		||||
	    
 | 
			
		||||
	    check_sorted (seq);
 | 
			
		||||
	    
 | 
			
		||||
	    for (i = 0; i < 15; ++i)
 | 
			
		||||
	    for (i = 0; i < N_TIMES; ++i)
 | 
			
		||||
	      {
 | 
			
		||||
		GSequenceIter *iter;
 | 
			
		||||
 | 
			
		||||
@@ -584,7 +618,7 @@ run_random_tests (guint32 seed)
 | 
			
		||||
	    
 | 
			
		||||
	    check_sorted (seq);
 | 
			
		||||
	    
 | 
			
		||||
	    for (i = 0; i < 15; ++i)
 | 
			
		||||
	    for (i = 0; i < N_TIMES; ++i)
 | 
			
		||||
	      {
 | 
			
		||||
		GList *link;
 | 
			
		||||
		GSequenceIter *iter = get_random_iter (seq, &link);
 | 
			
		||||
@@ -611,7 +645,7 @@ run_random_tests (guint32 seed)
 | 
			
		||||
	    
 | 
			
		||||
	    check_sorted (seq);
 | 
			
		||||
	    
 | 
			
		||||
	    for (i = 0; i < 15; ++i)
 | 
			
		||||
	    for (i = 0; i < N_TIMES; ++i)
 | 
			
		||||
	      {
 | 
			
		||||
		GList *link;
 | 
			
		||||
		GSequenceIter *iter = get_random_iter (seq, &link);
 | 
			
		||||
@@ -634,7 +668,7 @@ run_random_tests (guint32 seed)
 | 
			
		||||
	  {
 | 
			
		||||
	    int i;
 | 
			
		||||
	    
 | 
			
		||||
	    for (i = 0; i < 15; ++i)
 | 
			
		||||
	    for (i = 0; i < N_TIMES; ++i)
 | 
			
		||||
	      {
 | 
			
		||||
		GList *link;
 | 
			
		||||
		GSequenceIter *iter = get_random_iter (seq, &link);
 | 
			
		||||
@@ -796,7 +830,7 @@ run_random_tests (guint32 seed)
 | 
			
		||||
		g_assert (g_sequence_get (iter) == item);
 | 
			
		||||
		
 | 
			
		||||
		/* Make sure that existing items are freed */
 | 
			
		||||
		for (i = 0; i < 15; ++i)
 | 
			
		||||
		for (i = 0; i < N_TIMES; ++i)
 | 
			
		||||
		  g_sequence_set (iter, new_item (seq));
 | 
			
		||||
		
 | 
			
		||||
		check_integrity (seq);
 | 
			
		||||
@@ -1114,6 +1148,8 @@ test_insert_sorted_non_pointer (void)
 | 
			
		||||
					 compare_iter, NULL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      g_sequence_self_test_internal_to_glib_dont_use (seq);
 | 
			
		||||
      
 | 
			
		||||
      g_sequence_free (seq);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1130,15 +1166,23 @@ test_stable_sort (void)
 | 
			
		||||
  GSequenceIter *iter;
 | 
			
		||||
  
 | 
			
		||||
  for (i = 0; i < N_ITEMS; ++i)
 | 
			
		||||
    {
 | 
			
		||||
      iters[i] = g_sequence_append (seq, GINT_TO_POINTER (3000)); 
 | 
			
		||||
      g_sequence_self_test_internal_to_glib_dont_use (seq);
 | 
			
		||||
      g_assert (g_sequence_iter_get_sequence (iters[i]) == seq);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
  i = 0;
 | 
			
		||||
  iter = g_sequence_get_begin_iter (seq);
 | 
			
		||||
  g_assert (g_sequence_iter_get_sequence (iter) == seq);
 | 
			
		||||
  g_sequence_self_test_internal_to_glib_dont_use (seq);
 | 
			
		||||
  while (!g_sequence_iter_is_end (iter))
 | 
			
		||||
    {
 | 
			
		||||
      g_assert (g_sequence_iter_get_sequence (iters[i]) == seq);
 | 
			
		||||
      g_assert (iters[i++] == iter);
 | 
			
		||||
      
 | 
			
		||||
      iter = g_sequence_iter_next (iter);
 | 
			
		||||
      g_sequence_self_test_internal_to_glib_dont_use (seq);
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  g_sequence_sort (seq, compare, NULL);
 | 
			
		||||
@@ -1147,13 +1191,22 @@ test_stable_sort (void)
 | 
			
		||||
  iter = g_sequence_get_begin_iter (seq);
 | 
			
		||||
  while (!g_sequence_iter_is_end (iter))
 | 
			
		||||
    {
 | 
			
		||||
      g_assert (iters[i++] == iter);
 | 
			
		||||
      g_assert (g_sequence_iter_get_sequence (iters[i]) == seq);
 | 
			
		||||
      g_assert (iters[i] == iter);
 | 
			
		||||
      
 | 
			
		||||
      iter = g_sequence_iter_next (iter);
 | 
			
		||||
      g_sequence_self_test_internal_to_glib_dont_use (seq);
 | 
			
		||||
 | 
			
		||||
      i++;
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  for (i = N_ITEMS - 1; i >= 0; --i)
 | 
			
		||||
    {
 | 
			
		||||
      g_sequence_self_test_internal_to_glib_dont_use (seq);
 | 
			
		||||
      g_assert (g_sequence_iter_get_sequence (iters[i]) == seq);
 | 
			
		||||
      g_assert (g_sequence_get_end_iter (seq) != iters[i]);
 | 
			
		||||
      g_sequence_sort_changed (iters[i], compare, NULL);
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  i = 0;
 | 
			
		||||
  iter = g_sequence_get_begin_iter (seq);
 | 
			
		||||
@@ -1162,6 +1215,7 @@ test_stable_sort (void)
 | 
			
		||||
      g_assert (iters[i++] == iter);
 | 
			
		||||
      
 | 
			
		||||
      iter = g_sequence_iter_next (iter);
 | 
			
		||||
      g_sequence_self_test_internal_to_glib_dont_use (seq);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user