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   1829900 use strict;
  35         334  
  35         1436  
3 35     35   193 use warnings;
  35         75  
  35         1848  
4             package YAML::PP;
5              
6             our $VERSION = '0.036'; # VERSION
7              
8 35     35   15424 use YAML::PP::Schema;
  35         90  
  35         1112  
9 35     35   15085 use YAML::PP::Schema::JSON;
  35         89  
  35         1712  
10 35     35   13100 use YAML::PP::Loader;
  35         117  
  35         1182  
11 35     35   14669 use YAML::PP::Dumper;
  35         107  
  35         1284  
12 35     35   249 use Scalar::Util qw/ blessed /;
  35         91  
  35         1705  
13 35     35   228 use Carp qw/ croak /;
  35         76  
  35         1421  
14              
15 35     35   202 use base 'Exporter';
  35         95  
  35         51285  
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 185     185 1 242874 my ($class, %args) = @_;
23              
24 185         462 my $bool = delete $args{boolean};
25 185 100       593 $bool = 'perl' unless defined $bool;
26 185   100     864 my $schemas = delete $args{schema} || ['+'];
27 185   100     699 my $cyclic_refs = delete $args{cyclic_refs} || 'allow';
28 185         319 my $indent = delete $args{indent};
29 185         296 my $width = delete $args{width};
30 185         1824 my $writer = delete $args{writer};
31 185         365 my $header = delete $args{header};
32 185         303 my $footer = delete $args{footer};
33 185         300 my $duplicate_keys = delete $args{duplicate_keys};
34 185         663 my $yaml_version = $class->_arg_yaml_version(delete $args{yaml_version});
35 185         338 my $default_yaml_version = $yaml_version->[0];
36 185         296 my $version_directive = delete $args{version_directive};
37 185         284 my $preserve = delete $args{preserve};
38 185         287 my $parser = delete $args{parser};
39             my $emitter = delete $args{emitter} || {
40 185   50     942 indent => $indent,
41             width => $width,
42             writer => $writer,
43             };
44 185 50       528 if (keys %args) {
45 0         0 die "Unexpected arguments: " . join ', ', sort keys %args;
46             }
47              
48 185         285 my %schemas;
49 185         392 for my $v (@$yaml_version) {
50 187         250 my $schema;
51 187 50 33     933 if (blessed($schemas) and $schemas->isa('YAML::PP::Schema')) {
52 0         0 $schema = $schemas;
53             }
54             else {
55 187         887 $schema = YAML::PP::Schema->new(
56             boolean => $bool,
57             yaml_version => $v,
58             );
59 187         658 $schema->load_subschemas(@$schemas);
60             }
61 186         646 $schemas{ $v } = $schema;
62             }
63 184         368 my $default_schema = $schemas{ $default_yaml_version };
64              
65 184         939 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 183         878 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 183         697 my $self = bless {
83             schema => \%schemas,
84             loader => $loader,
85             dumper => $dumper,
86             }, $class;
87 183         1568 return $self;
88             }
89              
90             sub clone {
91 9     9 0 341 my ($self) = @_;
92 9         20 my $clone = {
93             schema => $self->schema,
94             loader => $self->loader->clone,
95             dumper => $self->dumper->clone,
96             };
97 9         28 return bless $clone, ref $self;
98             }
99              
100             sub _arg_yaml_version {
101 185     185   403 my ($class, $version) = @_;
102 185         451 my @versions = ('1.2');
103 185 100       481 if (defined $version) {
104 5         9 @versions = ();
105 5 100       15 if (not ref $version) {
106 1         2 $version = [$version];
107             }
108 5         11 for my $v (@$version) {
109 7 50       19 unless ($YAML_VERSIONS{ $v }) {
110 0         0 croak "YAML Version '$v' not supported";
111             }
112 7         13 push @versions, $v;
113             }
114             }
115 185         427 return \@versions;
116             }
117              
118              
119             sub loader {
120 1344 50   1344 1 3558 if (@_ > 1) {
121 0         0 $_[0]->{loader} = $_[1]
122             }
123 1344         4831 return $_[0]->{loader};
124             }
125              
126             sub dumper {
127 1199 50   1199 1 3341 if (@_ > 1) {
128 0         0 $_[0]->{dumper} = $_[1]
129             }
130 1199         4371 return $_[0]->{dumper};
131             }
132              
133             sub schema {
134 16 50   16 1 68 if (@_ > 1) { $_[0]->{schema}->{'1.2'} = $_[1] }
  0         0  
135 16         96 return $_[0]->{schema}->{'1.2'};
136             }
137              
138             sub default_schema {
139 3     3 1 189 my ($self, %args) = @_;
140             my $schema = YAML::PP::Schema->new(
141             boolean => $args{boolean},
142 3         67 );
143 3         15 $schema->load_subschemas(qw/ Core /);
144 3         17 return $schema;
145             }
146              
147             sub load_string {
148 1313     1313 1 898423 my ($self, $yaml) = @_;
149 1313         3104 return $self->loader->load_string($yaml);
150             }
151              
152             sub load_file {
153 19     19 1 66 my ($self, $file) = @_;
154 19         42 return $self->loader->load_file($file);
155             }
156              
157             sub dump {
158 1     1 1 8 my ($self, @data) = @_;
159 1         6 return $self->dumper->dump(@data);
160             }
161              
162             sub dump_string {
163 1183     1183 1 3580845 my ($self, @data) = @_;
164 1183         3122 return $self->dumper->dump_string(@data);
165             }
166              
167             sub dump_file {
168 6     6 1 38 my ($self, $file, @data) = @_;
169 6         21 return $self->dumper->dump_file($file, @data);
170             }
171              
172             # legagy interface
173             sub Load {
174 2     2 1 2996 my ($yaml) = @_;
175 2         12 YAML::PP->new->load_string($yaml);
176             }
177              
178             sub LoadFile {
179 3     3 1 1870 my ($file) = @_;
180 3         11 YAML::PP->new->load_file($file);
181             }
182              
183             sub Dump {
184 1     1 1 1940 my (@data) = @_;
185 1         6 YAML::PP->new->dump_string(@data);
186             }
187              
188             sub DumpFile {
189 4     4 1 716 my ($file, @data) = @_;
190 4         21 YAML::PP->new->dump_file($file, @data);
191             }
192              
193             sub preserved_scalar {
194 4     4 1 2864 my ($self, $value, %args) = @_;
195 4         22 my $scalar = YAML::PP::Preserve::Scalar->new(
196             value => $value,
197             %args,
198             );
199 4         15 return $scalar;
200             }
201              
202             sub preserved_mapping {
203 4     4 1 1458 my ($self, $hash, %args) = @_;
204 4         11 my $data = {};
205 4         16 tie %$data, 'YAML::PP::Preserve::Hash';
206 4         35 %$data = %$hash;
207 4         10 my $t = tied %$data;
208 4         8 $t->{style} = $args{style};
209 4         8 $t->{alias} = $args{alias};
210 4         11 return $data;
211             }
212              
213             sub preserved_sequence {
214 4     4 1 3018 my ($self, $array, %args) = @_;
215 4         8 my $data = [];
216 4         17 tie @$data, 'YAML::PP::Preserve::Array';
217 4         12 push @$data, @$array;
218 4         6 my $t = tied @$data;
219 4         9 $t->{style} = $args{style};
220 4         7 $t->{alias} = $args{alias};
221 4         15 return $data;
222             }
223              
224             package YAML::PP::Preserve::Hash;
225             # experimental
226 35     35   19402 use Tie::Hash;
  35         34502  
  35         1151  
227 35     35   260 use base qw/ Tie::StdHash /;
  35         91  
  35         11587  
228 35     35   295 use Scalar::Util qw/ reftype blessed /;
  35         86  
  35         22814  
229              
230             sub TIEHASH {
231 34     34   86 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   1039 my ($self, $key, $val) = @_;
240 127         173 my $keys = $self->{keys};
241 127 100       231 unless (exists $self->{data}->{ $key }) {
242 120         224 push @$keys, $key;
243             }
244 127 100 100     402 if (ref $val and not blessed($val)) {
245 39 100 100     214 if (reftype($val) eq 'HASH' and not tied %$val) {
    100 100        
246 1         4 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         384 $self->{data}->{ $key } = $val;
253             }
254              
255             sub FIRSTKEY {
256 91     91   3326 my ($self) = @_;
257 91         289 return $self->{keys}->[0];
258             }
259              
260             sub NEXTKEY {
261 320     320   1205 my ($self, $last) = @_;
262 320         424 my $keys = $self->{keys};
263 320         556 for my $i (0 .. $#$keys) {
264 1167 100       1827 if ("$keys->[ $i ]" eq "$last") {
265 320         1082 return $keys->[ $i + 1 ];
266             }
267             }
268 0         0 return;
269             }
270              
271             sub FETCH {
272 305     305   2800 my ($self, $key) = @_;
273 305         777 my $val = $self->{data}->{ $key };
274             }
275              
276             sub DELETE {
277 2     2   1807 my ($self, $key) = @_;
278 2         4 @{ $self->{keys} } = grep { "$_" ne "$key" } @{ $self->{keys} };
  2         24  
  12         22  
  2         6  
279 2         16 delete $self->{data}->{ $key };
280             }
281              
282             sub EXISTS {
283 34     34   732 my ($self, $key) = @_;
284 34         63 return exists $self->{data}->{ $key };
285             }
286              
287             sub CLEAR {
288 9     9   42 my ($self) = @_;
289 9         24 $self->{keys} = [];
290 9         36 $self->{data} = {};
291             }
292              
293             sub SCALAR {
294 3     3   1364 my ($self) = @_;
295 3         5 return scalar %{ $self->{data} };
  3         13  
296             }
297              
298             package YAML::PP::Preserve::Array;
299             # experimental
300 35     35   16826 use Tie::Array;
  35         44276  
  35         1185  
301 35     35   265 use base qw/ Tie::StdArray /;
  35         93  
  35         10630  
302 35     35   285 use Scalar::Util qw/ reftype blessed /;
  35         84  
  35         26754  
303              
304             sub TIEARRAY {
305 16     16   33 my ($class, @items) = @_;
306 16         74 my $self = bless {
307             data => [@items],
308             }, $class;
309 16         50 return $self;
310             }
311              
312             sub FETCH {
313 99     99   174 my ($self, $i) = @_;
314 99         317 return $self->{data}->[ $i ];
315             }
316             sub FETCHSIZE {
317 101     101   828 my ($self) = @_;
318 101         111 return $#{ $self->{data} } + 1;
  101         339  
319             }
320              
321             sub _preserve {
322 42     42   65 my ($val) = @_;
323 42 100 100     150 if (ref $val and not blessed($val)) {
324 13 100 100     79 if (reftype($val) eq 'HASH' and not tied %$val) {
    100 100        
325 5         15 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         147 return $val;
332             }
333              
334             sub STORE {
335 6     6   722 my ($self, $i, $val) = @_;
336 6         17 _preserve($val);
337 6         35 $self->{data}->[ $i ] = $val;
338             }
339             sub PUSH {
340 14     14   39 my ($self, @args) = @_;
341 14         21 push @{ $self->{data} }, map { _preserve $_ } @args;
  14         48  
  31         48  
342             }
343             sub STORESIZE {
344 1     1   10 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         4 delete $self->{data}->[ $i ];
350             }
351             sub EXISTS {
352 2     2   5 my ($self, $i) = @_;
353 2         12 return exists $self->{data}->[ $i ];
354             }
355             sub CLEAR {
356 1     1   11 my ($self) = @_;
357 1         8 $self->{data} = [];
358             }
359             sub SHIFT {
360 1     1   6 my ($self) = @_;
361 1         2 shift @{ $self->{data} };
  1         4  
362             }
363             sub UNSHIFT {
364 2     2   30 my ($self, @args) = @_;
365 2         3 unshift @{ $self->{data} }, map { _preserve $_ } @args;
  2         8  
  2         5  
366             }
367             sub SPLICE {
368 2     2   34 my ($self, $offset, $length, @args) = @_;
369 2         6 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         492 fallback => 1,
378             '+' => \&value,
379             '""' => \&value,
380             'bool' => \&value,
381 35     35   306 ;
  35         78  
382             sub new {
383 87     87   241 my ($class, %args) = @_;
384 87         246 my $self = {
385             %args,
386             };
387 87         318 bless $self, $class;
388             }
389 2218     2218   8296 sub value { $_[0]->{value} }
390 0     0   0 sub tag { $_[0]->{tag} }
391 21 100   21   61 sub style { $_[0]->{style} || 0 }
392 17     17   49 sub alias { $_[0]->{alias} }
393              
394             1;
395              
396             __END__