File Coverage

blib/lib/YAML/Old/Types.pm
Criterion Covered Total %
statement 121 154 78.5
branch 41 56 73.2
condition 3 5 60.0
subroutine 13 21 61.9
pod n/a
total 178 236 75.4


line stmt bran cond sub pod time code
1             package YAML::Old::Types;
2              
3 44     44   409 use YAML::Old::Mo;
  44         92  
  44         241  
4 44     44   237 use YAML::Old::Node;
  44         87  
  44         2184  
5              
6             # XXX These classes and their APIs could still use some refactoring,
7             # but at least they work for now.
8             #-------------------------------------------------------------------------------
9             package YAML::Old::Type::blessed;
10              
11 44     44   223 use YAML::Old::Mo; # XXX
  44         85  
  44         158  
12              
13             sub yaml_dump {
14 29     29   57 my $self = shift;
15 29         65 my ($value) = @_;
16 29         91 my ($class, $type) = YAML::Old::Mo::Object->node_info($value);
17 44     44   250 no strict 'refs';
  44         111  
  44         17820  
18 29         86 my $kind = lc($type) . ':';
19 29   66     50 my $tag = ${$class . '::ClassTag'} ||
20             "!perl/$kind$class";
21 29 100       154 if ($type eq 'REF') {
    100          
    100          
22             YAML::Old::Node->new(
23 1         5 {(&YAML::Old::VALUE, ${$_[0]})}, $tag
  1         7  
24             );
25             }
26             elsif ($type eq 'SCALAR') {
27 7         71 $_[1] = $$value;
28 7         35 YAML::Old::Node->new($_[1], $tag);
29             }
30             elsif ($type eq 'GLOB') {
31             # blessed glob support is minimal, and will not round-trip
32             # initial aim: to not cause an error
33 2         7 return YAML::Old::Type::glob->yaml_dump($value, $tag);
34             } else {
35 19         84 YAML::Old::Node->new($value, $tag);
36             }
37             }
38              
39             #-------------------------------------------------------------------------------
40             package YAML::Old::Type::undef;
41              
42             sub yaml_dump {
43 0     0   0 my $self = shift;
44             }
45              
46             sub yaml_load {
47 0     0   0 my $self = shift;
48             }
49              
50             #-------------------------------------------------------------------------------
51             package YAML::Old::Type::glob;
52              
53             sub yaml_dump {
54 8     8   15 my $self = shift;
55             # $_[0] remains as the glob
56 8 100       24 my $tag = pop @_ if 2==@_;
57              
58 8 100       23 $tag = '!perl/glob:' unless defined $tag;
59 8         32 my $ynode = YAML::Old::Node->new({}, $tag);
60 8         24 for my $type (qw(PACKAGE NAME SCALAR ARRAY HASH CODE IO)) {
61 56         78 my $value = *{$_[0]}{$type};
  56         116  
62 56 100       128 $value = $$value if $type eq 'SCALAR';
63 56 100       123 if (defined $value) {
64 28 100       54 if ($type eq 'IO') {
65 1         3 my @stats = qw(device inode mode links uid gid rdev size
66             atime mtime ctime blksize blocks);
67 1         2 undef $value;
68 1         2 $value->{stat} = YAML::Old::Node->new({});
69 1 50       2 if ($value->{fileno} = fileno(*{$_[0]})) {
  1         4  
70 1         3 local $^W;
71 1         2 map {$value->{stat}{shift @stats} = $_} stat(*{$_[0]});
  13         38  
  1         9  
72 1         3 $value->{tell} = tell(*{$_[0]});
  1         5  
73             }
74             }
75 28         94 $ynode->{$type} = $value;
76             }
77             }
78 8         27 return $ynode;
79             }
80              
81             sub yaml_load {
82 4     4   9 my $self = shift;
83 4         9 my ($node, $class, $loader) = @_;
84 4         6 my ($name, $package);
85 4 100       14 if (defined $node->{NAME}) {
86 3         6 $name = $node->{NAME};
87 3         8 delete $node->{NAME};
88             }
89             else {
90 1         4 $loader->warn('YAML_LOAD_WARN_GLOB_NAME');
91 1         610 return undef;
92             }
93 3 100       8 if (defined $node->{PACKAGE}) {
94 2         5 $package = $node->{PACKAGE};
95 2         5 delete $node->{PACKAGE};
96             }
97             else {
98 1         2 $package = 'main';
99             }
100 44     44   278 no strict 'refs';
  44         87  
  44         33344  
101 3 100       10 if (exists $node->{SCALAR}) {
102 2         5 *{"${package}::$name"} = \$node->{SCALAR};
  2         7  
103 2         4 delete $node->{SCALAR};
104             }
105 3         9 for my $elem (qw(ARRAY HASH CODE IO)) {
106 12 100       30 if (exists $node->{$elem}) {
107 2 50       6 if ($elem eq 'IO') {
108 0         0 $loader->warn('YAML_LOAD_WARN_GLOB_IO');
109 0         0 delete $node->{IO};
110 0         0 next;
111             }
112 2         4 *{"${package}::$name"} = $node->{$elem};
  2         6  
113 2         5 delete $node->{$elem};
114             }
115             }
116 3         10 for my $elem (sort keys %$node) {
117 1         4 $loader->warn('YAML_LOAD_WARN_BAD_GLOB_ELEM', $elem);
118             }
119 3         560 return *{"${package}::$name"};
  3         17  
120             }
121              
122             #-------------------------------------------------------------------------------
123             package YAML::Old::Type::code;
124              
125             my $dummy_warned = 0;
126             my $default = '{ "DUMMY" }';
127              
128             sub yaml_dump {
129 7     7   11 my $self = shift;
130 7         12 my $code;
131 7         11 my ($dumpflag, $value) = @_;
132 7         19 my ($class, $type) = YAML::Old::Mo::Object->node_info($value);
133 7         13 my $tag = "!perl/code";
134 7 100       23 $tag .= ":$class" if defined $class;
135 7 100       16 if (not $dumpflag) {
136 2         4 $code = $default;
137             }
138             else {
139 5 100       14 bless $value, "CODE" if $class;
140 5         10 eval { require B::Deparse };
  5         17  
141 5 50       10 return if $@;
142 5         80 my $deparse = B::Deparse->new();
143 5         9 eval {
144 5         18 local $^W = 0;
145 5         2426 $code = $deparse->coderef2text($value);
146             };
147 5 50       22 if ($@) {
148 0 0       0 warn YAML::Old::YAML_DUMP_WARN_DEPARSE_FAILED() if $^W;
149 0         0 $code = $default;
150             }
151 5 100       13 bless $value, $class if $class;
152 5         12 chomp $code;
153 5         16 $code .= "\n";
154             }
155 7         15 $_[2] = $code;
156 7         29 YAML::Old::Node->new($_[2], $tag);
157             }
158              
159             sub yaml_load {
160 4     4   8 my $self = shift;
161 4         10 my ($node, $class, $loader) = @_;
162 4 50       12 if ($loader->load_code) {
163 0         0 my $code = eval "package main; sub $node";
164 0 0       0 if ($@) {
165 0         0 $loader->warn('YAML_LOAD_WARN_PARSE_CODE', $@);
166 0     0   0 return sub {};
167             }
168             else {
169 0 0       0 CORE::bless $code, $class if $class;
170 0         0 return $code;
171             }
172             }
173             else {
174 4 50   0   9 return CORE::bless sub {}, $class if $class;
175 4     0   22 return sub {};
176             }
177             }
178              
179             #-------------------------------------------------------------------------------
180             package YAML::Old::Type::ref;
181              
182             sub yaml_dump {
183 33     33   62 my $self = shift;
184 33         82 YAML::Old::Node->new({(&YAML::Old::VALUE, ${$_[0]})}, '!perl/ref')
  33         157  
185             }
186              
187             sub yaml_load {
188 0     0   0 my $self = shift;
189 0         0 my ($node, $class, $loader) = @_;
190             $loader->die('YAML_LOAD_ERR_NO_DEFAULT_VALUE', 'ptr')
191 0 0       0 unless exists $node->{&YAML::Old::VALUE};
192 0         0 return \$node->{&YAML::Old::VALUE};
193             }
194              
195             #-------------------------------------------------------------------------------
196             package YAML::Old::Type::regexp;
197              
198             # XXX Be sure to handle blessed regexps (if possible)
199             sub yaml_dump {
200 0     0   0 die "YAML::Old::Type::regexp::yaml_dump not currently implemented";
201             }
202              
203             use constant _QR_TYPES => {
204 2         15 '' => sub { qr{$_[0]} },
205 0         0 x => sub { qr{$_[0]}x },
206 0         0 i => sub { qr{$_[0]}i },
207 0         0 s => sub { qr{$_[0]}s },
208 4         21 m => sub { qr{$_[0]}m },
209 0         0 ix => sub { qr{$_[0]}ix },
210 0         0 sx => sub { qr{$_[0]}sx },
211 0         0 mx => sub { qr{$_[0]}mx },
212 0         0 si => sub { qr{$_[0]}si },
213 0         0 mi => sub { qr{$_[0]}mi },
214 0         0 ms => sub { qr{$_[0]}sm },
215 0         0 six => sub { qr{$_[0]}six },
216 0         0 mix => sub { qr{$_[0]}mix },
217 0         0 msx => sub { qr{$_[0]}msx },
218 0         0 msi => sub { qr{$_[0]}msi },
219 0         0 msix => sub { qr{$_[0]}msix },
220 44     44   337 };
  44         92  
  44         10051  
221              
222             sub yaml_load {
223 6     6   10 my $self = shift;
224 6         11 my ($node, $class) = @_;
225 6 50       22 return qr{$node} unless $node =~ /^\(\?([\^\-xism]*):(.*)\)\z/s;
226 6         15 my ($flags, $re) = ($1, $2);
227 6         15 $flags =~ s/-.*//;
228 6         12 $flags =~ s/^\^//;
229 6   50 0   17 my $sub = _QR_TYPES->{$flags} || sub { qr{$_[0]} };
  0            
230 6         13 my $qr = &$sub($re);
231 6 100       19 bless $qr, $class if length $class;
232 6         18 return $qr;
233             }
234              
235             1;