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   1782147 use strict;
  35         303  
  35         1025  
3 35     35   184 use warnings;
  35         68  
  35         1848  
4             package YAML::PP;
5              
6             our $VERSION = '0.036_001'; # TRIAL VERSION
7              
8 35     35   15343 use YAML::PP::Schema;
  35         99  
  35         1161  
9 35     35   15018 use YAML::PP::Schema::JSON;
  35         84  
  35         1708  
10 35     35   13094 use YAML::PP::Loader;
  35         110  
  35         1180  
11 35     35   14261 use YAML::PP::Dumper;
  35         106  
  35         1304  
12 35     35   255 use Scalar::Util qw/ blessed /;
  35         76  
  35         1614  
13 35     35   205 use Carp qw/ croak /;
  35         87  
  35         1350  
14              
15 35     35   196 use base 'Exporter';
  35         72  
  35         49021  
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 1329132 my ($class, %args) = @_;
23              
24 747         1813 my $bool = delete $args{boolean};
25 747 100       2122 $bool = 'perl' unless defined $bool;
26 747   100     2874 my $schemas = delete $args{schema} || ['+'];
27 747   100     2695 my $cyclic_refs = delete $args{cyclic_refs} || 'fatal';
28 747         1217 my $indent = delete $args{indent};
29 747         1079 my $width = delete $args{width};
30 747         2666 my $writer = delete $args{writer};
31 747         1172 my $header = delete $args{header};
32 747         1131 my $footer = delete $args{footer};
33 747         1064 my $duplicate_keys = delete $args{duplicate_keys};
34 747         2207 my $yaml_version = $class->_arg_yaml_version(delete $args{yaml_version});
35 747         1346 my $default_yaml_version = $yaml_version->[0];
36 747         1109 my $version_directive = delete $args{version_directive};
37 747         1059 my $preserve = delete $args{preserve};
38 747         1142 my $parser = delete $args{parser};
39             my $emitter = delete $args{emitter} || {
40 747   50     3685 indent => $indent,
41             width => $width,
42             writer => $writer,
43             };
44 747 50       1947 if (keys %args) {
45 0         0 die "Unexpected arguments: " . join ', ', sort keys %args;
46             }
47              
48 747         1006 my %schemas;
49 747         1462 for my $v (@$yaml_version) {
50 749         981 my $schema;
51 749 50 33     2917 if (blessed($schemas) and $schemas->isa('YAML::PP::Schema')) {
52 0         0 $schema = $schemas;
53             }
54             else {
55 749         2841 $schema = YAML::PP::Schema->new(
56             boolean => $bool,
57             yaml_version => $v,
58             );
59 749         2451 $schema->load_subschemas(@$schemas);
60             }
61 748         2094 $schemas{ $v } = $schema;
62             }
63 746         1363 my $default_schema = $schemas{ $default_yaml_version };
64              
65 746         3178 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         2736 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         2472 my $self = bless {
83             schema => \%schemas,
84             loader => $loader,
85             dumper => $dumper,
86             }, $class;
87 745         4084 return $self;
88             }
89              
90             sub clone {
91 9     9 0 325 my ($self) = @_;
92 9         26 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   1403 my ($class, $version) = @_;
102 747         1623 my @versions = ('1.2');
103 747 100       1790 if (defined $version) {
104 5         8 @versions = ();
105 5 100       13 if (not ref $version) {
106 1         3 $version = [$version];
107             }
108 5         11 for my $v (@$version) {
109 7 50       18 unless ($YAML_VERSIONS{ $v }) {
110 0         0 croak "YAML Version '$v' not supported";
111             }
112 7         14 push @versions, $v;
113             }
114             }
115 747         1689 return \@versions;
116             }
117              
118              
119             sub loader {
120 2198 50   2198 1 5638 if (@_ > 1) {
121 0         0 $_[0]->{loader} = $_[1]
122             }
123 2198         7209 return $_[0]->{loader};
124             }
125              
126             sub dumper {
127 1491 50   1491 1 4217 if (@_ > 1) {
128 0         0 $_[0]->{dumper} = $_[1]
129             }
130 1491         5552 return $_[0]->{dumper};
131             }
132              
133             sub schema {
134 16 50   16 1 67 if (@_ > 1) { $_[0]->{schema}->{'1.2'} = $_[1] }
  0         0  
135 16         102 return $_[0]->{schema}->{'1.2'};
136             }
137              
138             sub default_schema {
139 3     3 1 199 my ($self, %args) = @_;
140             my $schema = YAML::PP::Schema->new(
141             boolean => $args{boolean},
142 3         52 );
143 3         15 $schema->load_subschemas(qw/ Core /);
144 3         18 return $schema;
145             }
146              
147             sub load_string {
148 2167     2167 1 840284 my ($self, $yaml) = @_;
149 2167         5052 return $self->loader->load_string($yaml);
150             }
151              
152             sub load_file {
153 19     19 1 56 my ($self, $file) = @_;
154 19         38 return $self->loader->load_file($file);
155             }
156              
157             sub dump {
158 1     1 1 7 my ($self, @data) = @_;
159 1         2 return $self->dumper->dump(@data);
160             }
161              
162             sub dump_string {
163 1475     1475 1 3356771 my ($self, @data) = @_;
164 1475         3455 return $self->dumper->dump_string(@data);
165             }
166              
167             sub dump_file {
168 6     6 1 22 my ($self, $file, @data) = @_;
169 6         19 return $self->dumper->dump_file($file, @data);
170             }
171              
172             # legagy interface
173             sub Load {
174 2     2 1 3397 my ($yaml) = @_;
175 2         11 YAML::PP->new->load_string($yaml);
176             }
177              
178             sub LoadFile {
179 3     3 1 1982 my ($file) = @_;
180 3         10 YAML::PP->new->load_file($file);
181             }
182              
183             sub Dump {
184 1     1 1 2032 my (@data) = @_;
185 1         7 YAML::PP->new->dump_string(@data);
186             }
187              
188             sub DumpFile {
189 4     4 1 775 my ($file, @data) = @_;
190 4         21 YAML::PP->new->dump_file($file, @data);
191             }
192              
193             sub preserved_scalar {
194 4     4 1 2814 my ($self, $value, %args) = @_;
195 4         18 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 1504 my ($self, $hash, %args) = @_;
204 4         8 my $data = {};
205 4         14 tie %$data, 'YAML::PP::Preserve::Hash';
206 4         16 %$data = %$hash;
207 4         9 my $t = tied %$data;
208 4         6 $t->{style} = $args{style};
209 4         9 $t->{alias} = $args{alias};
210 4         12 return $data;
211             }
212              
213             sub preserved_sequence {
214 4     4 1 2983 my ($self, $array, %args) = @_;
215 4         7 my $data = [];
216 4         15 tie @$data, 'YAML::PP::Preserve::Array';
217 4         13 push @$data, @$array;
218 4         9 my $t = tied @$data;
219 4         9 $t->{style} = $args{style};
220 4         6 $t->{alias} = $args{alias};
221 4         14 return $data;
222             }
223              
224             package YAML::PP::Preserve::Hash;
225             # experimental
226 35     35   18427 use Tie::Hash;
  35         32455  
  35         1176  
227 35     35   251 use base qw/ Tie::StdHash /;
  35         74  
  35         11284  
228 35     35   291 use Scalar::Util qw/ reftype blessed /;
  35         76  
  35         22210  
229              
230             sub TIEHASH {
231 34     34   75 my ($class, %args) = @_;
232 34         180 my $self = bless {
233             keys => [keys %args],
234             data => { %args },
235             }, $class;
236             }
237              
238             sub STORE {
239 127     127   994 my ($self, $key, $val) = @_;
240 127         192 my $keys = $self->{keys};
241 127 100       219 unless (exists $self->{data}->{ $key }) {
242 120         222 push @$keys, $key;
243             }
244 127 100 100     396 if (ref $val and not blessed($val)) {
245 39 100 100     210 if (reftype($val) eq 'HASH' and not tied %$val) {
    100 100        
246 1         6 tie %$val, 'YAML::PP::Preserve::Hash', %$val;
247             }
248             elsif (reftype($val) eq 'ARRAY' and not tied @$val) {
249 2         6 tie @$val, 'YAML::PP::Preserve::Array', @$val;
250             }
251             }
252 127         386 $self->{data}->{ $key } = $val;
253             }
254              
255             sub FIRSTKEY {
256 91     91   3156 my ($self) = @_;
257 91         287 return $self->{keys}->[0];
258             }
259              
260             sub NEXTKEY {
261 320     320   1187 my ($self, $last) = @_;
262 320         436 my $keys = $self->{keys};
263 320         580 for my $i (0 .. $#$keys) {
264 1167 100       1854 if ("$keys->[ $i ]" eq "$last") {
265 320         1067 return $keys->[ $i + 1 ];
266             }
267             }
268 0         0 return;
269             }
270              
271             sub FETCH {
272 305     305   2939 my ($self, $key) = @_;
273 305         735 my $val = $self->{data}->{ $key };
274             }
275              
276             sub DELETE {
277 2     2   1593 my ($self, $key) = @_;
278 2         3 @{ $self->{keys} } = grep { "$_" ne "$key" } @{ $self->{keys} };
  2         14  
  12         23  
  2         5  
279 2         11 delete $self->{data}->{ $key };
280             }
281              
282             sub EXISTS {
283 34     34   725 my ($self, $key) = @_;
284 34         65 return exists $self->{data}->{ $key };
285             }
286              
287             sub CLEAR {
288 9     9   33 my ($self) = @_;
289 9         22 $self->{keys} = [];
290 9         35 $self->{data} = {};
291             }
292              
293             sub SCALAR {
294 3     3   1344 my ($self) = @_;
295 3         6 return scalar %{ $self->{data} };
  3         11  
296             }
297              
298             package YAML::PP::Preserve::Array;
299             # experimental
300 35     35   16291 use Tie::Array;
  35         43013  
  35         1140  
301 35     35   241 use base qw/ Tie::StdArray /;
  35         94  
  35         10420  
302 35     35   269 use Scalar::Util qw/ reftype blessed /;
  35         86  
  35         25498  
303              
304             sub TIEARRAY {
305 16     16   38 my ($class, @items) = @_;
306 16         42 my $self = bless {
307             data => [@items],
308             }, $class;
309 16         43 return $self;
310             }
311              
312             sub FETCH {
313 99     99   173 my ($self, $i) = @_;
314 99         610 return $self->{data}->[ $i ];
315             }
316             sub FETCHSIZE {
317 101     101   795 my ($self) = @_;
318 101         117 return $#{ $self->{data} } + 1;
  101         368  
319             }
320              
321             sub _preserve {
322 42     42   67 my ($val) = @_;
323 42 100 100     146 if (ref $val and not blessed($val)) {
324 13 100 100     77 if (reftype($val) eq 'HASH' and not tied %$val) {
    100 100        
325 5         16 tie %$val, 'YAML::PP::Preserve::Hash', %$val;
326             }
327             elsif (reftype($val) eq 'ARRAY' and not tied @$val) {
328 1         4 tie @$val, 'YAML::PP::Preserve::Array', @$val;
329             }
330             }
331 42         131 return $val;
332             }
333              
334             sub STORE {
335 6     6   667 my ($self, $i, $val) = @_;
336 6         15 _preserve($val);
337 6         21 $self->{data}->[ $i ] = $val;
338             }
339             sub PUSH {
340 14     14   34 my ($self, @args) = @_;
341 14         21 push @{ $self->{data} }, map { _preserve $_ } @args;
  14         33  
  31         80  
342             }
343             sub STORESIZE {
344 1     1   11 my ($self, $i) = @_;
345 1         3 $#{ $self->{data} } = $i - 1;
  1         5  
346             }
347             sub DELETE {
348 1     1   4 my ($self, $i) = @_;
349 1         6 delete $self->{data}->[ $i ];
350             }
351             sub EXISTS {
352 2     2   5 my ($self, $i) = @_;
353 2         10 return exists $self->{data}->[ $i ];
354             }
355             sub CLEAR {
356 1     1   7 my ($self) = @_;
357 1         6 $self->{data} = [];
358             }
359             sub SHIFT {
360 1     1   4 my ($self) = @_;
361 1         2 shift @{ $self->{data} };
  1         5  
362             }
363             sub UNSHIFT {
364 2     2   10 my ($self, @args) = @_;
365 2         5 unshift @{ $self->{data} }, map { _preserve $_ } @args;
  2         5  
  2         5  
366             }
367             sub SPLICE {
368 2     2   10 my ($self, $offset, $length, @args) = @_;
369 2         4 splice @{ $self->{data} }, $offset, $length, map { _preserve $_ } @args;
  2         7  
  3         7  
370             }
371       1     sub EXTEND {}
372              
373              
374             package YAML::PP::Preserve::Scalar;
375              
376             use overload
377 35         504 fallback => 1,
378             '+' => \&value,
379             '""' => \&value,
380             'bool' => \&value,
381 35     35   279 ;
  35         75  
382             sub new {
383 87     87   219 my ($class, %args) = @_;
384 87         260 my $self = {
385             %args,
386             };
387 87         321 bless $self, $class;
388             }
389 2218     2218   8269 sub value { $_[0]->{value} }
390 0     0   0 sub tag { $_[0]->{tag} }
391 21 100   21   65 sub style { $_[0]->{style} || 0 }
392 17     17   45 sub alias { $_[0]->{alias} }
393              
394             1;
395              
396             __END__