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   425 use strict;
  57         116  
  57         2057  
3 57     57   345 use warnings;
  57         141  
  57         3067  
4 57     57   29081 use Gnuplot::Builder::PartiallyKeyedList;
  57         181  
  57         2573  
5 57     57   26870 use Gnuplot::Builder::Util qw(quote_gnuplot_str);
  57         179  
  57         4810  
6 57     57   438 use List::Util 1.28 qw(pairs);
  57         1501  
  57         124446  
7              
8             sub new {
9 1425     1425 1 2976 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     3195 }, $class;
17 1425         5387 return $self;
18             }
19              
20             sub _trim_whitespaces {
21 67     67   126 my ($val) = @_;
22 67         146 $val =~ s/^\s+//g;
23 67         157 $val =~ s/\s+$//g;
24 67         162 return $val;
25             }
26              
27             sub _parse_pairs {
28 15     15   33 my ($pairs_str) = @_;
29 15         27 my @pairs = ();
30 15         41 my $carried = "";
31 15         60 foreach my $line (split /^/, $pairs_str) {
32 62         225 $line =~ s/[\r\n]+$//g;
33 62 100       153 if($line =~ /\\$/) {
34 6         21 $carried .= substr($line, 0, -1);
35 6         7 next;
36             }
37 56         82 $line = $carried . $line;
38 56         83 $carried = "";
39 56 100       149 next if $line =~ /^#/;
40 52         191 $line =~ s/^\s+//g;
41 52 100       113 next if $line eq "";
42 40 100       140 if($line =~ /^([^=]*)=(.*)$/) {
43 27         87 my ($name, $value) = ($1, $2);
44 27         52 push(@pairs, _trim_whitespaces($name), _trim_whitespaces($value));
45             }else {
46 13         30 my $name = _trim_whitespaces($line);
47 13 100       37 if($name =~ /^-/) {
48 6         33 push(@pairs, substr($name, 1), undef);
49             }else {
50 7         36 push(@pairs, $name, "");
51             }
52             }
53             }
54 15         45 return \@pairs;
55             }
56              
57             sub set_entry {
58 231     231 1 838 my ($self, %args) = @_;
59 231 100       723 my $prefix = defined($args{key_prefix}) ? $args{key_prefix} : "";
60 231         407 my $quote = $args{quote};
61 231         401 my $entries = $args{entries};
62 231 100       703 if(@$entries == 1) {
63 15         108 $entries = _parse_pairs($entries->[0]);
64             }
65            
66             ## Multiple occurrences of the same key are combined into an array-ref value.
67 231         730 my $temp_list = Gnuplot::Builder::PartiallyKeyedList->new;
68 231         2145 foreach my $entry_pair (pairs @$entries) {
69 333         997 my ($given_key, $value) = @$entry_pair;
70 333         655 my $key = $prefix . $given_key;
71 333 100       986 if($temp_list->exists($key)) {
72 2         6 push(@{$temp_list->get($key)}, $value);
  2         10  
73             }else {
74 331         1063 $temp_list->set($key, [$value]);
75             }
76             }
77             $temp_list->each(sub {
78 331     331   749 my ($key, $value_arrayref) = @_;
79 331 100       925 my $value = (@$value_arrayref == 1) ? $value_arrayref->[0] : $value_arrayref;
80 331 100       1269 $self->{list}->set($key, $quote ? _wrap_value_with_quote($value) : $value);
81 231         3376 });
82             }
83              
84             sub _wrap_value_with_quote {
85 90     90   242 my ($value) = @_;
86 90         192 my $ref = ref($value);
87 90 100       341 if($ref eq "ARRAY") {
    100          
88 10         29 return [map { quote_gnuplot_str($_) } @$value];
  15         41  
89             }elsif($ref eq "CODE") {
90             return sub {
91 34     34   94 return map { quote_gnuplot_str($_) } $value->(@_);
  49         6255  
92 17         93 };
93             }else {
94 63         288 return quote_gnuplot_str($value);
95             }
96             }
97              
98             sub add_entry {
99 20     20 1 44 my ($self, @entries) = @_;
100 20         83 $self->{list}->add($_) foreach @entries;
101             }
102              
103 13     13 1 60 sub delete_entry { $_[0]->{list}->delete($_[1]) }
104              
105 1204     1204 1 2405 sub has_own_entry { return $_[0]->{list}->exists($_[1]) }
106              
107 1038     1038 1 1445 sub set_parent { $_[0]->{parent} = $_[1] }
108              
109 2923     2923 1 6638 sub get_parent { return $_[0]->{parent} }
110              
111             sub _create_inheritance_stack {
112 353     353   671 my ($self) = @_;
113 353         766 my @pdata_stack = ($self);
114 353         572 my $current = $self;
115 353         834 while(defined(my $parent = $current->get_parent)) {
116 1030         1283 push(@pdata_stack, $parent);
117 1030         1565 $current = $parent;
118             }
119 353         824 return \@pdata_stack;
120             }
121              
122             sub _create_merged_pkl {
123 353     353   764 my ($self) = @_;
124 353         1107 my $result = Gnuplot::Builder::PartiallyKeyedList->new;
125 353         850 my $pdata_stack = $self->_create_inheritance_stack();
126 353         1037 while(defined(my $cur_pdata = pop(@$pdata_stack))) {
127 1383         3087 $result->merge($cur_pdata->{list});
128             }
129 353         833 return $result;
130             }
131              
132             sub _normalize_value {
133 603     603   1285 my ($raw_value, $evaluator, $key) = @_;
134 603         4280 my $ref = ref($raw_value);
135 603 100 66     1992 if($ref eq "ARRAY") {
    100          
136 88         297 return @$raw_value;
137             }elsif($ref eq "CODE" && defined($evaluator)) {
138 90         238 return $evaluator->($key, $raw_value);
139             }else {
140 425         1611 return ($raw_value);
141             }
142             }
143              
144             sub get_resolved_entry {
145 167     167 1 337 my ($self, $key) = @_;
146 167         233 my $pdata_with_key = $self;
147 167   100     596 while(defined($pdata_with_key) && !$pdata_with_key->has_own_entry($key)) {
148 1049         1326 $pdata_with_key = $pdata_with_key->get_parent;
149             }
150 167 100       395 if(!defined($pdata_with_key)) {
151 12 100       94 return wantarray ? () : undef;
152             }
153 155         413 my $raw_value = $pdata_with_key->{list}->get($key);
154 155         437 my @normalized_values = _normalize_value($raw_value, $self->{entry_evaluator}, $key);
155 155 100       8503 return wantarray ? @normalized_values : $normalized_values[0];
156             }
157              
158             sub each_resolved_entry {
159 353     353 1 705 my ($self, $code) = @_;
160 353         928 my $merged = $self->_create_merged_pkl();
161             $merged->each(sub {
162 448     448   913 my ($key, $raw_value) = @_;
163 448         1060 $code->($key, [_normalize_value($raw_value, $self->{entry_evaluator}, $key)]);
164 353         1628 });
165             }
166              
167             sub set_attribute {
168 145     145 1 591 my ($self, %args) = @_;
169 145 100       773 $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 1168 my ($self, $name) = @_;
174 590         869 my $pdata_with_attr = $self;
175 590   100     1883 while(defined($pdata_with_attr) && !$pdata_with_attr->has_own_attribute($name)) {
176 491         1101 $pdata_with_attr = $pdata_with_attr->get_parent;
177             }
178 590 100       2043 return undef if not defined $pdata_with_attr;
179 172         363 my $raw_value = $pdata_with_attr->{attributes}{$name};
180 172 100 100     625 if(ref($raw_value) eq "CODE" && defined($self->{attribute_evaluator}{$name})) {
181 11         33 my ($result) = $self->{attribute_evaluator}{$name}->($name, $raw_value);
182 11         1251 return $result;
183             }else {
184 161         575 return $raw_value;
185             }
186             }
187              
188 663     663 1 2722 sub has_own_attribute { exists $_[0]->{attributes}{$_[1]} }
189              
190 20     20 1 77 sub delete_attribute { delete $_[0]->{attributes}{$_[1]} }
191              
192              
193             1;
194              
195             __END__