File Coverage

blib/lib/Var/Pairs/Pair_BuiltIn.pm
Criterion Covered Total %
statement 48 48 100.0
branch 10 10 100.0
condition 3 3 100.0
subroutine 15 15 100.0
pod n/a
total 76 76 100.0


line stmt bran cond sub pod time code
1             package
2             Var::Pairs::Pair_BuiltIn;
3              
4 21     21   9942 use strict;
  21         58  
  21         667  
5 21     21   152 use warnings;
  21         47  
  21         735  
6 21     21   9949 use experimental 'refaliasing';
  21         77362  
  21         125  
7              
8             # Class implementing each key/value pair...
9             # (aliasing via 5.22 built-in aliasing)
10             package Var::Pairs::Pair {
11 21     21   3845 use Scalar::Util qw< looks_like_number >;
  21         119  
  21         1170  
12              
13 21     21   151 use Carp;
  21         50  
  21         9773  
14              
15             # Each pair object has two attributes...
16             my @key_for;
17             my @value_for;
18             my @freed;
19              
20             # Accessors for the attributes (value is read/write)...
21 169     169   278 sub value :lvalue { $value_for[${shift()}] }
  169         493  
22 28     28   86 sub index { $key_for[${shift()}] }
  28         167  
23 89     89   2865 sub key { $key_for[${shift()}] }
  89         408  
24 6     6   16 sub kv { my $self = shift; $key_for[$$self], $value_for[$$self] }
  6         18  
25              
26             # The usual inside-out constructor...
27             sub new {
28 238     238   424 my ($class, $key, $container_ref, $container_type) = @_;
29              
30             # Create a scalar based object...
31 238         313 my $scalar = @key_for;
32 238         356 my $new_obj = bless \$scalar, $class;
33              
34             # Initialize its attributes (value needs to be an alias to the original)...
35 238         331 $key_for[$scalar] = $key;
36             \$value_for[$scalar] = $container_type eq 'array' ? \$container_ref->[$key]
37             : $container_type eq 'none' ? \$_[2]
38 238 100       442 : \$container_ref->{$key};
    100          
39 238         315 $freed[$scalar] = 0;
40              
41 238         539 return $new_obj;
42             }
43              
44             # Type coercions...
45             use overload (
46             # As a string, a pair is just: key => value
47             q{""} => sub {
48 15     15   42 my $self = shift;
49 15         28 my $value = $value_for[$$self];
50 15 100       68 $value = ref $value ? ref $value
    100          
51             : looks_like_number($value) ? $value
52             : qq{"$value"};
53 15         870 return "$key_for[$$self] => $value";
54             },
55              
56             # Can't numerify a pair (make it a hanging offence)...
57 9     9   2852 q{0+} => sub { croak "Can't convert Pair(".shift.") to a number" },
58              
59             # All pairs are true (just as in Perl 6)...
60 122     122   4916 q{bool} => sub { !!1 },
61              
62             # Everything else as normal...
63 21         239 fallback => 1,
64 21     21   23734 );
  21         19663  
65              
66             sub DESTROY {
67 238     238   9905 my $self = shift;
68              
69             # Mark current storage as reclaimable...
70 238         369 $freed[$$self] = 1;
71              
72             # Reclaim everything possible...
73 238 100       612 if ($freed[$#freed]) {
74 140         187 my $free_from = $#freed;
75 140   100     451 while ($free_from >= 0 && $freed[$free_from]) {
76 238         585 $free_from--;
77             }
78 140         218 splice @key_for, $free_from+1;
79 140         215 splice @value_for, $free_from+1;
80 140         942 splice @freed, $free_from+1;
81             }
82             }
83             }
84              
85             # Magic true value required at the end of a module...
86             1;