File Coverage

blib/lib/perl5i/2/SCALAR.pm
Criterion Covered Total %
statement 117 128 91.4
branch 50 58 86.2
condition 13 31 41.9
subroutine 30 33 90.9
pod 0 25 0.0
total 210 275 76.3


line stmt bran cond sub pod time code
1             # vi: set ts=4 sw=4 ht=4 et :
2             package perl5i::2::SCALAR;
3 103     103   2835 use 5.010;
  103         447  
  103         5032  
4              
5 103     103   663 use strict;
  103         318  
  103         4525  
6 103     103   583 use warnings;
  103         225  
  103         3723  
7             require Carp::Fix::1_25;
8 103     103   717 use perl5i::2::autobox;
  103         205  
  103         960  
9              
10             sub title_case {
11 4     4 0 43 my ($string) = @_;
12 4         50 $string =~ s/\b(\w)/\U$1/g;
13 4         29 return $string;
14             }
15              
16              
17             sub center {
18 27     27 0 29174 my ($string, $size, $char) = @_;
19 27 100       108 Carp::Fix::1_25::carp("Use of uninitialized value for size in center()") if !defined $size;
20 27   100     823 $size //= 0;
21 27   100     118 $char //= ' ';
22              
23 27 100       552 if (length $char > 1) {
24 1         3 my $bad = $char;
25 1         4 $char = substr $char, 0, 1;
26 1         14 Carp::Fix::1_25::carp("'$bad' is longer than one character, using '$char' instead");
27             }
28              
29 27         672 my $len = length $string;
30              
31 27 100       85 return $string if $size <= $len;
32              
33 21         36 my $padlen = $size - $len;
34              
35             # pad right with half the remaining characters
36 21         62 my $rpad = int( $padlen / 2 );
37              
38             # bias the left padding to one more space, if $size - $len is odd
39 21         32 my $lpad = $padlen - $rpad;
40              
41 21         230 return $char x $lpad . $string . $char x $rpad;
42             }
43              
44              
45             sub ltrim {
46 44     44 0 89 my ($string,$trim_charset) = @_;
47 44 100       153 $trim_charset = '\s' unless defined $trim_charset;
48 44         464 my $re = qr/^[$trim_charset]*/;
49 44         258 $string =~ s/$re//;
50 44         207 return $string;
51             }
52              
53              
54             sub rtrim {
55 44     44 0 81 my ($string,$trim_charset) = @_;
56 44 100       129 $trim_charset = '\s' unless defined $trim_charset;
57 44         281 my $re = qr/[$trim_charset]*$/;
58 44         1438 $string =~ s/$re//;
59 44         236 return $string;
60             }
61              
62              
63             sub trim {
64 28     28 0 61 my $charset = $_[1];
65              
66 28         101 return rtrim(ltrim($_[0], $charset), $charset);
67             }
68              
69              
70             sub wrap {
71 30     30 0 35616 my ($string, %args) = @_;
72              
73 30   100     148 my $width = $args{width} // 76;
74 30   50     97 my $separator = $args{separator} // "\n";
75              
76 30 100       134 return $string if $width <= 0;
77              
78 18         3075 require Text::Wrap;
79 18         22886 local $Text::Wrap::separator = $separator;
80 18         30 local $Text::Wrap::columns = $width;
81              
82 18         66 return Text::Wrap::wrap('', '', $string);
83              
84             }
85              
86              
87             # Always reverse the scalar, not a single element list.
88             sub reverse {
89 2     2 0 13 return scalar CORE::reverse $_[0];
90             }
91              
92              
93             # Compatiblity wrappers. Remove in 3.0.
94             sub untaint {
95 1     1 0 10 return $_[0]->mo->untaint;
96             }
97              
98             sub taint {
99 1     1 0 7 return $_[0]->mo->taint;
100             }
101              
102             sub is_tainted {
103 3     3 0 462 return $_[0]->mo->is_tainted;
104             }
105              
106              
107             sub require {
108 1053     1053 0 11585 my $error = do {
109             # Don't let them leak out or get reset
110 1053         7062 local($!,$@);
111 1053 100       2055 return $_[0] if eval { require $_[0]->module2path };
  1053         8363  
112 2         9 $@;
113             };
114              
115 2         8 my($pack, $file, $line) = caller;
116 2         24 $error =~ s{ at .*? line .*?\.\n$}{ at $file line $line.\n};
117 2         14 die $error;
118             }
119              
120              
121             sub alias {
122 3 100   3 0 2298 Carp::Fix::1_25::croak(<
123             Due to limitations in autoboxing, scalars cannot be aliased.
124             Sorry. Use a scalar reference instead.
125             ERROR
126              
127 2         8 goto &perl5i::2::UNIVERSAL::alias;
128             }
129              
130              
131             require POSIX;
132             *ceil = \&POSIX::ceil;
133             *floor = \&POSIX::floor;
134             *round_up = \&ceil;
135             *round_down = \&floor;
136             sub round {
137 7 100   7 0 7611 return 0 if $_[0] == 0;
138              
139 6 100       31 if( $_[0]->is_positive ) {
140 3 100       28 abs($_[0] - int($_[0])) < 0.5 ? round_down($_[0])
141             : round_up($_[0])
142             }
143             else {
144 3 100       33 abs($_[0] - int($_[0])) < 0.5 ? round_up($_[0])
145             : round_down($_[0])
146             }
147             }
148              
149             require Scalar::Util;
150             *is_number = \&Scalar::Util::looks_like_number;
151 31 100   31 0 1226 sub is_positive { $_[0]->is_number && $_[0] > 0 }
152 7 100   7 0 699 sub is_negative { $_[0]->is_number && $_[0] < 0 }
153             sub is_integer {
154 42 100   42 0 1898 return 0 if !$_[0]->is_number;
155 37         485 return $_[0] =~ m{ ^[+-]? \d+ $}x;
156             }
157             *is_int = \&is_integer;
158 5 100   5 0 36 sub is_even { $_[0]->is_integer && !($_[0] % 2) }
159 5 100   5 0 24 sub is_odd { $_[0]->is_integer && ($_[0] % 2) }
160             sub is_decimal {
161 9 100   9 0 750 return 0 if !$_[0]->is_number;
162              
163             # Fast and reliable way to spot most decimals
164 7 100       36 return 1 if ((int($_[0]) - $_[0]) != 0);
165              
166             # Final gate for tricky things like 1.0, 1. and .0
167 5         37 return $_[0] =~ m{^ [+-]? (?: \d+\.\d* | \.\d+ ) $}x;
168             }
169              
170             sub group_digits {
171 15     15 0 28 my($self, $opts) = @_;
172              
173 15         25 state $defaults = {
174             thousands_sep => ",",
175             grouping => 3,
176             decimal_point => ".",
177             };
178              
179 15         29 my $is_money = $opts->{currency};
180 15   0     46 my $sep = $opts->{separator} // (_get_from_locale("thousands_sep", $is_money)
      33        
181             || $defaults->{thousands_sep});
182 15   0     41 my $grouping = $opts->{grouping} // (_get_grouping($is_money)
      33        
183             || $defaults->{grouping});
184 15   0     41 my $decimal_point = $opts->{decimal_point} // (_get_from_locale("decimal_point", $is_money)
      33        
185             || $defaults->{decimal_point});
186 15 100       37 return $self if $grouping == 0;
187              
188 14         66 my($integer, $decimal) = split m{\.}, $self, 2;
189              
190 14         31 $integer = CORE::reverse $integer;
191 14         220 $integer =~ s/(\d{$grouping})(?=\d)(?!\d*\.)/$1$sep/g;
192 14         29 $integer = CORE::reverse $integer;
193              
194 14         21 my $number = $integer;
195 14 100       44 $number .= $decimal_point . $decimal if defined $decimal;
196              
197 14         112 return $number;
198             }
199              
200             sub commify {
201 15     15 0 3138 my($self, $args) = @_;
202              
203 15         30 state $defaults = {
204             separator => ",",
205             grouping => 3,
206             decimal_point => ".",
207             };
208              
209 15         86 my $opts = $defaults->merge($args);
210              
211 15         72 return $self->group_digits( $opts );
212             }
213              
214              
215             sub _get_lconv {
216 0   0 0   0 return eval {
217             require POSIX;
218             POSIX::localeconv();
219             } || {};
220             }
221              
222             sub _get_grouping {
223 0     0   0 my $is_money = shift;
224 0 0       0 my $key = $is_money ? "mon_grouping" : "grouping";
225              
226 0         0 my $lconv = _get_lconv;
227              
228 0 0       0 if( $lconv->{$key} ) {
229 0         0 return (unpack("C*", $lconv->{$key}))[0];
230             }
231             else {
232 0         0 return;
233             }
234             }
235              
236             sub _get_from_locale {
237 0     0   0 my($key, $is_money) = @_;
238 0 0       0 $key = "mon_$key" if $is_money;
239              
240 0         0 my $lconv = _get_lconv;
241 0         0 return $lconv->{$key};
242             }
243              
244              
245             sub path2module {
246 7     7 0 2528 my $path = shift;
247              
248 7         109 my($vol, $dirs, $file) = File::Spec->splitpath($path);
249 7         69 my @dirs = grep length, File::Spec->splitdir($dirs);
250              
251 7 100 100     559 Carp::Fix::1_25::croak("'$path' does not look like a Perl module path")
252             if $file !~ m{\.pm$} or File::Spec->file_name_is_absolute($path);
253              
254 4         23 $file =~ s{\.pm$}{};
255              
256 4         13 my $module = join "::", @dirs, $file;
257 4 50       18 Carp::Fix::1_25::croak("'$module' is not a valid module name") unless $module->is_module_name;
258              
259 4         20 return $module;
260             }
261              
262              
263             sub is_module_name {
264 1076     1076 0 8094 my $name = shift;
265              
266 1076 50       3350 return 0 unless defined($name);
267              
268 1076 100       25384 return 0 unless $name =~ qr{\A
269             [[:alpha:]_] # Must start with an alpha or _
270             [[:word:]]* # Then any number of alpha numerics or _
271             (?: :: [[:word:]]+ )* # Then optional ::word's
272             \z
273             }x;
274              
275 1066         5644 return 1;
276             }
277              
278              
279             sub module2path {
280 1060     1060 0 8337 my $module = shift;
281              
282 1060 100       7444 Carp::Fix::1_25::croak("'$module' is not a valid module name") unless $module->is_module_name;
283              
284 1056         6878 my @parts = split /::/, $module;
285 1056         2403 $parts[-1] .= ".pm";
286              
287 1056         735993 return join "/", @parts;
288             }
289              
290              
291             # On the first call, load Path::Tiny and replace our path() with
292             # Path::Tiny::path() so we don't try to load it again.
293             # Shaves about 1/6 off the call time.
294             sub path {
295 1     1 0 1838 require Path::Tiny;
296 103     103   467118 no warnings 'redefine';
  103         326  
  103         19074  
297 1         15008 *path = \&Path::Tiny::path;
298 1         6 goto &Path::Tiny::path;
299             }
300              
301             1;