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   3482236 use strict;
  48         76  
  48         1398  
3 48     48   242 use warnings;
  48         74  
  48         2943  
4             package YAML::PP;
5              
6             our $VERSION = 'v0.41.0'; # VERSION
7              
8 48     48   21834 use YAML::PP::Schema;
  48         107  
  48         1407  
9 48     48   19353 use YAML::PP::Schema::JSON;
  48         154  
  48         2399  
10 48     48   16130 use YAML::PP::Loader;
  48         146  
  48         1522  
11 48     48   17949 use YAML::PP::Dumper;
  48         147  
  48         1783  
12 48     48   243 use Scalar::Util qw/ blessed /;
  48         63  
  48         2229  
13 48     48   210 use Carp qw/ croak /;
  48         70  
  48         1741  
14              
15 48     48   210 use base 'Exporter';
  48         88  
  48         53767  
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 4956966 my ($class, %args) = @_;
23              
24 765         1786 my $bool = delete $args{boolean};
25 765 100       2446 $bool = 'perl' unless defined $bool;
26 765   100     2500 my $schemas = delete $args{schema} || ['+'];
27 765   100     3077 my $cyclic_refs = delete $args{cyclic_refs} || 'fatal';
28 765         1191 my $indent = delete $args{indent};
29 765         1022 my $width = delete $args{width};
30 765         1153 my $writer = delete $args{writer};
31 765         1231 my $header = delete $args{header};
32 765         1020 my $footer = delete $args{footer};
33 765         1218 my $require_footer = delete $args{require_footer};
34 765         1024 my $duplicate_keys = delete $args{duplicate_keys};
35 765         1083 my $max_depth = delete $args{max_depth};
36 765         2495 my $yaml_version = $class->_arg_yaml_version(delete $args{yaml_version});
37 765         1279 my $default_yaml_version = $yaml_version->[0];
38 765         980 my $version_directive = delete $args{version_directive};
39 765         1030 my $preserve = delete $args{preserve};
40 765         1068 my $parser = delete $args{parser};
41             my $emitter = delete $args{emitter} || {
42 765   50     3724 indent => $indent,
43             width => $width,
44             writer => $writer,
45             };
46 765 50       2496 if (keys %args) {
47 0         0 die "Unexpected arguments: " . join ', ', sort keys %args;
48             }
49              
50 765         1210 my %schemas;
51 765         1497 for my $v (@$yaml_version) {
52 767         975 my $schema;
53 767 50 33     2245 if (blessed($schemas) and $schemas->isa('YAML::PP::Schema')) {
54 0         0 $schema = $schemas;
55             }
56             else {
57 767         3729 $schema = YAML::PP::Schema->new(
58             boolean => $bool,
59             yaml_version => $v,
60             );
61 767         2630 $schema->load_subschemas(@$schemas);
62             }
63 766         1830 $schemas{ $v } = $schema;
64             }
65 764         1089 my $default_schema = $schemas{ $default_yaml_version };
66              
67 764         3313 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         3246 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         2180 my $self = bless {
87             schema => \%schemas,
88             loader => $loader,
89             dumper => $dumper,
90             }, $class;
91 763         4165 return $self;
92             }
93              
94             sub clone {
95 9     9 0 262 my ($self) = @_;
96 9         18 my $clone = {
97             schema => $self->schema,
98             loader => $self->loader->clone,
99             dumper => $self->dumper->clone,
100             };
101 9         30 return bless $clone, ref $self;
102             }
103              
104             sub _arg_yaml_version {
105 765     765   1440 my ($class, $version) = @_;
106 765         1730 my @versions = ('1.2');
107 765 100       1779 if (defined $version) {
108 5         9 @versions = ();
109 5 100       12 if (not ref $version) {
110 1         2 $version = [$version];
111             }
112 5         9 for my $v (@$version) {
113 7 50       16 unless ($YAML_VERSIONS{ $v }) {
114 0         0 croak "YAML Version '$v' not supported";
115             }
116 7         12 push @versions, $v;
117             }
118             }
119 765         1802 return \@versions;
120             }
121              
122              
123             sub loader {
124 2221 50   2221 1 5451 if (@_ > 1) {
125 0         0 $_[0]->{loader} = $_[1]
126             }
127 2221         7432 return $_[0]->{loader};
128             }
129              
130             sub dumper {
131 1494 50   1494 1 4616 if (@_ > 1) {
132 0         0 $_[0]->{dumper} = $_[1]
133             }
134 1494         5935 return $_[0]->{dumper};
135             }
136              
137             sub schema {
138 16 50   16 1 49 if (@_ > 1) { $_[0]->{schema}->{'1.2'} = $_[1] }
  0         0  
139 16         67 return $_[0]->{schema}->{'1.2'};
140             }
141              
142             sub default_schema {
143 3     3 1 12 my ($self, %args) = @_;
144             my $schema = YAML::PP::Schema->new(
145             boolean => $args{boolean},
146 3         25 );
147 3         13 $schema->load_subschemas(qw/ Core /);
148 3         16 return $schema;
149             }
150              
151             sub load_string {
152 2181     2181 1 985466 my ($self, $yaml) = @_;
153 2181         5391 return $self->loader->load_string($yaml);
154             }
155              
156             sub load_file {
157 28     28 1 73 my ($self, $file) = @_;
158 28         79 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 3371986 my ($self, @data) = @_;
168 1478         4214 return $self->dumper->dump_string(@data);
169             }
170              
171             sub dump_file {
172 6     6 1 17 my ($self, $file, @data) = @_;
173 6         12 return $self->dumper->dump_file($file, @data);
174             }
175              
176             # legagy interface
177             sub Load {
178 2     2 1 202407 my ($yaml) = @_;
179 2         17 YAML::PP->new->load_string($yaml);
180             }
181              
182             sub LoadFile {
183 12     12 1 1340223 my ($file) = @_;
184 12         61 YAML::PP->new->load_file($file);
185             }
186              
187             sub Dump {
188 1     1 1 2088 my (@data) = @_;
189 1         11 YAML::PP->new->dump_string(@data);
190             }
191              
192             sub DumpFile {
193 4     4 1 867 my ($file, @data) = @_;
194 4         24 YAML::PP->new->dump_file($file, @data);
195             }
196              
197             sub preserved_scalar {
198 4     4 1 3802 my ($self, $value, %args) = @_;
199 4         20 my $scalar = YAML::PP::Preserve::Scalar->new(
200             value => $value,
201             %args,
202             );
203 4         9 return $scalar;
204             }
205              
206             sub preserved_mapping {
207 4     4 1 1564 my ($self, $hash, %args) = @_;
208 4         7 my $data = {};
209 4         14 tie %$data, 'YAML::PP::Preserve::Hash';
210 4         14 %$data = %$hash;
211 4         7 my $t = tied %$data;
212 4         6 $t->{style} = $args{style};
213 4         7 $t->{alias} = $args{alias};
214 4         8 return $data;
215             }
216              
217             sub preserved_sequence {
218 4     4 1 4038 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         20 my $t = tied @$data;
223 4         8 $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   21469 use Tie::Hash;
  48         34810  
  48         1497  
231 48     48   275 use base qw/ Tie::StdHash /;
  48         61  
  48         12454  
232 48     48   301 use Scalar::Util qw/ reftype blessed /;
  48         64  
  48         24818  
233              
234             sub TIEHASH {
235 34     34   57 my ($class, %args) = @_;
236 34         166 my $self = bless {
237             keys => [keys %args],
238             data => { %args },
239             }, $class;
240             }
241              
242             sub STORE {
243 127     127   1094 my ($self, $key, $val) = @_;
244 127         148 my $keys = $self->{keys};
245 127 100       272 unless (exists $self->{data}->{ $key }) {
246 120         149 push @$keys, $key;
247             }
248 127 100 100     230 if (ref $val and not blessed($val)) {
249 39 100 100     132 if (reftype($val) eq 'HASH' and not tied %$val) {
    100 100        
250 1         3 tie %$val, 'YAML::PP::Preserve::Hash', %$val;
251             }
252             elsif (reftype($val) eq 'ARRAY' and not tied @$val) {
253 2         5 tie @$val, 'YAML::PP::Preserve::Array', @$val;
254             }
255             }
256 127         245 $self->{data}->{ $key } = $val;
257             }
258              
259             sub FIRSTKEY {
260 91     91   3437 my ($self) = @_;
261 91         244 return $self->{keys}->[0];
262             }
263              
264             sub NEXTKEY {
265 320     320   985 my ($self, $last) = @_;
266 320         306 my $keys = $self->{keys};
267 320         433 for my $i (0 .. $#$keys) {
268 1167 100       1354 if ("$keys->[ $i ]" eq "$last") {
269 320         814 return $keys->[ $i + 1 ];
270             }
271             }
272 0         0 return;
273             }
274              
275             sub FETCH {
276 305     305   3004 my ($self, $key) = @_;
277 305         576 my $val = $self->{data}->{ $key };
278             }
279              
280             sub DELETE {
281 2     2   1850 my ($self, $key) = @_;
282 2         5 @{ $self->{keys} } = grep { "$_" ne "$key" } @{ $self->{keys} };
  2         10  
  12         17  
  2         7  
283 2         12 delete $self->{data}->{ $key };
284             }
285              
286             sub EXISTS {
287 34     34   886 my ($self, $key) = @_;
288 34         50 return exists $self->{data}->{ $key };
289             }
290              
291             sub CLEAR {
292 9     9   20 my ($self) = @_;
293 9         15 $self->{keys} = [];
294 9         29 $self->{data} = {};
295             }
296              
297             sub SCALAR {
298 3     3   1440 my ($self) = @_;
299 3         4 return scalar %{ $self->{data} };
  3         10  
300             }
301              
302             package YAML::PP::Preserve::Array;
303             # experimental
304 48     48   18720 use Tie::Array;
  48         45056  
  48         1356  
305 48     48   239 use base qw/ Tie::StdArray /;
  48         78  
  48         11506  
306 48     48   262 use Scalar::Util qw/ reftype blessed /;
  48         59  
  48         27909  
307              
308             sub TIEARRAY {
309 16     16   29 my ($class, @items) = @_;
310 16         38 my $self = bless {
311             data => [@items],
312             }, $class;
313 16         34 return $self;
314             }
315              
316             sub FETCH {
317 99     99   121 my ($self, $i) = @_;
318 99         197 return $self->{data}->[ $i ];
319             }
320             sub FETCHSIZE {
321 101     101   595 my ($self) = @_;
322 101         91 return $#{ $self->{data} } + 1;
  101         285  
323             }
324              
325             sub _preserve {
326 42     42   55 my ($val) = @_;
327 42 100 100     111 if (ref $val and not blessed($val)) {
328 13 100 100     58 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         3 tie @$val, 'YAML::PP::Preserve::Array', @$val;
333             }
334             }
335 42         109 return $val;
336             }
337              
338             sub STORE {
339 6     6   837 my ($self, $i, $val) = @_;
340 6         10 _preserve($val);
341 6         16 $self->{data}->[ $i ] = $val;
342             }
343             sub PUSH {
344 14     14   36 my ($self, @args) = @_;
345 14         15 push @{ $self->{data} }, map { _preserve $_ } @args;
  14         63  
  31         47  
346             }
347             sub STORESIZE {
348 1     1   27 my ($self, $i) = @_;
349 1         2 $#{ $self->{data} } = $i - 1;
  1         5  
350             }
351             sub DELETE {
352 1     1   3 my ($self, $i) = @_;
353 1         4 delete $self->{data}->[ $i ];
354             }
355             sub EXISTS {
356 2     2   4 my ($self, $i) = @_;
357 2         9 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   2 my ($self) = @_;
365 1         2 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         6  
  3         4  
374             }
375       1     sub EXTEND {}
376              
377              
378             package YAML::PP::Preserve::Scalar;
379              
380             use overload
381 48         545 fallback => 1,
382             '+' => \&value,
383             '""' => \&value,
384             'bool' => \&value,
385 48     48   310 ;
  48         75  
386             sub new {
387 87     87   204 my ($class, %args) = @_;
388 87         203 my $self = {
389             %args,
390             };
391 87         277 bless $self, $class;
392             }
393 2218     2218   6147 sub value { $_[0]->{value} }
394 0     0   0 sub tag { $_[0]->{tag} }
395 21 100   21   48 sub style { $_[0]->{style} || 0 }
396 17     17   33 sub alias { $_[0]->{alias} }
397              
398             1;
399              
400             __END__