File Coverage

blib/lib/Test/Stream/HashBase.pm
Criterion Covered Total %
statement 64 64 100.0
branch 13 16 81.2
condition 6 8 75.0
subroutine 14 14 100.0
pod 2 3 66.6
total 99 105 94.2


line stmt bran cond sub pod time code
1             package Test::Stream::HashBase;
2 109     109   671 use strict;
  109         101  
  109         2443  
3 109     109   305 use warnings;
  109         96  
  109         2371  
4              
5 109     109   362 use Carp qw/confess croak carp/;
  109         90  
  109         4937  
6 109     109   378 use Scalar::Util qw/blessed reftype/;
  109         105  
  109         14194  
7              
8             $Carp::Internal{(__PACKAGE__)}++;
9              
10             my (%META);
11              
12             sub import {
13 3958     3958   8964 my ($class, %args) = @_;
14              
15 3958   33     15900 my $into = $args{into} || caller;
16 3958   100     9962 my $meta = $META{$into} = $args{accessors} || [];
17              
18             # Use the comment to change the filename slightly so that Devel::Cover does
19             # not try to cover the contents of the string eval.
20 3958         4097 my $file = __FILE__;
21 3958         60664 $file =~ s/(\.*)$/.eval$1/;
22 3958         7678 my $eval = "# line 1 \"$file\"\npackage $into;\n";
23              
24 109     109   442 my $isa = do { no strict 'refs'; \@{"$into\::ISA"} };
  109         112  
  109         22903  
  3958         3032  
  3958         2802  
  3958         13008  
25              
26 3958 50       7750 if(my @bmetas = map { $META{$_} or () } @$isa) {
  2554 100       10734  
27 2554         2452 $eval .= "sub " . uc($_) . "() { '$_' };\n" for map { @{$_} } @bmetas;
  2554         1739  
  2554         14933  
28             }
29              
30 3958 100       7624 if(my $base = $args{base}) {
31 4         572 carp "'base' argument to HashBase is deprecated.";
32 4   100     302 my $bmeta = $META{$base} || croak "Base class '$base' is not a HashBase class";
33              
34 1 50       10 unless ($into->isa($base)) {
35 1         7 $eval .= "sub " . uc($_) . "() { '$_' };\n" for @$bmeta;
36 1         5 push @$isa => $base;
37             }
38             }
39              
40             {
41 3955         3083 $eval .= join '' => map {
42 3955         4594 my $const = uc($_);
  14601         11917  
43             <<" EOT"
44             sub $const() { '$_' }
45             sub $_ { \$_[0]->{'$_'} }
46             sub set_$_ { \$_[0]->{'$_'} = \$_[1] }
47             sub clear_$_ { delete \$_[0]->{'$_'} }
48             EOT
49 14601         44370 } @$meta;
50             }
51              
52 3955 50       1058186 eval "${eval}1;" || die $@;
53              
54 3955 100       60893 return if $args{no_new};
55              
56 109     109   394 no strict 'refs';
  109         106  
  109         25598  
57 3860         5090 *{"$into\::new"} = \&_new;
  3860         928734  
58             }
59              
60             sub _new {
61 17092     17092   34205 my ($class, %params) = @_;
62 17092         19152 my $self = bless \%params, $class;
63 17092 100       68953 $self->init if $self->can('init');
64 17055         34917 $self;
65             }
66              
67             sub gen_accessor {
68 50     50 1 531 my $class = shift;
69 50         61 my ($field) = @_;
70             sub {
71 168     168   329 my $self = shift;
72 168 100       361 ($self->{$field}) = @_ if @_;
73 168         529 $self->{$field};
74 50         193 };
75             }
76              
77             sub gen_getter {
78 7     7 1 11 my $class = shift;
79 7         9 my ($field) = @_;
80 7     9   32 sub { $_[0]->{$field} };
  9         27  
81             }
82              
83             sub gen_setter {
84 7     7 0 13 my $class = shift;
85 7         7 my ($field) = @_;
86 7     8   30 sub { $_[0]->{$field} = $_[1] };
  8         26  
87             }
88              
89             1;
90              
91             __END__