* Copyright (C) 1998 Tim Janik
*
* This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
*
- * You should have received a copy of the GNU Library General Public
+ * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
- * Modified by the GLib Team and others 1997-1999. See the AUTHORS
+ * Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
* MT safe
*/
+#include "config.h"
+
#include "glib.h"
+#ifndef DISABLE_MEM_POOLS
/* node allocation
*/
struct _GAllocator /* from gmem.c */
g_node_push_allocator (GAllocator *allocator)
{
G_LOCK (current_allocator);
- g_node_validate_allocator ( allocator );
+ g_node_validate_allocator (allocator);
allocator->last = current_allocator;
current_allocator = allocator;
G_UNLOCK (current_allocator);
{
if (parent->children)
g_nodes_free (parent->children);
+
+#ifdef ENABLE_GC_FRIENDLY
+ parent->data = NULL;
+ parent->prev = NULL;
+ parent->parent = NULL;
+ parent->children = NULL;
+#endif /* ENABLE_GC_FRIENDLY */
+
if (parent->next)
parent = parent->next;
else
current_allocator->free_nodes = node;
G_UNLOCK (current_allocator);
}
+#else /* DISABLE_MEM_POOLS */
+
+GNode*
+g_node_new (gpointer data)
+{
+ GNode *node;
+
+ node = g_new0 (GNode, 1);
+
+ node->data = data;
+
+ return node;
+}
+
+static void
+g_nodes_free (GNode *root)
+{
+ GNode *node, *next;
+
+ node = root;
+ while (node != NULL)
+ {
+ next = node->next;
+ g_nodes_free (node->children);
+ g_free (node);
+ node = next;
+ }
+}
+#endif
void
g_node_destroy (GNode *root)
node->prev = NULL;
}
+/**
+ * g_node_copy_deep:
+ * @node: a #GNode
+ * @copy_func: the function which is called to copy the data inside each node,
+ * or %NULL to use the original data.
+ * @data: data to pass to @copy_func
+ *
+ * Recursively copies a #GNode and its data.
+ *
+ * Return value: a new #GNode containing copies of the data in @node.
+ *
+ * Since: 2.4
+ **/
+GNode*
+g_node_copy_deep (GNode *node,
+ GCopyFunc copy_func,
+ gpointer data)
+{
+ GNode *new_node = NULL;
+
+ if (copy_func == NULL)
+ return g_node_copy (node);
+
+ if (node)
+ {
+ GNode *child, *new_child;
+
+ new_node = g_node_new (copy_func (node->data, data));
+
+ for (child = g_node_last_child (node); child; child = child->prev)
+ {
+ new_child = g_node_copy_deep (child, copy_func, data);
+ g_node_prepend (new_node, new_child);
+ }
+ }
+
+ return new_node;
+}
+
+GNode*
+g_node_copy (GNode *node)
+{
+ GNode *new_node = NULL;
+
+ if (node)
+ {
+ GNode *child;
+
+ new_node = g_node_new (node->data);
+
+ for (child = g_node_last_child (node); child; child = child->prev)
+ g_node_prepend (new_node, g_node_copy (child));
+ }
+
+ return new_node;
+}
+
GNode*
g_node_insert (GNode *parent,
gint position,
}
GNode*
+g_node_insert_after (GNode *parent,
+ GNode *sibling,
+ GNode *node)
+{
+ g_return_val_if_fail (parent != NULL, node);
+ g_return_val_if_fail (node != NULL, node);
+ g_return_val_if_fail (G_NODE_IS_ROOT (node), node);
+ if (sibling)
+ g_return_val_if_fail (sibling->parent == parent, node);
+
+ node->parent = parent;
+
+ if (sibling)
+ {
+ if (sibling->next)
+ {
+ sibling->next->prev = node;
+ }
+ node->next = sibling->next;
+ node->prev = sibling;
+ sibling->next = node;
+ }
+ else
+ {
+ if (parent->children)
+ {
+ node->next = parent->children;
+ parent->children->prev = node;
+ }
+ parent->children = node;
+ }
+
+ return node;
+}
+
+GNode*
g_node_prepend (GNode *parent,
GNode *node)
{
}
static gboolean
-g_node_traverse_children (GNode *node,
- GTraverseFlags flags,
- GNodeTraverseFunc func,
- gpointer data)
+g_node_traverse_level (GNode *node,
+ GTraverseFlags flags,
+ guint level,
+ GNodeTraverseFunc func,
+ gpointer data,
+ gboolean *more_levels)
{
- GNode *child;
-
- child = node->children;
-
- while (child)
+ if (level == 0)
{
- register GNode *current;
-
- current = child;
- child = current->next;
-
- if (current->children)
+ if (node->children)
{
- if ((flags & G_TRAVERSE_NON_LEAFS) &&
- func (current, data))
- return TRUE;
+ *more_levels = TRUE;
+ return (flags & G_TRAVERSE_NON_LEAFS) && func (node, data);
+ }
+ else
+ {
+ return (flags & G_TRAVERSE_LEAFS) && func (node, data);
}
- else if ((flags & G_TRAVERSE_LEAFS) &&
- func (current, data))
- return TRUE;
}
-
- child = node->children;
-
- while (child)
+ else
{
- register GNode *current;
+ node = node->children;
- current = child;
- child = current->next;
-
- if (current->children &&
- g_node_traverse_children (current, flags, func, data))
- return TRUE;
+ while (node)
+ {
+ if (g_node_traverse_level (node, flags, level - 1, func, data, more_levels))
+ return TRUE;
+
+ node = node->next;
+ }
}
-
+
return FALSE;
}
static gboolean
-g_node_depth_traverse_children (GNode *node,
- GTraverseFlags flags,
- guint depth,
- GNodeTraverseFunc func,
- gpointer data)
+g_node_depth_traverse_level (GNode *node,
+ GTraverseFlags flags,
+ guint depth,
+ GNodeTraverseFunc func,
+ gpointer data)
{
- GNode *child;
-
- child = node->children;
-
- while (child)
- {
- register GNode *current;
-
- current = child;
- child = current->next;
-
- if (current->children)
- {
- if ((flags & G_TRAVERSE_NON_LEAFS) &&
- func (current, data))
- return TRUE;
- }
- else if ((flags & G_TRAVERSE_LEAFS) &&
- func (current, data))
- return TRUE;
- }
-
- depth--;
- if (!depth)
- return FALSE;
-
- child = node->children;
-
- while (child)
+ gint level;
+ gboolean more_levels;
+
+ level = 0;
+ while (level != depth)
{
- register GNode *current;
-
- current = child;
- child = current->next;
-
- if (current->children &&
- g_node_depth_traverse_children (current, flags, depth, func, data))
+ more_levels = FALSE;
+ if (g_node_traverse_level (node, flags, level, func, data, &more_levels))
return TRUE;
+ if (!more_levels)
+ break;
+ level++;
}
-
return FALSE;
}
g_node_depth_traverse_in_order (root, flags, depth, func, data);
break;
case G_LEVEL_ORDER:
- if (root->children)
- {
- if (!((flags & G_TRAVERSE_NON_LEAFS) &&
- func (root, data)))
- {
- if (depth < 0)
- g_node_traverse_children (root, flags, func, data);
- else
- {
- depth--;
- if (depth)
- g_node_depth_traverse_children (root, flags, depth, func, data);
- }
- }
- }
- else if (flags & G_TRAVERSE_LEAFS)
- func (root, data);
+ g_node_depth_traverse_level (root, flags, depth, func, data);
break;
}
}
{
g_return_val_if_fail (node != NULL, NULL);
+ if (node->parent)
+ return node->parent->children;
+
while (node->prev)
node = node->prev;