line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Class::Accessor::PackedString::Set; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
our $DATE = '2017-10-15'; # 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
|
|
536
|
my ($class0, $spec) = @_; |
13
|
3
|
|
|
|
|
7
|
my $caller = caller(); |
14
|
|
|
|
|
|
|
|
15
|
3
|
|
|
|
|
42
|
my $class = $caller; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
#IFUNBUILT |
18
|
|
|
|
|
|
|
# no warnings 'redefine'; |
19
|
|
|
|
|
|
|
#END IFUNBUILT |
20
|
|
|
|
|
|
|
|
21
|
3
|
|
|
|
|
6
|
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
|
|
|
|
|
3
|
@{"$class\::HAS_PACKED"} = @$attrs; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
13
|
|
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# generate accessors |
32
|
3
|
|
|
|
|
7
|
my %idx ; # key = attribute name, value = index |
33
|
|
|
|
|
|
|
my %tmpl ; # key = attribute name, value = pack() template |
34
|
3
|
|
|
|
|
0
|
my %tmplsize; # key = attribute name, value = pack() data size |
35
|
3
|
|
|
|
|
6
|
my @attrs = @$attrs; |
36
|
3
|
|
|
|
|
10
|
while (my ($name, $template) = splice @attrs, 0, 2) { |
37
|
7
|
|
|
|
|
14
|
$idx{$name} = keys %idx; |
38
|
7
|
|
|
|
|
9
|
$tmpl{$name} = $template; |
39
|
7
|
|
|
|
|
27
|
$tmplsize{$name} = length(pack $template); |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
3
|
|
|
|
|
7
|
@attrs = @$attrs; |
43
|
3
|
|
|
|
|
8
|
while (my ($name, $template) = splice @attrs, 0, 2) { |
44
|
7
|
|
|
|
|
12
|
my $idx = $idx{$name}; |
45
|
7
|
|
|
|
|
11
|
my $code_str = 'sub (;$) {' . "\n"; |
46
|
7
|
|
|
|
|
10
|
$code_str .= qq( my \$self = shift;\n); |
47
|
|
|
|
|
|
|
|
48
|
7
|
|
|
|
|
9
|
$code_str .= qq( my \$val;\n my \$pos = 0;\n while (1) {\n last if \$pos >= length(\$\$self);\n my \$idx = ord(substr(\$\$self, \$pos++, 1));\n); |
49
|
7
|
|
|
|
|
23
|
for my $attr (sort {$idx{$a} <=> $idx{$b}} keys %idx) { |
|
13
|
|
|
|
|
32
|
|
50
|
17
|
|
|
|
|
21
|
my $idx = $idx{$attr}; |
51
|
17
|
100
|
|
|
|
48
|
$code_str .= qq| |.($idx == 0 ? "if " : "elsif").qq| (\$idx == $idx) { my \$v = unpack("| . $tmpl{$attr} . qq|", substr(\$\$self, \$pos, | . $tmplsize{$attr} . qq|));|; |
52
|
17
|
100
|
|
|
|
28
|
if ($attr eq $name) { |
53
|
7
|
|
|
|
|
14
|
$code_str .= qq| \$val = \$v; if (\@_ && defined \$_[0]) { substr(\$\$self, \$pos, | . $tmplsize{$attr} . qq|) = pack("| . $tmpl{$attr} . qq|", \$_[0]); return \$val } last|; |
54
|
|
|
|
|
|
|
} else { |
55
|
10
|
|
|
|
|
16
|
$code_str .= qq| \$pos += | . $tmplsize{$attr} . qq|; next|; |
56
|
|
|
|
|
|
|
} |
57
|
17
|
|
|
|
|
26
|
$code_str .= qq| }\n|; |
58
|
|
|
|
|
|
|
} |
59
|
7
|
|
|
|
|
12
|
$code_str .= qq( else { die "Invalid data in object \$self: invalid index \$idx" }\n); |
60
|
7
|
|
|
|
|
8
|
$code_str .= qq( }\n); |
61
|
|
|
|
|
|
|
|
62
|
7
|
|
|
|
|
9
|
$code_str .= qq( return \$val unless \@_;\n); |
63
|
7
|
|
|
|
|
11
|
$code_str .= qq( if (defined \$_[0]) {\n); # set a newly set attribute, append |
64
|
7
|
|
|
|
|
11
|
$code_str .= qq| \$\$self .= chr($idx) . pack("|. $tmpl{$name} . qq|", \$_[0]);\n|; |
65
|
7
|
|
|
|
|
11
|
$code_str .= qq( } elsif (defined \$val) {\n); # delete unset attribute |
66
|
7
|
|
|
|
|
10
|
$code_str .= qq| substr(\$\$self, \$pos-1, | . $tmplsize{$name} . qq|+1) = "";\n|; |
67
|
7
|
|
|
|
|
8
|
$code_str .= qq( }\n); |
68
|
7
|
|
|
|
|
10
|
$code_str .= qq( return \$val;\n); |
69
|
7
|
|
|
|
|
10
|
$code_str .= "}\n"; |
70
|
|
|
|
|
|
|
#print "D:accessor code for $name: ", $code_str, "\n"; |
71
|
7
|
50
|
0
|
1
|
|
1478
|
*{"$class\::$name"} = eval $code_str; |
|
7
|
0
|
0
|
|
|
34
|
|
|
1
|
0
|
100
|
|
|
23
|
|
|
1
|
0
|
0
|
|
|
2
|
|
|
1
|
0
|
0
|
|
|
2
|
|
|
1
|
50
|
0
|
|
|
2
|
|
|
1
|
50
|
100
|
|
|
8
|
|
|
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
|
100
|
|
|
|
0
|
|
|
0
|
100
|
|
|
|
0
|
|
|
0
|
100
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
100
|
|
|
|
0
|
|
|
0
|
100
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
1
|
0
|
|
|
|
3
|
|
|
1
|
0
|
|
|
|
4
|
|
|
1
|
0
|
|
|
|
5
|
|
|
0
|
0
|
|
|
|
0
|
|
|
1
|
0
|
|
|
|
2
|
|
|
0
|
0
|
|
|
|
0
|
|
|
0
|
0
|
|
|
|
0
|
|
|
0
|
100
|
|
|
|
0
|
|
|
0
|
0
|
|
|
|
0
|
|
|
0
|
100
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
0
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
0
|
|
|
|
0
|
|
|
0
|
100
|
|
|
|
0
|
|
|
0
|
0
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
0
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
0
|
0
|
|
|
|
0
|
|
|
0
|
100
|
|
|
|
0
|
|
|
0
|
100
|
|
|
|
0
|
|
|
0
|
100
|
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
|
6
|
100
|
|
|
|
13
|
|
|
6
|
100
|
|
|
|
9
|
|
|
6
|
50
|
|
|
|
8
|
|
|
6
|
|
|
|
|
11
|
|
|
10
|
|
|
|
|
20
|
|
|
8
|
|
|
|
|
15
|
|
|
8
|
|
|
|
|
19
|
|
|
4
|
|
|
|
|
11
|
|
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
14
|
|
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
2
|
|
|
3
|
|
|
|
|
5
|
|
|
0
|
|
|
|
|
0
|
|
|
5
|
|
|
|
|
18
|
|
|
2
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
4
|
|
|
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
|
|
|
1
|
|
|
|
|
26
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2
|
|
|
3
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
23
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
13
|
|
|
1
|
|
|
|
|
6
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
22
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
5
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
3
|
|
|
6
|
|
|
|
|
1294
|
|
|
6
|
|
|
|
|
10
|
|
|
6
|
|
|
|
|
8
|
|
|
6
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
20
|
|
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
17
|
|
|
4
|
|
|
|
|
12
|
|
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
16
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
3
|
|
|
3
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
3
|
|
|
0
|
|
|
|
|
0
|
|
|
5
|
|
|
|
|
23
|
|
|
2
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
5
|
|
72
|
7
|
50
|
|
|
|
34
|
die if $@; |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
# generate constructor |
76
|
|
|
|
|
|
|
{ |
77
|
3
|
|
|
|
|
5
|
my $code_str; |
|
3
|
|
|
|
|
3
|
|
78
|
|
|
|
|
|
|
|
79
|
3
|
|
|
|
|
5
|
$code_str = 'sub { my $o = ""; bless \$o, shift }'; |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
# TODO |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
#$code_str = 'sub { my ($class, %args) = @_;'; |
84
|
|
|
|
|
|
|
#$code_str .= qq( no warnings 'uninitialized';); |
85
|
|
|
|
|
|
|
#$code_str .= qq( my \@attrs = map { undef } 1..$num_attrs;); |
86
|
|
|
|
|
|
|
#for my $attr (sort keys %$attrs) { |
87
|
|
|
|
|
|
|
# my $idx = $idx{$attr}; |
88
|
|
|
|
|
|
|
# $code_str .= qq( if (exists \$args{'$attr'}) { \$attrs[$idx] = delete \$args{'$attr'} }); |
89
|
|
|
|
|
|
|
#} |
90
|
|
|
|
|
|
|
#$code_str .= ' die "Unknown $class attributes in constructor: ".join(", ", sort keys %args) if keys %args;'; |
91
|
|
|
|
|
|
|
#$code_str .= qq( my \$self = pack('$pack_template', \@attrs); bless \\\$self, '$class';); |
92
|
|
|
|
|
|
|
#$code_str .= ' }'; |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
#print "D:constructor code for class $class: ", $code_str, "\n"; |
95
|
3
|
|
100
|
|
|
12
|
my $constructor = $spec->{constructor} || "new"; |
96
|
3
|
50
|
|
|
|
5
|
unless (*{"$class\::$constructor"}{CODE}) { |
|
3
|
|
|
|
|
13
|
|
97
|
3
|
|
|
1
|
|
196
|
*{"$class\::$constructor"} = eval $code_str; |
|
3
|
|
|
|
|
10
|
|
|
1
|
|
|
|
|
974
|
|
|
1
|
|
|
|
|
4
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
2324
|
|
|
1
|
|
|
|
|
3
|
|
98
|
3
|
50
|
|
|
|
72
|
die if $@; |
99
|
|
|
|
|
|
|
}; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
1; |
104
|
|
|
|
|
|
|
# ABSTRACT: Like Class::Accessor::PackedString, but store attributes as they are set |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
__END__ |