File Coverage

blib/lib/Gnuplot/Builder/PrototypedData.pm
Criterion Covered Total %
statement 123 123 100.0
branch 40 40 100.0
condition 13 14 92.8
subroutine 27 27 100.0
pod 13 13 100.0
total 216 217 99.5


line stmt bran cond sub pod time code
1             package Gnuplot::Builder::PrototypedData;
2 57     57   324 use strict;
  57         125  
  57         1549  
3 57     57   218 use warnings;
  57         109  
  57         2144  
4 57     57   20646 use Gnuplot::Builder::PartiallyKeyedList;
  57         150  
  57         1872  
5 57     57   19589 use Gnuplot::Builder::Util qw(quote_gnuplot_str);
  57         134  
  57         3643  
6 57     57   316 use List::Util 1.28 qw(pairs);
  57         1202  
  57         85458  
7              
8             sub new {
9 1425     1425 1 2594 my ($class, %args) = @_;
10             my $self = bless {
11             list => Gnuplot::Builder::PartiallyKeyedList->new,
12             attributes => {},
13             parent => undef,
14             entry_evaluator => $args{entry_evaluator},
15             attribute_evaluator => $args{attribute_evaluator} || {},
16 1425   100     2749 }, $class;
17 1425         4237 return $self;
18             }
19              
20             sub _trim_whitespaces {
21 67     67   96 my ($val) = @_;
22 67         233 $val =~ s/^\s+//g;
23 67         139 $val =~ s/\s+$//g;
24 67         138 return $val;
25             }
26              
27             sub _parse_pairs {
28 15     15   30 my ($pairs_str) = @_;
29 15         24 my @pairs = ();
30 15         26 my $carried = "";
31 15         54 foreach my $line (split /^/, $pairs_str) {
32 62         204 $line =~ s/[\r\n]+$//g;
33 62 100       129 if($line =~ /\\$/) {
34 6         9 $carried .= substr($line, 0, -1);
35 6         8 next;
36             }
37 56         71 $line = $carried . $line;
38 56         70 $carried = "";
39 56 100       122 next if $line =~ /^#/;
40 52         97 $line =~ s/^\s+//g;
41 52 100       85 next if $line eq "";
42 40 100       168 if($line =~ /^([^=]*)=(.*)$/) {
43 27         71 my ($name, $value) = ($1, $2);
44 27         49 push(@pairs, _trim_whitespaces($name), _trim_whitespaces($value));
45             }else {
46 13         26 my $name = _trim_whitespaces($line);
47 13 100       35 if($name =~ /^-/) {
48 6         18 push(@pairs, substr($name, 1), undef);
49             }else {
50 7         18 push(@pairs, $name, "");
51             }
52             }
53             }
54 15         40 return \@pairs;
55             }
56              
57             sub set_entry {
58 231     231 1 614 my ($self, %args) = @_;
59 231 100       633 my $prefix = defined($args{key_prefix}) ? $args{key_prefix} : "";
60 231         305 my $quote = $args{quote};
61 231         320 my $entries = $args{entries};
62 231 100       551 if(@$entries == 1) {
63 15         53 $entries = _parse_pairs($entries->[0]);
64             }
65            
66             ## Multiple occurrences of the same key are combined into an array-ref value.
67 231         522 my $temp_list = Gnuplot::Builder::PartiallyKeyedList->new;
68 231         1635 foreach my $entry_pair (pairs @$entries) {
69 333         760 my ($given_key, $value) = @$entry_pair;
70 333         469 my $key = $prefix . $given_key;
71 333 100       763 if($temp_list->exists($key)) {
72 2         3 push(@{$temp_list->get($key)}, $value);
  2         7  
73             }else {
74 331         778 $temp_list->set($key, [$value]);
75             }
76             }
77             $temp_list->each(sub {
78 331     331   573 my ($key, $value_arrayref) = @_;
79 331 100       737 my $value = (@$value_arrayref == 1) ? $value_arrayref->[0] : $value_arrayref;
80 331 100       960 $self->{list}->set($key, $quote ? _wrap_value_with_quote($value) : $value);
81 231         1448 });
82             }
83              
84             sub _wrap_value_with_quote {
85 90     90   194 my ($value) = @_;
86 90         184 my $ref = ref($value);
87 90 100       254 if($ref eq "ARRAY") {
    100          
88 10         22 return [map { quote_gnuplot_str($_) } @$value];
  15         33  
89             }elsif($ref eq "CODE") {
90             return sub {
91 34     34   80 return map { quote_gnuplot_str($_) } $value->(@_);
  49         5213  
92 17         64 };
93             }else {
94 63         202 return quote_gnuplot_str($value);
95             }
96             }
97              
98             sub add_entry {
99 20     20 1 33 my ($self, @entries) = @_;
100 20         60 $self->{list}->add($_) foreach @entries;
101             }
102              
103 13     13 1 72 sub delete_entry { $_[0]->{list}->delete($_[1]) }
104              
105 1204     1204 1 1979 sub has_own_entry { return $_[0]->{list}->exists($_[1]) }
106              
107 1038     1038 1 1305 sub set_parent { $_[0]->{parent} = $_[1] }
108              
109 2923     2923 1 5233 sub get_parent { return $_[0]->{parent} }
110              
111             sub _create_inheritance_stack {
112 353     353   546 my ($self) = @_;
113 353         681 my @pdata_stack = ($self);
114 353         452 my $current = $self;
115 353         671 while(defined(my $parent = $current->get_parent)) {
116 1030         1149 push(@pdata_stack, $parent);
117 1030         1214 $current = $parent;
118             }
119 353         676 return \@pdata_stack;
120             }
121              
122             sub _create_merged_pkl {
123 353     353   548 my ($self) = @_;
124 353         889 my $result = Gnuplot::Builder::PartiallyKeyedList->new;
125 353         676 my $pdata_stack = $self->_create_inheritance_stack();
126 353         904 while(defined(my $cur_pdata = pop(@$pdata_stack))) {
127 1383         2257 $result->merge($cur_pdata->{list});
128             }
129 353         633 return $result;
130             }
131              
132             sub _normalize_value {
133 603     603   963 my ($raw_value, $evaluator, $key) = @_;
134 603         891 my $ref = ref($raw_value);
135 603 100 66     1546 if($ref eq "ARRAY") {
    100          
136 88         231 return @$raw_value;
137             }elsif($ref eq "CODE" && defined($evaluator)) {
138 90         185 return $evaluator->($key, $raw_value);
139             }else {
140 425         1140 return ($raw_value);
141             }
142             }
143              
144             sub get_resolved_entry {
145 167     167 1 273 my ($self, $key) = @_;
146 167         207 my $pdata_with_key = $self;
147 167   100     539 while(defined($pdata_with_key) && !$pdata_with_key->has_own_entry($key)) {
148 1049         1262 $pdata_with_key = $pdata_with_key->get_parent;
149             }
150 167 100       302 if(!defined($pdata_with_key)) {
151 12 100       97 return wantarray ? () : undef;
152             }
153 155         339 my $raw_value = $pdata_with_key->{list}->get($key);
154 155         348 my @normalized_values = _normalize_value($raw_value, $self->{entry_evaluator}, $key);
155 155 100       7958 return wantarray ? @normalized_values : $normalized_values[0];
156             }
157              
158             sub each_resolved_entry {
159 353     353 1 622 my ($self, $code) = @_;
160 353         678 my $merged = $self->_create_merged_pkl();
161             $merged->each(sub {
162 448     448   682 my ($key, $raw_value) = @_;
163 448         782 $code->($key, [_normalize_value($raw_value, $self->{entry_evaluator}, $key)]);
164 353         1182 });
165             }
166              
167             sub set_attribute {
168 145     145 1 447 my ($self, %args) = @_;
169 145 100       588 $self->{attributes}{$args{key}} = $args{quote} ? _wrap_value_with_quote($args{value}) : $args{value};
170             }
171              
172             sub get_resolved_attribute {
173 590     590 1 928 my ($self, $name) = @_;
174 590         741 my $pdata_with_attr = $self;
175 590   100     1472 while(defined($pdata_with_attr) && !$pdata_with_attr->has_own_attribute($name)) {
176 491         896 $pdata_with_attr = $pdata_with_attr->get_parent;
177             }
178 590 100       1661 return undef if not defined $pdata_with_attr;
179 172         286 my $raw_value = $pdata_with_attr->{attributes}{$name};
180 172 100 100     501 if(ref($raw_value) eq "CODE" && defined($self->{attribute_evaluator}{$name})) {
181 11         24 my ($result) = $self->{attribute_evaluator}{$name}->($name, $raw_value);
182 11         897 return $result;
183             }else {
184 161         458 return $raw_value;
185             }
186             }
187              
188 663     663 1 2105 sub has_own_attribute { exists $_[0]->{attributes}{$_[1]} }
189              
190 20     20 1 67 sub delete_attribute { delete $_[0]->{attributes}{$_[1]} }
191              
192              
193             1;
194              
195             __END__