package Graph::Reader::TGF;
use base qw(Graph::Reader);
use strict;
use warnings;
use Encode qw(decode_utf8);
use Error::Pure qw(err);
our $VERSION = 0.04;
# Edge callback.
sub _edge_callback {
my ($self, $graph, $id1, $id2, $edge_label) = @_;
$graph->set_edge_attribute($id1, $id2, 'label', $edge_label);
return;
}
# Init.
sub _init {
my ($self, $param_hr) = @_;
$self->SUPER::_init();
if (exists $param_hr->{'edge_callback'}
&& defined $param_hr->{'edge_callback'}
&& ref $param_hr->{'edge_callback'} ne 'CODE') {
err "Parameter 'edge_callback' isn't reference to code.";
}
$self->{'edge_callback'} = $param_hr->{'edge_callback'};
if (exists $param_hr->{'vertex_callback'}
&& defined $param_hr->{'vertex_callback'}
&& ref $param_hr->{'vertex_callback'} ne 'CODE') {
err "Parameter 'vertex_callback' isn't reference to code.";
}
$self->{'vertex_callback'} = $param_hr->{'vertex_callback'};
return;
}
# Read graph subroutine.
sub _read_graph {
my ($self, $graph, $fh) = @_;
my $vertexes = 1;
while (my $line = decode_utf8(<$fh>)) {
chomp $line;
# End of vertexes section.
if ($line =~ m/^#/ms) {
$vertexes = 0;
next;
}
# Vertexes.
if ($vertexes) {
my ($id, $vertex_label) = split m/\s+/ms, $line, 2;
if (! defined $vertex_label) {
$vertex_label = $id;
}
$graph->add_vertex($id);
if ($self->{'vertex_callback'}) {
$self->{'vertex_callback'}->($self, $graph,
$id, $vertex_label);
} else {
$self->_vertex_callback($graph, $id,
$vertex_label);
}
# Edges.
} else {
my ($id1, $id2, $edge_label) = split m/\s+/ms, $line, 3;
$graph->add_edge($id1, $id2);
if ($self->{'edge_callback'}) {
$self->{'edge_callback'}->($self, $graph, $id1,
$id2, $edge_label);
} else {
$self->_edge_callback($graph, $id1, $id2,
$edge_label);
}
}
}
return;
}
# Vertex callback.
sub _vertex_callback {
my ($self, $graph, $id, $vertex_label) = @_;
$graph->set_vertex_attribute($id, 'label', $vertex_label);
return;
}
1;
__END__
=pod
=encoding utf8
=head1 NAME
Graph::Reader::TGF - Perl class for reading a graph from TGF format.
=head1 SYNOPSIS
use Graph::Reader::TGF;
my $obj = Graph::Reader::TGF->new;
my $graph = $obj->read_graph($tgf_file);
=head1 METHODS
=head2 C<new>
my $obj = Graph::Reader::TGF->new;
Constructor.
This doesn't take any arguments.
Returns Graph::Reader::TGF object.
=head2 C<read_graph>
my $graph = $obj->read_graph($tgf_file);
Read a graph from the specified file.
The argument can either be a filename, or a filehandle for a previously opened file.
Returns Graph object.
=head1 TGF FILE FORMAT
TGF = Trivial Graph Format
TGF file format is described on L<English Wikipedia - Trivial Graph Format|https://en.wikipedia.org/wiki/Trivial_Graph_Format>
Example:
1 First node
2 Second node
#
1 2 Edge between the two
=head1 ERRORS
new():
Parameter 'edge_callback' isn't reference to code.
Parameter 'vertex_callback' isn't reference to code.
=head1 EXAMPLE1
=for comment filename=read_tgf_trivial_and_print.pl
use strict;
use warnings;
use File::Temp qw(tempfile);
use Graph::Reader::TGF;
use IO::Barf qw(barf);
# Example data.
my $data = <<'END';
1 First node
2 Second node
#
1 2 Edge between the two
END
# Temporary file.
my (undef, $tempfile) = tempfile();
# Save data to temp file.
barf($tempfile, $data);
# Reader object.
my $obj = Graph::Reader::TGF->new;
# Get graph from file.
my $g = $obj->read_graph($tempfile);
# Print to output.
print $g."\n";
# Clean temporary file.
unlink $tempfile;
# Output:
# 1-2
=head1 EXAMPLE2
=for comment filename=read_tgf_advanced_and_print.pl
use strict;
use warnings;
use File::Temp qw(tempfile);
use Graph::Reader::TGF;
use IO::Barf qw(barf);
# Example data.
my $data = <<'END';
1 Node #1
2 Node #2
3 Node #3
4 Node #4
5 Node #5
6 Node #6
7 Node #7
8 Node #8
9 Node #9
10 Node #10
#
1 2
1 3
1 5
1 6
1 10
3 4
6 7
6 8
6 9
END
# Temporary file.
my (undef, $tempfile) = tempfile();
# Save data to temp file.
barf($tempfile, $data);
# Reader object.
my $obj = Graph::Reader::TGF->new;
# Get graph from file.
my $g = $obj->read_graph($tempfile);
# Print to output.
print $g."\n";
# Clean temporary file.
unlink $tempfile;
# Output:
# 1-10,1-2,1-3,1-5,1-6,3-4,6-7,6-8,6-9
=head1 DEPENDENCIES
L<Encode>,
L<Error::Pure>,
L<Graph::Reader>.
=head1 SEE ALSO
=over
=item L<Graph::Reader>
base class for Graph file format readers
=item L<Task::Graph::Reader>
Install the Graph::Reader modules.
=back
=head1 REPOSITORY
L<https://github.com/michal-josef-spacek/Graph-Reader-TGF>
=head1 AUTHOR
Michal Josef Špaček L<mailto:skim@cpan.org>
L<http://skim.cz>
=head1 LICENSE AND COPYRIGHT
© Michal Josef Špaček 2014-2023
BSD 2-Clause License
=head1 VERSION
0.04
=cut