File Coverage

blib/lib/Class/Accessor/Array/Glob.pm
Criterion Covered Total %
statement 62 68 91.1
branch 18 36 50.0
condition 8 10 80.0
subroutine 7 7 100.0
pod n/a
total 95 121 78.5


line stmt bran cond sub pod time code
1             package Class::Accessor::Array::Glob;
2              
3             our $DATE = '2016-03-29'; # DATE
4             our $VERSION = '0.01'; # VERSION
5              
6 1     1   15008 use 5.010001;
  1         4  
7 1     1   3 use strict 'subs', 'vars';
  1         2  
  1         21  
8 1     1   3 use warnings;
  1         1  
  1         44  
9              
10             sub import {
11 2     2   279 my ($class0, $spec) = @_;
12 2         3 my $caller = caller();
13              
14 1     1   3 no warnings 'redefine';
  1         1  
  1         238  
15              
16 2         2 my $max_idx;
17 2         2 for (values %{$spec->{accessors}}) {
  2         5  
18 8 100 100     26 $max_idx = $_ if !defined($max_idx) || $max_idx < $_;
19             }
20              
21 2         3 my $glob_attribute = $spec->{glob_attribute};
22              
23             # generate accessors
24 2         2 for my $meth (keys %{$spec->{accessors}}) {
  2         4  
25 8         10 my $idx = $spec->{accessors}{$meth};
26 8         6 my $is = 'rw';
27 8 50       14 my $code_str = $is eq 'rw' ? 'sub (;$) { ' : 'sub () { ';
28 8 100 100     24 if (defined($glob_attribute) && $glob_attribute eq $meth) {
29 1 50       4 die "Glob attribute must be put at the last index"
30             unless $idx == $max_idx;
31 1 50       3 $code_str .= "splice(\@{\$_[0]}, $idx, scalar(\@{\$_[0]}), \@{\$_[1]}) if \@_ > 1; "
32             if $is eq 'rw';
33 1         2 $code_str .= "[ \@{\$_[0]}[$idx .. \$#{\$_[0]}] ]; ";
34             } else {
35 7 50       16 $code_str .= "\$_[0][$idx] = \$_[1] if \@_ > 1; "
36             if $is eq 'rw';
37 7         7 $code_str .= "\$_[0][$idx]; ";
38             }
39 8         7 $code_str .= "}";
40             #say "D:accessor code for $meth: ", $code_str;
41 8 50   1   563 *{"$caller\::$meth"} = eval $code_str;
  8 50       33  
  1 50       28  
  1 0       2  
  1 50       23  
  1 50       2  
  1 0       1  
  1 0       3  
  1         2  
  1         4  
  1         2  
  1         22  
  1         2  
  0         0  
  0         0  
  1         26  
  1         2  
  1         24  
  1         1  
  0         0  
  0         0  
  0         0  
  0         0  
42 8 50       17 die if $@;
43             }
44              
45             # generate constructor
46             {
47 2 100 50     2 my $n = ($max_idx // 0) + 1; $n-- if defined $glob_attribute;
  2         5  
  2         3  
48 2         4 my $code_str = 'sub { my $class = shift; bless [(undef) x '.$n.'], $class }';
49              
50             #say "D:constructor code for class $caller: ", $code_str;
51 2   50     6 my $constructor = $spec->{constructor} || "new";
52 2 50       3 unless (*{"$caller\::$constructor"}{CODE}) {
  2         7  
53 2     1   107 *{"$caller\::$constructor"} = eval $code_str;
  2         6  
  1         44  
  1         27  
  1         1773  
  1         4  
54 2 50       38 die if $@;
55             };
56             }
57             }
58              
59             1;
60             # ABSTRACT: Generate accessors/constructor for array-based object (supports globbing attribute)
61              
62             __END__