File Coverage

blib/lib/Data/Hopen/Util/Data.pm
Criterion Covered Total %
statement 53 53 100.0
branch 32 32 100.0
condition 8 8 100.0
subroutine 11 11 100.0
pod 4 4 100.0
total 108 108 100.0


line stmt bran cond sub pod time code
1             # Data::Hopen::Util::Data - general-purpose data-manipulation functions
2             package Data::Hopen::Util::Data;
3 18     18   132 use Data::Hopen;
  18         38  
  18         1031  
4 18     18   107 use strict;
  18         31  
  18         363  
5 18     18   108 use Data::Hopen::Base;
  18         33  
  18         142  
6              
7             our $VERSION = '0.000017';
8              
9 18     18   4241 use parent 'Exporter';
  18         41  
  18         233  
10             our (@EXPORT, @EXPORT_OK, %EXPORT_TAGS);
11             BEGIN {
12 18     18   2452 @EXPORT = qw();
13 18         60 @EXPORT_OK = qw(boolify clone dedent forward_opts identical);
14 18         584 %EXPORT_TAGS = (
15             default => [@EXPORT],
16             all => [@EXPORT, @EXPORT_OK]
17             );
18             }
19              
20 18     18   127 use Scalar::Util qw( refaddr blessed );
  18         34  
  18         7898  
21              
22             # Docs {{{1
23              
24             =head1 NAME
25              
26             Data::Hopen::Util::Data - general-purpose data-manipulation functions
27              
28             =head1 FUNCTIONS
29              
30             Nothing is exported by default --- specify C<:all> if you want it all.
31              
32             =cut
33              
34             # }}}1
35              
36             =head2 boolify
37              
38             Convert a scalar to a Boolean as Perl does, except:
39              
40             =over
41              
42             =item * Falsy
43              
44             C
45              
46             =back
47              
48             So C, C, C, empty string, C, numeric C<0>, and
49             string C<'0'> are falsy, and all other values are truthy.
50              
51             =cut
52              
53             sub boolify {
54 9 100 100 9 1 3359 return false if ($_[0]//'') =~ /^(false|off|no)$/i;
55 6         25 return !!$_[0];
56             } #boolify()
57              
58             =head2 clone
59              
60             Clones a scalar or a reference. Thin wrapper around L.
61              
62             =cut
63              
64             sub clone {
65 25     25 1 393 my $val = shift;
66 25 100       135 return $val unless ref($val);
67 1         94 return Storable::dclone($val);
68             } #clone()
69              
70             =head2 dedent
71              
72             Yet Another routine for dedenting multiline strings. Removes the leading
73             horizontal whitespace on the first nonblank line from all lines. If the first
74             argument is a reference, also trims for use in multiline C/C.
75             Usage:
76              
77             dedent " some\n multiline string";
78             dedent [], q(
79             very indented
80             ); # [] (or any ref) means do the extra trimming.
81              
82             The extra trimming includes:
83              
84             =over
85              
86             =item *
87              
88             Removing the initial C<\n>, if any; and
89              
90             =item *
91              
92             Removing trailing horizontal whitespace between the last C<\n> and the
93             end of the string.
94              
95             =back
96              
97             =cut
98              
99             sub dedent {
100 16 100 100 16 1 9972 my $extra_trim = (@_ && ref $_[0]) ? (shift, true) : false;
101 16 100       43 my $val = @_ ? $_[0] : $_;
102 16         23 my $initial_NL;
103              
104 16 100       47 if(substr($val, 0, 1) eq "\n") {
105 4         7 $initial_NL = true;
106 4         10 $val = substr($val, 1);
107             }
108              
109             # Find first nonblank
110 16         22 my $ws;
111 16         100 while($val =~ m/^(.*)$/mg) {
112 18         47 my $line = $1;
113 18 100       81 if($line =~ m/^(?\h+)\S/m) { # nonblank with leading ws
    100          
114 18     18   8515 $ws = $+{ws};
  18         7009  
  18         6172  
  6         41  
115 6         17 last;
116             } elsif($line =~ m/\S/) { # nonblank without leading ws
117 10         22 last;
118             }
119             }
120              
121             # Strip leading WS
122 16 100       96 $val =~ s/^\Q$ws\E//gm if defined $ws;
123              
124 16 100       42 $val =~ s/^\h+\z//m if $extra_trim;
125              
126 16 100 100     79 return (($initial_NL && !$extra_trim) ? "\n" : '') . $val;
127             } #dedent()
128              
129             =head2 forward_opts
130              
131             Returns a list of key-value pairs extracted from a given hashref. Usage:
132              
133             my %forwarded_opts = forward_opts(\%original_opts, [option hashref,]
134             'name'[, 'name2'...]);
135              
136             If the option hashref is given, the following can be provided:
137              
138             =over
139              
140             =item lc
141              
142             If truthy, lower-case the key names in the output
143              
144             =item '-'
145              
146             If present, add C<-> to the beginning of each name in the output.
147             This is useful with L.
148              
149             =back
150              
151             =cut
152              
153             sub forward_opts {
154 756 100   756 1 5195 my $hrIn = shift or croak 'Need an input option set';
155 755 100       2007 croak 'Need a hashref' unless ref $hrIn eq 'HASH';
156 754         1283 my $hrOpts = {};
157 754 100       1978 $hrOpts = shift if ref $_[0] eq 'HASH';
158              
159 754         1137 my %result;
160 754         1487 foreach my $name (@_) {
161 1493 100       3148 next unless exists $hrIn->{$name};
162              
163 883 100       1914 my $newname = $hrOpts->{lc} ? lc($name) : $name;
164 883 100       2311 $newname = "-$newname" if $hrOpts->{'-'};
165 883         2250 $result{$newname} = $hrIn->{$name}
166             }
167              
168 754         3770 return %result;
169             } #forward_opts()
170              
171             # The following are commented out as they are not currently in use.
172             #=head2 identical
173             #
174             #Return truthy if the given parameters are identical objects.
175             #Taken from L by Paul Evans, which is licensed under the same
176             #terms as Perl itself.
177             #
178             #=cut
179             #
180             #sub _describe
181             #{
182             # my ( $ref ) = @_;
183             #
184             # if( !defined $ref ) {
185             # return "undef";
186             # }
187             # elsif( !refaddr $ref ) {
188             # return "a non-reference";
189             # }
190             # elsif( blessed $ref ) {
191             # return "a reference to a " . ref( $ref );
192             # }
193             # else {
194             # return "an anonymous " . ref( $ref ) . " ref";
195             # }
196             #} #_describe()
197             #
198             #sub identical($$)
199             #{
200             # my ( $got, $expected ) = @_;
201             #
202             # my $got_desc = _describe $got;
203             # my $exp_desc = _describe $expected;
204             #
205             # # TODO: Consider if undef/undef ought to do this...
206             # if( $got_desc ne $exp_desc ) {
207             # return false;
208             # }
209             #
210             # if( !defined $got ) {
211             # # Two undefs
212             # return true;
213             # }
214             #
215             # my $got_addr = refaddr $got;
216             # my $exp_addr = refaddr $expected;
217             #
218             # if( $got_addr != $exp_addr ) {
219             # return false;
220             # }
221             #
222             # return true;
223             #} #identical()
224              
225             1;
226             __END__