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 43     43   2501056 use strict;
  43         63  
  43         1319  
3 43     43   162 use warnings;
  43         79  
  43         2581  
4             package YAML::PP;
5              
6             our $VERSION = 'v0.40.0'; # VERSION
7              
8 43     43   15960 use YAML::PP::Schema;
  43         98  
  43         1309  
9 43     43   16165 use YAML::PP::Schema::JSON;
  43         136  
  43         2217  
10 43     43   14268 use YAML::PP::Loader;
  43         123  
  43         1294  
11 43     43   15012 use YAML::PP::Dumper;
  43         131  
  43         1521  
12 43     43   229 use Scalar::Util qw/ blessed /;
  43         80  
  43         1970  
13 43     43   184 use Carp qw/ croak /;
  43         53  
  43         1485  
14              
15 43     43   157 use base 'Exporter';
  43         56  
  43         49742  
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 756     756 1 5112605 my ($class, %args) = @_;
23              
24 756         1682 my $bool = delete $args{boolean};
25 756 100       2277 $bool = 'perl' unless defined $bool;
26 756   100     2368 my $schemas = delete $args{schema} || ['+'];
27 756   100     2804 my $cyclic_refs = delete $args{cyclic_refs} || 'fatal';
28 756         1366 my $indent = delete $args{indent};
29 756         966 my $width = delete $args{width};
30 756         986 my $writer = delete $args{writer};
31 756         906 my $header = delete $args{header};
32 756         1000 my $footer = delete $args{footer};
33 756         775 my $require_footer = delete $args{require_footer};
34 756         893 my $duplicate_keys = delete $args{duplicate_keys};
35 756         915 my $max_depth = delete $args{max_depth};
36 756         2240 my $yaml_version = $class->_arg_yaml_version(delete $args{yaml_version});
37 756         1027 my $default_yaml_version = $yaml_version->[0];
38 756         826 my $version_directive = delete $args{version_directive};
39 756         924 my $preserve = delete $args{preserve};
40 756         803 my $parser = delete $args{parser};
41             my $emitter = delete $args{emitter} || {
42 756   50     3382 indent => $indent,
43             width => $width,
44             writer => $writer,
45             };
46 756 50       1548 if (keys %args) {
47 0         0 die "Unexpected arguments: " . join ', ', sort keys %args;
48             }
49              
50 756         989 my %schemas;
51 756         1284 for my $v (@$yaml_version) {
52 758         867 my $schema;
53 758 50 33     2013 if (blessed($schemas) and $schemas->isa('YAML::PP::Schema')) {
54 0         0 $schema = $schemas;
55             }
56             else {
57 758         3046 $schema = YAML::PP::Schema->new(
58             boolean => $bool,
59             yaml_version => $v,
60             );
61 758         2174 $schema->load_subschemas(@$schemas);
62             }
63 757         1681 $schemas{ $v } = $schema;
64             }
65 755         1157 my $default_schema = $schemas{ $default_yaml_version };
66              
67 755         3586 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 754         3147 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 754         2254 my $self = bless {
87             schema => \%schemas,
88             loader => $loader,
89             dumper => $dumper,
90             }, $class;
91 754         3919 return $self;
92             }
93              
94             sub clone {
95 9     9 0 290 my ($self) = @_;
96 9         16 my $clone = {
97             schema => $self->schema,
98             loader => $self->loader->clone,
99             dumper => $self->dumper->clone,
100             };
101 9         21 return bless $clone, ref $self;
102             }
103              
104             sub _arg_yaml_version {
105 756     756   1204 my ($class, $version) = @_;
106 756         1621 my @versions = ('1.2');
107 756 100       1574 if (defined $version) {
108 5         9 @versions = ();
109 5 100       11 if (not ref $version) {
110 1         2 $version = [$version];
111             }
112 5         12 for my $v (@$version) {
113 7 50       17 unless ($YAML_VERSIONS{ $v }) {
114 0         0 croak "YAML Version '$v' not supported";
115             }
116 7         13 push @versions, $v;
117             }
118             }
119 756         1568 return \@versions;
120             }
121              
122              
123             sub loader {
124 2212 50   2212 1 6087 if (@_ > 1) {
125 0         0 $_[0]->{loader} = $_[1]
126             }
127 2212         7485 return $_[0]->{loader};
128             }
129              
130             sub dumper {
131 1494 50   1494 1 4068 if (@_ > 1) {
132 0         0 $_[0]->{dumper} = $_[1]
133             }
134 1494         6098 return $_[0]->{dumper};
135             }
136              
137             sub schema {
138 16 50   16 1 69 if (@_ > 1) { $_[0]->{schema}->{'1.2'} = $_[1] }
  0         0  
139 16         77 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         23 );
147 3         15 $schema->load_subschemas(qw/ Core /);
148 3         15 return $schema;
149             }
150              
151             sub load_string {
152 2181     2181 1 978992 my ($self, $yaml) = @_;
153 2181         5545 return $self->loader->load_string($yaml);
154             }
155              
156             sub load_file {
157 19     19 1 40 my ($self, $file) = @_;
158 19         47 return $self->loader->load_file($file);
159             }
160              
161             sub dump {
162 1     1 1 5 my ($self, @data) = @_;
163 1         3 return $self->dumper->dump(@data);
164             }
165              
166             sub dump_string {
167 1478     1478 1 3411055 my ($self, @data) = @_;
168 1478         4460 return $self->dumper->dump_string(@data);
169             }
170              
171             sub dump_file {
172 6     6 1 14 my ($self, $file, @data) = @_;
173 6         18 return $self->dumper->dump_file($file, @data);
174             }
175              
176             # legagy interface
177             sub Load {
178 2     2 1 171535 my ($yaml) = @_;
179 2         13 YAML::PP->new->load_string($yaml);
180             }
181              
182             sub LoadFile {
183 3     3 1 2829 my ($file) = @_;
184 3         11 YAML::PP->new->load_file($file);
185             }
186              
187             sub Dump {
188 1     1 1 1524 my (@data) = @_;
189 1         7 YAML::PP->new->dump_string(@data);
190             }
191              
192             sub DumpFile {
193 4     4 1 659 my ($file, @data) = @_;
194 4         24 YAML::PP->new->dump_file($file, @data);
195             }
196              
197             sub preserved_scalar {
198 4     4 1 3574 my ($self, $value, %args) = @_;
199 4         35 my $scalar = YAML::PP::Preserve::Scalar->new(
200             value => $value,
201             %args,
202             );
203 4         10 return $scalar;
204             }
205              
206             sub preserved_mapping {
207 4     4 1 1355 my ($self, $hash, %args) = @_;
208 4         6 my $data = {};
209 4         15 tie %$data, 'YAML::PP::Preserve::Hash';
210 4         14 %$data = %$hash;
211 4         7 my $t = tied %$data;
212 4         8 $t->{style} = $args{style};
213 4         6 $t->{alias} = $args{alias};
214 4         9 return $data;
215             }
216              
217             sub preserved_sequence {
218 4     4 1 3200 my ($self, $array, %args) = @_;
219 4         5 my $data = [];
220 4         14 tie @$data, 'YAML::PP::Preserve::Array';
221 4         12 push @$data, @$array;
222 4         7 my $t = tied @$data;
223 4         6 $t->{style} = $args{style};
224 4         5 $t->{alias} = $args{alias};
225 4         10 return $data;
226             }
227              
228             package YAML::PP::Preserve::Hash;
229             # experimental
230 43     43   19432 use Tie::Hash;
  43         31584  
  43         1351  
231 43     43   216 use base qw/ Tie::StdHash /;
  43         83  
  43         10812  
232 43     43   251 use Scalar::Util qw/ reftype blessed /;
  43         68  
  43         21979  
233              
234             sub TIEHASH {
235 34     34   66 my ($class, %args) = @_;
236 34         168 my $self = bless {
237             keys => [keys %args],
238             data => { %args },
239             }, $class;
240             }
241              
242             sub STORE {
243 127     127   1352 my ($self, $key, $val) = @_;
244 127         166 my $keys = $self->{keys};
245 127 100       274 unless (exists $self->{data}->{ $key }) {
246 120         173 push @$keys, $key;
247             }
248 127 100 100     293 if (ref $val and not blessed($val)) {
249 39 100 100     159 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         7 tie @$val, 'YAML::PP::Preserve::Array', @$val;
254             }
255             }
256 127         307 $self->{data}->{ $key } = $val;
257             }
258              
259             sub FIRSTKEY {
260 91     91   4595 my ($self) = @_;
261 91         307 return $self->{keys}->[0];
262             }
263              
264             sub NEXTKEY {
265 320     320   1488 my ($self, $last) = @_;
266 320         346 my $keys = $self->{keys};
267 320         459 for my $i (0 .. $#$keys) {
268 1167 100       1513 if ("$keys->[ $i ]" eq "$last") {
269 320         874 return $keys->[ $i + 1 ];
270             }
271             }
272 0         0 return;
273             }
274              
275             sub FETCH {
276 305     305   3657 my ($self, $key) = @_;
277 305         641 my $val = $self->{data}->{ $key };
278             }
279              
280             sub DELETE {
281 2     2   2060 my ($self, $key) = @_;
282 2         4 @{ $self->{keys} } = grep { "$_" ne "$key" } @{ $self->{keys} };
  2         12  
  12         22  
  2         8  
283 2         14 delete $self->{data}->{ $key };
284             }
285              
286             sub EXISTS {
287 34     34   1236 my ($self, $key) = @_;
288 34         56 return exists $self->{data}->{ $key };
289             }
290              
291             sub CLEAR {
292 9     9   21 my ($self) = @_;
293 9         23 $self->{keys} = [];
294 9         55 $self->{data} = {};
295             }
296              
297             sub SCALAR {
298 3     3   2383 my ($self) = @_;
299 3         8 return scalar %{ $self->{data} };
  3         15  
300             }
301              
302             package YAML::PP::Preserve::Array;
303             # experimental
304 43     43   17154 use Tie::Array;
  43         41085  
  43         1270  
305 43     43   231 use base qw/ Tie::StdArray /;
  43         55  
  43         10532  
306 43     43   234 use Scalar::Util qw/ reftype blessed /;
  43         52  
  43         25769  
307              
308             sub TIEARRAY {
309 16     16   29 my ($class, @items) = @_;
310 16         45 my $self = bless {
311             data => [@items],
312             }, $class;
313 16         42 return $self;
314             }
315              
316             sub FETCH {
317 99     99   137 my ($self, $i) = @_;
318 99         209 return $self->{data}->[ $i ];
319             }
320             sub FETCHSIZE {
321 101     101   656 my ($self) = @_;
322 101         108 return $#{ $self->{data} } + 1;
  101         277  
323             }
324              
325             sub _preserve {
326 42     42   56 my ($val) = @_;
327 42 100 100     129 if (ref $val and not blessed($val)) {
328 13 100 100     62 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         123 return $val;
336             }
337              
338             sub STORE {
339 6     6   799 my ($self, $i, $val) = @_;
340 6         10 _preserve($val);
341 6         15 $self->{data}->[ $i ] = $val;
342             }
343             sub PUSH {
344 14     14   35 my ($self, @args) = @_;
345 14         18 push @{ $self->{data} }, map { _preserve $_ } @args;
  14         32  
  31         46  
346             }
347             sub STORESIZE {
348 1     1   8 my ($self, $i) = @_;
349 1         4 $#{ $self->{data} } = $i - 1;
  1         6  
350             }
351             sub DELETE {
352 1     1   3 my ($self, $i) = @_;
353 1         3 delete $self->{data}->[ $i ];
354             }
355             sub EXISTS {
356 2     2   7 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   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   8 my ($self, $offset, $length, @args) = @_;
373 2         4 splice @{ $self->{data} }, $offset, $length, map { _preserve $_ } @args;
  2         5  
  3         5  
374             }
375       1     sub EXTEND {}
376              
377              
378             package YAML::PP::Preserve::Scalar;
379              
380             use overload
381 43         462 fallback => 1,
382             '+' => \&value,
383             '""' => \&value,
384             'bool' => \&value,
385 43     43   284 ;
  43         58  
386             sub new {
387 87     87   202 my ($class, %args) = @_;
388 87         235 my $self = {
389             %args,
390             };
391 87         303 bless $self, $class;
392             }
393 2218     2218   6033 sub value { $_[0]->{value} }
394 0     0   0 sub tag { $_[0]->{tag} }
395 21 100   21   65 sub style { $_[0]->{style} || 0 }
396 17     17   59 sub alias { $_[0]->{alias} }
397              
398             1;
399              
400             __END__