File Coverage

blib/lib/YAML/PP.pm
Criterion Covered Total %
statement 219 227 96.4
branch 30 36 83.3
condition 24 27 88.8
subroutine 62 63 98.4
pod 17 18 94.4
total 352 371 94.8


line stmt bran cond sub pod time code
1             # ABSTRACT: YAML 1.2 Processor
2 35     35   1815290 use strict;
  35         325  
  35         1145  
3 35     35   195 use warnings;
  35         66  
  35         1953  
4             package YAML::PP;
5              
6             our $VERSION = '0.036_002'; # TRIAL VERSION
7              
8 35     35   15248 use YAML::PP::Schema;
  35         97  
  35         1139  
9 35     35   15209 use YAML::PP::Schema::JSON;
  35         101  
  35         1786  
10 35     35   13216 use YAML::PP::Loader;
  35         100  
  35         1255  
11 35     35   14514 use YAML::PP::Dumper;
  35         108  
  35         1304  
12 35     35   240 use Scalar::Util qw/ blessed /;
  35         85  
  35         1698  
13 35     35   216 use Carp qw/ croak /;
  35         87  
  35         1407  
14              
15 35     35   210 use base 'Exporter';
  35         92  
  35         49836  
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 747     747 1 1349704 my ($class, %args) = @_;
23              
24 747         1770 my $bool = delete $args{boolean};
25 747 100       2180 $bool = 'perl' unless defined $bool;
26 747   100     2881 my $schemas = delete $args{schema} || ['+'];
27 747   100     2590 my $cyclic_refs = delete $args{cyclic_refs} || 'fatal';
28 747         1241 my $indent = delete $args{indent};
29 747         1139 my $width = delete $args{width};
30 747         2789 my $writer = delete $args{writer};
31 747         1214 my $header = delete $args{header};
32 747         1049 my $footer = delete $args{footer};
33 747         1186 my $duplicate_keys = delete $args{duplicate_keys};
34 747         2449 my $yaml_version = $class->_arg_yaml_version(delete $args{yaml_version});
35 747         1321 my $default_yaml_version = $yaml_version->[0];
36 747         1174 my $version_directive = delete $args{version_directive};
37 747         1092 my $preserve = delete $args{preserve};
38 747         1191 my $parser = delete $args{parser};
39             my $emitter = delete $args{emitter} || {
40 747   50     4139 indent => $indent,
41             width => $width,
42             writer => $writer,
43             };
44 747 50       1992 if (keys %args) {
45 0         0 die "Unexpected arguments: " . join ', ', sort keys %args;
46             }
47              
48 747         1114 my %schemas;
49 747         1453 for my $v (@$yaml_version) {
50 749         1153 my $schema;
51 749 50 33     2890 if (blessed($schemas) and $schemas->isa('YAML::PP::Schema')) {
52 0         0 $schema = $schemas;
53             }
54             else {
55 749         2875 $schema = YAML::PP::Schema->new(
56             boolean => $bool,
57             yaml_version => $v,
58             );
59 749         2329 $schema->load_subschemas(@$schemas);
60             }
61 748         2132 $schemas{ $v } = $schema;
62             }
63 746         1346 my $default_schema = $schemas{ $default_yaml_version };
64              
65 746         3253 my $loader = YAML::PP::Loader->new(
66             schemas => \%schemas,
67             cyclic_refs => $cyclic_refs,
68             parser => $parser,
69             default_yaml_version => $default_yaml_version,
70             preserve => $preserve,
71             duplicate_keys => $duplicate_keys,
72             );
73 745         2816 my $dumper = YAML::PP::Dumper->new(
74             schema => $default_schema,
75             emitter => $emitter,
76             header => $header,
77             footer => $footer,
78             version_directive => $version_directive,
79             preserve => $preserve,
80             );
81              
82 745         2503 my $self = bless {
83             schema => \%schemas,
84             loader => $loader,
85             dumper => $dumper,
86             }, $class;
87 745         4421 return $self;
88             }
89              
90             sub clone {
91 9     9 0 366 my ($self) = @_;
92 9         21 my $clone = {
93             schema => $self->schema,
94             loader => $self->loader->clone,
95             dumper => $self->dumper->clone,
96             };
97 9         30 return bless $clone, ref $self;
98             }
99              
100             sub _arg_yaml_version {
101 747     747   1400 my ($class, $version) = @_;
102 747         1690 my @versions = ('1.2');
103 747 100       1804 if (defined $version) {
104 5         13 @versions = ();
105 5 100       32 if (not ref $version) {
106 1         3 $version = [$version];
107             }
108 5         11 for my $v (@$version) {
109 7 50       22 unless ($YAML_VERSIONS{ $v }) {
110 0         0 croak "YAML Version '$v' not supported";
111             }
112 7         13 push @versions, $v;
113             }
114             }
115 747         1753 return \@versions;
116             }
117              
118              
119             sub loader {
120 2198 50   2198 1 6020 if (@_ > 1) {
121 0         0 $_[0]->{loader} = $_[1]
122             }
123 2198         7225 return $_[0]->{loader};
124             }
125              
126             sub dumper {
127 1491 50   1491 1 4023 if (@_ > 1) {
128 0         0 $_[0]->{dumper} = $_[1]
129             }
130 1491         5570 return $_[0]->{dumper};
131             }
132              
133             sub schema {
134 16 50   16 1 77 if (@_ > 1) { $_[0]->{schema}->{'1.2'} = $_[1] }
  0         0  
135 16         95 return $_[0]->{schema}->{'1.2'};
136             }
137              
138             sub default_schema {
139 3     3 1 179 my ($self, %args) = @_;
140             my $schema = YAML::PP::Schema->new(
141             boolean => $args{boolean},
142 3         55 );
143 3         18 $schema->load_subschemas(qw/ Core /);
144 3         16 return $schema;
145             }
146              
147             sub load_string {
148 2167     2167 1 805559 my ($self, $yaml) = @_;
149 2167         5221 return $self->loader->load_string($yaml);
150             }
151              
152             sub load_file {
153 19     19 1 58 my ($self, $file) = @_;
154 19         45 return $self->loader->load_file($file);
155             }
156              
157             sub dump {
158 1     1 1 8 my ($self, @data) = @_;
159 1         4 return $self->dumper->dump(@data);
160             }
161              
162             sub dump_string {
163 1475     1475 1 3315382 my ($self, @data) = @_;
164 1475         3654 return $self->dumper->dump_string(@data);
165             }
166              
167             sub dump_file {
168 6     6 1 20 my ($self, $file, @data) = @_;
169 6         16 return $self->dumper->dump_file($file, @data);
170             }
171              
172             # legagy interface
173             sub Load {
174 2     2 1 4228 my ($yaml) = @_;
175 2         14 YAML::PP->new->load_string($yaml);
176             }
177              
178             sub LoadFile {
179 3     3 1 2766 my ($file) = @_;
180 3         13 YAML::PP->new->load_file($file);
181             }
182              
183             sub Dump {
184 1     1 1 2231 my (@data) = @_;
185 1         7 YAML::PP->new->dump_string(@data);
186             }
187              
188             sub DumpFile {
189 4     4 1 747 my ($file, @data) = @_;
190 4         20 YAML::PP->new->dump_file($file, @data);
191             }
192              
193             sub preserved_scalar {
194 4     4 1 2609 my ($self, $value, %args) = @_;
195 4         24 my $scalar = YAML::PP::Preserve::Scalar->new(
196             value => $value,
197             %args,
198             );
199 4         13 return $scalar;
200             }
201              
202             sub preserved_mapping {
203 4     4 1 1363 my ($self, $hash, %args) = @_;
204 4         7 my $data = {};
205 4         17 tie %$data, 'YAML::PP::Preserve::Hash';
206 4         19 %$data = %$hash;
207 4         8 my $t = tied %$data;
208 4         9 $t->{style} = $args{style};
209 4         7 $t->{alias} = $args{alias};
210 4         11 return $data;
211             }
212              
213             sub preserved_sequence {
214 4     4 1 3007 my ($self, $array, %args) = @_;
215 4         6 my $data = [];
216 4         18 tie @$data, 'YAML::PP::Preserve::Array';
217 4         12 push @$data, @$array;
218 4         7 my $t = tied @$data;
219 4         9 $t->{style} = $args{style};
220 4         9 $t->{alias} = $args{alias};
221 4         14 return $data;
222             }
223              
224             package YAML::PP::Preserve::Hash;
225             # experimental
226 35     35   18648 use Tie::Hash;
  35         33699  
  35         1175  
227 35     35   252 use base qw/ Tie::StdHash /;
  35         75  
  35         11460  
228 35     35   322 use Scalar::Util qw/ reftype blessed /;
  35         82  
  35         22463  
229              
230             sub TIEHASH {
231 34     34   75 my ($class, %args) = @_;
232 34         188 my $self = bless {
233             keys => [keys %args],
234             data => { %args },
235             }, $class;
236             }
237              
238             sub STORE {
239 127     127   943 my ($self, $key, $val) = @_;
240 127         188 my $keys = $self->{keys};
241 127 100       235 unless (exists $self->{data}->{ $key }) {
242 120         246 push @$keys, $key;
243             }
244 127 100 100     420 if (ref $val and not blessed($val)) {
245 39 100 100     249 if (reftype($val) eq 'HASH' and not tied %$val) {
    100 100        
246 1         5 tie %$val, 'YAML::PP::Preserve::Hash', %$val;
247             }
248             elsif (reftype($val) eq 'ARRAY' and not tied @$val) {
249 2         7 tie @$val, 'YAML::PP::Preserve::Array', @$val;
250             }
251             }
252 127         392 $self->{data}->{ $key } = $val;
253             }
254              
255             sub FIRSTKEY {
256 91     91   2941 my ($self) = @_;
257 91         299 return $self->{keys}->[0];
258             }
259              
260             sub NEXTKEY {
261 320     320   1131 my ($self, $last) = @_;
262 320         425 my $keys = $self->{keys};
263 320         614 for my $i (0 .. $#$keys) {
264 1167 100       1887 if ("$keys->[ $i ]" eq "$last") {
265 320         1093 return $keys->[ $i + 1 ];
266             }
267             }
268 0         0 return;
269             }
270              
271             sub FETCH {
272 305     305   2602 my ($self, $key) = @_;
273 305         742 my $val = $self->{data}->{ $key };
274             }
275              
276             sub DELETE {
277 2     2   1465 my ($self, $key) = @_;
278 2         4 @{ $self->{keys} } = grep { "$_" ne "$key" } @{ $self->{keys} };
  2         13  
  12         24  
  2         5  
279 2         11 delete $self->{data}->{ $key };
280             }
281              
282             sub EXISTS {
283 34     34   711 my ($self, $key) = @_;
284 34         58 return exists $self->{data}->{ $key };
285             }
286              
287             sub CLEAR {
288 9     9   31 my ($self) = @_;
289 9         19 $self->{keys} = [];
290 9         37 $self->{data} = {};
291             }
292              
293             sub SCALAR {
294 3     3   1158 my ($self) = @_;
295 3         6 return scalar %{ $self->{data} };
  3         14  
296             }
297              
298             package YAML::PP::Preserve::Array;
299             # experimental
300 35     35   16518 use Tie::Array;
  35         42907  
  35         1191  
301 35     35   244 use base qw/ Tie::StdArray /;
  35         88  
  35         10697  
302 35     35   283 use Scalar::Util qw/ reftype blessed /;
  35         81  
  35         25986  
303              
304             sub TIEARRAY {
305 16     16   39 my ($class, @items) = @_;
306 16         51 my $self = bless {
307             data => [@items],
308             }, $class;
309 16         43 return $self;
310             }
311              
312             sub FETCH {
313 99     99   174 my ($self, $i) = @_;
314 99         252 return $self->{data}->[ $i ];
315             }
316             sub FETCHSIZE {
317 101     101   799 my ($self) = @_;
318 101         122 return $#{ $self->{data} } + 1;
  101         320  
319             }
320              
321             sub _preserve {
322 42     42   69 my ($val) = @_;
323 42 100 100     179 if (ref $val and not blessed($val)) {
324 13 100 100     85 if (reftype($val) eq 'HASH' and not tied %$val) {
    100 100        
325 5         18 tie %$val, 'YAML::PP::Preserve::Hash', %$val;
326             }
327             elsif (reftype($val) eq 'ARRAY' and not tied @$val) {
328 1         5 tie @$val, 'YAML::PP::Preserve::Array', @$val;
329             }
330             }
331 42         150 return $val;
332             }
333              
334             sub STORE {
335 6     6   597 my ($self, $i, $val) = @_;
336 6         14 _preserve($val);
337 6         18 $self->{data}->[ $i ] = $val;
338             }
339             sub PUSH {
340 14     14   39 my ($self, @args) = @_;
341 14         17 push @{ $self->{data} }, map { _preserve $_ } @args;
  14         36  
  31         53  
342             }
343             sub STORESIZE {
344 1     1   10 my ($self, $i) = @_;
345 1         3 $#{ $self->{data} } = $i - 1;
  1         4  
346             }
347             sub DELETE {
348 1     1   4 my ($self, $i) = @_;
349 1         4 delete $self->{data}->[ $i ];
350             }
351             sub EXISTS {
352 2     2   6 my ($self, $i) = @_;
353 2         14 return exists $self->{data}->[ $i ];
354             }
355             sub CLEAR {
356 1     1   9 my ($self) = @_;
357 1         8 $self->{data} = [];
358             }
359             sub SHIFT {
360 1     1   3 my ($self) = @_;
361 1         3 shift @{ $self->{data} };
  1         5  
362             }
363             sub UNSHIFT {
364 2     2   12 my ($self, @args) = @_;
365 2         5 unshift @{ $self->{data} }, map { _preserve $_ } @args;
  2         8  
  2         8  
366             }
367             sub SPLICE {
368 2     2   22 my ($self, $offset, $length, @args) = @_;
369 2         4 splice @{ $self->{data} }, $offset, $length, map { _preserve $_ } @args;
  2         8  
  3         8  
370             }
371       1     sub EXTEND {}
372              
373              
374             package YAML::PP::Preserve::Scalar;
375              
376             use overload
377 35         461 fallback => 1,
378             '+' => \&value,
379             '""' => \&value,
380             'bool' => \&value,
381 35     35   316 ;
  35         104  
382             sub new {
383 87     87   250 my ($class, %args) = @_;
384 87         253 my $self = {
385             %args,
386             };
387 87         332 bless $self, $class;
388             }
389 2218     2218   8160 sub value { $_[0]->{value} }
390 0     0   0 sub tag { $_[0]->{tag} }
391 21 100   21   64 sub style { $_[0]->{style} || 0 }
392 17     17   79 sub alias { $_[0]->{alias} }
393              
394             1;
395              
396             __END__