File Coverage

inc/YAML/Base.pm
Criterion Covered Total %
statement 163 247 65.9
branch 124 208 59.6
condition 8 17 47.0
subroutine 9 12 75.0
pod 0 6 0.0
total 304 490 62.0


line stmt bran cond sub pod time code
1             #line 1
2 1     1   6 package YAML::Base;
  1     1   3  
  1         37  
  1         5  
  1         2  
  1         30  
3 1     1   6 use strict; use warnings;
  1         2  
  1         8  
4             use base 'Exporter';
5              
6             our @EXPORT = qw(field XXX);
7              
8 4     4 0 13 sub new {
9 4   33     31 my $class = shift;
10 4         13 $class = ref($class) || $class;
11 4         14 my $self = bless {}, $class;
12 0         0 while (@_) {
13 0         0 my $method = shift;
14             $self->$method(shift);
15 4         17 }
16             return $self;
17             }
18              
19             # Use lexical subs to reduce pollution of private methods by base class.
20             my ($_new_error, $_info, $_scalar_info, $parse_arguments, $default_as_code);
21              
22 0     0 0 0 sub XXX {
23 0         0 require Data::Dumper;
24             CORE::die(Data::Dumper::Dumper(@_));
25             }
26              
27             my %code = (
28             sub_start =>
29             "sub {\n",
30             set_default =>
31             " \$_[0]->{%s} = %s\n unless exists \$_[0]->{%s};\n",
32             init =>
33             " return \$_[0]->{%s} = do { my \$self = \$_[0]; %s }\n" .
34             " unless \$#_ > 0 or defined \$_[0]->{%s};\n",
35             return_if_get =>
36             " return \$_[0]->{%s} unless \$#_ > 0;\n",
37             set =>
38             " \$_[0]->{%s} = \$_[1];\n",
39             sub_end =>
40             " return \$_[0]->{%s};\n}\n",
41             );
42              
43 45     45 0 96 sub field {
44 45         132 my $package = caller;
45             my ($args, @values) = &$parse_arguments(
46             [ qw(-package -init) ],
47             @_,
48 45         97 );
49 45 50       120 my ($field, $default) = @values;
50 45 50       42 $package = $args->{-package} if defined $args->{-package};
  45         305  
51 45 100 66     213 return if defined &{"${package}::$field"};
    100 66        
52             my $default_string =
53             ( ref($default) eq 'ARRAY' and not @$default )
54             ? '[]'
55             : (ref($default) eq 'HASH' and not keys %$default )
56             ? '{}'
57             : &$default_as_code($default);
58 45         78  
59 45 100       112 my $code = $code{sub_start};
60 2         3 if ($args->{-init}) {
61 2         11 my $fragment = $code{init};
62             $code .= sprintf $fragment, $field, $args->{-init}, ($field) x 4;
63 45 100       200 }
64             $code .= sprintf $code{set_default}, $field, $default_string, $field
65 45         94 if defined $default;
66 45         76 $code .= sprintf $code{return_if_get}, $field;
67 45         76 $code .= sprintf $code{set}, $field;
68             $code .= sprintf $code{sub_end}, $field;
69 45 50 33 1   5551  
  1 50 33     7  
  1 50       8  
  0 0       0  
  0 100       0  
  1 50       17  
  1 50       2  
  1 100       4  
  0 50       0  
  0 50       0  
  0 50       0  
  8 50       30  
  8 100       38  
  0 100       0  
  0 100       0  
  19 50       51  
  19 0       429  
  1 0       2  
  1 50       3  
  1 50       10  
  1 50       11  
  0 50       0  
  0 100       0  
  1 100       6  
  1 100       4  
  1 100       3  
  1 0       4  
  2 0       9  
  2 100       9  
  1 50       3  
  1 100       3  
  5 100       20  
  5 100       149  
  0 100       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 50       0  
  1 50       5  
  1 100       9  
  0 100       0  
  0 0       0  
  1 0       7  
  1 0       4  
  1 0       3  
  1 100       3  
  4 50       19  
  4 100       71  
  1 100       3  
  1 50       2  
  66 50       161  
  66 100       216  
  32 50       49  
  32 0       64  
  0 0       0  
  0 100       0  
  0 100       0  
  0 50       0  
  2 50       16  
  2 100       29  
  0 100       0  
  0 100       0  
  2 100       20  
  2 50       118  
  1 50       3  
  1 100       6  
  5 100       32  
  5 0       20  
  2 0       5  
  2 50       6  
  0 50       0  
  0 100       0  
  0 50       0  
  0 50       0  
  0 0       0  
  0 100       0  
  0 50       0  
  0 100       0  
  1 100       9  
  1 100       9  
  0 50       0  
  0 100       0  
  37 100       103  
  37 100       160  
  1 100       3  
  1 0       4  
  0 0       0  
  0 50       0  
  0 50       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  48         134  
  48         501  
  0         0  
  0         0  
  31         85  
  31         308  
  8         16  
  8         21  
  1         8  
  1         6  
  1         4  
  1         7  
  3         14  
  3         423  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  44         114  
  44         693  
  14         21  
  14         30  
  1         7  
  1         9  
  0         0  
  0         0  
  32         109  
  32         247  
  14         21  
  14         31  
  29         76  
  29         137  
  14         28  
  14         28  
  1         6  
  1         4  
  1         2  
  1         3  
  3         12  
  3         45  
  1         3  
  1         2  
  0         0  
  0         0  
  0         0  
  0         0  
  1         6  
  1         10  
  0         0  
  0         0  
  12         127  
  12         315  
  0         0  
  0         0  
  1         13  
  1         2  
  1         7  
  0         0  
  0         0  
  0         0  
  4         16  
  4         21  
  0         0  
  0         0  
  118         364  
  118         1604  
  1         4  
  1         4  
  2         22  
  2         22  
  0         0  
  0         0  
  12         39  
  12         174  
  1         4  
  1         3  
  6         23  
  6         43  
  1         3  
  1         5  
  0         0  
  0         0  
  0         0  
  0         0  
  1         7  
  1         4  
  1         4  
  1         3  
70 45 50       116 my $sub = eval $code;
71 1     1   7 die $@ if $@;
  1         2  
  1         925  
72 45         47 no strict 'refs';
  45         227  
73 45 50       202 *{"${package}::$field"} = $sub;
74             return $code if defined wantarray;
75             }
76              
77 0     0 0 0 sub die {
78 0         0 my $self = shift;
79 0         0 my $error = $self->$_new_error(@_);
80 0         0 $error->type('Error');
81             Carp::croak($error->format_message);
82             }
83              
84 0     0 0 0 sub warn {
85 0 0       0 my $self = shift;
86 0         0 return unless $^W;
87 0         0 my $error = $self->$_new_error(@_);
88 0         0 $error->type('Warning');
89             Carp::cluck($error->format_message);
90             }
91              
92             # This code needs to be refactored to be simpler and more precise, and no,
93             # Scalar::Util doesn't DWIM.
94             #
95             # Can't handle:
96             # * blessed regexp
97 9     9 0 13 sub node_info {
98 9   50     40 my $self = shift;
99             my $stringify = $_[1] || 0;
100             my ($class, $type, $id) =
101             ref($_[0])
102             ? $stringify
103 9 50       28 ? &$_info("$_[0]")
    50          
104 9         44 : do {
105 9         36 require overload;
106 9 50       37 my @info = &$_info(overload::StrVal($_[0]));
107 0         0 if (ref($_[0]) eq 'Regexp') {
108             @info[0, 1] = (undef, 'REGEXP');
109 9         25 }
110             @info;
111             }
112 9 50       23 : &$_scalar_info($_[0]);
113             ($class, $type, $id) = &$_scalar_info("$_[0]")
114 9 50       50 unless $id;
115             return wantarray ? ($class, $type, $id) : $id;
116             }
117              
118             #-------------------------------------------------------------------------------
119             $_info = sub {
120             return (($_[0]) =~ qr{^(?:(.*)\=)?([^=]*)\(([^\(]*)\)$}o);
121             };
122              
123             $_scalar_info = sub {
124             my $id = 'undef';
125             if (defined $_[0]) {
126             \$_[0] =~ /\((\w+)\)$/o or CORE::die();
127             $id = "$1-S";
128             }
129             return (undef, undef, $id);
130             };
131              
132             $_new_error = sub {
133             require Carp;
134             my $self = shift;
135             require YAML::Error;
136              
137             my $code = shift || 'unknown error';
138             my $error = YAML::Error->new(code => $code);
139             $error->line($self->line) if $self->can('line');
140             $error->document($self->document) if $self->can('document');
141             $error->arguments([@_]);
142             return $error;
143             };
144            
145             $parse_arguments = sub {
146             my $paired_arguments = shift || [];
147             my ($args, @values) = ({}, ());
148             my %pairs = map { ($_, 1) } @$paired_arguments;
149             while (@_) {
150             my $elem = shift;
151             if (defined $elem and defined $pairs{$elem} and @_) {
152             $args->{$elem} = shift;
153             }
154             else {
155             push @values, $elem;
156             }
157             }
158             return wantarray ? ($args, @values) : $args;
159             };
160              
161 1     1   7 $default_as_code = sub {
  1         12  
  1         155  
162             no warnings 'once';
163             require Data::Dumper;
164             local $Data::Dumper::Sortkeys = 1;
165             my $code = Data::Dumper::Dumper(shift);
166             $code =~ s/^\$VAR1 = //;
167             $code =~ s/;$//;
168             return $code;
169             };
170              
171             1;
172              
173             __END__