line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Tie::Array::BoundedIndex; |
2
|
5
|
|
|
5
|
|
148404
|
use strict; |
|
5
|
|
|
|
|
11
|
|
|
5
|
|
|
|
|
199
|
|
3
|
5
|
|
|
5
|
|
28
|
use warnings; |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
169
|
|
4
|
5
|
|
|
5
|
|
31
|
use Carp; |
|
5
|
|
|
|
|
15
|
|
|
5
|
|
|
|
|
517
|
|
5
|
|
|
|
|
|
|
|
6
|
5
|
|
|
5
|
|
4716
|
use Tie::Array; |
|
5
|
|
|
|
|
6524
|
|
|
5
|
|
|
|
|
427
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = '0.06'; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
BEGIN |
11
|
|
|
|
|
|
|
{ |
12
|
5
|
|
|
5
|
|
11
|
$DB::single = 1; |
13
|
5
|
|
|
|
|
322
|
eval "require Attribute::Handlers"; |
14
|
5
|
50
|
|
|
|
43563
|
return if $@; |
15
|
5
|
|
|
|
|
47
|
Attribute::Handlers->import(autotie => { '__CALLER__::Bounded' |
16
|
|
|
|
|
|
|
=> __PACKAGE__ }); |
17
|
|
|
|
|
|
|
} |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# The underlying object contains the bounds and also an |
20
|
|
|
|
|
|
|
# inner object that is the result of tying an array to |
21
|
|
|
|
|
|
|
# Tie::StdArray. When the user performs an operation on |
22
|
|
|
|
|
|
|
# the array tied to this class, it is passed on to the |
23
|
|
|
|
|
|
|
# inner array after bounds checking and shifting the |
24
|
|
|
|
|
|
|
# indices so that the inner array's indices start at 0 |
25
|
|
|
|
|
|
|
# and go up to - |
26
|
|
|
|
|
|
|
sub TIEARRAY |
27
|
|
|
|
|
|
|
{ |
28
|
4
|
|
|
4
|
|
2358
|
my ($class, %arg) = @_; |
29
|
4
|
|
|
|
|
16
|
my ($upper, $lower) = delete @arg{qw(upper lower)}; |
30
|
4
|
50
|
|
|
|
14
|
croak "Illegal arguments in tie" if %arg; |
31
|
4
|
50
|
|
|
|
18
|
croak "No upper bound for array" unless defined $upper; |
32
|
|
|
|
|
|
|
|
33
|
4
|
|
100
|
|
|
22
|
$lower ||= 0; |
34
|
|
|
|
|
|
|
|
35
|
4
|
|
33
|
|
|
26
|
/\D/ and croak "Array bound '$_' must be integer" for ($upper, $lower); |
36
|
|
|
|
|
|
|
|
37
|
4
|
50
|
|
|
|
11
|
croak "Upper bound < lower bound" if $upper < $lower; |
38
|
|
|
|
|
|
|
|
39
|
4
|
|
|
|
|
5
|
my @array; |
40
|
4
|
|
|
|
|
23
|
my $inner = tie @array, 'Tie::StdArray'; |
41
|
|
|
|
|
|
|
|
42
|
4
|
|
|
|
|
80
|
return bless { upper => $upper, |
43
|
|
|
|
|
|
|
lower => $lower, |
44
|
|
|
|
|
|
|
inner => $inner |
45
|
|
|
|
|
|
|
}, $class; |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
# Delegate anything we haven't overridden to the inner array, |
49
|
|
|
|
|
|
|
# which, being tied to Tie::StdArray, knows what to do. |
50
|
|
|
|
|
|
|
# In this class we only need to implement methods that have |
51
|
|
|
|
|
|
|
# to adjust an array index. |
52
|
|
|
|
|
|
|
sub AUTOLOAD |
53
|
|
|
|
|
|
|
{ |
54
|
30
|
|
|
30
|
|
4388
|
(my $method = our $AUTOLOAD) =~ s/.*://; |
55
|
30
|
|
|
|
|
47
|
my $self = shift; |
56
|
30
|
|
|
|
|
663
|
$self->{inner}->$method(@_); |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
|
59
|
0
|
|
|
0
|
|
0
|
sub DESTROY { } |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
sub _bound_check |
62
|
|
|
|
|
|
|
{ |
63
|
37
|
|
|
37
|
|
44
|
my ($self, $index) = @_; |
64
|
37
|
|
|
|
|
39
|
my ($upper, $lower) = @{$self}{qw(upper lower)}; |
|
37
|
|
|
|
|
72
|
|
65
|
|
|
|
|
|
|
|
66
|
37
|
100
|
100
|
|
|
1097
|
croak "Index $index out of range [$lower, $upper]" |
67
|
|
|
|
|
|
|
if $index < $lower || $index > $upper; |
68
|
|
|
|
|
|
|
|
69
|
29
|
|
|
|
|
55
|
return $lower; # Convenience for several callers |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# Only need to implement methods that can increase the |
73
|
|
|
|
|
|
|
# size of the array or store outside the bounds. |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub STORE |
76
|
|
|
|
|
|
|
{ |
77
|
10
|
|
|
10
|
|
806
|
my ($self, $index, $value) = @_; |
78
|
10
|
|
|
|
|
21
|
my $lower = $self->_bound_check($index); |
79
|
7
|
|
|
|
|
25
|
$self->{inner}->STORE($index - $lower, $value); |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
sub FETCH |
83
|
|
|
|
|
|
|
{ |
84
|
16
|
|
|
16
|
|
1669
|
my ($self, $index) = @_; |
85
|
16
|
|
|
|
|
30
|
my $lower = $self->_bound_check($index); |
86
|
16
|
|
|
|
|
53
|
$self->{inner}->FETCH($index - $lower); |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
sub STORESIZE |
90
|
|
|
|
|
|
|
{ |
91
|
0
|
|
|
0
|
|
0
|
my ($self, $size) = @_; |
92
|
0
|
|
|
|
|
0
|
$self->_bound_check($size-1); |
93
|
0
|
|
|
|
|
0
|
$self->{inner}->STORESIZE($size); |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
sub EXTEND |
97
|
|
|
|
|
|
|
{ |
98
|
8
|
|
|
8
|
|
33
|
my ($self, $newsize) = @_; |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
# We may get called with a new size of 0, indicating that |
101
|
|
|
|
|
|
|
# the caller doesn't want to extend the array at all. |
102
|
|
|
|
|
|
|
# But since that would result in a bound check on |
103
|
|
|
|
|
|
|
# - 1, we return at that point since otherwise |
104
|
|
|
|
|
|
|
# we would generate an exception. Our arrays are |
105
|
|
|
|
|
|
|
# guaranteed to have at least one elenment in them. |
106
|
|
|
|
|
|
|
|
107
|
8
|
100
|
|
|
|
18
|
return unless $newsize; |
108
|
7
|
|
|
|
|
11
|
my $lower = $self->{lower}; |
109
|
7
|
|
|
|
|
16
|
$self->_bound_check($lower+$newsize-1); |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub PUSH |
113
|
|
|
|
|
|
|
{ |
114
|
4
|
|
|
4
|
|
1386
|
my ($self, @new) = @_; |
115
|
4
|
|
|
|
|
17
|
$self->EXTEND($self->FETCHSIZE + @new); |
116
|
2
|
|
|
|
|
9
|
$self->{inner}->PUSH(@new); |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
sub UNSHIFT |
120
|
|
|
|
|
|
|
{ |
121
|
1
|
|
|
1
|
|
67
|
my ($self, @new) = @_; |
122
|
1
|
|
|
|
|
9
|
$self->EXTEND($self->FETCHSIZE + @new); |
123
|
0
|
|
|
|
|
0
|
$self->{inner}->UNSHIFT(@new); |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub SPLICE |
127
|
|
|
|
|
|
|
{ |
128
|
4
|
|
|
4
|
|
2098
|
my $self = shift; |
129
|
4
|
|
|
|
|
8
|
my $lower = $self->{lower}; |
130
|
|
|
|
|
|
|
|
131
|
4
|
|
|
|
|
6
|
my $offset = shift; |
132
|
4
|
50
|
|
|
|
14
|
defined($offset) or $offset = $lower; |
133
|
|
|
|
|
|
|
|
134
|
4
|
|
|
|
|
16
|
my $size = $self->FETCHSIZE; |
135
|
|
|
|
|
|
|
|
136
|
4
|
50
|
|
|
|
24
|
$offset < 0 and $offset = $size + $lower - $offset; |
137
|
4
|
|
|
|
|
9
|
$self->_bound_check($offset); |
138
|
|
|
|
|
|
|
|
139
|
3
|
|
66
|
|
|
12
|
my $length = shift || $size - $offset + $lower; |
140
|
3
|
50
|
|
|
|
24
|
$length < 0 and $length = $lower + $size - $offset + $length; |
141
|
3
|
100
|
|
|
|
8
|
$length > $lower + $size - $offset and $length = $lower + $size - $offset; |
142
|
|
|
|
|
|
|
|
143
|
3
|
|
|
|
|
8
|
$self->EXTEND($size + @_ - $length); |
144
|
2
|
|
|
|
|
9
|
$self->{inner}->SPLICE($offset - $lower, $length, @_) |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
1; |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
__END__ |