|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
  
 
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package JSONSchema::Validator::Util;  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # ABSTRACT: Useful functions  | 
| 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
5
 | 
6
 | 
 
 | 
 
 | 
  
6
  
 | 
 
 | 
41
 | 
 use strict;  | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
    | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
165
 | 
    | 
| 
6
 | 
6
 | 
 
 | 
 
 | 
  
6
  
 | 
 
 | 
29
 | 
 use warnings;  | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
    | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
170
 | 
    | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
8
 | 
6
 | 
 
 | 
 
 | 
  
6
  
 | 
 
 | 
28
 | 
 use URI 1.00;  | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
147
 | 
    | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
142
 | 
    | 
| 
9
 | 
6
 | 
 
 | 
 
 | 
  
6
  
 | 
 
 | 
35
 | 
 use File::Basename;  | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
    | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
409
 | 
    | 
| 
10
 | 
6
 | 
 
 | 
 
 | 
  
6
  
 | 
 
 | 
49
 | 
 use B;  | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
    | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
230
 | 
    | 
| 
11
 | 
6
 | 
 
 | 
 
 | 
  
6
  
 | 
 
 | 
33
 | 
 use Carp 'croak';  | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
    | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
270
 | 
    | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
13
 | 
6
 | 
 
 | 
 
 | 
  
6
  
 | 
 
 | 
35
 | 
 use Scalar::Util 'looks_like_number';  | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
    | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
665
 | 
    | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our @ISA = 'Exporter';  | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our @EXPORT_OK = qw(  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     json_encode json_decode user_agent_get serialize unbool  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     round read_file is_type detect_type get_resource decode_content  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     data_section  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
22
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1062
 | 
 use constant FILE_SUFFIX_TO_MIME_TYPE => {  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'yaml' => 'text/vnd.yaml',  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'yml' => 'text/vnd.yaml',  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'json' => 'application/json'  | 
| 
26
 | 
6
 | 
 
 | 
 
 | 
  
6
  
 | 
 
 | 
65
 | 
 };  | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
    | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
28
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
475
 | 
 use constant TYPE_MAP => {  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'array' => \&is_array,  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'boolean' => \&is_bool,  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'integer' => \&is_integer,  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'number' => \&is_number,  | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'object' => \&is_object,  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'null' => \&is_null, # for OAS30 null is not defined  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'string' => \&is_string,  | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # it is for some buggy code  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     '_ref' => \&is_ref  | 
| 
39
 | 
6
 | 
 
 | 
 
 | 
  
6
  
 | 
 
 | 
41
 | 
 };  | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
    | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # such order is required  | 
| 
42
 | 
6
 | 
 
 | 
 
 | 
  
6
  
 | 
 
 | 
39
 | 
 use constant TYPE_LIST => ['array', 'object', 'null', '_ref', 'integer', 'number', 'boolean', 'string'];  | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
    | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3820
 | 
    | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 BEGIN {  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # YAML  | 
| 
46
 | 
6
 | 
  
 50
  
 | 
 
 | 
  
6
  
 | 
 
 | 
26
 | 
     if (eval { require YAML::XS; YAML::XS->VERSION(0.67); 1; }) {  | 
| 
 
 | 
6
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
860
 | 
    | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
47
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         *yaml_load = sub { local $YAML::XS::Boolean = 'JSON::PP'; YAML::XS::Load(@_) };  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
49
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
635
 | 
     elsif (eval { require YAML::PP; 1; }) {  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
50
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $pp = YAML::PP->new(boolean => 'JSON::PP');  | 
| 
51
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         *yaml_load = sub { $pp->load_string(@_) };  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
53
 | 
6
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
40
 | 
         *yaml_load = sub { croak 'No YAML package installed' };  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # JSON  | 
| 
57
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
     my $json_class;  | 
| 
58
 | 
6
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     if (eval { require Cpanel::JSON::XS; 1; }) {  | 
| 
 
 | 
6
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
5514
 | 
    | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21853
 | 
    | 
| 
59
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
         $json_class = 'Cpanel::JSON::XS';  | 
| 
60
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     } elsif (eval { require JSON::XS; JSON::XS->VERSION(3.0); 1; }) {  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
61
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $json_class = 'JSON::XS';  | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
63
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         require JSON::PP;  | 
| 
64
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $json_class = 'JSON::PP';  | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
66
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
46
 | 
     my $json = $json_class->new->canonical(1)->utf8;  | 
| 
67
 | 
6
 | 
 
 | 
 
 | 
  
8
  
 | 
 
 | 
35
 | 
     *json_encode = sub { $json->encode(@_); };  | 
| 
 
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
106
 | 
    | 
| 
68
 | 
6
 | 
 
 | 
 
 | 
  
91
  
 | 
 
 | 
21
 | 
     *json_decode = sub { $json->decode(@_); };  | 
| 
 
 | 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6230
 | 
    | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # UserAgent  | 
| 
71
 | 
6
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
11
 | 
     if (eval { require LWP::UserAgent; 1; }) {  | 
| 
 
 | 
6
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
773
 | 
    | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
72
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $ua = LWP::UserAgent->new;  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         *user_agent_get = sub {  | 
| 
74
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             my $uri = shift;  | 
| 
75
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             my $response = $ua->get($uri);  | 
| 
76
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             if ($response->is_success) {  | 
| 
77
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 return $response->decoded_content, $response->headers->content_type;  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
79
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             croak "Can not get uri $uri";  | 
| 
80
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         };  | 
| 
81
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
708
 | 
     } elsif (eval { require Mojo::UserAgent; 1; }) {  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
82
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $ua = Mojo::UserAgent->new;  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         *user_agent_get = sub {  | 
| 
84
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             my $uri = shift;  | 
| 
85
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             my $response = $ua->get($uri)->result;  | 
| 
86
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             if ($response->is_success) {  | 
| 
87
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 return $response->body, $response->headers->content_type;  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
89
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             croak "Can not get uri $uri";  | 
| 
90
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         };  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
92
 | 
6
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
7767
 | 
         *user_agent_get = sub { croak 'No UserAgent package installed' };  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub unbool {  | 
| 
97
 | 
8
 | 
 
 | 
 
 | 
  
8
  
 | 
  
0
  
 | 
38
 | 
     my $x = shift;  | 
| 
98
 | 
8
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
30
 | 
     return "$x" if ref $x eq 'JSON::PP::Boolean';  | 
| 
99
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $x if ref $x;  | 
| 
100
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     return '1' if $x && $x eq '1';  | 
| 
101
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     return '0' if !defined $x || $x eq '0' || $x eq '';  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
102
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $x;  | 
| 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
105
 | 
8
 | 
 
 | 
 
 | 
  
8
  
 | 
  
0
  
 | 
25
 | 
 sub serialize { json_encode(shift) }  | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub round {  | 
| 
108
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
     my $value = shift;  | 
| 
109
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return int($value + ($value >= 0 ? 0.5 : -0.5));  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
111
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # scheme_handlers - map[scheme -> handler]  | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # uri - string  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_resource {  | 
| 
115
 | 
31
 | 
 
 | 
 
 | 
  
31
  
 | 
  
0
  
 | 
23842
 | 
     my ($scheme_handlers, $resource) = @_;  | 
| 
116
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
130
 | 
     my $uri = URI->new($resource);  | 
| 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
118
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1776
 | 
     for my $s ('http', 'https') {  | 
| 
119
 | 
62
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
268
 | 
         $scheme_handlers->{$s} = \&user_agent_get unless exists $scheme_handlers->{$s};  | 
| 
120
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
122
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
126
 | 
     my $scheme = $uri->scheme;  | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
124
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
798
 | 
     my ($response, $mime_type);  | 
| 
125
 | 
31
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
92
 | 
     if ($scheme) {  | 
| 
126
 | 
31
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
134
 | 
         if (exists $scheme_handlers->{$scheme}) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
127
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             ($response, $mime_type) = $scheme_handlers->{$scheme}->($uri->as_string);  | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif ($scheme eq 'file') {  | 
| 
129
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
128
 | 
             ($response, $mime_type) = read_file($uri->file);  | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
131
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             croak 'Unsupported scheme of uri ' . $uri->as_string;  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # may it is path of local file without scheme?  | 
| 
135
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         ($response, $mime_type) = read_file($resource);  | 
| 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
137
 | 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
203
 | 
     return ($response, $mime_type);  | 
| 
138
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub decode_content {  | 
| 
141
 | 
77
 | 
 
 | 
 
 | 
  
77
  
 | 
  
0
  
 | 
252
 | 
     my ($response, $mime_type, $resource) = @_;  | 
| 
142
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
143
 | 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
121
 | 
     my $schema;  | 
| 
144
 | 
77
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
228
 | 
     if ($mime_type) {  | 
| 
145
 | 
77
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
423
 | 
         if ($mime_type =~ m{yaml}) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
146
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $schema = eval{ yaml_load($response) };  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
147
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             croak "Failed to load resource $resource as $mime_type ( $@ )" if $@;  | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         elsif ($mime_type =~ m{json}) {  | 
| 
150
 | 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
165
 | 
             $schema = eval{ json_decode($response) };  | 
| 
 
 | 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
296
 | 
    | 
| 
151
 | 
77
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
274
 | 
             croak "Failed to load resource $resource as $mime_type ( $@ )" if $@;  | 
| 
152
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
153
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
154
 | 
77
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
203
 | 
     unless ($schema) {  | 
| 
155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # try to guess  | 
| 
156
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $schema = eval { json_decode($response) };  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
157
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $schema = eval { yaml_load($response) } if $@;  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
158
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         croak "Unsupported mime type $mime_type of resource $resource" unless $schema;  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
160
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
161
 | 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
249
 | 
     return $schema;  | 
| 
162
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub read_file {  | 
| 
165
 | 
77
 | 
 
 | 
 
 | 
  
77
  
 | 
  
0
  
 | 
22355
 | 
     my $path = shift;  | 
| 
166
 | 
77
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
1782
 | 
     croak "File $path does not exists" unless -e $path;  | 
| 
167
 | 
77
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
558
 | 
     croak "File $path does not have read permission" unless -r _;  | 
| 
168
 | 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
222
 | 
     my $size = -s _;  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
170
 | 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4218
 | 
     my ($filename, $dir, $suffix) = File::Basename::fileparse($path, 'yml', 'yaml', 'json');  | 
| 
171
 | 
77
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
314
 | 
     croak "Unknown file format of $path" unless $suffix;  | 
| 
172
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
173
 | 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
223
 | 
     my $mime_type = FILE_SUFFIX_TO_MIME_TYPE->{$suffix};  | 
| 
174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
175
 | 
77
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
3668
 | 
     open my $fh, '<', $path or croak "Open file $path error: $!";  | 
| 
176
 | 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2767
 | 
     read $fh, (my $file_content), $size;  | 
| 
177
 | 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
998
 | 
     close $fh;  | 
| 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
179
 | 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
667
 | 
     return $file_content, $mime_type;  | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
181
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # params: $value, $type, $is_strict  | 
| 
183
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub is_type {  | 
| 
184
 | 
7711
 | 
  
 50
  
 | 
 
 | 
  
7711
  
 | 
  
0
  
 | 
16220
 | 
     return 0 unless exists TYPE_MAP->{$_[1]};  | 
| 
185
 | 
7711
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15158
 | 
     return TYPE_MAP->{$_[1]}->($_[0], $_[2]);  | 
| 
186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
188
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # params: $value, $is_strict  | 
| 
189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub detect_type {  | 
| 
190
 | 
45
 | 
 
 | 
 
 | 
  
45
  
 | 
  
0
  
 | 
82
 | 
     for my $type (@{TYPE_LIST()}) {  | 
| 
 
 | 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
93
 | 
    | 
| 
191
 | 
321
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
609
 | 
         return $type if TYPE_MAP->{$type}->(@_);  | 
| 
192
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # it must be unreachable code  | 
| 
194
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     croak 'Unknown type detected';  | 
| 
195
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # params: $value, $is_strict  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub is_array {  | 
| 
199
 | 
896
 | 
 
 | 
 
 | 
  
896
  
 | 
  
0
  
 | 
3095
 | 
     return ref $_[0] eq 'ARRAY';  | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # params: $value, $is_strict  | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub is_bool {  | 
| 
204
 | 
2965
 | 
 
 | 
 
 | 
  
2965
  
 | 
  
0
  
 | 
5065
 | 
     my $type = ref $_[0];  | 
| 
205
 | 
2965
 | 
  
 50
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
11985
 | 
     return 1 if $type eq 'JSON::PP::Boolean' or  | 
| 
 
 | 
 
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
206
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 $type eq 'JSON::XS::Boolean' or  | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 $type eq 'Cpanel::JSON::XS::Boolean';  | 
| 
208
 | 
2900
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
8571
 | 
     return 0 if $_[1]; # is strict  | 
| 
209
 | 
7
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
36
 | 
     my $is_number = looks_like_number($_[0]) && ($_[0] == 1 || $_[0] == 0);  | 
| 
210
 | 
7
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
112
 | 
     my $is_string = defined $_[0] && $_[0] eq '';  | 
| 
211
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
     my $is_undef = !defined $_[0];  | 
| 
212
 | 
7
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
42
 | 
     return 1 if $is_number || $is_string || $is_undef;  | 
| 
 
 | 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
213
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
     return 0;  | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
215
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
216
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # params: $value, $is_strict  | 
| 
217
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub is_integer {  | 
| 
218
 | 
220
 | 
  
100
  
 | 
 
 | 
  
220
  
 | 
  
0
  
 | 
1359
 | 
     return 1 if B::svref_2object(\$_[0])->FLAGS & B::SVf_IOK();  | 
| 
219
 | 
110
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
384
 | 
     return 0 if $_[1]; # is strict  | 
| 
220
 | 
42
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
110
 | 
     return 0 if ref $_[0];  | 
| 
221
 | 
34
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
211
 | 
     return 1 if looks_like_number($_[0]) && int($_[0]) == $_[0];  | 
| 
222
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
52
 | 
     return 0;  | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
224
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
225
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # params: $value, $is_strict  | 
| 
226
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub is_number {  | 
| 
227
 | 
1074
 | 
  
100
  
 | 
 
 | 
  
1074
  
 | 
  
0
  
 | 
4653
 | 
     return 1 if B::svref_2object(\$_[0])->FLAGS & (B::SVf_IOK() | B::SVf_NOK());  | 
| 
228
 | 
967
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
5021
 | 
     return 0 if $_[1]; # is strict  | 
| 
229
 | 
9
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
31
 | 
     return 0 if ref $_[0];  | 
| 
230
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
24
 | 
     return 1 if looks_like_number($_[0]);  | 
| 
231
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
     return 0;  | 
| 
232
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
233
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # params: $value, $is_strict  | 
| 
235
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub is_ref {  | 
| 
236
 | 
40
 | 
 
 | 
 
 | 
  
40
  
 | 
  
0
  
 | 
72
 | 
     my $ref = ref $_[0];  | 
| 
237
 | 
40
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
107
 | 
     return 0 unless $ref;  | 
| 
238
 | 
10
 | 
  
  0
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
33
 | 
     return 0 if $ref eq 'JSON::PP::Boolean' ||  | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
239
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 $ref eq 'HASH' ||  | 
| 
240
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 $ref eq 'ARRAY';  | 
| 
241
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return 1;  | 
| 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
243
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # params: $value, $is_strict  | 
| 
245
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub is_object {  | 
| 
246
 | 
2243
 | 
 
 | 
 
 | 
  
2243
  
 | 
  
0
  
 | 
7045
 | 
     return ref $_[0] eq 'HASH';  | 
| 
247
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
249
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # params: $value, $is_strict  | 
| 
250
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub is_null {  | 
| 
251
 | 
431
 | 
 
 | 
 
 | 
  
431
  
 | 
  
0
  
 | 
1285
 | 
     return !(defined $_[0]);  | 
| 
252
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
253
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
254
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # params: $value, $is_strict  | 
| 
255
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub is_string {  | 
| 
256
 | 
467
 | 
  
100
  
 | 
  
100
  
 | 
  
467
  
 | 
  
0
  
 | 
1415
 | 
     return !(ref $_[0]) && !is_number(@_) && defined $_[0] if $_[1]; # is strict  | 
| 
257
 | 
157
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
668
 | 
     return !(ref $_[0]) && defined $_[0];  | 
| 
258
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub data_section {  | 
| 
261
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
     my $class = shift;  | 
| 
262
 | 
6
 | 
 
 | 
 
 | 
  
6
  
 | 
 
 | 
58
 | 
     my $handle = do { no strict 'refs'; \*{"${class}::DATA"} };  | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
    | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1077
 | 
    | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
263
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return unless fileno $handle;  | 
| 
264
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     seek $handle, 0, 0;  | 
| 
265
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     local $/ = undef;  | 
| 
266
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $data = <$handle>;  | 
| 
267
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $data =~ s/^.*\n__DATA__\r?\n//s;  | 
| 
268
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $data =~ s/\r?\n__END__\r?\n.*$//s;  | 
| 
269
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return $data;  | 
| 
270
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
272
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
274
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |