File Coverage

blib/lib/Tie/Array/PackedC.pm
Criterion Covered Total %
statement 156 245 63.6
branch 33 80 41.2
condition 4 12 33.3
subroutine 38 61 62.3
pod 5 6 83.3
total 236 404 58.4


line stmt bran cond sub pod time code
1             package Tie::Array::PackedC;
2 1     1   24061 use constant ALLOC=>1024;
  1         2  
  1         76  
3 1     1   4 use constant PACK=>'l!*';
  1         2  
  1         31  
4 1     1   11 no warnings;
  1         6  
  1         50  
5 1     1   4 use constant NULL=>pack PACK,"";
  1         2  
  1         45  
6 1     1   5 use constant SIZE=>length NULL;
  1         2  
  1         47  
7 1     1   5 use base qw(Tie::Array);
  1         3  
  1         1002  
8 1     1   1588 use strict;
  1         2  
  1         30  
9 1     1   5 use warnings;
  1         2  
  1         2324  
10             our $DEBUG;
11              
12             sub import {
13 2 100 66 2   6623 if (@_>1 and $_[1]=~/[A-Z]/ and $_[0] eq __PACKAGE__) {
      66        
14 1         4 my ($class,$name,$format,%args)=@_;
15 1 50       6 $format.="*" unless $format=~/\*$/;
16 1         4 my $new=$class."::".$name;
17 1 50       76 open my $f,"<",__FILE__ or die __FILE__ . "$!";
18 1         3 local $_=do {local $/="\n__END__\n"; scalar <$f>};
  1         7  
  1         51  
19 1         22 close $f;
20 1         15 s/(?<=package )\w+(::\w+)*;/$new;/;
21 1         11 s/(?<=PACK)\s*=>'.+';/=>'$format';/;
22 1 50       4 s/(?<=ALLOC)\s*=>.+;/=>$args{ALLOC};/ if $args{ALLOC};
23 1 50       3 s/(?<=SIZE)\s*=>.+;/=>$args{SIZE};/ if $args{SIZE};
24 1 50 0 1   10 eval "no warnings; $_";
  1 50 0 1   1  
  1 0   1   66  
  1 0   1   6  
  1 0   1   14  
  1 0   1   71  
  1 50   1   4  
  1 50   1   2  
  1 50   1   65  
  1 50   0   6  
  1 50   1   1  
  1 50   1   59  
  1 50   2   5  
  1 0   0   2  
  1 0   22   59  
  1 0   1   5  
  1 0   0   2  
  1 0   0   50  
  1 0   0   5  
  1 0   1   2  
  1     0   112  
  1     1   5  
  1     0   3  
  1     1   33  
  1     0   5  
  1     0   3  
  1     1   3644  
  1     0   97  
  0     0   0  
  0     0   0  
  0     0   0  
  1         3  
  1         8  
  1         7  
  1         3  
  1         5  
  1         369  
  1         4  
  1         10  
  2         14  
  0         0  
  0         0  
  22         96  
  22         60  
  22         127  
  1         398  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  1         3  
  1         7  
  1         4  
  1         4  
  1         5  
  0         0  
  0         0  
  0         0  
  0         0  
  1         5  
  1         5  
  0         0  
  1         4  
  1         3  
  1         11  
  0         0  
  0         0  
  1         6  
  1         5  
  1         8  
  1         5  
  0         0  
  0         0  
  1         2  
  1         5  
  1         3  
  1         3  
  1         2  
  1         3  
  1         29  
  1         2  
  1         9  
  1         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         2  
  1         10  
  1         4  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
25 1 50       6 warn $_ if $args{DEBUG};
26 1 50       21 $@ and die "Failed to build package $new!\n$@\n$_"
27             } else {
28 1         172 __PACKAGE__->export_to_level(1,@_);
29             }
30             }
31              
32              
33             our @ISA=qw(Exporter);
34             our $VERSION=0.03;
35             our @EXPORT_OK=qw(packed_array packed_array_string $DEBUG);
36              
37             my %count;
38             my %type;
39              
40             sub packed_array {
41 1     1 1 11 my (@a,$s);
42 1         10 tie @a,__PACKAGE__,$s,@_;
43 1         3 return \@a;
44             }
45              
46             sub packed_array_string {
47 0     0 1 0 my @a;
48 0         0 tie @a,__PACKAGE__,@_;
49 0         0 return \@a;
50             }
51              
52              
53 1     1 1 344 sub string { return substr ${$_[0]},0,$count{$_[0]}*SIZE };
  1         9  
54              
55             sub trim {
56             #printf STDERR "%d %d %d\n",$count{$_[0]},$count{$_[0]}*SIZE,length(${$_[0]});
57 1     1 1 358 substr ${$_[0]}, $count{$_[0]}*SIZE, length(${$_[0]}) - ($count{$_[0]}*SIZE), "";
  1         5  
  1         4  
58 1         4 return $_[0];
59             }
60              
61 0     0 0 0 sub reallen { return $count{$_[0]}*SIZE };
62              
63             sub hex_dump {
64 0     0 1 0 my @words=map { sprintf "%02x " x SIZE,unpack "C*",pack PACK,$_; } unpack PACK,${$_[0]};
  0         0  
  0         0  
65 0         0 for (my $ofs=0;$ofs<@words;$ofs+=4) {
66 0         0 printf "#%4d : %5d : %s\n",$ofs,$ofs*SIZE,join"| ",grep defined $_,@words[$ofs..$ofs+3]
67             }
68             }
69              
70              
71             sub DESTROY {
72 2     2   4 my $self=shift;
73 2         6 delete $count{$self};
74 2         109 delete $type{$self};
75             }
76              
77             sub _alloc {
78 3     3   7 my ($self,$size)=@_;
79 3 100       12 return if $size<$count{$self};
80 2         3 my $before=length($$self);
81 2         5 $count{$self}=$size;
82 2         4 my $alloc=int ($size * 1.2);
83 2         5 $alloc+=ALLOC - ($alloc % ALLOC);
84 2         40 $$self.=NULL x ( $alloc - length($$self)/SIZE );
85 2         4 my $after=length($$self);
86 2 50       7 warn "Resize. Reallen:".$self->reallen()." Len: $before -> $after\n" if $DEBUG;
87 2         4 $self;
88             }
89              
90              
91             sub TIEARRAY {
92 2     2   6 my ($class,$str,@args)=@_;
93 2 50       10 my $strref=@_>1 ? \$_[1] : \do{my $x};
  0         0  
94 2 100       8 $$strref="" unless defined $$strref;
95 2         6 my $self=bless $strref,$class;
96              
97              
98 2 50       15 length($$strref) % SIZE and Carp::confess <
99 0         0 Initialized with bad string length! Expecting multiples of @{[SIZE]} bytes,
  0         0  
100             got @{[length($$strref) % SIZE]} bytes extra.
101             BAD_LENGTH
102 2         9 $count{$self}=int length($$strref)/SIZE;
103             #preallocate a chunk of memory
104 2         7 $self->_alloc(scalar @args);
105 2         10 substr($$self,0,@args*SIZE,pack(PACK,@args));
106 2         8 $self;
107             }
108              
109             sub FETCH {
110 42     42   1722 my ($s,$o)=@_;
111 42 100       116 return undef if $o>=$count{$s};
112 41         191 return unpack(PACK,substr($$s,$o * SIZE,SIZE));
113             }
114              
115             sub STORE {
116 2     2   6 my ($s,$o,$v)=@_;
117 2 100       16 $s->_alloc($o+1) if length($$s)<($o+1)*SIZE;
118 2 100       11 $count{$s}=$o+1 if $count{$s}<=$o;
119 2         8 substr($$s,$o * SIZE,SIZE)=pack(PACK,$v);
120 2         8 $v
121             }
122              
123 6     6   1587 sub FETCHSIZE {$count{shift(@_)}}
124              
125             sub STORESIZE {
126 0     0   0 my ($s,$l)=@_;
127             #print "STORESIZE $l\n";
128 0         0 $s->_alloc($l+1);
129 0         0 substr($$s,int($l*SIZE/ALLOC+1)*ALLOC)='';
130 0         0 $s
131             }
132              
133             sub EXTEND {
134 0     0   0 my ($s,$l)=@_;
135 0         0 $s->STORESIZE($l);
136             }
137              
138             sub POP{
139 1     1   381 my ($s)=@_;
140 1 50       12 length($$s) ? unpack PACK,substr($$s,--$count{$s}*SIZE,SIZE,NULL) : undef
141             }
142              
143             sub PUSH{
144 1     1   4 my ($s,@args)=@_;
145 1 50       5 return unless @args;
146 1         5 my $tail=$count{$s}*SIZE;
147 1 50       6 if (($count{$s}+@args)*SIZE>length($$s)) {
148 0         0 $s->_alloc($count{$s}+@args);
149             } else {
150 1         4 $count{$s}+=@args;
151             }
152 1         10 substr($$s,$tail,@args*SIZE)=pack(PACK,@args);
153              
154             }
155              
156 0     0     sub CLEAR { ${$_[0]}=NULL x (ALLOC/SIZE); $count{$_[0]}=0 }
  0            
  0            
157              
158             sub SHIFT {
159 0     0     my ($s)=@_;
160 0 0         length($$s) ? unpack PACK,substr($$s,0,SIZE,'') : undef
161             }
162             sub UNSHIFT {
163 0     0     my ($s,@args)=@_;
164 0           $$s=pack(PACK,@args).$$s;
165             }
166              
167 0     0     sub EXISTS { $_[1] < $count{$_[0]} }
168             sub DELETE {
169 0     0     my ($s,$o)=@_;
170 0 0         return unless $o < $count{$s};
171 0           my $v=unpack PACK,substr($$s,$o * SIZE,SIZE);
172 0           substr($$s,$o * SIZE,SIZE,NULL);
173 0           return $v
174             }
175              
176             #sub SPLICE {
177             #
178             #}
179              
180             1;
181              
182              
183             __END__