File Coverage

blib/lib/App/sdif/LabelStack.pm
Criterion Covered Total %
statement 11 140 7.8
branch 0 36 0.0
condition 0 6 0.0
subroutine 4 25 16.0
pod 0 19 0.0
total 15 226 6.6


line stmt bran cond sub pod time code
1             package App::sdif::LabelStack;
2              
3 1     1   1185 use v5.14;
  1         3  
4 1     1   5 use warnings;
  1         2  
  1         38  
5 1     1   7 use Carp;
  1         1  
  1         65  
6              
7 1     1   623 use Data::Dumper;
  1         6553  
  1         1437  
8              
9             sub new {
10 0     0 0   my $class = shift;
11 0           my $obj = bless {
12             LABELS => [],
13             COUNTS => {},
14             LISTS => [],
15             OPTION => { UNIQUE => 1 },
16             ATTR => {},
17             }, $class;
18              
19 0 0         $obj->option(@_) if @_;
20              
21 0 0         if (my $initial_label = $obj->option('START')) {
22 0           $obj->newlabel($initial_label);
23             }
24              
25 0           $obj;
26             }
27              
28 0     0 0   sub option { splice @_, 1, 0, 'OPTION' ; goto &__attr }
  0            
29 0     0 0   sub attr { splice @_, 1, 0, 'ATTR' ; goto &__attr }
  0            
30             sub __attr {
31 0     0     my $obj = shift;
32 0           my $attr_name = shift;
33              
34 0 0         return undef if @_ < 1;
35 0 0         return $obj->{$attr_name}->{+shift} if @_ == 1;
36              
37 0           my $hash = $obj->{$attr_name};
38 0           while (my($name, $value) = splice @_, 0, 2) {
39 0           $hash->{$name} = $value;
40             }
41              
42 0           $obj;
43             }
44              
45             sub exists {
46 0     0 0   my $obj = shift;
47 0           my $label = shift;
48 0           $obj->{COUNTS}->{$label};
49             }
50              
51             sub count {
52 0     0 0   my $obj = shift;
53 0           scalar @{$obj->{LISTS}};
  0            
54             }
55              
56             sub newlabel {
57 0     0 0   my $obj = shift;
58 0           my $label = shift;
59 0 0         if (my $order = $obj->option('ORDER')) {
60 0           for my $l (@$order) {
61 0 0         last if $l eq $label;
62 0 0         $obj->exists($l) or $obj->_createlabel($l);
63             }
64             }
65 0           $obj->_createlabel($label);
66 0           $obj;
67             }
68              
69             sub _createlabel {
70 0     0     my $obj = shift;
71 0           my $label = shift;
72 0 0 0       if ($obj->option('UNIQUE') and $obj->{COUNTS}->{$label}) {
73 0           croak "Duplicated label: $label\n";
74             }
75 0           $obj->{COUNTS}->{$label}++;
76 0           push @{$obj->{LABELS}}, $label;
  0            
77 0           push @{$obj->{LISTS}}, [];
  0            
78 0           $obj;
79             }
80              
81             sub append {
82 0     0 0   my $obj = shift;
83 0           my($label, $line) = @_;
84 0 0 0       if ($obj->labels == 0 or $label ne $obj->lastlabel) {
85 0           $obj->newlabel($label);
86             }
87 0           push @{$obj->{LISTS}->[-1]}, $line;
  0            
88 0           $obj;
89             }
90              
91             sub labels {
92 0     0 0   my $obj = shift;
93 0 0         if (@_ == 0) {
94 0           @{$obj->{LABELS}};
  0            
95             } else {
96 0           map { @{$obj->{LABELS}[$_]} } @_;
  0            
  0            
97             }
98             }
99              
100             sub lastlabel {
101 0     0 0   my $obj = shift;
102 0           $obj->{LABELS}->[-1];
103             }
104              
105             sub lists {
106 0     0 0   my $obj = shift;
107 0 0         if (@_ == 0) {
108 0           @{$obj->{LISTS}};
  0            
109             } else {
110 0           map { @{$obj->{LISTS}[$_]} } @_;
  0            
  0            
111             }
112             }
113              
114             sub blocks {
115 0     0 0   my $obj = shift;
116 0           map { join '', @$_ } $obj->lists;
  0            
117             }
118              
119             sub listpair {
120 0     0 0   my $obj = shift;
121 0           my @labels = $obj->labels;
122 0           map { $labels[$_] => $obj->{LISTS}[$_] } 0 .. $#labels;
  0            
123             }
124              
125             sub blockpair {
126 0     0 0   my $obj = shift;
127 0           my @labels = $obj->labels;
128 0           my @blocks = $obj->blocks;
129 0           map { $labels[$_] => $blocks[$_] } 0 .. $#labels;
  0            
130             }
131              
132             sub match {
133 0     0 0   my $obj = shift;
134 0           my $cond = shift;
135 0           my @labels = $obj->labels;
136 0           my @index = do {
137 0 0         if (ref($cond) eq 'CODE') {
    0          
138             grep {
139 0           local $_ = $labels[$_];
  0            
140 0           $cond->();
141             }
142             0 .. $#labels;
143             } elsif (ref $cond eq 'Regexp') {
144 0           grep { $labels[$_] =~ $cond } 0 .. $#labels;
  0            
145             } else {
146 0           grep { $labels[$_] eq $cond } 0 .. $#labels;
  0            
147             }
148             };
149 0           @{$obj->{LISTS}}[ @index ];
  0            
150             }
151              
152             sub collect {
153 0     0 0   my $obj = shift;
154 0           my @list = map { @$_ } $obj->match(@_);
  0            
155 0 0         wantarray ? @list : join '', @list;
156             }
157              
158             sub push {
159 0     0 0   my $obj = CORE::shift;
160 0 0         croak "Invalid argument." if @_ % 2;
161 0           while (my($label, $data) = splice @_, 0, 2) {
162 0           CORE::push @{$obj->{LABELS}}, $label;
  0            
163 0           CORE::push @{$obj->{LISTS}}, $data;
  0            
164 0           $obj->{COUNTS}{$label}++;
165             }
166 0           $obj;
167             }
168              
169             sub pop {
170 0     0 0   my $obj = CORE::shift;
171 0 0         return () if $obj->count == 0;
172 0           my $label = CORE::pop @{$obj->{LABELS}};
  0            
173 0           my $entry = CORE::pop @{$obj->{LISTS}};
  0            
174 0           $obj->{COUNTS}{$label}--;
175 0           ($label, $entry);
176             }
177              
178             sub unshift {
179 0     0 0   my $obj = CORE::shift;
180 0 0         croak "Invalid argument." if @_ % 2;
181 0           while (my($label, $data) = splice @_, 0, 2) {
182 0           CORE::unshift @{$obj->{LABELS}}, $label;
  0            
183 0           CORE::unshift @{$obj->{LISTS}}, $data;
  0            
184 0           $obj->{COUNTS}{$label}++;
185             }
186 0           $obj;
187             }
188              
189             sub shift {
190 0     0 0   my $obj = CORE::shift;
191 0 0         return () if $obj->count == 0;
192 0           my $label = CORE::shift @{$obj->{LABELS}};
  0            
193 0           my $entry = CORE::shift @{$obj->{LISTS}};
  0            
194 0           $obj->{COUNTS}{$label}--;
195 0           ($label, $entry);
196             }
197              
198             1;