line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
2
|
|
|
2
|
|
74091
|
use strict; |
|
2
|
|
|
|
|
12
|
|
|
2
|
|
|
|
|
70
|
|
2
|
2
|
|
|
2
|
|
11
|
use warnings; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
96
|
|
3
|
|
|
|
|
|
|
package Data::OptList; |
4
|
|
|
|
|
|
|
# ABSTRACT: parse and validate simple name/value option pairs |
5
|
|
|
|
|
|
|
$Data::OptList::VERSION = '0.112'; |
6
|
2
|
|
|
2
|
|
11
|
use List::Util (); |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
34
|
|
7
|
2
|
|
|
2
|
|
1061
|
use Params::Util (); |
|
2
|
|
|
|
|
13019
|
|
|
2
|
|
|
|
|
62
|
|
8
|
2
|
|
|
2
|
|
500
|
use Sub::Install 0.921 (); |
|
2
|
|
|
|
|
1765
|
|
|
2
|
|
|
|
|
175
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
#pod =head1 SYNOPSIS |
11
|
|
|
|
|
|
|
#pod |
12
|
|
|
|
|
|
|
#pod use Data::OptList; |
13
|
|
|
|
|
|
|
#pod |
14
|
|
|
|
|
|
|
#pod my $options = Data::OptList::mkopt([ |
15
|
|
|
|
|
|
|
#pod qw(key1 key2 key3 key4), |
16
|
|
|
|
|
|
|
#pod key5 => { ... }, |
17
|
|
|
|
|
|
|
#pod key6 => [ ... ], |
18
|
|
|
|
|
|
|
#pod key7 => sub { ... }, |
19
|
|
|
|
|
|
|
#pod key8 => { ... }, |
20
|
|
|
|
|
|
|
#pod key8 => [ ... ], |
21
|
|
|
|
|
|
|
#pod ]); |
22
|
|
|
|
|
|
|
#pod |
23
|
|
|
|
|
|
|
#pod ...is the same thing, more or less, as: |
24
|
|
|
|
|
|
|
#pod |
25
|
|
|
|
|
|
|
#pod my $options = [ |
26
|
|
|
|
|
|
|
#pod [ key1 => undef, ], |
27
|
|
|
|
|
|
|
#pod [ key2 => undef, ], |
28
|
|
|
|
|
|
|
#pod [ key3 => undef, ], |
29
|
|
|
|
|
|
|
#pod [ key4 => undef, ], |
30
|
|
|
|
|
|
|
#pod [ key5 => { ... }, ], |
31
|
|
|
|
|
|
|
#pod [ key6 => [ ... ], ], |
32
|
|
|
|
|
|
|
#pod [ key7 => sub { ... }, ], |
33
|
|
|
|
|
|
|
#pod [ key8 => { ... }, ], |
34
|
|
|
|
|
|
|
#pod [ key8 => [ ... ], ], |
35
|
|
|
|
|
|
|
#pod ]); |
36
|
|
|
|
|
|
|
#pod |
37
|
|
|
|
|
|
|
#pod =head1 DESCRIPTION |
38
|
|
|
|
|
|
|
#pod |
39
|
|
|
|
|
|
|
#pod Hashes are great for storing named data, but if you want more than one entry |
40
|
|
|
|
|
|
|
#pod for a name, you have to use a list of pairs. Even then, this is really boring |
41
|
|
|
|
|
|
|
#pod to write: |
42
|
|
|
|
|
|
|
#pod |
43
|
|
|
|
|
|
|
#pod $values = [ |
44
|
|
|
|
|
|
|
#pod foo => undef, |
45
|
|
|
|
|
|
|
#pod bar => undef, |
46
|
|
|
|
|
|
|
#pod baz => undef, |
47
|
|
|
|
|
|
|
#pod xyz => { ... }, |
48
|
|
|
|
|
|
|
#pod ]; |
49
|
|
|
|
|
|
|
#pod |
50
|
|
|
|
|
|
|
#pod Just look at all those undefs! Don't worry, we can get rid of those: |
51
|
|
|
|
|
|
|
#pod |
52
|
|
|
|
|
|
|
#pod $values = [ |
53
|
|
|
|
|
|
|
#pod map { $_ => undef } qw(foo bar baz), |
54
|
|
|
|
|
|
|
#pod xyz => { ... }, |
55
|
|
|
|
|
|
|
#pod ]; |
56
|
|
|
|
|
|
|
#pod |
57
|
|
|
|
|
|
|
#pod Aaaauuugh! We've saved a little typing, but now it requires thought to read, |
58
|
|
|
|
|
|
|
#pod and thinking is even worse than typing... and it's got a bug! It looked right, |
59
|
|
|
|
|
|
|
#pod didn't it? Well, the C<< xyz => { ... } >> gets consumed by the map, and we |
60
|
|
|
|
|
|
|
#pod don't get the data we wanted. |
61
|
|
|
|
|
|
|
#pod |
62
|
|
|
|
|
|
|
#pod With Data::OptList, you can do this instead: |
63
|
|
|
|
|
|
|
#pod |
64
|
|
|
|
|
|
|
#pod $values = Data::OptList::mkopt([ |
65
|
|
|
|
|
|
|
#pod qw(foo bar baz), |
66
|
|
|
|
|
|
|
#pod xyz => { ... }, |
67
|
|
|
|
|
|
|
#pod ]); |
68
|
|
|
|
|
|
|
#pod |
69
|
|
|
|
|
|
|
#pod This works by assuming that any defined scalar is a name and any reference |
70
|
|
|
|
|
|
|
#pod following a name is its value. |
71
|
|
|
|
|
|
|
#pod |
72
|
|
|
|
|
|
|
#pod =func mkopt |
73
|
|
|
|
|
|
|
#pod |
74
|
|
|
|
|
|
|
#pod my $opt_list = Data::OptList::mkopt($input, \%arg); |
75
|
|
|
|
|
|
|
#pod |
76
|
|
|
|
|
|
|
#pod Valid arguments are: |
77
|
|
|
|
|
|
|
#pod |
78
|
|
|
|
|
|
|
#pod moniker - a word used in errors to describe the opt list; encouraged |
79
|
|
|
|
|
|
|
#pod require_unique - if true, no name may appear more than once |
80
|
|
|
|
|
|
|
#pod must_be - types to which opt list values are limited (described below) |
81
|
|
|
|
|
|
|
#pod name_test - a coderef used to test whether a value can be a name |
82
|
|
|
|
|
|
|
#pod (described below, but you probably don't want this) |
83
|
|
|
|
|
|
|
#pod |
84
|
|
|
|
|
|
|
#pod This produces an array of arrays; the inner arrays are name/value pairs. |
85
|
|
|
|
|
|
|
#pod Values will be either "undef" or a reference. |
86
|
|
|
|
|
|
|
#pod |
87
|
|
|
|
|
|
|
#pod Positional parameters may be used for compatibility with the old C |
88
|
|
|
|
|
|
|
#pod interface: |
89
|
|
|
|
|
|
|
#pod |
90
|
|
|
|
|
|
|
#pod my $opt_list = Data::OptList::mkopt($input, $moniker, $req_uni, $must_be); |
91
|
|
|
|
|
|
|
#pod |
92
|
|
|
|
|
|
|
#pod Valid values for C<$input>: |
93
|
|
|
|
|
|
|
#pod |
94
|
|
|
|
|
|
|
#pod undef -> [] |
95
|
|
|
|
|
|
|
#pod hashref -> [ [ key1 => value1 ] ... ] # non-ref values become undef |
96
|
|
|
|
|
|
|
#pod arrayref -> every name followed by a non-name becomes a pair: [ name => ref ] |
97
|
|
|
|
|
|
|
#pod every name followed by undef becomes a pair: [ name => undef ] |
98
|
|
|
|
|
|
|
#pod otherwise, it becomes [ name => undef ] like so: |
99
|
|
|
|
|
|
|
#pod [ "a", "b", [ 1, 2 ] ] -> [ [ a => undef ], [ b => [ 1, 2 ] ] ] |
100
|
|
|
|
|
|
|
#pod |
101
|
|
|
|
|
|
|
#pod By default, a I is any defined non-reference. The C parameter |
102
|
|
|
|
|
|
|
#pod can be a code ref that tests whether the argument passed it is a name or not. |
103
|
|
|
|
|
|
|
#pod This should be used rarely. Interactions between C and |
104
|
|
|
|
|
|
|
#pod C are not yet particularly elegant, as C just tests |
105
|
|
|
|
|
|
|
#pod string equality. B |
106
|
|
|
|
|
|
|
#pod |
107
|
|
|
|
|
|
|
#pod The C parameter is either a scalar or array of scalars; it defines |
108
|
|
|
|
|
|
|
#pod what kind(s) of refs may be values. If an invalid value is found, an exception |
109
|
|
|
|
|
|
|
#pod is thrown. If no value is passed for this argument, any reference is valid. |
110
|
|
|
|
|
|
|
#pod If C specifies that values must be CODE, HASH, ARRAY, or SCALAR, then |
111
|
|
|
|
|
|
|
#pod Params::Util is used to check whether the given value can provide that |
112
|
|
|
|
|
|
|
#pod interface. Otherwise, it checks that the given value is an object of the kind. |
113
|
|
|
|
|
|
|
#pod |
114
|
|
|
|
|
|
|
#pod In other words: |
115
|
|
|
|
|
|
|
#pod |
116
|
|
|
|
|
|
|
#pod [ qw(SCALAR HASH Object::Known) ] |
117
|
|
|
|
|
|
|
#pod |
118
|
|
|
|
|
|
|
#pod Means: |
119
|
|
|
|
|
|
|
#pod |
120
|
|
|
|
|
|
|
#pod _SCALAR0($value) or _HASH($value) or _INSTANCE($value, 'Object::Known') |
121
|
|
|
|
|
|
|
#pod |
122
|
|
|
|
|
|
|
#pod =cut |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
my %test_for; |
125
|
|
|
|
|
|
|
BEGIN { |
126
|
2
|
|
|
2
|
|
1283
|
%test_for = ( |
127
|
|
|
|
|
|
|
CODE => \&Params::Util::_CODELIKE, ## no critic |
128
|
|
|
|
|
|
|
HASH => \&Params::Util::_HASHLIKE, ## no critic |
129
|
|
|
|
|
|
|
ARRAY => \&Params::Util::_ARRAYLIKE, ## no critic |
130
|
|
|
|
|
|
|
SCALAR => \&Params::Util::_SCALAR0, ## no critic |
131
|
|
|
|
|
|
|
); |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub mkopt { |
135
|
37
|
|
|
37
|
1
|
7682
|
my ($opt_list) = shift; |
136
|
|
|
|
|
|
|
|
137
|
37
|
|
|
|
|
87
|
my ($moniker, $require_unique, $must_be); # the old positional args |
138
|
37
|
|
|
|
|
0
|
my ($name_test, $is_a); |
139
|
|
|
|
|
|
|
|
140
|
37
|
100
|
|
|
|
83
|
if (@_) { |
141
|
30
|
100
|
66
|
|
|
98
|
if (@_ == 1 and Params::Util::_HASHLIKE($_[0])) { |
142
|
|
|
|
|
|
|
($moniker, $require_unique, $must_be, $name_test) |
143
|
3
|
|
|
|
|
5
|
= @{$_[0]}{ qw(moniker require_unique must_be name_test) }; |
|
3
|
|
|
|
|
11
|
|
144
|
|
|
|
|
|
|
} else { |
145
|
27
|
|
|
|
|
55
|
($moniker, $require_unique, $must_be) = @_; |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# Transform the $must_be specification into a closure $is_a |
149
|
|
|
|
|
|
|
# that will check if a value matches the spec |
150
|
|
|
|
|
|
|
|
151
|
30
|
100
|
|
|
|
67
|
if (defined $must_be) { |
152
|
20
|
100
|
|
|
|
46
|
$must_be = [ $must_be ] unless ref $must_be; |
153
|
|
|
|
|
|
|
my @checks = map { |
154
|
20
|
|
|
|
|
42
|
my $class = $_; |
|
31
|
|
|
|
|
47
|
|
155
|
|
|
|
|
|
|
$test_for{$class} |
156
|
7
|
|
|
7
|
|
48
|
|| sub { Params::Util::_INSTANCE($_[0], $class) } |
157
|
31
|
100
|
|
|
|
136
|
} @$must_be; |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
$is_a = (@checks == 1) |
160
|
|
|
|
|
|
|
? $checks[0] |
161
|
|
|
|
|
|
|
: sub { |
162
|
6
|
|
|
6
|
|
10
|
my $value = $_[0]; |
163
|
12
|
|
|
|
|
92
|
List::Util::first { defined($_->($value)) } @checks |
164
|
20
|
100
|
|
|
|
61
|
}; |
|
6
|
|
|
|
|
27
|
|
165
|
|
|
|
|
|
|
|
166
|
20
|
50
|
|
|
|
49
|
$moniker = 'unnamed' unless defined $moniker; |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
|
170
|
37
|
100
|
|
|
|
76
|
return [] unless $opt_list; |
171
|
|
|
|
|
|
|
|
172
|
36
|
|
100
|
59
|
|
277
|
$name_test ||= sub { ! ref $_[0] }; |
|
59
|
|
|
|
|
142
|
|
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
$opt_list = [ |
175
|
36
|
100
|
|
|
|
104
|
map { $_ => (ref $opt_list->{$_} ? $opt_list->{$_} : ()) } keys %$opt_list |
|
15
|
100
|
|
|
|
42
|
|
176
|
|
|
|
|
|
|
] if ref $opt_list eq 'HASH'; |
177
|
|
|
|
|
|
|
|
178
|
36
|
|
|
|
|
66
|
my @return; |
179
|
|
|
|
|
|
|
my %seen; |
180
|
|
|
|
|
|
|
|
181
|
36
|
|
|
|
|
93
|
for (my $i = 0; $i < @$opt_list; $i++) { ## no critic |
182
|
88
|
|
|
|
|
127
|
my $name = $opt_list->[$i]; |
183
|
|
|
|
|
|
|
|
184
|
88
|
100
|
|
|
|
155
|
if ($require_unique) { |
185
|
30
|
100
|
|
|
|
152
|
Carp::croak "multiple definitions provided for $name" if $seen{$name}++; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
87
|
|
|
|
|
115
|
my $value; |
189
|
|
|
|
|
|
|
|
190
|
87
|
100
|
|
|
|
147
|
if ($i < $#$opt_list) { |
191
|
68
|
100
|
|
|
|
184
|
if (not defined $opt_list->[$i+1]) { |
|
|
100
|
|
|
|
|
|
192
|
6
|
|
|
|
|
8
|
$i++ |
193
|
|
|
|
|
|
|
} elsif (! $name_test->($opt_list->[$i+1])) { |
194
|
29
|
|
|
|
|
66
|
$value = $opt_list->[++$i]; |
195
|
29
|
100
|
100
|
|
|
99
|
if ($is_a && !$is_a->($value)) { |
196
|
9
|
|
|
|
|
14
|
my $ref = ref $value; |
197
|
9
|
|
|
|
|
952
|
Carp::croak "$ref-ref values are not valid in $moniker opt list"; |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
|
202
|
78
|
|
|
|
|
234
|
push @return, [ $name => $value ]; |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
|
205
|
26
|
|
|
|
|
234
|
return \@return; |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
#pod =func mkopt_hash |
209
|
|
|
|
|
|
|
#pod |
210
|
|
|
|
|
|
|
#pod my $opt_hash = Data::OptList::mkopt_hash($input, $moniker, $must_be); |
211
|
|
|
|
|
|
|
#pod |
212
|
|
|
|
|
|
|
#pod Given valid C> input, this routine returns a reference to a hash. It |
213
|
|
|
|
|
|
|
#pod will throw an exception if any name has more than one value. |
214
|
|
|
|
|
|
|
#pod |
215
|
|
|
|
|
|
|
#pod =cut |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
sub mkopt_hash { |
218
|
12
|
|
|
12
|
1
|
894
|
my ($opt_list, $moniker, $must_be) = @_; |
219
|
12
|
100
|
|
|
|
36
|
return {} unless $opt_list; |
220
|
|
|
|
|
|
|
|
221
|
10
|
|
|
|
|
22
|
$opt_list = mkopt($opt_list, $moniker, 1, $must_be); |
222
|
8
|
|
|
|
|
21
|
my %hash = map { $_->[0] => $_->[1] } @$opt_list; |
|
18
|
|
|
|
|
41
|
|
223
|
8
|
|
|
|
|
52
|
return \%hash; |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
#pod =head1 EXPORTS |
227
|
|
|
|
|
|
|
#pod |
228
|
|
|
|
|
|
|
#pod Both C and C may be exported on request. |
229
|
|
|
|
|
|
|
#pod |
230
|
|
|
|
|
|
|
#pod =cut |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
BEGIN { |
233
|
2
|
|
|
2
|
|
20
|
*import = Sub::Install::exporter { |
234
|
|
|
|
|
|
|
exports => [qw(mkopt mkopt_hash)], |
235
|
|
|
|
|
|
|
}; |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
1; |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
__END__ |