File Coverage

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


line stmt bran cond sub pod time code
1             package
2             Var::Pairs::Pair_BuiltIn;
3              
4 20     20   7061 use strict;
  20         21  
  20         472  
5 20     20   64 use warnings;
  20         19  
  20         527  
6 20     20   8539 use experimental 'refaliasing';
  20         48777  
  20         88  
7              
8             # Class implementing each key/value pair...
9             # (aliasing via 5.22 built-in aliasing)
10             package Var::Pairs::Pair {
11 20     20   2377 use Scalar::Util qw< looks_like_number >;
  20         37  
  20         1515  
12              
13 20     20   72 use Carp;
  20         21  
  20         6400  
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 159     159   190 sub value :lvalue { $value_for[${shift()}] }
  159         360  
22 18     18   35 sub index { $key_for[${shift()}] }
  18         87  
23 89     89   2873 sub key { $key_for[${shift()}] }
  89         302  
24 6     6   13 sub kv { my $self = shift; $key_for[$$self], $value_for[$$self] }
  6         32  
25              
26             # The usual inside-out constructor...
27             sub new {
28 226     226   201 my ($class, $key, $container_ref, $container_type) = @_;
29              
30             # Create a scalar based object...
31 226         167 my $scalar = @key_for;
32 226         216 my $new_obj = bless \$scalar, $class;
33              
34             # Initialize its attributes (value needs to be an alias to the original)...
35 226         192 $key_for[$scalar] = $key;
36             \$value_for[$scalar] = $container_type eq 'array' ? \$container_ref->[$key]
37             : $container_type eq 'none' ? \$_[2]
38 226 100       336 : \$container_ref->{$key};
    100          
39 226         180 $freed[$scalar] = 0;
40              
41 226         423 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   28 my $self = shift;
49 15         20 my $value = $value_for[$$self];
50 15 100       54 $value = ref $value ? ref $value
    100          
51             : looks_like_number($value) ? $value
52             : qq{"$value"};
53 15         698 return "$key_for[$$self] => $value";
54             },
55              
56             # Can't numerify a pair (make it a hanging offence)...
57 9     9   2138 q{0+} => sub { croak "Can't convert Pair(".shift.") to a number" },
58              
59             # All pairs are true (just as in Perl 6)...
60 112     112   3572 q{bool} => sub { !!1 },
61              
62             # Everything else as normal...
63 20         181 fallback => 1,
64 20     20   18536 );
  20         14844  
65              
66             sub DESTROY {
67 226     226   7247 my $self = shift;
68              
69             # Mark current storage as reclaimable...
70 226         184 $freed[$$self] = 1;
71              
72             # Reclaim everything possible...
73 226 100       441 if ($freed[$#freed]) {
74 136         103 my $free_from = $#freed;
75 136   66     371 while ($free_from >= 0 && $freed[$free_from]) {
76 226         403 $free_from--;
77             }
78 136         145 splice @key_for, $free_from+1;
79 136         116 splice @value_for, $free_from+1;
80 136         349 splice @freed, $free_from+1;
81             }
82             }
83             }
84              
85             # Magic true value required at the end of a module...
86             1;