File Coverage

blib/lib/Class/Accessor/PackedString.pm
Criterion Covered Total %
statement 92 124 74.1
branch 17 40 42.5
condition 2 2 100.0
subroutine 5 6 83.3
pod n/a
total 116 172 67.4


line stmt bran cond sub pod time code
1             package Class::Accessor::PackedString;
2              
3             our $DATE = '2017-09-01'; # DATE
4             our $VERSION = '0.001'; # VERSION
5              
6             #IFUNBUILT
7             # use strict 'subs', 'vars';
8             # use warnings;
9             #END IFUNBUILT
10              
11             sub import {
12 3     3   675 my ($class0, $spec) = @_;
13 3         10 my $caller = caller();
14              
15 3         53 my $class = $caller;
16              
17             #IFUNBUILT
18             # no warnings 'redefine';
19             #END IFUNBUILT
20              
21 3         8 my $attrs = $spec->{accessors};
22              
23             # store list of accessors in the package
24             {
25             #IFUNBUILT
26             # no warnings 'once';
27             #END IFUNBUILT
28 3         5 %{"$class\::HAS_PACKED"} = %$attrs;
  3         11  
  3         20  
29             }
30              
31             # generate accessors
32 3         8 my %idx; # key = attribute name, value = index
33 3         5 my $pack_template = "";
34 3         17 for my $attr (sort keys %$attrs) {
35 7         14 $idx{$attr} = keys(%idx);
36 7         11 $pack_template .= $attrs->{$attr};
37             }
38 3         5 my $num_attrs = keys %$attrs;
39              
40 3         6 for my $attr (keys %$attrs) {
41 7         12 my $idx = $idx{$attr};
42 7         9 my $code_str = 'sub (;$) {';
43 7         13 $code_str .= qq( my \$self = shift;);
44 7         10 $code_str .= qq( my \@attrs = unpack("$pack_template", \$\$self););
45 7         14 $code_str .= qq( if (\@_) { \$attrs[$idx] = \$_[0]; \$\$self = pack("$pack_template", \@attrs) });
46 7         11 $code_str .= qq( return \$attrs[$idx];);
47 7         9 $code_str .= " }";
48             #print "D:accessor code for $attr: ", $code_str, "\n";
49 7 0   0   676 *{"$class\::$attr"} = eval $code_str;
  7 100       37  
  0 100       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0         0  
  4         45  
  4         16  
  4         11  
  2         4  
  2         5  
  4         17  
  4         946  
  4         21  
  4         12  
  2         6  
  2         8  
  4         19  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
50 7 50       33 die if $@;
51             }
52              
53             # generate constructor
54             {
55 3         6 my $code_str;
  3         5  
56 3         7 $code_str = 'sub { my ($class, %args) = @_;';
57 3         5 $code_str .= qq( no warnings 'uninitialized';);
58 3         9 $code_str .= qq( my \@attrs = map { undef } 1..$num_attrs;);
59 3         11 for my $attr (sort keys %$attrs) {
60 7         14 my $idx = $idx{$attr};
61 7         16 $code_str .= qq( if (exists \$args{'$attr'}) { \$attrs[$idx] = delete \$args{'$attr'} });
62             }
63 3         6 $code_str .= ' die "Unknown $class attributes in constructor: ".join(", ", sort keys %args) if keys %args;';
64 3         7 $code_str .= qq( my \$self = pack('$pack_template', \@attrs); bless \\\$self, '$class';);
65 3         6 $code_str .= ' }';
66              
67             #print "D:constructor code for class $class: ", $code_str, "\n";
68 3   100     12 my $constructor = $spec->{constructor} || "new";
69 3 50       6 unless (*{"$class\::$constructor"}{CODE}) {
  3         23  
70 1 50   1   9 *{"$class\::$constructor"} = eval $code_str;
  1 50   1   2  
  1 50   1   125  
  1 50   1   6  
  1 50       2  
  1 50       131  
  1 50       6  
  1 50       2  
  1 50       126  
  3 50       222  
  3         14  
  1         2494  
  1         3  
  2         6  
  1         5  
  1         3  
  1         4  
  1         2  
  1         4  
  1         4  
  1         5  
  1         1122  
  1         4  
  2         6  
  1         5  
  0         0  
  1         4  
  0         0  
  1         4  
  1         9  
  1         4  
  1         2396  
  1         4  
  3         7  
  1         5  
  1         4  
  1         4  
  1         3  
  1         3  
  1         3  
  1         4  
  1         7  
  1         5  
71 3 50       73 die if $@;
72             };
73             }
74             }
75              
76             1;
77             # ABSTRACT: Generate accessors/constructor for object that use pack()-ed string as storage backend
78              
79             __END__