File Coverage

blib/lib/Const/Fast.pm
Criterion Covered Total %
statement 53 54 98.1
branch 21 26 80.7
condition 16 18 88.8
subroutine 10 10 100.0
pod 1 1 100.0
total 101 109 92.6


line stmt bran cond sub pod time code
1             package Const::Fast;
2             {
3             $Const::Fast::VERSION = '0.014';
4             }
5              
6 1     1   31324 use 5.008;
  1         4  
  1         39  
7 1     1   5 use strict;
  1         2  
  1         34  
8 1     1   6 use warnings FATAL => 'all';
  1         2  
  1         45  
9              
10 1     1   5 use Scalar::Util qw/reftype blessed/;
  1         2  
  1         114  
11 1     1   5 use Carp qw/croak/;
  1         2  
  1         76  
12 1     1   837 use Sub::Exporter::Progressive 0.001007 -setup => { exports => [qw/const/], groups => { default => [qw/const/] } };
  1         1597  
  1         13  
13              
14             sub _dclone($) {
15 1     1   1383 require Storable;
16 1     1   286 no warnings 'redefine';
  1         2  
  1         663  
17 1         6028 *_dclone = \&Storable::dclone;
18 1         113 goto &Storable::dclone;
19             }
20              
21             ## no critic (RequireArgUnpacking, ProhibitAmpersandSigils)
22             # The use of $_[0] is deliberate and essential, to be able to use it as an lvalue and to keep the refcount down.
23              
24             my %skip = map { $_ => 1 } qw/CODE GLOB/;
25              
26             sub _make_readonly {
27 55     55   84 my (undef, $dont_clone) = @_;
28 55 100 100     526 if (my $reftype = reftype $_[0] and not blessed($_[0]) and not &Internals::SvREADONLY($_[0])) {
      100        
29 25 50 66     81 $_[0] = _dclone($_[0]) if !$dont_clone && &Internals::SvREFCNT($_[0]) > 1 && !$skip{$reftype};
      66        
30 25         45 &Internals::SvREADONLY($_[0], 1);
31 25 100 100     340 if ($reftype eq 'SCALAR' || $reftype eq 'REF') {
    100          
    50          
32 14         17 _make_readonly(${ $_[0] }, 1);
  14         39  
33             }
34             elsif ($reftype eq 'ARRAY') {
35 3         4 _make_readonly($_) for @{ $_[0] };
  3         12  
36             }
37             elsif ($reftype eq 'HASH') {
38 8         19 &Internals::hv_clear_placeholders($_[0]);
39 8         10 _make_readonly($_) for values %{ $_[0] };
  8         34  
40             }
41             }
42 55         101 Internals::SvREADONLY($_[0], 1);
43 55         115 return;
44             }
45              
46             ## no critic (ProhibitSubroutinePrototypes, ManyArgs)
47             sub const(\[$@%]@) {
48 22     22 1 21735 my (undef, @args) = @_;
49 22 100       277 croak 'Invalid first argument, need an reference' if not defined reftype($_[0]);
50 21 100       458 croak 'Attempt to reassign a readonly variable' if &Internals::SvREADONLY($_[0]);
51 18 100 100     141 if (reftype $_[0] eq 'SCALAR' or reftype $_[0] eq 'REF') {
    100          
    50          
52 8 50       22 croak 'No value for readonly variable' if @args == 0;
53 8 50       20 croak 'Too many arguments in readonly assignment' if @args > 1;
54 8         9 ${ $_[0] } = $args[0];
  8         18  
55             }
56             elsif (reftype $_[0] eq 'ARRAY') {
57 3         6 @{ $_[0] } = @args;
  3         8  
58             }
59             elsif (reftype $_[0] eq 'HASH') {
60 7 100       193 croak 'Odd number of elements in hash assignment' if @args % 2;
61 6         12 %{ $_[0] } = @args;
  6         22  
62             }
63             else {
64 0         0 croak 'Can\'t make variable readonly';
65             }
66 17         40 _make_readonly($_[0], 1);
67 17         44 return;
68             }
69              
70             1; # End of Const::Fast
71              
72             # ABSTRACT: Facility for creating read-only scalars, arrays, and hashes
73              
74             __END__