line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Google::RestApi::Utils; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
25049
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
32
|
|
4
|
1
|
|
|
1
|
|
10
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
44
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '1.0.4'; |
7
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
6
|
use feature 'state'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
81
|
|
9
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
6
|
use autodie; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
8
|
|
11
|
1
|
|
|
1
|
|
7023
|
use File::Spec::Functions qw( catfile ); |
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
79
|
|
12
|
1
|
|
|
1
|
|
6
|
use File::Basename qw( dirname ); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
68
|
|
13
|
1
|
|
|
1
|
|
1206
|
use Hash::Merge (); |
|
1
|
|
|
|
|
8228
|
|
|
1
|
|
|
|
|
26
|
|
14
|
1
|
|
|
1
|
|
10
|
use Log::Log4perl qw( :easy ); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
11
|
|
15
|
1
|
|
|
1
|
|
908
|
use Scalar::Util qw( blessed ); |
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
47
|
|
16
|
1
|
|
|
1
|
|
14
|
use Type::Params qw( compile compile_named ); |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
12
|
|
17
|
1
|
|
|
1
|
|
490
|
use Types::Standard qw( Str StrMatch HashRef Any slurpy ); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
14
|
|
18
|
1
|
|
|
1
|
|
3038
|
use YAML::Any qw( Dump LoadFile ); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
5
|
|
19
|
|
|
|
|
|
|
|
20
|
1
|
|
|
1
|
|
730
|
use Google::RestApi::Types qw( ReadableFile ); |
|
1
|
|
|
|
|
17
|
|
|
1
|
|
|
|
|
9
|
|
21
|
|
|
|
|
|
|
|
22
|
1
|
|
|
1
|
|
711
|
no autovivification; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
10
|
|
23
|
|
|
|
|
|
|
|
24
|
1
|
|
|
1
|
|
58
|
use Exporter qw(import); |
|
1
|
|
|
|
|
19
|
|
|
1
|
|
|
|
|
1373
|
|
25
|
|
|
|
|
|
|
our @EXPORT_OK = qw( |
26
|
|
|
|
|
|
|
named_extra |
27
|
|
|
|
|
|
|
merge_config_file resolve_config_file_path |
28
|
|
|
|
|
|
|
flatten_range |
29
|
|
|
|
|
|
|
bool |
30
|
|
|
|
|
|
|
dim_any dims_any dims_all |
31
|
|
|
|
|
|
|
cl_black cl_white |
32
|
|
|
|
|
|
|
strip |
33
|
|
|
|
|
|
|
); |
34
|
|
|
|
|
|
|
our %EXPORT_TAGS = (all => [ @EXPORT_OK ]); |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# used by validation with type::params. |
37
|
|
|
|
|
|
|
# similar to allow_extra in params::validate, simply returns the |
38
|
|
|
|
|
|
|
# extra key/value pairs we aren't interested in in the checked |
39
|
|
|
|
|
|
|
# argument hash. |
40
|
|
|
|
|
|
|
sub named_extra { |
41
|
932
|
|
|
932
|
0
|
25140
|
state $check = compile_named( |
42
|
|
|
|
|
|
|
_extra_ => HashRef, |
43
|
|
|
|
|
|
|
validated => slurpy HashRef, |
44
|
|
|
|
|
|
|
); |
45
|
932
|
|
|
|
|
6539
|
my $p = $check->(@_); |
46
|
931
|
|
|
|
|
24903
|
my $extra = delete $p->{_extra_}; |
47
|
|
|
|
|
|
|
|
48
|
931
|
|
|
|
|
1519
|
my %p; |
49
|
931
|
50
|
|
|
|
2826
|
%p = %{ $p->{validated} } if $p->{validated}; # these are validated by the caller. |
|
931
|
|
|
|
|
3066
|
|
50
|
931
|
|
|
|
|
4136
|
@p{ keys %$extra } = values %$extra; # stuff back the ones the caller wasn't interested in. |
51
|
931
|
|
|
|
|
3462
|
return \%p; |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub merge_config_file { |
55
|
301
|
|
|
301
|
0
|
2950
|
state $check = compile_named( |
56
|
|
|
|
|
|
|
config_file => ReadableFile, { optional => 1 }, |
57
|
|
|
|
|
|
|
_extra_ => slurpy Any, |
58
|
|
|
|
|
|
|
); |
59
|
301
|
|
|
|
|
55671
|
my $passed_config = named_extra($check->(@_)); |
60
|
|
|
|
|
|
|
|
61
|
299
|
|
|
|
|
986
|
my $config_file = $passed_config->{config_file}; |
62
|
299
|
100
|
|
|
|
1050
|
return $passed_config if !$config_file; |
63
|
|
|
|
|
|
|
|
64
|
154
|
|
|
|
|
330
|
my $config_from_file = eval { LoadFile($config_file); }; |
|
154
|
|
|
|
|
552
|
|
65
|
154
|
50
|
|
|
|
588365
|
LOGDIE "Unable to load config file '$config_file': $@" if $@; |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
# left_precedence, the passed config wins over anything in the file. |
68
|
|
|
|
|
|
|
# can't merge coderefs, error comes from Storable buried deep in hash::merge. |
69
|
154
|
|
|
|
|
708
|
my $merged_config = Hash::Merge::merge($passed_config, $config_from_file); |
70
|
154
|
|
|
|
|
14181
|
TRACE("Config used:\n". Dump($merged_config)); |
71
|
|
|
|
|
|
|
|
72
|
154
|
|
|
|
|
478938
|
return $merged_config; |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
# a standard way to store file names in a config and resolve them |
76
|
|
|
|
|
|
|
# to a full path. can be used in Auth configs, possibly others. |
77
|
|
|
|
|
|
|
# see sub RestApi::auth for more. |
78
|
|
|
|
|
|
|
sub resolve_config_file_path { |
79
|
288
|
|
|
288
|
0
|
4293
|
state $check = compile(HashRef, Str); |
80
|
288
|
|
|
|
|
3524
|
my ($config, $file_key) = $check->(@_); |
81
|
|
|
|
|
|
|
|
82
|
288
|
100
|
|
|
|
3995
|
my $config_file = $config->{$file_key} or return; |
83
|
145
|
100
|
|
|
|
2052
|
return $config_file if -f $config_file; |
84
|
|
|
|
|
|
|
|
85
|
143
|
|
|
|
|
448
|
my $full_file_path; |
86
|
143
|
100
|
66
|
|
|
1142
|
if ($file_key ne 'config_file' && $config->{config_file}) { |
87
|
2
|
|
|
|
|
80
|
my $dir = dirname($config->{config_file}); |
88
|
2
|
|
|
|
|
18
|
my $path = catfile($dir, $config_file); |
89
|
2
|
100
|
|
|
|
55
|
$full_file_path = $path if -f $path |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
|
92
|
143
|
100
|
|
|
|
469
|
if (!$full_file_path) { |
93
|
142
|
|
|
|
|
459
|
my $dir = $config->{config_dir}; |
94
|
142
|
100
|
|
|
|
393
|
if ($dir) { |
95
|
139
|
|
|
|
|
1036
|
my $path = catfile($dir, $config_file); |
96
|
139
|
50
|
|
|
|
2794
|
$full_file_path = $path if -f $path |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
143
|
100
|
|
|
|
626
|
LOGDIE("Unable to resolve config file '$file_key => $config_file' to a full file path") |
101
|
|
|
|
|
|
|
if !$full_file_path; |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
# action at a distance, but is convenient to stuff the real file name in the config here. |
104
|
140
|
|
|
|
|
406
|
$config->{$file_key} = $full_file_path; |
105
|
|
|
|
|
|
|
|
106
|
140
|
|
|
|
|
449
|
return $full_file_path; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# these are just used for debug message just above |
110
|
|
|
|
|
|
|
# to display the original range in a pretty format. |
111
|
|
|
|
|
|
|
sub flatten_range { |
112
|
861
|
|
|
861
|
0
|
86776
|
my $range = shift; |
113
|
861
|
100
|
|
|
|
2711
|
$range = $range->range_to_hash() if blessed($range); |
114
|
861
|
100
|
|
|
|
1819
|
return 'False' if !$range; |
115
|
818
|
100
|
|
|
|
3182
|
return $range if !ref($range); |
116
|
254
|
100
|
|
|
|
765
|
return _flatten_range_hash($range) if ref($range) eq 'HASH'; |
117
|
104
|
50
|
|
|
|
372
|
return _flatten_range_array($range) if ref($range) eq 'ARRAY'; |
118
|
0
|
|
|
|
|
0
|
LOGDIE("Unable to flatten: " . ref($range)); |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
sub _flatten_range_hash { |
122
|
150
|
|
|
150
|
|
269
|
my $range = shift; |
123
|
150
|
|
|
|
|
684
|
my @flat = map { "$_ => " . flatten_range($range->{$_}); } sort keys %$range; |
|
287
|
|
|
|
|
789
|
|
124
|
150
|
|
|
|
|
449
|
my $flat = join(', ', @flat); |
125
|
150
|
|
|
|
|
733
|
return "{ $flat }"; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
sub _flatten_range_array { |
129
|
104
|
|
|
104
|
|
172
|
my $range = shift; |
130
|
104
|
|
|
|
|
222
|
my @flat = map { flatten_range($_); } @$range; |
|
187
|
|
|
|
|
341
|
|
131
|
104
|
|
|
|
|
320
|
my $flat = join(', ', @flat); |
132
|
104
|
|
|
|
|
563
|
return "[ $flat ]"; |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
# changes perl boolean to json boolean. |
136
|
|
|
|
|
|
|
sub bool { |
137
|
25
|
|
|
25
|
0
|
4475
|
my $bool = shift; |
138
|
25
|
100
|
|
|
|
128
|
return 'true' if !defined $bool; # bold() should turn on bold. |
139
|
12
|
100
|
|
|
|
98
|
return 'false' if $bool =~ qr/^false$/i; |
140
|
10
|
100
|
|
|
|
76
|
return $bool ? 'true' : 'false'; # converts bold(0) to 'false'. |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub dims_any { |
144
|
223
|
|
|
223
|
0
|
497
|
state $check = compile(StrMatch[qr/^(col|row)/i]); |
145
|
223
|
|
|
|
|
4028
|
my ($dims) = $check->(@_); |
146
|
222
|
100
|
|
|
|
4019
|
return $dims =~ /^col/i ? "COLUMNS" : "ROWS"; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
sub dims_all { |
150
|
3
|
|
|
3
|
0
|
8
|
my $dims = eval { dims_any(@_); }; |
|
3
|
|
|
|
|
8
|
|
151
|
3
|
100
|
|
|
|
210
|
return $dims if $dims; |
152
|
1
|
|
|
|
|
8
|
state $check = compile(StrMatch[qr/^all/i]); |
153
|
1
|
|
|
|
|
3586
|
($dims) = $check->(@_); |
154
|
1
|
|
|
|
|
23
|
return "ALL"; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
5
|
|
|
5
|
0
|
148
|
sub cl_black { { red => 0, blue => 0, green => 0, alpha => 1 }; } |
158
|
5
|
|
|
5
|
0
|
31
|
sub cl_white { { red => 1, blue => 1, green => 1, alpha => 1 }; } |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
sub strip { |
161
|
0
|
|
0
|
0
|
0
|
|
my $p = shift // ''; |
162
|
0
|
|
|
|
|
|
$p =~ s/^\s+|\s+$//g; |
163
|
0
|
|
|
|
|
|
return $p; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
1; |