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         37  
  18         991  
4 18     18   102 use strict;
  18         37  
  18         378  
5 18     18   89 use Data::Hopen::Base;
  18         55  
  18         128  
6              
7             our $VERSION = '0.000019';
8              
9 18     18   4267 use parent 'Exporter';
  18         41  
  18         182  
10             our (@EXPORT, @EXPORT_OK, %EXPORT_TAGS);
11             BEGIN {
12 18     18   2335 @EXPORT = qw();
13 18         60 @EXPORT_OK = qw(boolify clone dedent forward_opts identical);
14 18         516 %EXPORT_TAGS = (
15             default => [@EXPORT],
16             all => [@EXPORT, @EXPORT_OK]
17             );
18             }
19              
20 18     18   135 use Scalar::Util qw( refaddr blessed );
  18         39  
  18         8153  
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 3167 return false if ($_[0]//'') =~ /^(false|off|no)$/i;
55 6         26 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 340 my $val = shift;
66 25 100       141 return $val unless ref($val);
67 1         113 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 9860 my $extra_trim = (@_ && ref $_[0]) ? (shift, true) : false;
101 16 100       36 my $val = @_ ? $_[0] : $_;
102 16         24 my $initial_NL;
103              
104 16 100       48 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         25 my $ws;
111 16         100 while($val =~ m/^(.*)$/mg) {
112 18         45 my $line = $1;
113 18 100       83 if($line =~ m/^(?\h+)\S/m) { # nonblank with leading ws
    100          
114 18     18   9003 $ws = $+{ws};
  18         6959  
  18         6137  
  6         42  
115 6         17 last;
116             } elsif($line =~ m/\S/) { # nonblank without leading ws
117 10         20 last;
118             }
119             }
120              
121             # Strip leading WS
122 16 100       104 $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     80 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 745 100   745 1 4128 my $hrIn = shift or croak 'Need an input option set';
155 744 100       1821 croak 'Need a hashref' unless ref $hrIn eq 'HASH';
156 743         1170 my $hrOpts = {};
157 743 100       2027 $hrOpts = shift if ref $_[0] eq 'HASH';
158              
159 743         1068 my %result;
160 743         1417 foreach my $name (@_) {
161 1283 100       2729 next unless exists $hrIn->{$name};
162              
163 883 100       1750 my $newname = $hrOpts->{lc} ? lc($name) : $name;
164 883 100       2189 $newname = "-$newname" if $hrOpts->{'-'};
165 883         2105 $result{$newname} = $hrIn->{$name}
166             }
167              
168 743         3604 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__