File Coverage

blib/lib/Hash/Objectify.pm
Criterion Covered Total %
statement 58 58 100.0
branch 16 16 100.0
condition 3 9 33.3
subroutine 13 14 92.8
pod n/a
total 90 97 92.7


line stmt bran cond sub pod time code
1 2     2   30235 use 5.008001;
  2         5  
2 2     2   6 use strict;
  2         2  
  2         29  
3 2     2   5 use warnings;
  2         1  
  2         67  
4              
5             package Hash::Objectify;
6              
7             # ABSTRACT: Create objects from hashes on the fly
8              
9             our $VERSION = '0.006';
10              
11 2     2   6 use Carp;
  2         2  
  2         77  
12 2     2   759 use Sub::Install;
  2         2229  
  2         5  
13 2     2   46 use Scalar::Util qw/blessed/;
  2         2  
  2         240  
14              
15             my %CACHE;
16             my $COUNTER = 0;
17              
18             sub import {
19 2     2   10 my ($class) = @_;
20 2         3 my $caller = caller;
21              
22             Sub::Install::install_sub(
23             {
24             code => sub {
25 11     11   3519 my ( $ref, $package ) = @_;
26 11         18 my $type = ref $ref;
27 11 100       22 unless ( $type eq 'HASH' ) {
28 3 100       14 $type =
    100          
29             $type eq '' ? "a scalar value"
30             : blessed($ref) ? "an object of class $type"
31             : "a reference of type $type";
32 3         307 croak "Error: Can't objectify $type";
33             }
34 8 100       10 if ( defined $package ) {
35 2     2   7 no strict 'refs';
  2         2  
  2         136  
36 2 100       13 @{ $package . '::ISA' } = 'Hash::Objectified'
  1         10  
37             unless $package->isa('Hash::Objectified');
38             }
39             else {
40 6         11 my ( $caller, undef, $line ) = caller;
41 6         19 my $cachekey = join "", sort keys %$ref;
42 6 100       13 if ( !defined $CACHE{$caller}{$line}{$cachekey} ) {
43 2     2   7 no strict 'refs';
  2         1  
  2         198  
44 5         9 $package = $CACHE{$caller}{$line}{$cachekey} = "Hash::Objectified$COUNTER";
45 5         6 $COUNTER++;
46 5         4 @{ $package . '::ISA' } = 'Hash::Objectified';
  5         49  
47             }
48             else {
49 1         2 $package = $CACHE{$caller}{$line}{$cachekey};
50             }
51             }
52 8         27 bless {%$ref}, $package;
53             },
54 2         12 into => $caller,
55             as => 'objectify',
56             }
57             );
58             }
59              
60             package Hash::Objectified;
61              
62 2     2   801 use Class::XSAccessor;
  2         3317  
  2         11  
63              
64             our $AUTOLOAD;
65              
66             sub can {
67 5     5   1185 my ( $self, $key ) = @_;
68 5 100 33     42 return undef unless ref $self && exists $self->{$key}; ## no critic
69 4         20 $self->$key; # install accessor if not installed
70 4         17 return $self->SUPER::can($key);
71             }
72              
73             sub AUTOLOAD {
74 6     6   1085 my $self = shift;
75 6         6 my $method = $AUTOLOAD;
76 6         21 $method =~ s/.*:://;
77 6 100 33     26 if ( ref $self && exists $self->{$method} ) {
78 5         21 Class::XSAccessor->import(
79             accessors => { $method => $method },
80             class => ref $self
81             );
82             }
83             else {
84 1   33     3 my $class = ref $self || $self;
85 1         9 die qq{Can't locate object method "$method" via package "$class"};
86             }
87 5         470 return $self->$method(@_);
88             }
89              
90       0     sub DESTROY { } # because we AUTOLOAD, we need this too
91              
92             1;
93              
94              
95             # vim: ts=4 sts=4 sw=4 et:
96              
97             __END__