glib/libglib/src/gnode.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /* GLIB - Library of useful routines for C programming
       
     2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
       
     3  *
       
     4  * GNode: N-way tree implementation.
       
     5  * Copyright (C) 1998 Tim Janik
       
     6  * Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
       
     7  *
       
     8  * This library is free software; you can redistribute it and/or
       
     9  * modify it under the terms of the GNU Lesser General Public
       
    10  * License as published by the Free Software Foundation; either
       
    11  * version 2 of the License, or (at your option) any later version.
       
    12  *
       
    13  * This library is distributed in the hope that it will be useful,
       
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
       
    16  * Lesser General Public License for more details.
       
    17  *
       
    18  * You should have received a copy of the GNU Lesser General Public
       
    19  * License along with this library; if not, write to the
       
    20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    21  * Boston, MA 02111-1307, USA.
       
    22  */
       
    23 
       
    24 /*
       
    25  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
       
    26  * file for a list of people on the GLib Team.  See the ChangeLog
       
    27  * files for a list of changes.  These files are distributed with
       
    28  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
       
    29  */
       
    30 
       
    31 /* 
       
    32  * MT safe
       
    33  */
       
    34 
       
    35 #include "config.h"
       
    36 
       
    37 #include "glib.h"
       
    38 #include "galias.h"
       
    39 
       
    40 EXPORT_C void g_node_push_allocator (gpointer dummy) { /* present for binary compat only */ }
       
    41 EXPORT_C void g_node_pop_allocator  (void)           { /* present for binary compat only */ }
       
    42 
       
    43 #define g_node_alloc0()         g_slice_new0 (GNode)
       
    44 #define g_node_free(node)       g_slice_free (GNode, node)
       
    45 
       
    46 /* --- functions --- */
       
    47 EXPORT_C GNode*
       
    48 g_node_new (gpointer data)
       
    49 {
       
    50   GNode *node = g_node_alloc0();
       
    51   node->data = data;
       
    52   return node;
       
    53 }
       
    54 
       
    55 static void
       
    56 g_nodes_free (GNode *node)
       
    57 {
       
    58   while (node)
       
    59     {
       
    60       GNode *next = node->next;
       
    61       if (node->children)
       
    62         g_nodes_free (node->children);
       
    63       g_node_free (node);
       
    64       node = next;
       
    65     }
       
    66 }
       
    67 
       
    68 EXPORT_C void
       
    69 g_node_destroy (GNode *root)
       
    70 {
       
    71   g_return_if_fail (root != NULL);
       
    72   
       
    73   if (!G_NODE_IS_ROOT (root))
       
    74     g_node_unlink (root);
       
    75   
       
    76   g_nodes_free (root);
       
    77 }
       
    78 
       
    79 EXPORT_C void
       
    80 g_node_unlink (GNode *node)
       
    81 {
       
    82   g_return_if_fail (node != NULL);
       
    83   
       
    84   if (node->prev)
       
    85     node->prev->next = node->next;
       
    86   else if (node->parent)
       
    87     node->parent->children = node->next;
       
    88   node->parent = NULL;
       
    89   if (node->next)
       
    90     {
       
    91       node->next->prev = node->prev;
       
    92       node->next = NULL;
       
    93     }
       
    94   node->prev = NULL;
       
    95 }
       
    96 
       
    97 /**
       
    98  * g_node_copy_deep:
       
    99  * @node: a #GNode
       
   100  * @copy_func: the function which is called to copy the data inside each node,
       
   101  *   or %NULL to use the original data.
       
   102  * @data: data to pass to @copy_func
       
   103  * 
       
   104  * Recursively copies a #GNode and its data.
       
   105  * 
       
   106  * Return value: a new #GNode containing copies of the data in @node.
       
   107  *
       
   108  * Since: 2.4
       
   109  **/
       
   110 EXPORT_C GNode*
       
   111 g_node_copy_deep (GNode     *node, 
       
   112 		  GCopyFunc  copy_func,
       
   113 		  gpointer   data)
       
   114 {
       
   115   GNode *new_node = NULL;
       
   116 
       
   117   if (copy_func == NULL)
       
   118 	return g_node_copy (node);
       
   119 
       
   120   if (node)
       
   121     {
       
   122       GNode *child, *new_child;
       
   123       
       
   124       new_node = g_node_new (copy_func (node->data, data));
       
   125       
       
   126       for (child = g_node_last_child (node); child; child = child->prev) 
       
   127 	{
       
   128 	  new_child = g_node_copy_deep (child, copy_func, data);
       
   129 	  g_node_prepend (new_node, new_child);
       
   130 	}
       
   131     }
       
   132   
       
   133   return new_node;
       
   134 }
       
   135 
       
   136 EXPORT_C GNode*
       
   137 g_node_copy (GNode *node)
       
   138 {
       
   139   GNode *new_node = NULL;
       
   140   
       
   141   if (node)
       
   142     {
       
   143       GNode *child;
       
   144       
       
   145       new_node = g_node_new (node->data);
       
   146       
       
   147       for (child = g_node_last_child (node); child; child = child->prev)
       
   148 	g_node_prepend (new_node, g_node_copy (child));
       
   149     }
       
   150   
       
   151   return new_node;
       
   152 }
       
   153 
       
   154 EXPORT_C GNode*
       
   155 g_node_insert (GNode *parent,
       
   156 	       gint   position,
       
   157 	       GNode *node)
       
   158 {
       
   159   g_return_val_if_fail (parent != NULL, node);
       
   160   g_return_val_if_fail (node != NULL, node);
       
   161   g_return_val_if_fail (G_NODE_IS_ROOT (node), node);
       
   162   
       
   163   if (position > 0)
       
   164     return g_node_insert_before (parent,
       
   165 				 g_node_nth_child (parent, position),
       
   166 				 node);
       
   167   else if (position == 0)
       
   168     return g_node_prepend (parent, node);
       
   169   else /* if (position < 0) */
       
   170     return g_node_append (parent, node);
       
   171 }
       
   172 
       
   173 EXPORT_C GNode*
       
   174 g_node_insert_before (GNode *parent,
       
   175 		      GNode *sibling,
       
   176 		      GNode *node)
       
   177 {
       
   178   g_return_val_if_fail (parent != NULL, node);
       
   179   g_return_val_if_fail (node != NULL, node);
       
   180   g_return_val_if_fail (G_NODE_IS_ROOT (node), node);
       
   181   if (sibling)
       
   182     g_return_val_if_fail (sibling->parent == parent, node);
       
   183   
       
   184   node->parent = parent;
       
   185   
       
   186   if (sibling)
       
   187     {
       
   188       if (sibling->prev)
       
   189 	{
       
   190 	  node->prev = sibling->prev;
       
   191 	  node->prev->next = node;
       
   192 	  node->next = sibling;
       
   193 	  sibling->prev = node;
       
   194 	}
       
   195       else
       
   196 	{
       
   197 	  node->parent->children = node;
       
   198 	  node->next = sibling;
       
   199 	  sibling->prev = node;
       
   200 	}
       
   201     }
       
   202   else
       
   203     {
       
   204       if (parent->children)
       
   205 	{
       
   206 	  sibling = parent->children;
       
   207 	  while (sibling->next)
       
   208 	    sibling = sibling->next;
       
   209 	  node->prev = sibling;
       
   210 	  sibling->next = node;
       
   211 	}
       
   212       else
       
   213 	node->parent->children = node;
       
   214     }
       
   215 
       
   216   return node;
       
   217 }
       
   218 
       
   219 EXPORT_C GNode*
       
   220 g_node_insert_after (GNode *parent,
       
   221 		     GNode *sibling,
       
   222 		     GNode *node)
       
   223 {
       
   224   g_return_val_if_fail (parent != NULL, node);
       
   225   g_return_val_if_fail (node != NULL, node);
       
   226   g_return_val_if_fail (G_NODE_IS_ROOT (node), node);
       
   227   if (sibling)
       
   228     g_return_val_if_fail (sibling->parent == parent, node);
       
   229 
       
   230   node->parent = parent;
       
   231 
       
   232   if (sibling)
       
   233     {
       
   234       if (sibling->next)
       
   235 	{
       
   236 	  sibling->next->prev = node;
       
   237 	}
       
   238       node->next = sibling->next;
       
   239       node->prev = sibling;
       
   240       sibling->next = node;
       
   241     }
       
   242   else
       
   243     {
       
   244       if (parent->children)
       
   245 	{
       
   246 	  node->next = parent->children;
       
   247 	  parent->children->prev = node;
       
   248 	}
       
   249       parent->children = node;
       
   250     }
       
   251 
       
   252   return node;
       
   253 }
       
   254 
       
   255 EXPORT_C GNode*
       
   256 g_node_prepend (GNode *parent,
       
   257 		GNode *node)
       
   258 {
       
   259   g_return_val_if_fail (parent != NULL, node);
       
   260   
       
   261   return g_node_insert_before (parent, parent->children, node);
       
   262 }
       
   263 
       
   264 EXPORT_C GNode*
       
   265 g_node_get_root (GNode *node)
       
   266 {
       
   267   g_return_val_if_fail (node != NULL, NULL);
       
   268   
       
   269   while (node->parent)
       
   270     node = node->parent;
       
   271   
       
   272   return node;
       
   273 }
       
   274 
       
   275 EXPORT_C gboolean
       
   276 g_node_is_ancestor (GNode *node,
       
   277 		    GNode *descendant)
       
   278 {
       
   279   g_return_val_if_fail (node != NULL, FALSE);
       
   280   g_return_val_if_fail (descendant != NULL, FALSE);
       
   281   
       
   282   while (descendant)
       
   283     {
       
   284       if (descendant->parent == node)
       
   285 	return TRUE;
       
   286       
       
   287       descendant = descendant->parent;
       
   288     }
       
   289   
       
   290   return FALSE;
       
   291 }
       
   292 
       
   293 /* returns 1 for root, 2 for first level children,
       
   294  * 3 for children's children...
       
   295  */
       
   296 EXPORT_C guint
       
   297 g_node_depth (GNode *node)
       
   298 {
       
   299   register guint depth = 0;
       
   300   
       
   301   while (node)
       
   302     {
       
   303       depth++;
       
   304       node = node->parent;
       
   305     }
       
   306   
       
   307   return depth;
       
   308 }
       
   309 
       
   310 EXPORT_C void
       
   311 g_node_reverse_children (GNode *node)
       
   312 {
       
   313   GNode *child;
       
   314   GNode *last;
       
   315   
       
   316   g_return_if_fail (node != NULL);
       
   317   
       
   318   child = node->children;
       
   319   last = NULL;
       
   320   while (child)
       
   321     {
       
   322       last = child;
       
   323       child = last->next;
       
   324       last->next = last->prev;
       
   325       last->prev = child;
       
   326     }
       
   327   node->children = last;
       
   328 }
       
   329 
       
   330 EXPORT_C guint
       
   331 g_node_max_height (GNode *root)
       
   332 {
       
   333   register GNode *child;
       
   334   register guint max_height = 0;
       
   335   
       
   336   if (!root)
       
   337     return 0;
       
   338   
       
   339   child = root->children;
       
   340   while (child)
       
   341     {
       
   342       register guint tmp_height;
       
   343       
       
   344       tmp_height = g_node_max_height (child);
       
   345       if (tmp_height > max_height)
       
   346 	max_height = tmp_height;
       
   347       child = child->next;
       
   348     }
       
   349   
       
   350   return max_height + 1;
       
   351 }
       
   352 
       
   353 static gboolean
       
   354 g_node_traverse_pre_order (GNode	    *node,
       
   355 			   GTraverseFlags    flags,
       
   356 			   GNodeTraverseFunc func,
       
   357 			   gpointer	     data)
       
   358 {
       
   359   if (node->children)
       
   360     {
       
   361       GNode *child;
       
   362       
       
   363       if ((flags & G_TRAVERSE_NON_LEAFS) &&
       
   364 	  func (node, data))
       
   365 	return TRUE;
       
   366       
       
   367       child = node->children;
       
   368       while (child)
       
   369 	{
       
   370 	  register GNode *current;
       
   371 	  
       
   372 	  current = child;
       
   373 	  child = current->next;
       
   374 	  if (g_node_traverse_pre_order (current, flags, func, data))
       
   375 	    return TRUE;
       
   376 	}
       
   377     }
       
   378   else if ((flags & G_TRAVERSE_LEAFS) &&
       
   379 	   func (node, data))
       
   380     return TRUE;
       
   381   
       
   382   return FALSE;
       
   383 }
       
   384 
       
   385 static gboolean
       
   386 g_node_depth_traverse_pre_order (GNode		  *node,
       
   387 				 GTraverseFlags	   flags,
       
   388 				 guint		   depth,
       
   389 				 GNodeTraverseFunc func,
       
   390 				 gpointer	   data)
       
   391 {
       
   392   if (node->children)
       
   393     {
       
   394       GNode *child;
       
   395       
       
   396       if ((flags & G_TRAVERSE_NON_LEAFS) &&
       
   397 	  func (node, data))
       
   398 	return TRUE;
       
   399       
       
   400       depth--;
       
   401       if (!depth)
       
   402 	return FALSE;
       
   403       
       
   404       child = node->children;
       
   405       while (child)
       
   406 	{
       
   407 	  register GNode *current;
       
   408 	  
       
   409 	  current = child;
       
   410 	  child = current->next;
       
   411 	  if (g_node_depth_traverse_pre_order (current, flags, depth, func, data))
       
   412 	    return TRUE;
       
   413 	}
       
   414     }
       
   415   else if ((flags & G_TRAVERSE_LEAFS) &&
       
   416 	   func (node, data))
       
   417     return TRUE;
       
   418   
       
   419   return FALSE;
       
   420 }
       
   421 
       
   422 static gboolean
       
   423 g_node_traverse_post_order (GNode	     *node,
       
   424 			    GTraverseFlags    flags,
       
   425 			    GNodeTraverseFunc func,
       
   426 			    gpointer	      data)
       
   427 {
       
   428   if (node->children)
       
   429     {
       
   430       GNode *child;
       
   431       
       
   432       child = node->children;
       
   433       while (child)
       
   434 	{
       
   435 	  register GNode *current;
       
   436 	  
       
   437 	  current = child;
       
   438 	  child = current->next;
       
   439 	  if (g_node_traverse_post_order (current, flags, func, data))
       
   440 	    return TRUE;
       
   441 	}
       
   442       
       
   443       if ((flags & G_TRAVERSE_NON_LEAFS) &&
       
   444 	  func (node, data))
       
   445 	return TRUE;
       
   446       
       
   447     }
       
   448   else if ((flags & G_TRAVERSE_LEAFS) &&
       
   449 	   func (node, data))
       
   450     return TRUE;
       
   451   
       
   452   return FALSE;
       
   453 }
       
   454 
       
   455 static gboolean
       
   456 g_node_depth_traverse_post_order (GNode		   *node,
       
   457 				  GTraverseFlags    flags,
       
   458 				  guint		    depth,
       
   459 				  GNodeTraverseFunc func,
       
   460 				  gpointer	    data)
       
   461 {
       
   462   if (node->children)
       
   463     {
       
   464       depth--;
       
   465       if (depth)
       
   466 	{
       
   467 	  GNode *child;
       
   468 	  
       
   469 	  child = node->children;
       
   470 	  while (child)
       
   471 	    {
       
   472 	      register GNode *current;
       
   473 	      
       
   474 	      current = child;
       
   475 	      child = current->next;
       
   476 	      if (g_node_depth_traverse_post_order (current, flags, depth, func, data))
       
   477 		return TRUE;
       
   478 	    }
       
   479 	}
       
   480       
       
   481       if ((flags & G_TRAVERSE_NON_LEAFS) &&
       
   482 	  func (node, data))
       
   483 	return TRUE;
       
   484       
       
   485     }
       
   486   else if ((flags & G_TRAVERSE_LEAFS) &&
       
   487 	   func (node, data))
       
   488     return TRUE;
       
   489   
       
   490   return FALSE;
       
   491 }
       
   492 
       
   493 static gboolean
       
   494 g_node_traverse_in_order (GNode		   *node,
       
   495 			  GTraverseFlags    flags,
       
   496 			  GNodeTraverseFunc func,
       
   497 			  gpointer	    data)
       
   498 {
       
   499   if (node->children)
       
   500     {
       
   501       GNode *child;
       
   502       register GNode *current;
       
   503       
       
   504       child = node->children;
       
   505       current = child;
       
   506       child = current->next;
       
   507       
       
   508       if (g_node_traverse_in_order (current, flags, func, data))
       
   509 	return TRUE;
       
   510       
       
   511       if ((flags & G_TRAVERSE_NON_LEAFS) &&
       
   512 	  func (node, data))
       
   513 	return TRUE;
       
   514       
       
   515       while (child)
       
   516 	{
       
   517 	  current = child;
       
   518 	  child = current->next;
       
   519 	  if (g_node_traverse_in_order (current, flags, func, data))
       
   520 	    return TRUE;
       
   521 	}
       
   522     }
       
   523   else if ((flags & G_TRAVERSE_LEAFS) &&
       
   524 	   func (node, data))
       
   525     return TRUE;
       
   526   
       
   527   return FALSE;
       
   528 }
       
   529 
       
   530 static gboolean
       
   531 g_node_depth_traverse_in_order (GNode		 *node,
       
   532 				GTraverseFlags	  flags,
       
   533 				guint		  depth,
       
   534 				GNodeTraverseFunc func,
       
   535 				gpointer	  data)
       
   536 {
       
   537   if (node->children)
       
   538     {
       
   539       depth--;
       
   540       if (depth)
       
   541 	{
       
   542 	  GNode *child;
       
   543 	  register GNode *current;
       
   544 	  
       
   545 	  child = node->children;
       
   546 	  current = child;
       
   547 	  child = current->next;
       
   548 	  
       
   549 	  if (g_node_depth_traverse_in_order (current, flags, depth, func, data))
       
   550 	    return TRUE;
       
   551 	  
       
   552 	  if ((flags & G_TRAVERSE_NON_LEAFS) &&
       
   553 	      func (node, data))
       
   554 	    return TRUE;
       
   555 	  
       
   556 	  while (child)
       
   557 	    {
       
   558 	      current = child;
       
   559 	      child = current->next;
       
   560 	      if (g_node_depth_traverse_in_order (current, flags, depth, func, data))
       
   561 		return TRUE;
       
   562 	    }
       
   563 	}
       
   564       else if ((flags & G_TRAVERSE_NON_LEAFS) &&
       
   565 	       func (node, data))
       
   566 	return TRUE;
       
   567     }
       
   568   else if ((flags & G_TRAVERSE_LEAFS) &&
       
   569 	   func (node, data))
       
   570     return TRUE;
       
   571   
       
   572   return FALSE;
       
   573 }
       
   574 
       
   575 static gboolean
       
   576 g_node_traverse_level (GNode		 *node,
       
   577 		       GTraverseFlags	  flags,
       
   578 		       guint		  level,
       
   579 		       GNodeTraverseFunc func,
       
   580 		       gpointer	  data,
       
   581 		       gboolean         *more_levels)
       
   582 {
       
   583   if (level == 0) 
       
   584     {
       
   585       if (node->children)
       
   586 	{
       
   587 	  *more_levels = TRUE;
       
   588 	  return (flags & G_TRAVERSE_NON_LEAFS) && func (node, data);
       
   589 	}
       
   590       else
       
   591 	{
       
   592 	  return (flags & G_TRAVERSE_LEAFS) && func (node, data);
       
   593 	}
       
   594     }
       
   595   else 
       
   596     {
       
   597       node = node->children;
       
   598       
       
   599       while (node)
       
   600 	{
       
   601 	  if (g_node_traverse_level (node, flags, level - 1, func, data, more_levels))
       
   602 	    return TRUE;
       
   603 
       
   604 	  node = node->next;
       
   605 	}
       
   606     }
       
   607 
       
   608   return FALSE;
       
   609 }
       
   610 
       
   611 static gboolean
       
   612 g_node_depth_traverse_level (GNode		 *node,
       
   613 			     GTraverseFlags	  flags,
       
   614 			     guint		  depth,
       
   615 			     GNodeTraverseFunc func,
       
   616 			     gpointer	  data)
       
   617 {
       
   618   guint level;
       
   619   gboolean more_levels;
       
   620 
       
   621   level = 0;  
       
   622   while (level != depth) 
       
   623     {
       
   624       more_levels = FALSE;
       
   625       if (g_node_traverse_level (node, flags, level, func, data, &more_levels))
       
   626 	return TRUE;
       
   627       if (!more_levels)
       
   628 	break;
       
   629       level++;
       
   630     }
       
   631   return FALSE;
       
   632 }
       
   633 
       
   634 EXPORT_C void
       
   635 g_node_traverse (GNode		  *root,
       
   636 		 GTraverseType	   order,
       
   637 		 GTraverseFlags	   flags,
       
   638 		 gint		   depth,
       
   639 		 GNodeTraverseFunc func,
       
   640 		 gpointer	   data)
       
   641 {
       
   642   g_return_if_fail (root != NULL);
       
   643   g_return_if_fail (func != NULL);
       
   644   g_return_if_fail (order <= G_LEVEL_ORDER);
       
   645   g_return_if_fail (flags <= G_TRAVERSE_MASK);
       
   646   g_return_if_fail (depth == -1 || depth > 0);
       
   647   
       
   648   switch (order)
       
   649     {
       
   650     case G_PRE_ORDER:
       
   651       if (depth < 0)
       
   652 	g_node_traverse_pre_order (root, flags, func, data);
       
   653       else
       
   654 	g_node_depth_traverse_pre_order (root, flags, depth, func, data);
       
   655       break;
       
   656     case G_POST_ORDER:
       
   657       if (depth < 0)
       
   658 	g_node_traverse_post_order (root, flags, func, data);
       
   659       else
       
   660 	g_node_depth_traverse_post_order (root, flags, depth, func, data);
       
   661       break;
       
   662     case G_IN_ORDER:
       
   663       if (depth < 0)
       
   664 	g_node_traverse_in_order (root, flags, func, data);
       
   665       else
       
   666 	g_node_depth_traverse_in_order (root, flags, depth, func, data);
       
   667       break;
       
   668     case G_LEVEL_ORDER:
       
   669       g_node_depth_traverse_level (root, flags, depth, func, data);
       
   670       break;
       
   671     }
       
   672 }
       
   673 
       
   674 static gboolean
       
   675 g_node_find_func (GNode	  *node,
       
   676 		  gpointer data)
       
   677 {
       
   678   register gpointer *d = data;
       
   679   
       
   680   if (*d != node->data)
       
   681     return FALSE;
       
   682   
       
   683   *(++d) = node;
       
   684   
       
   685   return TRUE;
       
   686 }
       
   687 
       
   688 EXPORT_C GNode*
       
   689 g_node_find (GNode	       *root,
       
   690 	     GTraverseType	order,
       
   691 	     GTraverseFlags	flags,
       
   692 	     gpointer		data)
       
   693 {
       
   694   gpointer d[2];
       
   695   
       
   696   g_return_val_if_fail (root != NULL, NULL);
       
   697   g_return_val_if_fail (order <= G_LEVEL_ORDER, NULL);
       
   698   g_return_val_if_fail (flags <= G_TRAVERSE_MASK, NULL);
       
   699   
       
   700   d[0] = data;
       
   701   d[1] = NULL;
       
   702   
       
   703   g_node_traverse (root, order, flags, -1, g_node_find_func, d);
       
   704   
       
   705   return d[1];
       
   706 }
       
   707 
       
   708 static void
       
   709 g_node_count_func (GNode	 *node,
       
   710 		   GTraverseFlags flags,
       
   711 		   guint	 *n)
       
   712 {
       
   713   if (node->children)
       
   714     {
       
   715       GNode *child;
       
   716       
       
   717       if (flags & G_TRAVERSE_NON_LEAFS)
       
   718 	(*n)++;
       
   719       
       
   720       child = node->children;
       
   721       while (child)
       
   722 	{
       
   723 	  g_node_count_func (child, flags, n);
       
   724 	  child = child->next;
       
   725 	}
       
   726     }
       
   727   else if (flags & G_TRAVERSE_LEAFS)
       
   728     (*n)++;
       
   729 }
       
   730 
       
   731 EXPORT_C guint
       
   732 g_node_n_nodes (GNode	      *root,
       
   733 		GTraverseFlags flags)
       
   734 {
       
   735   guint n = 0;
       
   736   
       
   737   g_return_val_if_fail (root != NULL, 0);
       
   738   g_return_val_if_fail (flags <= G_TRAVERSE_MASK, 0);
       
   739   
       
   740   g_node_count_func (root, flags, &n);
       
   741   
       
   742   return n;
       
   743 }
       
   744 
       
   745 EXPORT_C GNode*
       
   746 g_node_last_child (GNode *node)
       
   747 {
       
   748   g_return_val_if_fail (node != NULL, NULL);
       
   749   
       
   750   node = node->children;
       
   751   if (node)
       
   752     while (node->next)
       
   753       node = node->next;
       
   754   
       
   755   return node;
       
   756 }
       
   757 
       
   758 EXPORT_C GNode*
       
   759 g_node_nth_child (GNode *node,
       
   760 		  guint	 n)
       
   761 {
       
   762   g_return_val_if_fail (node != NULL, NULL);
       
   763   
       
   764   node = node->children;
       
   765   if (node)
       
   766     while ((n-- > 0) && node)
       
   767       node = node->next;
       
   768   
       
   769   return node;
       
   770 }
       
   771 
       
   772 EXPORT_C guint
       
   773 g_node_n_children (GNode *node)
       
   774 {
       
   775   guint n = 0;
       
   776   
       
   777   g_return_val_if_fail (node != NULL, 0);
       
   778   
       
   779   node = node->children;
       
   780   while (node)
       
   781     {
       
   782       n++;
       
   783       node = node->next;
       
   784     }
       
   785   
       
   786   return n;
       
   787 }
       
   788 
       
   789 EXPORT_C GNode*
       
   790 g_node_find_child (GNode	 *node,
       
   791 		   GTraverseFlags flags,
       
   792 		   gpointer	  data)
       
   793 {
       
   794   g_return_val_if_fail (node != NULL, NULL);
       
   795   g_return_val_if_fail (flags <= G_TRAVERSE_MASK, NULL);
       
   796   
       
   797   node = node->children;
       
   798   while (node)
       
   799     {
       
   800       if (node->data == data)
       
   801 	{
       
   802 	  if (G_NODE_IS_LEAF (node))
       
   803 	    {
       
   804 	      if (flags & G_TRAVERSE_LEAFS)
       
   805 		return node;
       
   806 	    }
       
   807 	  else
       
   808 	    {
       
   809 	      if (flags & G_TRAVERSE_NON_LEAFS)
       
   810 		return node;
       
   811 	    }
       
   812 	}
       
   813       node = node->next;
       
   814     }
       
   815   
       
   816   return NULL;
       
   817 }
       
   818 
       
   819 EXPORT_C gint
       
   820 g_node_child_position (GNode *node,
       
   821 		       GNode *child)
       
   822 {
       
   823   register guint n = 0;
       
   824   
       
   825   g_return_val_if_fail (node != NULL, -1);
       
   826   g_return_val_if_fail (child != NULL, -1);
       
   827   g_return_val_if_fail (child->parent == node, -1);
       
   828   
       
   829   node = node->children;
       
   830   while (node)
       
   831     {
       
   832       if (node == child)
       
   833 	return n;
       
   834       n++;
       
   835       node = node->next;
       
   836     }
       
   837   
       
   838   return -1;
       
   839 }
       
   840 
       
   841 EXPORT_C gint
       
   842 g_node_child_index (GNode   *node,
       
   843 		    gpointer data)
       
   844 {
       
   845   register guint n = 0;
       
   846   
       
   847   g_return_val_if_fail (node != NULL, -1);
       
   848   
       
   849   node = node->children;
       
   850   while (node)
       
   851     {
       
   852       if (node->data == data)
       
   853 	return n;
       
   854       n++;
       
   855       node = node->next;
       
   856     }
       
   857   
       
   858   return -1;
       
   859 }
       
   860 
       
   861 EXPORT_C GNode*
       
   862 g_node_first_sibling (GNode *node)
       
   863 {
       
   864   g_return_val_if_fail (node != NULL, NULL);
       
   865   
       
   866   if (node->parent)
       
   867     return node->parent->children;
       
   868   
       
   869   while (node->prev)
       
   870     node = node->prev;
       
   871   
       
   872   return node;
       
   873 }
       
   874 
       
   875 EXPORT_C GNode*
       
   876 g_node_last_sibling (GNode *node)
       
   877 {
       
   878   g_return_val_if_fail (node != NULL, NULL);
       
   879   
       
   880   while (node->next)
       
   881     node = node->next;
       
   882   
       
   883   return node;
       
   884 }
       
   885 
       
   886 EXPORT_C void
       
   887 g_node_children_foreach (GNode		 *node,
       
   888 			 GTraverseFlags	  flags,
       
   889 			 GNodeForeachFunc func,
       
   890 			 gpointer	  data)
       
   891 {
       
   892   g_return_if_fail (node != NULL);
       
   893   g_return_if_fail (flags <= G_TRAVERSE_MASK);
       
   894   g_return_if_fail (func != NULL);
       
   895   
       
   896   node = node->children;
       
   897   while (node)
       
   898     {
       
   899       register GNode *current;
       
   900       
       
   901       current = node;
       
   902       node = current->next;
       
   903       if (G_NODE_IS_LEAF (current))
       
   904 	{
       
   905 	  if (flags & G_TRAVERSE_LEAFS)
       
   906 	    func (current, data);
       
   907 	}
       
   908       else
       
   909 	{
       
   910 	  if (flags & G_TRAVERSE_NON_LEAFS)
       
   911 	    func (current, data);
       
   912 	}
       
   913     }
       
   914 }
       
   915 
       
   916 #define __G_NODE_C__
       
   917 #include "galiasdef.c"