57 GHashTable *by_id = g_hash_table_new(g_str_hash, g_str_equal);
61 for(GList *it = g_list_first(input_nodes); it; it = g_list_next(it))
68 if(!canon->
tag && in->
tag) canon->
tag = g_strdup(in->
tag);
72 if(((!strcmp(canon->
tag,
"dst") && !strcmp(in->
tag,
"src"))
73 || (!strcmp(canon->
tag,
"src") && !strcmp(in->
tag,
"dst"))))
76 canon->
tag = g_strdup(
"dst+src");
78 else if(strcmp(canon->
tag,
"dst+src"))
81 canon->
tag = g_strdup(
"mixed");
87 for(GList *it = g_list_first(input_nodes); it; it = g_list_next(it))
94 for(GList *
p = g_list_first(in->
previous);
p;
p = g_list_next(
p))
102 gboolean found =
FALSE;
103 for(GList *q = g_list_first(self->
previous); q; q = g_list_next(q))
105 if(q->data == cpred) { found =
TRUE;
break; }
112 GHashTable *added = g_hash_table_new(g_str_hash, g_str_equal);
115 g_hash_table_destroy(by_id);
119 for(GList *it = g_list_first(input_nodes); it; it = g_list_next(it))
124 if(g_hash_table_contains(added, in->
id))
continue;
129 *out_nodes = g_list_append(*out_nodes, canon);
130 g_hash_table_add(added, (gpointer)canon->
id);
136 gpointer
key = NULL, val = NULL;
137 g_hash_table_iter_init(&iter, by_id);
138 while(g_hash_table_iter_next(&iter, &
key, &val))
140 const char *
id = (
const char *)
key;
142 if(!g_hash_table_contains(added,
id)) *out_nodes = g_list_append(*out_nodes, canon);
145 g_hash_table_destroy(added);
146 g_hash_table_destroy(by_id);
209 GHashTable *outgoing,
220 fprintf(stderr,
"[toposort] Cycle detected visiting node '%s'\n",
n->id);
226 fprintf(stderr,
"[toposort] Already finished node '%s'\n",
n->id);
230 *dfs_count = *dfs_count + 1;
233 if(dfs_stack) *dfs_stack = g_list_prepend(*dfs_stack,
n);
237 GList *nbrs = (GList *)g_hash_table_lookup(outgoing,
n);
238 for(GList *it = nbrs; it; it = g_list_next(it))
241 if(
_dfs_visit(
m, outgoing, color, result, dfs_count, dfs_stack, cycle_out))
244 if(dfs_stack && *dfs_stack) *dfs_stack = g_list_delete_link(*dfs_stack, *dfs_stack);
250 *result = g_list_prepend(*result,
n);
253 if(dfs_stack && *dfs_stack) *dfs_stack = g_list_delete_link(*dfs_stack, *dfs_stack);
261 if(cycle_out) *cycle_out = NULL;
264 fprintf(stderr,
"[toposort] Initial node list and constraints:\n");
265 for(GList *it = g_list_first(nodes); it; it = g_list_next(it))
268 fprintf(stderr,
"[toposort] node '%s'",
n->id);
269 if(
n->tag) fprintf(stderr,
" [%s]",
n->tag);
270 fprintf(stderr,
" (predecessors:");
271 for(GList *
p = g_list_first(
n->previous);
p;
p = g_list_next(
p))
274 fprintf(stderr,
" '%s'", pred->
id);
276 fprintf(stderr,
")\n");
280 fprintf(stderr,
"[toposort] Edges:\n");
281 for(GList *it = g_list_first(nodes); it; it = g_list_next(it))
284 for(GList *
p = g_list_first(
n->previous);
p;
p = g_list_next(
p))
287 fprintf(stderr,
"[toposort] '%s' -> '%s'\n", pred->
id,
n->id);
291 GHashTable *outgoing = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL);
292 GHashTable *color = g_hash_table_new(g_direct_hash, g_direct_equal);
295 if(outgoing) g_hash_table_destroy(outgoing);
296 if(color) g_hash_table_destroy(color);
301 for(GList *it = g_list_first(nodes); it; it = g_list_next(it))
306 if(!g_hash_table_contains(outgoing,
n)) g_hash_table_insert(outgoing,
n, NULL);
307 if(!g_hash_table_contains(color,
n)) g_hash_table_insert(color,
n, GINT_TO_POINTER(
DT_VISIT_WHITE));
311 for(GList *it = g_list_first(nodes); it; it = g_list_next(it))
316 for(GList *
p = g_list_first(self->
previous);
p;
p = g_list_next(
p))
321 if(!g_hash_table_contains(outgoing, pred)) g_hash_table_insert(outgoing, pred, NULL);
322 if(!g_hash_table_contains(color, pred))
323 g_hash_table_insert(color, pred, GINT_TO_POINTER(
DT_VISIT_WHITE));
330 GList *result = NULL;
332 GList *dfs_stack = NULL;
337 gpointer
key = NULL, val = NULL;
338 g_hash_table_iter_init(&iter, outgoing);
339 while(g_hash_table_iter_next(&iter, &
key, &val))
345 if(
_dfs_visit(
n, outgoing, color, &result, &dfs_count, &dfs_stack, &cycle))
351 g_list_free(dfs_stack);
354 g_hash_table_destroy(outgoing);
355 g_hash_table_destroy(color);
357 if(cycle_out) *cycle_out = cycle;
358 else if(cycle) g_list_free(cycle);
367 g_list_free(dfs_stack);
376 g_hash_table_destroy(outgoing);
377 g_hash_table_destroy(color);
382 fprintf(stderr,
"[toposort] Solution order:\n");
384 for(GList *it = g_list_first(result); it; it = g_list_next(it), idx++)
387 fprintf(stderr,
"[toposort] %d: '%s'", idx,
n->id);
388 if(
n->tag) fprintf(stderr,
" [%s]",
n->tag);
389 fprintf(stderr,
"\n");
392 fprintf(stderr,
"[toposort] DFS visits performed: %d\n", dfs_count);
void dt_digraph_cleanup_full(GList *nodes, GHashTable *node_ht, dt_node_user_data_destroy_t user_destroy)
Free a canonical graph (nodes, constraints, ids) in one call.
static gboolean _dfs_visit(dt_digraph_node_t *n, GHashTable *outgoing, GHashTable *color, GList **result, int *dfs_count, GList **dfs_stack, GList **cycle_out)