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         974  
4 18     18   103 use strict;
  18         34  
  18         357  
5 18     18   91 use Data::Hopen::Base;
  18         43  
  18         143  
6              
7             our $VERSION = '0.000018';
8              
9 18     18   4270 use parent 'Exporter';
  18         34  
  18         178  
10             our (@EXPORT, @EXPORT_OK, %EXPORT_TAGS);
11             BEGIN {
12 18     18   2343 @EXPORT = qw();
13 18         58 @EXPORT_OK = qw(boolify clone dedent forward_opts identical);
14 18         465 %EXPORT_TAGS = (
15             default => [@EXPORT],
16             all => [@EXPORT, @EXPORT_OK]
17             );
18             }
19              
20 18     18   125 use Scalar::Util qw( refaddr blessed );
  18         39  
  18         7817  
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 3635 return false if ($_[0]//'') =~ /^(false|off|no)$/i;
55 6         20 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 373 my $val = shift;
66 25 100       116 return $val unless ref($val);
67 1         84 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 9936 my $extra_trim = (@_ && ref $_[0]) ? (shift, true) : false;
101 16 100       34 my $val = @_ ? $_[0] : $_;
102 16         19 my $initial_NL;
103              
104 16 100       40 if(substr($val, 0, 1) eq "\n") {
105 4         9 $initial_NL = true;
106 4         8 $val = substr($val, 1);
107             }
108              
109             # Find first nonblank
110 16         21 my $ws;
111 16         84 while($val =~ m/^(.*)$/mg) {
112 18         42 my $line = $1;
113 18 100       66 if($line =~ m/^(?\h+)\S/m) { # nonblank with leading ws
    100          
114 18     18   8490 $ws = $+{ws};
  18         6823  
  18         6269  
  6         38  
115 6         16 last;
116             } elsif($line =~ m/\S/) { # nonblank without leading ws
117 10         20 last;
118             }
119             }
120              
121             # Strip leading WS
122 16 100       120 $val =~ s/^\Q$ws\E//gm if defined $ws;
123              
124 16 100       35 $val =~ s/^\h+\z//m if $extra_trim;
125              
126 16 100 100     69 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 4382 my $hrIn = shift or croak 'Need an input option set';
155 755 100       2079 croak 'Need a hashref' unless ref $hrIn eq 'HASH';
156 754         1260 my $hrOpts = {};
157 754 100       1936 $hrOpts = shift if ref $_[0] eq 'HASH';
158              
159 754         1165 my %result;
160 754         1476 foreach my $name (@_) {
161 1493 100       3165 next unless exists $hrIn->{$name};
162              
163 883 100       1783 my $newname = $hrOpts->{lc} ? lc($name) : $name;
164 883 100       2154 $newname = "-$newname" if $hrOpts->{'-'};
165 883         2187 $result{$newname} = $hrIn->{$name}
166             }
167              
168 754         3638 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__