File Coverage

blib/lib/YAML/PP.pm
Criterion Covered Total %
statement 221 229 96.5
branch 30 36 83.3
condition 24 27 88.8
subroutine 62 63 98.4
pod 17 18 94.4
total 354 373 94.9


line stmt bran cond sub pod time code
1             # ABSTRACT: YAML 1.2 Processor
2 48     48   3412561 use strict;
  48         71  
  48         1428  
3 48     48   201 use warnings;
  48         92  
  48         2943  
4             package YAML::PP;
5              
6             our $VERSION = 'v0.40.1'; # TRIAL VERSION
7              
8 48     48   19617 use YAML::PP::Schema;
  48         106  
  48         1425  
9 48     48   17822 use YAML::PP::Schema::JSON;
  48         120  
  48         2352  
10 48     48   15753 use YAML::PP::Loader;
  48         145  
  48         1493  
11 48     48   16821 use YAML::PP::Dumper;
  48         158  
  48         1663  
12 48     48   261 use Scalar::Util qw/ blessed /;
  48         57  
  48         2011  
13 48     48   188 use Carp qw/ croak /;
  48         59  
  48         1691  
14              
15 48     48   179 use base 'Exporter';
  48         56  
  48         52339  
16             our @EXPORT_OK = qw/ Load LoadFile Dump DumpFile /;
17              
18             my %YAML_VERSIONS = ('1.1' => 1, '1.2' => 1);
19              
20              
21             sub new {
22 765     765 1 4786444 my ($class, %args) = @_;
23              
24 765         1872 my $bool = delete $args{boolean};
25 765 100       2243 $bool = 'perl' unless defined $bool;
26 765   100     2272 my $schemas = delete $args{schema} || ['+'];
27 765   100     3055 my $cyclic_refs = delete $args{cyclic_refs} || 'fatal';
28 765         1184 my $indent = delete $args{indent};
29 765         1122 my $width = delete $args{width};
30 765         1129 my $writer = delete $args{writer};
31 765         1006 my $header = delete $args{header};
32 765         990 my $footer = delete $args{footer};
33 765         930 my $require_footer = delete $args{require_footer};
34 765         967 my $duplicate_keys = delete $args{duplicate_keys};
35 765         1067 my $max_depth = delete $args{max_depth};
36 765         2543 my $yaml_version = $class->_arg_yaml_version(delete $args{yaml_version});
37 765         1186 my $default_yaml_version = $yaml_version->[0];
38 765         988 my $version_directive = delete $args{version_directive};
39 765         1055 my $preserve = delete $args{preserve};
40 765         943 my $parser = delete $args{parser};
41             my $emitter = delete $args{emitter} || {
42 765   50     3329 indent => $indent,
43             width => $width,
44             writer => $writer,
45             };
46 765 50       1703 if (keys %args) {
47 0         0 die "Unexpected arguments: " . join ', ', sort keys %args;
48             }
49              
50 765         1051 my %schemas;
51 765         1399 for my $v (@$yaml_version) {
52 767         895 my $schema;
53 767 50 33     2162 if (blessed($schemas) and $schemas->isa('YAML::PP::Schema')) {
54 0         0 $schema = $schemas;
55             }
56             else {
57 767         3187 $schema = YAML::PP::Schema->new(
58             boolean => $bool,
59             yaml_version => $v,
60             );
61 767         2460 $schema->load_subschemas(@$schemas);
62             }
63 766         1731 $schemas{ $v } = $schema;
64             }
65 764         1163 my $default_schema = $schemas{ $default_yaml_version };
66              
67 764         3463 my $loader = YAML::PP::Loader->new(
68             schemas => \%schemas,
69             cyclic_refs => $cyclic_refs,
70             parser => $parser,
71             default_yaml_version => $default_yaml_version,
72             preserve => $preserve,
73             duplicate_keys => $duplicate_keys,
74             require_footer => $require_footer,
75             max_depth => $max_depth,
76             );
77 763         2980 my $dumper = YAML::PP::Dumper->new(
78             schema => $default_schema,
79             emitter => $emitter,
80             header => $header,
81             footer => $footer,
82             version_directive => $version_directive,
83             preserve => $preserve,
84             );
85              
86 763         2168 my $self = bless {
87             schema => \%schemas,
88             loader => $loader,
89             dumper => $dumper,
90             }, $class;
91 763         3941 return $self;
92             }
93              
94             sub clone {
95 9     9 0 286 my ($self) = @_;
96 9         20 my $clone = {
97             schema => $self->schema,
98             loader => $self->loader->clone,
99             dumper => $self->dumper->clone,
100             };
101 9         25 return bless $clone, ref $self;
102             }
103              
104             sub _arg_yaml_version {
105 765     765   1403 my ($class, $version) = @_;
106 765         1910 my @versions = ('1.2');
107 765 100       1757 if (defined $version) {
108 5         9 @versions = ();
109 5 100       9 if (not ref $version) {
110 1         3 $version = [$version];
111             }
112 5         10 for my $v (@$version) {
113 7 50       14 unless ($YAML_VERSIONS{ $v }) {
114 0         0 croak "YAML Version '$v' not supported";
115             }
116 7         10 push @versions, $v;
117             }
118             }
119 765         1798 return \@versions;
120             }
121              
122              
123             sub loader {
124 2221 50   2221 1 5911 if (@_ > 1) {
125 0         0 $_[0]->{loader} = $_[1]
126             }
127 2221         8323 return $_[0]->{loader};
128             }
129              
130             sub dumper {
131 1494 50   1494 1 4141 if (@_ > 1) {
132 0         0 $_[0]->{dumper} = $_[1]
133             }
134 1494         6203 return $_[0]->{dumper};
135             }
136              
137             sub schema {
138 16 50   16 1 51 if (@_ > 1) { $_[0]->{schema}->{'1.2'} = $_[1] }
  0         0  
139 16         90 return $_[0]->{schema}->{'1.2'};
140             }
141              
142             sub default_schema {
143 3     3 1 10 my ($self, %args) = @_;
144             my $schema = YAML::PP::Schema->new(
145             boolean => $args{boolean},
146 3         41 );
147 3         14 $schema->load_subschemas(qw/ Core /);
148 3         14 return $schema;
149             }
150              
151             sub load_string {
152 2181     2181 1 978892 my ($self, $yaml) = @_;
153 2181         6051 return $self->loader->load_string($yaml);
154             }
155              
156             sub load_file {
157 28     28 1 63 my ($self, $file) = @_;
158 28         84 return $self->loader->load_file($file);
159             }
160              
161             sub dump {
162 1     1 1 6 my ($self, @data) = @_;
163 1         2 return $self->dumper->dump(@data);
164             }
165              
166             sub dump_string {
167 1478     1478 1 3423081 my ($self, @data) = @_;
168 1478         4431 return $self->dumper->dump_string(@data);
169             }
170              
171             sub dump_file {
172 6     6 1 14 my ($self, $file, @data) = @_;
173 6         14 return $self->dumper->dump_file($file, @data);
174             }
175              
176             # legagy interface
177             sub Load {
178 2     2 1 166640 my ($yaml) = @_;
179 2         13 YAML::PP->new->load_string($yaml);
180             }
181              
182             sub LoadFile {
183 12     12 1 1367704 my ($file) = @_;
184 12         67 YAML::PP->new->load_file($file);
185             }
186              
187             sub Dump {
188 1     1 1 1432 my (@data) = @_;
189 1         5 YAML::PP->new->dump_string(@data);
190             }
191              
192             sub DumpFile {
193 4     4 1 1010 my ($file, @data) = @_;
194 4         20 YAML::PP->new->dump_file($file, @data);
195             }
196              
197             sub preserved_scalar {
198 4     4 1 3957 my ($self, $value, %args) = @_;
199 4         21 my $scalar = YAML::PP::Preserve::Scalar->new(
200             value => $value,
201             %args,
202             );
203 4         12 return $scalar;
204             }
205              
206             sub preserved_mapping {
207 4     4 1 1428 my ($self, $hash, %args) = @_;
208 4         6 my $data = {};
209 4         23 tie %$data, 'YAML::PP::Preserve::Hash';
210 4         15 %$data = %$hash;
211 4         7 my $t = tied %$data;
212 4         9 $t->{style} = $args{style};
213 4         8 $t->{alias} = $args{alias};
214 4         11 return $data;
215             }
216              
217             sub preserved_sequence {
218 4     4 1 3001 my ($self, $array, %args) = @_;
219 4         6 my $data = [];
220 4         13 tie @$data, 'YAML::PP::Preserve::Array';
221 4         10 push @$data, @$array;
222 4         5 my $t = tied @$data;
223 4         7 $t->{style} = $args{style};
224 4         5 $t->{alias} = $args{alias};
225 4         11 return $data;
226             }
227              
228             package YAML::PP::Preserve::Hash;
229             # experimental
230 48     48   20844 use Tie::Hash;
  48         33681  
  48         1444  
231 48     48   232 use base qw/ Tie::StdHash /;
  48         59  
  48         11859  
232 48     48   271 use Scalar::Util qw/ reftype blessed /;
  48         70  
  48         23384  
233              
234             sub TIEHASH {
235 34     34   63 my ($class, %args) = @_;
236 34         175 my $self = bless {
237             keys => [keys %args],
238             data => { %args },
239             }, $class;
240             }
241              
242             sub STORE {
243 127     127   1231 my ($self, $key, $val) = @_;
244 127         145 my $keys = $self->{keys};
245 127 100       248 unless (exists $self->{data}->{ $key }) {
246 120         150 push @$keys, $key;
247             }
248 127 100 100     245 if (ref $val and not blessed($val)) {
249 39 100 100     157 if (reftype($val) eq 'HASH' and not tied %$val) {
    100 100        
250 1         2 tie %$val, 'YAML::PP::Preserve::Hash', %$val;
251             }
252             elsif (reftype($val) eq 'ARRAY' and not tied @$val) {
253 2         6 tie @$val, 'YAML::PP::Preserve::Array', @$val;
254             }
255             }
256 127         257 $self->{data}->{ $key } = $val;
257             }
258              
259             sub FIRSTKEY {
260 91     91   2975 my ($self) = @_;
261 91         251 return $self->{keys}->[0];
262             }
263              
264             sub NEXTKEY {
265 320     320   1028 my ($self, $last) = @_;
266 320         309 my $keys = $self->{keys};
267 320         412 for my $i (0 .. $#$keys) {
268 1167 100       1397 if ("$keys->[ $i ]" eq "$last") {
269 320         797 return $keys->[ $i + 1 ];
270             }
271             }
272 0         0 return;
273             }
274              
275             sub FETCH {
276 305     305   2791 my ($self, $key) = @_;
277 305         570 my $val = $self->{data}->{ $key };
278             }
279              
280             sub DELETE {
281 2     2   1520 my ($self, $key) = @_;
282 2         7 @{ $self->{keys} } = grep { "$_" ne "$key" } @{ $self->{keys} };
  2         12  
  12         24  
  2         5  
283 2         13 delete $self->{data}->{ $key };
284             }
285              
286             sub EXISTS {
287 34     34   691 my ($self, $key) = @_;
288 34         50 return exists $self->{data}->{ $key };
289             }
290              
291             sub CLEAR {
292 9     9   31 my ($self) = @_;
293 9         20 $self->{keys} = [];
294 9         32 $self->{data} = {};
295             }
296              
297             sub SCALAR {
298 3     3   1291 my ($self) = @_;
299 3         3 return scalar %{ $self->{data} };
  3         11  
300             }
301              
302             package YAML::PP::Preserve::Array;
303             # experimental
304 48     48   18277 use Tie::Array;
  48         43075  
  48         1365  
305 48     48   258 use base qw/ Tie::StdArray /;
  48         57  
  48         11227  
306 48     48   279 use Scalar::Util qw/ reftype blessed /;
  48         63  
  48         27088  
307              
308             sub TIEARRAY {
309 16     16   29 my ($class, @items) = @_;
310 16         40 my $self = bless {
311             data => [@items],
312             }, $class;
313 16         35 return $self;
314             }
315              
316             sub FETCH {
317 99     99   153 my ($self, $i) = @_;
318 99         226 return $self->{data}->[ $i ];
319             }
320             sub FETCHSIZE {
321 101     101   663 my ($self) = @_;
322 101         96 return $#{ $self->{data} } + 1;
  101         265  
323             }
324              
325             sub _preserve {
326 42     42   49 my ($val) = @_;
327 42 100 100     103 if (ref $val and not blessed($val)) {
328 13 100 100     80 if (reftype($val) eq 'HASH' and not tied %$val) {
    100 100        
329 5         9 tie %$val, 'YAML::PP::Preserve::Hash', %$val;
330             }
331             elsif (reftype($val) eq 'ARRAY' and not tied @$val) {
332 1         2 tie @$val, 'YAML::PP::Preserve::Array', @$val;
333             }
334             }
335 42         106 return $val;
336             }
337              
338             sub STORE {
339 6     6   662 my ($self, $i, $val) = @_;
340 6         11 _preserve($val);
341 6         14 $self->{data}->[ $i ] = $val;
342             }
343             sub PUSH {
344 14     14   31 my ($self, @args) = @_;
345 14         17 push @{ $self->{data} }, map { _preserve $_ } @args;
  14         35  
  31         49  
346             }
347             sub STORESIZE {
348 1     1   7 my ($self, $i) = @_;
349 1         2 $#{ $self->{data} } = $i - 1;
  1         4  
350             }
351             sub DELETE {
352 1     1   2 my ($self, $i) = @_;
353 1         3 delete $self->{data}->[ $i ];
354             }
355             sub EXISTS {
356 2     2   6 my ($self, $i) = @_;
357 2         13 return exists $self->{data}->[ $i ];
358             }
359             sub CLEAR {
360 1     1   7 my ($self) = @_;
361 1         5 $self->{data} = [];
362             }
363             sub SHIFT {
364 1     1   3 my ($self) = @_;
365 1         1 shift @{ $self->{data} };
  1         3  
366             }
367             sub UNSHIFT {
368 2     2   7 my ($self, @args) = @_;
369 2         3 unshift @{ $self->{data} }, map { _preserve $_ } @args;
  2         4  
  2         5  
370             }
371             sub SPLICE {
372 2     2   9 my ($self, $offset, $length, @args) = @_;
373 2         3 splice @{ $self->{data} }, $offset, $length, map { _preserve $_ } @args;
  2         5  
  3         6  
374             }
375       1     sub EXTEND {}
376              
377              
378             package YAML::PP::Preserve::Scalar;
379              
380             use overload
381 48         476 fallback => 1,
382             '+' => \&value,
383             '""' => \&value,
384             'bool' => \&value,
385 48     48   311 ;
  48         79  
386             sub new {
387 87     87   204 my ($class, %args) = @_;
388 87         253 my $self = {
389             %args,
390             };
391 87         336 bless $self, $class;
392             }
393 2218     2218   6916 sub value { $_[0]->{value} }
394 0     0   0 sub tag { $_[0]->{tag} }
395 21 100   21   52 sub style { $_[0]->{style} || 0 }
396 17     17   35 sub alias { $_[0]->{alias} }
397              
398             1;
399              
400             __END__