Skip to content

Commit

Permalink
ungraph: new module
Browse files Browse the repository at this point in the history
Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Apr 27, 2023
1 parent 0fad975 commit 7b7e635
Show file tree
Hide file tree
Showing 5 changed files with 992 additions and 0 deletions.
1 change: 1 addition & 0 deletions ccan/ungraph/LICENSE
77 changes: 77 additions & 0 deletions ccan/ungraph/_info
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#include "config.h"
#include <stdio.h>
#include <string.h>

/**
* ungraph - extract a graph from an ASCII diagram.
*
* This code takes an ASCII diagram and converts it to a graph.
* The following things are assumed:
* 1. The input consists of \n-terminated lines
* 2. /-\|+ are used for edges.
* 3. <^>v are used for arrowheads.
* 4. + can be used to cross-over.
* 5. No arrowheads or both-ended arrowheads are shortcuts for "both ways".
* 6. Edges can turn with or without a +, by up to 90 degrees.
* 7. Edges must go from one node name to another.
* 8. Any other text is an edge label which must be next to an edge or
* another label.
*
* License: BSD-MIT
* Example:
* // Convert an ASCII graph to Graphviz dot format
* #include <ccan/err/err.h>
* #include <ccan/grab_file/grab_file.h>
* #include <ccan/ungraph/ungraph.h>
*
* // Just return the name as our node.
* static void *add_node(const tal_t *ctx,
* const char *name,
* const char **errstr,
* void *unused)
* {
* return (void *)name;
* }
*
* static const char *add_edge(const tal_t *ctx,
* void *source_node,
* void *dest_node,
* bool bidir,
* const char **labels,
* void *arg)
* {
* printf("%s -> %s;\n",
* (char *)source_node, (char *)dest_node);
* if (bidir)
* printf("%s -> %s;\n",
* (char *)dest_node, (char *)source_node);
* return NULL;
* }
*
* int main(int argc, char *argv[])
* {
* const char *graph = grab_file(NULL, argv[1], NULL), *errmsg;
* printf("digraph %s {\n", argv[1] ? argv[1] : "stdin");
* errmsg = ungraph(NULL, graph, add_node, add_edge, NULL);
* if (errmsg)
* errx(1, "%s", errmsg);
* printf("}");
* }
*
* Author: Rusty Russell <[email protected]>
*/
int main(int argc, char *argv[])
{
/* Expect exactly one argument */
if (argc != 2)
return 1;

if (strcmp(argv[1], "depends") == 0) {
printf("ccan/tal\n");
printf("ccan/tal/str\n");
printf("ccan/typesafe_cb\n");
return 0;
}

return 1;
}
140 changes: 140 additions & 0 deletions ccan/ungraph/test/run.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#include <ccan/ungraph/ungraph.h>
/* Include the C files directly. */
#include <ccan/ungraph/ungraph.c>
#include <ccan/tap/tap.h>
#include <assert.h>

static void *add_node(const tal_t *ctx,
const char *name,
const char **errstr,
char **out)
{
tal_append_fmt(out, "add_node %s\n", (char *)name);
return (void *)tal_steal(ctx, name);
}

static const char *add_edge(const tal_t *ctx,
void *source_node,
void *dest_node,
bool bidir,
const char **labels,
char **out)
{
tal_append_fmt(out, "add_edge %s-%s bidir=%i\n",
(char *)source_node,
(char *)dest_node,
bidir);
for (size_t i = 0; i < tal_count(labels); i++)
tal_append_fmt(out, "- label %s\n", labels[i]);
return NULL;
}

int main(void)
{
const tal_t *ctx = tal(NULL, char);
char *out = tal_arrz(ctx, char, 1);
/* This is how many tests you plan to run */
plan_tests(16);

ok1(ungraph(ctx,
"AAA----->BBB",
add_node, add_edge, &out) == NULL);
ok1(strcmp(out,
"add_node AAA\n"
"add_node BBB\n"
"add_edge AAA-BBB bidir=0\n") == 0);

out = tal_arrz(ctx, char, 1);
ok1(ungraph(ctx,
"AAA<------BBB",
add_node, add_edge, &out) == NULL);
ok1(strcmp(out,
"add_node AAA\n"
"add_node BBB\n"
"add_edge BBB-AAA bidir=0\n") == 0);

out = tal_arrz(ctx, char, 1);
ok1(ungraph(ctx,
"AAA------BBB",
add_node, add_edge, &out) == NULL);
ok1(strcmp(out,
"add_node AAA\n"
"add_node BBB\n"
"add_edge AAA-BBB bidir=1\n") == 0);

out = tal_arrz(ctx, char, 1);
ok1(ungraph(ctx,
"AAA<------>BBB",
add_node, add_edge, &out) == NULL);
ok1(strcmp(out,
"add_node AAA\n"
"add_node BBB\n"
"add_edge AAA-BBB bidir=1\n") == 0);

out = tal_arrz(ctx, char, 1);
ok1(ungraph(ctx,
"AAA\n"
" ^ \n"
" | \n"
" | \n"
" v \n"
"BBB",
add_node, add_edge, &out) == NULL);
ok1(strcmp(out,
"add_node AAA\n"
"add_node BBB\n"
"add_edge AAA-BBB bidir=1\n") == 0);

out = tal_arrz(ctx, char, 1);
ok1(ungraph(ctx,
"AAA\n"
" / \n"
"| \n"
" \\ \n"
" v \n"
" BBB\n",
add_node, add_edge, &out) == NULL);
ok1(strcmp(out,
"add_node AAA\n"
"add_node BBB\n"
"add_edge AAA-BBB bidir=0\n") == 0);

out = tal_arrz(ctx, char, 1);
ok1(ungraph(ctx,
"AAA\n"
" / \n"
"|xyx \n"
" \\ \n"
" v \n"
" BBB",
add_node, add_edge, &out) == NULL);
ok1(strcmp(out,
"add_node AAA\n"
"add_node BBB\n"
"add_edge AAA-BBB bidir=0\n"
"- label xyx\n") == 0);

out = tal_arrz(ctx, char, 1);
ok1(ungraph(ctx,
" AAA \n"
" | \n"
"A-+----B \n"
" | LABEL \n"
" | xyz\n"
" v \n"
" BBB",
add_node, add_edge, &out) == NULL);
ok1(strcmp(out,
"add_node AAA\n"
"add_node BBB\n"
"add_node A\n"
"add_node B\n"
"add_edge AAA-BBB bidir=0\n"
"add_edge A-B bidir=1\n"
"- label LABEL\n"
"- label xyz\n") == 0);

tal_free(ctx);
/* This exits depending on whether all tests passed */
return exit_status();
}
Loading

0 comments on commit 7b7e635

Please sign in to comment.