static void build_func_tree(GHashTable *methods) { struct lua_cmd_entry *entry; GNode *parent; GNode *node; gchar **pp; GList *list; if (lua_cmd_queue.length == 0) return; main_tree = g_node_new(NULL); for (list = lua_cmd_queue.head; list != NULL; list = list->next) { entry = (struct lua_cmd_entry *) list->data; parent = main_tree; pp = entry->cmdv; if (entry->method != NULL) { if (g_hash_table_lookup(methods, entry->method) == NULL) continue; } while (*pp != NULL) { node = g_node_first_child(parent); if (node == NULL || strcmp(*pp, node->data)) node = g_node_prepend(parent, g_node_new(*pp)); parent = node; pp++; } g_node_prepend(node, g_node_new(entry)); } }
/** * 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; }
/** * g_node_copy: * @node: a #GNode * * Recursively copies a #GNode (but does not deep-copy the data inside the * nodes, see g_node_copy_deep() if you need that). * * Returns: a new #GNode containing the same data pointers */ 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; }
/** * g_node_insert: * @parent: the #GNode to place @node under * @position: the position to place @node at, with respect to its siblings * If position is -1, @node is inserted as the last child of @parent * @node: the #GNode to insert * * Inserts a #GNode beneath the parent at the given position. * * Returns: the inserted #GNode */ GNode* g_node_insert (GNode *parent, gint position, 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 (position > 0) return g_node_insert_before (parent, g_node_nth_child (parent, position), node); else if (position == 0) return g_node_prepend (parent, node); else /* if (position < 0) */ return g_node_append (parent, node); }
static void g_node_test (void) { GNode *root; GNode *node; GNode *node_B; GNode *node_D; GNode *node_F; GNode *node_G; GNode *node_J; guint i; gchar *tstring; failed = FALSE; root = g_node_new (C2P ('A')); TEST (NULL, g_node_depth (root) == 1 && g_node_max_height (root) == 1); node_B = g_node_new (C2P ('B')); g_node_append (root, node_B); TEST (NULL, root->children == node_B); g_node_append_data (node_B, C2P ('E')); g_node_prepend_data (node_B, C2P ('C')); node_D = g_node_new (C2P ('D')); g_node_insert (node_B, 1, node_D); node_F = g_node_new (C2P ('F')); g_node_append (root, node_F); TEST (NULL, root->children->next == node_F); node_G = g_node_new (C2P ('G')); g_node_append (node_F, node_G); node_J = g_node_new (C2P ('J')); g_node_prepend (node_G, node_J); g_node_insert (node_G, 42, g_node_new (C2P ('K'))); g_node_insert_data (node_G, 0, C2P ('H')); g_node_insert (node_G, 1, g_node_new (C2P ('I'))); TEST (NULL, g_node_depth (root) == 1); TEST (NULL, g_node_max_height (root) == 4); TEST (NULL, g_node_depth (node_G->children->next) == 4); TEST (NULL, g_node_n_nodes (root, G_TRAVERSE_LEAFS) == 7); TEST (NULL, g_node_n_nodes (root, G_TRAVERSE_NON_LEAFS) == 4); TEST (NULL, g_node_n_nodes (root, G_TRAVERSE_ALL) == 11); TEST (NULL, g_node_max_height (node_F) == 3); TEST (NULL, g_node_n_children (node_G) == 4); TEST (NULL, g_node_find_child (root, G_TRAVERSE_ALL, C2P ('F')) == node_F); TEST (NULL, g_node_find (root, G_LEVEL_ORDER, G_TRAVERSE_NON_LEAFS, C2P ('I')) == NULL); TEST (NULL, g_node_find (root, G_IN_ORDER, G_TRAVERSE_LEAFS, C2P ('J')) == node_J); for (i = 0; i < g_node_n_children (node_B); i++) { node = g_node_nth_child (node_B, i); TEST (NULL, P2C (node->data) == ('C' + i)); } for (i = 0; i < g_node_n_children (node_G); i++) TEST (NULL, g_node_child_position (node_G, g_node_nth_child (node_G, i)) == i); /* we have built: A * / \ * B F * / | \ \ * C D E G * / /\ \ * H I J K * * for in-order traversal, 'G' is considered to be the "left" * child of 'F', which will cause 'F' to be the last node visited. */ tstring = NULL; g_node_traverse (root, G_PRE_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring); TEST (tstring, strcmp (tstring, "ABCDEFGHIJK") == 0); g_free (tstring); tstring = NULL; g_node_traverse (root, G_POST_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring); TEST (tstring, strcmp (tstring, "CDEBHIJKGFA") == 0); g_free (tstring); tstring = NULL; g_node_traverse (root, G_IN_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring); TEST (tstring, strcmp (tstring, "CBDEAHGIJKF") == 0); g_free (tstring); tstring = NULL; g_node_traverse (root, G_LEVEL_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring); TEST (tstring, strcmp (tstring, "ABFCDEGHIJK") == 0); g_free (tstring); tstring = NULL; g_node_traverse (root, G_LEVEL_ORDER, G_TRAVERSE_LEAFS, -1, node_build_string, &tstring); TEST (tstring, strcmp (tstring, "CDEHIJK") == 0); g_free (tstring); tstring = NULL; g_node_traverse (root, G_PRE_ORDER, G_TRAVERSE_NON_LEAFS, -1, node_build_string, &tstring); TEST (tstring, strcmp (tstring, "ABFG") == 0); g_free (tstring); tstring = NULL; g_node_reverse_children (node_B); g_node_reverse_children (node_G); g_node_traverse (root, G_LEVEL_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring); TEST (tstring, strcmp (tstring, "ABFEDCGKJIH") == 0); g_free (tstring); tstring = NULL; g_node_append (node_D, g_node_new (C2P ('L'))); g_node_append (node_D, g_node_new (C2P ('M'))); g_node_traverse (root, G_LEVEL_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring); TEST (tstring, strcmp (tstring, "ABFEDCGLMKJIH") == 0); g_free (tstring); tstring = NULL; g_node_destroy (root); /* allocation tests */ root = g_node_new (NULL); node = root; for (i = 0; i < 2048; i++) { g_node_append (node, g_node_new (NULL)); if ((i%5) == 4) node = node->children->next; } TEST (NULL, g_node_max_height (root) > 100); TEST (NULL, g_node_n_nodes (root, G_TRAVERSE_ALL) == 1 + 2048); g_node_destroy (root); if (failed) exit(1); }
/** * gts_bb_tree_new: * @bboxes: a list of #GtsBBox. * * Builds a new hierarchy of bounding boxes for @bboxes. At each * level, the GNode->data field contains a #GtsBBox bounding box of * all the children. The tree is binary and is built by repeatedly * cutting in two approximately equal halves the bounding boxes at * each level until a leaf node (i.e. a bounding box given in @bboxes) * is reached. In order to minimize the depth of the tree, the cutting * direction is always chosen as perpendicular to the longest * dimension of the bounding box. * * Returns: a new hierarchy of bounding boxes. */ GNode * gts_bb_tree_new (GSList * bboxes) { GSList * i, * positive = NULL, * negative = NULL; GNode * node; GtsBBox * bbox; guint dir, np = 0, nn = 0; gdouble * p1, * p2; gdouble cut; g_return_val_if_fail (bboxes != NULL, NULL); if (bboxes->next == NULL) /* leaf node */ return g_node_new (bboxes->data); bbox = gts_bbox_bboxes (gts_bbox_class (), bboxes); node = g_node_new (bbox); if (bbox->x2 - bbox->x1 > bbox->y2 - bbox->y1) { if (bbox->z2 - bbox->z1 > bbox->x2 - bbox->x1) dir = 2; else dir = 0; } else if (bbox->z2 - bbox->z1 > bbox->y2 - bbox->y1) dir = 2; else dir = 1; p1 = (gdouble *) &bbox->x1; p2 = (gdouble *) &bbox->x2; cut = (p1[dir] + p2[dir])/2.; i = bboxes; while (i) { bbox = i->data; p1 = (gdouble *) &bbox->x1; p2 = (gdouble *) &bbox->x2; if ((p1[dir] + p2[dir])/2. > cut) { positive = g_slist_prepend (positive, bbox); np++; } else { negative = g_slist_prepend (negative, bbox); nn++; } i = i->next; } if (!positive) { GSList * last = g_slist_nth (negative, (nn - 1)/2); positive = last->next; last->next = NULL; } else if (!negative) { GSList * last = g_slist_nth (positive, (np - 1)/2); negative = last->next; last->next = NULL; } g_node_prepend (node, gts_bb_tree_new (positive)); g_slist_free (positive); g_node_prepend (node, gts_bb_tree_new (negative)); g_slist_free (negative); return node; }