File Coverage

blib/lib/Text/Table/Read/RelationOn/Tiny.pm
Criterion Covered Total %
statement 91 91 100.0
branch 57 58 98.2
condition 7 7 100.0
subroutine 13 13 100.0
pod 7 7 100.0
total 175 176 99.4


line stmt bran cond sub pod time code
1             package Text::Table::Read::RelationOn::Tiny;
2            
3 4     4   252079 use 5.010_001;
  4         39  
4 4     4   22 use strict;
  4         7  
  4         96  
5 4     4   27 use warnings;
  4         7  
  4         131  
6 4     4   1980 use autodie;
  4         57524  
  4         19  
7            
8 4     4   24375 use Carp qw(confess);
  4         8  
  4         5048  
9            
10             our $VERSION = '0.01';
11            
12             sub new {
13 10     10 1 8779 my $class = shift;
14 10 50       32 $class = ref($class) if ref($class);
15 10         28 my %arguments = @_;
16 10   100     45 my $inc = delete $arguments{inc} // "X";
17 10   100     43 my $noinc = delete $arguments{noinc} // "";
18 10 100       345 confess(join(", ", sort(keys(%arguments))) . ": unexpected argument")
19             if %arguments;
20 9 100       138 confess("inc must be a scalar") if ref($inc);
21 8 100       133 confess("noinc must be a scalar") if ref($noinc);
22 7 100       190 confess("inc and noinc must be different") if $inc eq $noinc;
23 6         35 return bless({inc => $inc,
24             noinc => $noinc,
25             matrix => undef,
26             set => undef},
27             $class);
28             }
29            
30            
31             sub get {
32 22     22 1 17693 my $self = shift;
33 22 100       167 confess("Wrong number of arguments") if @_ != 1;
34 21         27 my @lines;
35 21 100       96 if (ref($_[0])) {
    100          
36 3 100       103 confess("Invalid argument") if ref($_[0]) ne 'ARRAY';
37 2         3 @lines = @{$_[0]};
  2         6  
38             } elsif ($_[0] !~ /\n/) {
39 4         16 open(my $h, '<', $_[0]);
40 4         2849 @lines = <$h>;
41 4         24 close($h);
42             } else {
43 14         86 @lines = split(/\n/, $_[0]);
44             }
45            
46 20         1022 my ($elem_array, $elem_ids) = _get_elems_from_header(\@lines);
47 18         34 my %remaining_elements = map {$_ => undef} @{$elem_array};
  26         60  
  18         32  
48 18         31 my ($inc, $noinc) = @{$self}{qw(inc noinc)};
  18         52  
49 18         26 my %matrix;
50             my %seen;
51 18         32 foreach my $line (@lines) {
52 53         100 $line =~ s/^\s+//;
53 53 100       87 last if $line eq "";
54 51 100       114 next if substr($line, 0, 2) eq "|-";
55 25 100       196 $line =~ s/^\|\s*([^|]*?)\s*\|\s*// or confess("Wrong row format: '$line'");
56 24         53 my $element = $1;
57 24 100       176 confess("'$element': duplicate element") if exists($seen{$element});
58 23 100       141 confess("'$element': not in header") if !exists($remaining_elements{$element});
59 22         34 delete $remaining_elements{$element};
60 22         30 $seen{$element} = undef;
61 22         115 $line =~ s/\s*\|\s*$//;
62 22         33 my %new_row;
63 22         32 my $index = 0;
64 22         70 foreach my $entry (split(/\s*\|\s*/, $line, -1)) {
65 70 100       126 if ($entry eq $inc) {
    100          
66 20         38 $new_row{$index} = undef;
67             } elsif ($entry ne $noinc) {
68 1         93 confess("'$entry': unexpected entry");
69             }
70 69         90 $index++;
71             }
72 21 100       66 $matrix{$elem_ids->{$element}} = \%new_row if %new_row;
73             }
74 14 100       123 confess(join(', ', map("'$_'", keys(%remaining_elements))) . ": no rows for these elements")
75             if %remaining_elements;
76            
77 13         27 $self->{matrix} = \%matrix;
78 13         22 $self->{elems} = $elem_array;
79 13         20 $self->{elem_ids} = $elem_ids;
80 13 100       70 return wantarray ? (\%matrix, $elem_array, $elem_ids) : $self;
81             }
82            
83            
84 3 100   3 1 1783 sub inc {confess("Unexpected arguments") if @_ > 1; $_[0]->{inc};}
  2         16  
85 3 100   3 1 830 sub noinc {confess("Unexpected arguments") if @_ > 1; $_[0]->{noinc};}
  2         8  
86 11 100   11 1 806 sub matrix {confess("Unexpected arguments") if @_ > 1; $_[0]->{matrix};}
  10         40  
87 11 100   11 1 799 sub elems {confess("Unexpected arguments") if @_ > 1; $_[0]->{elems};}
  10         34  
88 11 100   11 1 791 sub elem_ids {confess("Unexpected arguments") if @_ > 1; $_[0]->{elem_ids};}
  10         29  
89            
90            
91             sub _get_elems_from_header {
92 20     20   30 my $lines = shift;
93 20         29 my $header;
94 20   100     32 while (defined($header = shift(@{$lines})) and $header !~ /\S/) { 1; }
  14         20  
  34         161  
95 20 100       52 return ([], {}) if !defined($header);
96 15 100       212 $header =~ s/^\s*\|.*?\|\s*// or confess("'$header': Wrong header format");
97 14 100       77 my @elem_array = $header eq "|" ? ('') : split(/\s*\|\s*/, $header);
98 14 100       34 return ([], {}) if $header eq "";
99 13         22 my $index = 0;
100 13         21 my %elem_ids;
101 13         26 foreach my $name (@elem_array) {
102 28 100       164 confess("'$name': duplicate name in header") if exists($elem_ids{$name});
103 27         58 $elem_ids{$name} = $index++;
104             }
105 12         31 return (\@elem_array, \%elem_ids);
106             }
107            
108            
109            
110             1; # End of Text::Table::Read::RelationOn::Tiny
111            
112            
113            
114             __END__