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   9559 use strict;
  21         63  
  21         616  
5 21     21   108 use warnings;
  21         54  
  21         621  
6 21     21   9954 use experimental 'refaliasing';
  21         74334  
  21         118  
7              
8             # Class implementing each key/value pair...
9             # (aliasing via 5.22 built-in aliasing)
10             package Var::Pairs::Pair {
11 21     21   4103 use Scalar::Util qw< looks_like_number >;
  21         46  
  21         1067  
12              
13 21     21   134 use Carp;
  21         38  
  21         9689  
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   339 sub value :lvalue { $value_for[${shift()}] }
  169         515  
22 28     28   105 sub index { $key_for[${shift()}] }
  28         144  
23 89     89   3070 sub key { $key_for[${shift()}] }
  89         419  
24 6     6   22 sub kv { my $self = shift; $key_for[$$self], $value_for[$$self] }
  6         20  
25              
26             # The usual inside-out constructor...
27             sub new {
28 238     238   466 my ($class, $key, $container_ref, $container_type) = @_;
29              
30             # Create a scalar based object...
31 238         337 my $scalar = @key_for;
32 238         405 my $new_obj = bless \$scalar, $class;
33              
34             # Initialize its attributes (value needs to be an alias to the original)...
35 238         374 $key_for[$scalar] = $key;
36             \$value_for[$scalar] = $container_type eq 'array' ? \$container_ref->[$key]
37             : $container_type eq 'none' ? \$_[2]
38 238 100       506 : \$container_ref->{$key};
    100          
39 238         343 $freed[$scalar] = 0;
40              
41 238         621 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   45 my $self = shift;
49 15         31 my $value = $value_for[$$self];
50 15 100       74 $value = ref $value ? ref $value
    100          
51             : looks_like_number($value) ? $value
52             : qq{"$value"};
53 15         858 return "$key_for[$$self] => $value";
54             },
55              
56             # Can't numerify a pair (make it a hanging offence)...
57 9     9   3326 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   5557 q{bool} => sub { !!1 },
61              
62             # Everything else as normal...
63 21         237 fallback => 1,
64 21     21   25921 );
  21         20453  
65              
66             sub DESTROY {
67 238     238   9772 my $self = shift;
68              
69             # Mark current storage as reclaimable...
70 238         392 $freed[$$self] = 1;
71              
72             # Reclaim everything possible...
73 238 100       677 if ($freed[$#freed]) {
74 140         207 my $free_from = $#freed;
75 140   100     478 while ($free_from >= 0 && $freed[$free_from]) {
76 238         620 $free_from--;
77             }
78 140         250 splice @key_for, $free_from+1;
79 140         210 splice @value_for, $free_from+1;
80 140         954 splice @freed, $free_from+1;
81             }
82             }
83             }
84              
85             # Magic true value required at the end of a module...
86             1;