File Coverage

blib/lib/Scalar/Type.pm
Criterion Covered Total %
statement 46 48 95.8
branch 28 34 82.3
condition 4 6 66.6
subroutine 17 17 100.0
pod 6 6 100.0
total 101 111 90.9


line stmt bran cond sub pod time code
1             package Scalar::Type;
2              
3 3     3   209026 use strict;
  3         48  
  3         88  
4 3     3   13 use warnings;
  3         6  
  3         161  
5              
6             our $IS_BOOL_FN;
7              
8             # these shenanigans can be pared back a bit once 5.36 is out
9             BEGIN {
10 3 50   3   126 $IS_BOOL_FN = $] >= 5.035010 ? 'builtin::is_bool' :
    50          
11             $] >= 5.035007 ? 'builtin::isbool' :
12             0
13             }
14 99     99 1 773 sub bool_supported { $IS_BOOL_FN; }
15              
16             # 5.35.7 has this without the underscore, and it's not yet marked experimental
17 3     3   2038 use if bool_supported() eq 'builtin::isbool', qw(builtin);
  3         37  
  3         9  
18             # 5.35.10-to-be has the underscore, and it's experimental
19 3     3   203 use if bool_supported() eq 'builtin::is_bool', qw(experimental builtin);
  3         6  
  3         8  
20              
21 3     3   80 use Carp qw(croak);
  3         9  
  3         190  
22 3     3   17 use Config;
  3         5  
  3         168  
23              
24             our $VERSION = '0.3.2';
25              
26             require XSLoader;
27             XSLoader::load(__PACKAGE__, $VERSION);
28              
29 3     3   15 use Scalar::Util qw(blessed);
  3         6  
  3         137  
30              
31 3     3   18 use base qw(Exporter);
  3         5  
  3         858  
32              
33             =head1 NAME
34              
35             Scalar::Type
36              
37             =head1 DESCRIPTION
38              
39             Figure out what type a scalar is
40              
41             =head1 SYNOPSIS
42              
43             use Scalar::Type qw(is_number);
44              
45             if(is_number(2)) {
46             # yep, 2 is a number
47             # it is_integer too
48             }
49              
50             if(is_number("2")) {
51             # no, "2" is a string
52             }
53              
54             =head1 OVERVIEW
55              
56             Perl scalars can be either strings or numbers, and normally you don't really
57             care which is which as it will do all the necessary type conversions automagically.
58             This means that you can perform numeric operations on strings and provided that they
59             B a number you'll get a sensible result:
60              
61             my $string = "4";
62             my $number = 1;
63             my $result = $string + $number; # 5
64              
65             But in some rare cases, generally when you are serialising data, the difference
66             matters. This package provides some useful functions to help you figure out what's
67             what. The following functions are available. None of them are exported by default.
68             If you want them all, export ':all':
69              
70             use Scalar::Type qw(:all);
71              
72             and if you just want the 'is_*' functions you can get them all in one go:
73              
74             use Scalar::Type qw(is_*);
75              
76             For Reasons, C<:is_*> is equivalent.
77              
78             =cut
79              
80             our @EXPORT_OK = qw(
81             type sizeof is_integer is_number is_bool bool_supported
82             );
83             our %EXPORT_TAGS = (
84             all => \@EXPORT_OK,
85             'is_*' => [grep { /^is_/ } @EXPORT_OK]
86             );
87              
88             sub import {
89 3 100   3   23 __PACKAGE__->export_to_level(1, map { $_ eq 'is_*' ? ':is_*' : $_ } @_);
  7         4465  
90             }
91              
92             =head1 FUNCTIONS
93              
94             All of these functions require an argument. It is a fatal error to call
95             them without.
96              
97             =head2 type
98              
99             Returns the type of its argument.
100              
101             If the argument is a reference then it returns either
102             C (if it's an object),
103             or C<'REF_TO_'.ref($argument)>.
104              
105             If the argument is C then it returns C<'UNDEF'>.
106              
107             If you are using perl 5.35.7 or later and the argument is the result of a
108             comparison then it returns C<'BOOL'>.
109              
110             Otherwise it looks for the IOK or NOK flags on the underlying SV (see
111             L for the exact mechanics) and returns C or C
112             as appropriate. Finally, if neither of those are set it returns C.
113              
114             =head2 bool_supported
115              
116             Returns true if the C<'BOOL'> type is supported on this perl (ie if your
117             perl version is 5.35.7 or later) and false otherwise.
118              
119             =cut
120              
121             sub type {
122 99 100   99 1 20923 croak(__PACKAGE__."::type requires an argument") if($#_ == -1);
123 98         147 my $arg = shift;
124 3     3   20 no strict 'refs';
  3         17  
  3         1273  
125             return blessed($arg) ? blessed($arg) :
126             ref($arg) ? 'REF_TO_'.ref($arg) :
127             !defined($arg) ? 'UNDEF' :
128 98 50 33     390 (bool_supported && &{$IS_BOOL_FN}($arg)) ? 'BOOL' :
    100          
    100          
    100          
129             _scalar_type($arg);
130             }
131              
132             =head2 sizeof
133              
134             Returns the size, in bytes, of the underlying storage for numeric types, and die()s for any other type.
135              
136             =cut
137              
138             sub sizeof {
139 4 100   4 1 7870 croak(__PACKAGE__."::sizeof requires an argument") if($#_ == -1);
140 3         8 my $arg = shift;
141 3         26 my $type = type($arg);
142 3 100       14 if($type eq 'INTEGER') {
    100          
143 1         106 return $Config{ivsize};
144             } elsif($type eq 'NUMBER') {
145 1         97 return $Config{nvsize};
146             } else {
147 1         5 croak(__PACKAGE__."::sizeof: '$arg' isn't numeric: ".type($arg)."\n");
148             }
149             }
150              
151             =head2 is_integer
152              
153             Returns true if its argument is an integer. Note that "1" is not an integer, it
154             is a string. 1 is an integer. 1.1 is obviously not an integer. 1.0 is also not
155             an integer, as it makes a different statement about precision - 1 is *exactly*
156             one, but 1.0 is only one to two significant figures.
157              
158             All integers are of course also numbers.
159              
160             =cut
161              
162             sub is_integer {
163 57 100   57 1 19259 croak(__PACKAGE__."::is_integer requires an argument") if($#_ == -1);
164 56 100       87 type(@_) eq 'INTEGER' ? 1 : 0;
165             }
166              
167             =head2 is_number
168              
169             Returns true if its argument is a number. "1" is not a number, it is a string.
170             1 is a number. 1.0 and 1.1 are numbers too.
171              
172             =cut
173              
174             sub is_number {
175 24 100   24 1 3037 croak(__PACKAGE__."::is_number requires an argument") if($#_ == -1);
176 23 100 100     38 is_integer(@_) || type(@_) eq 'NUMBER' ? 1 : 0;
177             }
178              
179             =head2 is_bool
180              
181             It is a fatal error to call this on perl versions earlier than 5.35.7.
182              
183             Returns true if its argument is a Boolean - ie, the result of a comparison.
184              
185             =cut
186              
187             sub is_bool {
188 1 50   1 1 78 croak(__PACKAGE__."::is_bool not supported on your perl") if(!bool_supported);
189 0 0         croak(__PACKAGE__."::is_bool requires an argument") if($#_ == -1);
190 0           type(@_) eq 'BOOL';
191             }
192              
193             =head1 GORY DETAILS
194              
195             =head2 PERL VARIABLE INTERNALS
196              
197             As far as Perl code is concerned scalars will present themselves as integers,
198             floats or strings on demand. Internally scalars are stored in a C structure,
199             called an SV (scalar value), which contains several slots. The important ones
200             for our purposes are:
201              
202             =over
203              
204             =item IV
205              
206             an integer value
207              
208             =item UV
209              
210             an unsigned integer value, only used for ints > MAXINT / 2.
211              
212             =item NV
213              
214             a numeric value (ie a float)
215              
216             =item PV
217              
218             a pointer value (ie a string)
219              
220             =back
221              
222             When a value is created one of those slots will be filled. As various
223             operations are done on a value the slot's contents may change, and other
224             slots may be filled.
225              
226             For example:
227              
228             my $foo = "4"; # fill $foo's PV slot, as "4" is a string
229              
230             my $bar = $foo + 1; # fill $bar's IV slot, as 4 + 1 is an int,
231             # and fill $foo's IV slot, as we had to figure
232             # out the numeric value of the string
233              
234             $foo = "lemon"; # fill $foo's PV slot, as "lemon" is a string
235              
236             That last operation immediately shows a problem. C<$foo>'s IV slot was
237             filled with the integer value C<4>, but the assignment of the string
238             C<"lemon"> only filled the PV slot. So what's in the IV slot? There's a
239             handy tool for that, L, which is distributed with perl.
240             Here's part of Devel::Peek's output:
241              
242             $ perl -MDevel::Peek -E 'my $foo = 4; $foo = "lemon"; Dump($foo);'
243             IV = 4
244             PV = 0x7fe6e6c04c90 "lemon"\0
245              
246             So how, then, does perl know that even thought there's a value in the IV
247             slot it shouldn't be used? Because once you've assigned C<"lemon"> to
248             the variable you can't get that C<4> to show itself ever again, at least
249             not from pure perl code.
250              
251             The SV also has a flags field, which I missed out above. (I've also missed
252             out some of the flags here, I'm only showing you the relevant ones):
253              
254             $ perl -MDevel::Peek -E 'my $foo = 4; $foo = "lemon"; Dump($foo);'
255             FLAGS = (POK)
256             IV = 4
257             PV = 0x7fe6e6c04c90 "lemon"\0
258              
259             The C flag means, as you might have guessed, that the C slot has
260             valid contents - in case you're wondering, the C slot there contains
261             a pointer to the memory address C<0x7fe6e6c04c90>, at which can be found
262             the word C.
263              
264             It's possible to have multiple flags set. That's the case in the second
265             line of code in the example. In that example a variable contains the
266             string C<"4">, so the C slot is filled and the C flag is set. We
267             then take the value of that variable, add 1, and assign the result to
268             another variable. Obviously adding 1 to a string is meaningless, so the
269             string has to first be converted to a number. That fills the C slot:
270              
271             $ perl -MDevel::Peek -E 'my $foo = "4"; my $bar = $foo + 1; Dump($foo);'
272             FLAGS = (IOK,POK)
273             IV = 4
274             PV = 0x7fd6e7d05210 "4"\0
275              
276             Notice that there are now two flags. C means that the C slot's
277             contents are valid, and C that the C slot's contents are valid.
278             Why do we need both slots in this case? Because a non-numeric string such
279             as C<"lemon"> is treated as the integer C<0> if you perform numeric
280             operations on it.
281              
282             All that I have said above about Cs also applies to Cs, and you
283             will sometimes come across a variable with both the C and C slots
284             filled, or even all three:
285              
286             $ perl -MDevel::Peek -E 'my $foo = 1e2; my $bar = $foo + 0; $bar = $foo . ""; Dump($foo)'
287             FLAGS = (IOK,NOK,POK)
288             IV = 100
289             NV = 100
290             PV = 0x7f9ee9d12790 "100"\0
291              
292             Finally, it's possible to have multiple flags set even though the slots
293             contain what looks (to a human) like different values:
294              
295             $ perl -MDevel::Peek -E 'my $foo = "007"; $foo + 0; Dump($foo)'
296             FLAGS = (IOK,POK)
297             IV = 7
298             PV = 0x7fcf425046c0 "007"\0
299              
300             That code initialises the variable to the string C<"007">, then uses it
301             in a numeric operation. That causes the string to be numified, the C
302             slot to be filled, and the C flag set. It should, of course, be clear
303             to any fan of classic literature that "007" and 7 are very different things.
304             "007" is not an integer.
305              
306             =head3 Booleans
307              
308             In perl 5.35.7 and later, Boolean values - ie the results of comparisons -
309             have some extra magic. As well as their value, which is either C<1> (true,
310             an integer) or C<''> (false, an empty string), they have a flag to indicate
311             their Booleanness. This is exposed via the C perl function
312             so we don't need to do XS voodoo to interrogate it.
313              
314             =head2 WHAT Scalar::Type DOES (at least in version 0.1.0)
315              
316             NB that this section documents an internal function that is not intended
317             for public use. The interface of C<_scalar_type> should be considered to
318             be unstable, not fit for human consumption, and subject to change without
319             notice. This documentation is correct as of version 0.1.0 but may not be
320             updated for future versions - its purpose is pedagogical only.
321              
322             The C functions are just wrappers around the C function. That
323             in turn delegates most of the work to a few lines of C code which grovel
324             around looking at the contents of the individual slots and flags. That
325             function isn't exported, but if you really want to call it directly it's
326             called C<_scalar_type> and will return one of four strings, C,
327             C, or C. It will return C even for a reference or
328             undef, which is why I said that the C function only *mostly* wraps
329             around it :-)
330              
331             The first thing that C<_scalar_type> does is look at the C flag.
332             If it's set, and the C flag is not set, the it returns C.
333             If C and C are set it stringifies the contents of the C slot,
334             compares to the contents of the C slot, and returns C if
335             they are the same, or C otherwise.
336              
337             The reason for jumping through those hoops is so that we can correctly
338             divine the type of C<"007"> in the last example above.
339              
340             If C isn't set we then look at C. That follows exactly the same
341             logic, looking also at C, and returning either C or C,
342             being careful about strings like C<"007.5">.
343              
344             If neither C nor C is set then we return C.
345              
346             And what about Cs? They are treated exactly the same as Cs, and a
347             variable with a valid C slot will have the B> flag set. It will
348             also have the C flag set, which we use to determine how to stringify
349             the number.
350              
351             =head1 SEE ALSO
352              
353             L in particular its C function.
354              
355             L if you have perl 5.35.7 or later.
356              
357             =head1 BUGS
358              
359             If you find any bugs please report them on Github, preferably with a test case.
360              
361             Integers that are specifed using exponential notation, such as if you say 1e2
362             instead of 100, are *not* internally treated as integers. The perl parser is
363             lazy and only bothers to convert them into an integer after you perform int-ish
364             operations on them, such as adding 0. Likewise if you add 0 to the thoroughly
365             non-numeric "100" perl will convert it to an integer. These edge cases are partly
366             why you almost certainly don't care about what this module does. If they irk
367             you, complain to p5p.
368              
369             =head1 FEEDBACK
370              
371             I welcome feedback about my code, especially constructive criticism.
372              
373             =head1 AUTHOR, COPYRIGHT and LICENCE
374              
375             Copyright 2021 David Cantrell EFE
376              
377             This software is free-as-in-speech software, and may be used,
378             distributed, and modified under the terms of either the GNU
379             General Public Licence version 2 or the Artistic Licence. It's
380             up to you which one you use. The full text of the licences can
381             be found in the files GPL2.txt and ARTISTIC.txt, respectively.
382              
383             =head1 CONSPIRACY
384              
385             This module is also free-as-in-mason software.
386              
387             =cut
388              
389             1;