File Coverage

blib/lib/YAML/PP/Schema/YAML1_1.pm
Criterion Covered Total %
statement 72 72 100.0
branch 8 8 100.0
condition n/a
subroutine 11 11 100.0
pod 1 1 100.0
total 92 92 100.0


line stmt bran cond sub pod time code
1 2     2   1069 use strict;
  2         5  
  2         62  
2 2     2   11 use warnings;
  2         4  
  2         116  
3             package YAML::PP::Schema::YAML1_1;
4              
5             our $VERSION = '0.036'; # VERSION
6              
7 2         161 use YAML::PP::Schema::JSON qw/
8             represent_int represent_float represent_literal represent_bool
9             represent_undef
10 2     2   11 /;
  2         4  
11              
12 2     2   15 use YAML::PP::Common qw/ YAML_PLAIN_SCALAR_STYLE /;
  2         4  
  2         2397  
13              
14             #https://yaml.org/type/bool.html
15             # y|Y|yes|Yes|YES|n|N|no|No|NO
16             # |true|True|TRUE|false|False|FALSE
17             # |on|On|ON|off|Off|OFF
18              
19             # https://yaml.org/type/float.html
20             # [-+]?([0-9][0-9_]*)?\.[0-9.]*([eE][-+][0-9]+)? (base 10)
21             # |[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\.[0-9_]* (base 60)
22             # |[-+]?\.(inf|Inf|INF) # (infinity)
23             # |\.(nan|NaN|NAN) # (not a number)
24              
25             # https://yaml.org/type/int.html
26             # [-+]?0b[0-1_]+ # (base 2)
27             # |[-+]?0[0-7_]+ # (base 8)
28             # |[-+]?(0|[1-9][0-9_]*) # (base 10)
29             # |[-+]?0x[0-9a-fA-F_]+ # (base 16)
30             # |[-+]?[1-9][0-9_]*(:[0-5]?[0-9])+ # (base 60)
31              
32             # https://yaml.org/type/null.html
33             # ~ # (canonical)
34             # |null|Null|NULL # (English)
35             # | # (Empty)
36              
37             my $RE_INT_1_1 = qr{^([+-]?(?:0|[1-9][0-9_]*))$};
38             #my $RE_FLOAT_1_1 = qr{^([+-]?([0-9][0-9_]*)?\.[0-9.]*([eE][+-][0-9]+)?)$};
39             # https://yaml.org/type/float.html has a bug. The regex says \.[0-9.], but
40             # probably means \.[0-9_]
41             my $RE_FLOAT_1_1 = qr{^([+-]?(?:[0-9][0-9_]*)?\.[0-9_]*(?:[eE][+-][0-9]+)?)$};
42             my $RE_SEXAGESIMAL = qr{^([+-]?[0-9][0-9_]*(:[0-5]?[0-9])+\.[0-9_]*)$};
43             my $RE_SEXAGESIMAL_INT = qr{^([-+]?[1-9][0-9_]*(:[0-5]?[0-9])+)$};
44             my $RE_INT_OCTAL_1_1 = qr{^([+-]?)0([0-7_]+)$};
45             my $RE_INT_HEX_1_1 = qr{^([+-]?)(0x[0-9a-fA-F_]+)$};
46             my $RE_INT_BIN_1_1 = qr{^([-+]?)(0b[0-1_]+)$};
47              
48             sub _from_oct {
49 22     22   51 my ($constructor, $event, $matches) = @_;
50 22         49 my ($sign, $oct) = @$matches;
51 22         54 $oct =~ tr/_//d;
52 22         82 my $result = oct $oct;
53 22 100       71 $result = -$result if $sign eq '-';
54 22         98 return $result;
55             }
56             sub _from_hex {
57 12     12   39 my ($constructor, $event, $matches) = @_;
58 12         28 my ($sign, $hex) = @$matches;
59 12         34 my $result = hex $hex;
60 12 100       40 $result = -$result if $sign eq '-';
61 12         52 return $result;
62             }
63             sub _sexa_to_float {
64 8     8   35 my ($constructor, $event, $matches) = @_;
65 8         20 my ($float) = @$matches;
66 8         19 my $result = 0;
67 8         13 my $i = 0;
68 8         18 my $sign = 1;
69 8 100       37 $float =~ s/^-// and $sign = -1;
70 8         43 for my $part (reverse split m/:/, $float) {
71 24         67 $result += $part * ( 60 ** $i );
72 24         45 $i++;
73             }
74 8         94 $result = unpack F => pack F => $result;
75 8         55 return $result * $sign;
76             }
77             sub _to_float {
78 24     24   57 my ($constructor, $event, $matches) = @_;
79 24         61 my ($float) = @$matches;
80 24         73 $float =~ tr/_//d;
81 24         140 $float = unpack F => pack F => $float;
82 24         115 return $float;
83             }
84             sub _to_int {
85 14     14   43 my ($constructor, $event, $matches) = @_;
86 14         39 my ($int) = @$matches;
87 14         42 $int =~ tr/_//d;
88 14         78 0 + $int;
89             }
90              
91             sub register {
92 5     5 1 23 my ($self, %args) = @_;
93 5         12 my $schema = $args{schema};
94              
95             $schema->add_resolver(
96             tag => 'tag:yaml.org,2002:null',
97             match => [ equals => $_ => undef ],
98 5         27 ) for (qw/ null NULL Null ~ /, '');
99             $schema->add_resolver(
100             tag => 'tag:yaml.org,2002:bool',
101             match => [ equals => $_ => $schema->true ],
102 5         22 ) for (qw/ true TRUE True y Y yes Yes YES on On ON /);
103             $schema->add_resolver(
104             tag => 'tag:yaml.org,2002:bool',
105             match => [ equals => $_ => $schema->false ],
106 5         20 ) for (qw/ false FALSE False n N no No NO off Off OFF /);
107 5         22 $schema->add_resolver(
108             tag => 'tag:yaml.org,2002:int',
109             match => [ regex => $RE_INT_OCTAL_1_1 => \&_from_oct ],
110             );
111 5         22 $schema->add_resolver(
112             tag => 'tag:yaml.org,2002:int',
113             match => [ regex => $RE_INT_1_1 => \&_to_int ],
114             );
115 5         24 $schema->add_resolver(
116             tag => 'tag:yaml.org,2002:int',
117             match => [ regex => $RE_INT_HEX_1_1 => \&_from_hex ],
118             );
119 5         21 $schema->add_resolver(
120             tag => 'tag:yaml.org,2002:float',
121             match => [ regex => $RE_FLOAT_1_1 => \&_to_float ],
122             );
123 5         22 $schema->add_resolver(
124             tag => 'tag:yaml.org,2002:int',
125             match => [ regex => $RE_INT_BIN_1_1 => \&_from_oct ],
126             );
127 5         27 $schema->add_resolver(
128             tag => 'tag:yaml.org,2002:int',
129             match => [ regex => $RE_SEXAGESIMAL_INT => \&_sexa_to_float ],
130             );
131 5         21 $schema->add_resolver(
132             tag => 'tag:yaml.org,2002:float',
133             match => [ regex => $RE_SEXAGESIMAL => \&_sexa_to_float ],
134             );
135             $schema->add_resolver(
136             tag => 'tag:yaml.org,2002:float',
137             match => [ equals => $_ => 0 + "inf" ],
138 5         34 ) for (qw/ .inf .Inf .INF +.inf +.Inf +.INF /);
139             $schema->add_resolver(
140             tag => 'tag:yaml.org,2002:float',
141             match => [ equals => $_ => 0 - "inf" ],
142 5         18 ) for (qw/ -.inf -.Inf -.INF /);
143             $schema->add_resolver(
144             tag => 'tag:yaml.org,2002:float',
145             match => [ equals => $_ => 0 + "nan" ],
146 5         25 ) for (qw/ .nan .NaN .NAN /);
147             $schema->add_resolver(
148             tag => 'tag:yaml.org,2002:str',
149 5     81   34 match => [ all => sub { $_[1]->{value} } ],
  81         279  
150             implicit => 0,
151             );
152              
153 5         16 my $int_flags = B::SVp_IOK;
154 5         8 my $float_flags = B::SVp_NOK;
155 5         19 $schema->add_representer(
156             flags => $int_flags,
157             code => \&represent_int,
158             );
159 5         14 $schema->add_representer(
160             flags => $float_flags,
161             code => \&represent_float,
162             );
163 5         28 $schema->add_representer(
164             undefined => \&represent_undef,
165             );
166             $schema->add_representer(
167             equals => $_,
168             code => \&represent_literal,
169 5         32 ) for ("", qw/
170             true TRUE True y Y yes Yes YES on On ON
171             false FALSE False n N n no No NO off Off OFF
172             null NULL Null ~
173             .inf .Inf .INF -.inf -.Inf -.INF +.inf +.Inf +.INF .nan .NaN .NAN
174             /);
175 5         250 $schema->add_representer(
176             regex => qr{$RE_INT_1_1|$RE_FLOAT_1_1|$RE_INT_OCTAL_1_1|$RE_INT_HEX_1_1|$RE_INT_BIN_1_1|$RE_SEXAGESIMAL_INT|$RE_SEXAGESIMAL},
177             code => \&represent_literal,
178             );
179              
180 5 100       19 if ($schema->bool_class) {
181 1         2 for my $class (@{ $schema->bool_class }) {
  1         2  
182 1         4 $schema->add_representer(
183             class_equals => $class,
184             code => \&represent_bool,
185             );
186             }
187             }
188              
189 5         31 return;
190             }
191              
192              
193             1;
194              
195             __END__