xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/lib/Tie/Array.pm (revision 0:68f95e015346)
1*0Sstevel@tonic-gatepackage Tie::Array;
2*0Sstevel@tonic-gate
3*0Sstevel@tonic-gateuse 5.006_001;
4*0Sstevel@tonic-gateuse strict;
5*0Sstevel@tonic-gateuse Carp;
6*0Sstevel@tonic-gateour $VERSION = '1.03';
7*0Sstevel@tonic-gate
8*0Sstevel@tonic-gate# Pod documentation after __END__ below.
9*0Sstevel@tonic-gate
10*0Sstevel@tonic-gatesub DESTROY { }
11*0Sstevel@tonic-gatesub EXTEND  { }
12*0Sstevel@tonic-gatesub UNSHIFT { scalar shift->SPLICE(0,0,@_) }
13*0Sstevel@tonic-gatesub SHIFT { shift->SPLICE(0,1) }
14*0Sstevel@tonic-gatesub CLEAR   { shift->STORESIZE(0) }
15*0Sstevel@tonic-gate
16*0Sstevel@tonic-gatesub PUSH
17*0Sstevel@tonic-gate{
18*0Sstevel@tonic-gate my $obj = shift;
19*0Sstevel@tonic-gate my $i   = $obj->FETCHSIZE;
20*0Sstevel@tonic-gate $obj->STORE($i++, shift) while (@_);
21*0Sstevel@tonic-gate}
22*0Sstevel@tonic-gate
23*0Sstevel@tonic-gatesub POP
24*0Sstevel@tonic-gate{
25*0Sstevel@tonic-gate my $obj = shift;
26*0Sstevel@tonic-gate my $newsize = $obj->FETCHSIZE - 1;
27*0Sstevel@tonic-gate my $val;
28*0Sstevel@tonic-gate if ($newsize >= 0)
29*0Sstevel@tonic-gate  {
30*0Sstevel@tonic-gate   $val = $obj->FETCH($newsize);
31*0Sstevel@tonic-gate   $obj->STORESIZE($newsize);
32*0Sstevel@tonic-gate  }
33*0Sstevel@tonic-gate $val;
34*0Sstevel@tonic-gate}
35*0Sstevel@tonic-gate
36*0Sstevel@tonic-gatesub SPLICE {
37*0Sstevel@tonic-gate    my $obj = shift;
38*0Sstevel@tonic-gate    my $sz  = $obj->FETCHSIZE;
39*0Sstevel@tonic-gate    my $off = (@_) ? shift : 0;
40*0Sstevel@tonic-gate    $off += $sz if ($off < 0);
41*0Sstevel@tonic-gate    my $len = (@_) ? shift : $sz - $off;
42*0Sstevel@tonic-gate    $len += $sz - $off if $len < 0;
43*0Sstevel@tonic-gate    my @result;
44*0Sstevel@tonic-gate    for (my $i = 0; $i < $len; $i++) {
45*0Sstevel@tonic-gate        push(@result,$obj->FETCH($off+$i));
46*0Sstevel@tonic-gate    }
47*0Sstevel@tonic-gate    $off = $sz if $off > $sz;
48*0Sstevel@tonic-gate    $len -= $off + $len - $sz if $off + $len > $sz;
49*0Sstevel@tonic-gate    if (@_ > $len) {
50*0Sstevel@tonic-gate        # Move items up to make room
51*0Sstevel@tonic-gate        my $d = @_ - $len;
52*0Sstevel@tonic-gate        my $e = $off+$len;
53*0Sstevel@tonic-gate        $obj->EXTEND($sz+$d);
54*0Sstevel@tonic-gate        for (my $i=$sz-1; $i >= $e; $i--) {
55*0Sstevel@tonic-gate            my $val = $obj->FETCH($i);
56*0Sstevel@tonic-gate            $obj->STORE($i+$d,$val);
57*0Sstevel@tonic-gate        }
58*0Sstevel@tonic-gate    }
59*0Sstevel@tonic-gate    elsif (@_ < $len) {
60*0Sstevel@tonic-gate        # Move items down to close the gap
61*0Sstevel@tonic-gate        my $d = $len - @_;
62*0Sstevel@tonic-gate        my $e = $off+$len;
63*0Sstevel@tonic-gate        for (my $i=$off+$len; $i < $sz; $i++) {
64*0Sstevel@tonic-gate            my $val = $obj->FETCH($i);
65*0Sstevel@tonic-gate            $obj->STORE($i-$d,$val);
66*0Sstevel@tonic-gate        }
67*0Sstevel@tonic-gate        $obj->STORESIZE($sz-$d);
68*0Sstevel@tonic-gate    }
69*0Sstevel@tonic-gate    for (my $i=0; $i < @_; $i++) {
70*0Sstevel@tonic-gate        $obj->STORE($off+$i,$_[$i]);
71*0Sstevel@tonic-gate    }
72*0Sstevel@tonic-gate    return wantarray ? @result : pop @result;
73*0Sstevel@tonic-gate}
74*0Sstevel@tonic-gate
75*0Sstevel@tonic-gatesub EXISTS {
76*0Sstevel@tonic-gate    my $pkg = ref $_[0];
77*0Sstevel@tonic-gate    croak "$pkg doesn't define an EXISTS method";
78*0Sstevel@tonic-gate}
79*0Sstevel@tonic-gate
80*0Sstevel@tonic-gatesub DELETE {
81*0Sstevel@tonic-gate    my $pkg = ref $_[0];
82*0Sstevel@tonic-gate    croak "$pkg doesn't define a DELETE method";
83*0Sstevel@tonic-gate}
84*0Sstevel@tonic-gate
85*0Sstevel@tonic-gatepackage Tie::StdArray;
86*0Sstevel@tonic-gateuse vars qw(@ISA);
87*0Sstevel@tonic-gate@ISA = 'Tie::Array';
88*0Sstevel@tonic-gate
89*0Sstevel@tonic-gatesub TIEARRAY  { bless [], $_[0] }
90*0Sstevel@tonic-gatesub FETCHSIZE { scalar @{$_[0]} }
91*0Sstevel@tonic-gatesub STORESIZE { $#{$_[0]} = $_[1]-1 }
92*0Sstevel@tonic-gatesub STORE     { $_[0]->[$_[1]] = $_[2] }
93*0Sstevel@tonic-gatesub FETCH     { $_[0]->[$_[1]] }
94*0Sstevel@tonic-gatesub CLEAR     { @{$_[0]} = () }
95*0Sstevel@tonic-gatesub POP       { pop(@{$_[0]}) }
96*0Sstevel@tonic-gatesub PUSH      { my $o = shift; push(@$o,@_) }
97*0Sstevel@tonic-gatesub SHIFT     { shift(@{$_[0]}) }
98*0Sstevel@tonic-gatesub UNSHIFT   { my $o = shift; unshift(@$o,@_) }
99*0Sstevel@tonic-gatesub EXISTS    { exists $_[0]->[$_[1]] }
100*0Sstevel@tonic-gatesub DELETE    { delete $_[0]->[$_[1]] }
101*0Sstevel@tonic-gate
102*0Sstevel@tonic-gatesub SPLICE
103*0Sstevel@tonic-gate{
104*0Sstevel@tonic-gate my $ob  = shift;
105*0Sstevel@tonic-gate my $sz  = $ob->FETCHSIZE;
106*0Sstevel@tonic-gate my $off = @_ ? shift : 0;
107*0Sstevel@tonic-gate $off   += $sz if $off < 0;
108*0Sstevel@tonic-gate my $len = @_ ? shift : $sz-$off;
109*0Sstevel@tonic-gate return splice(@$ob,$off,$len,@_);
110*0Sstevel@tonic-gate}
111*0Sstevel@tonic-gate
112*0Sstevel@tonic-gate1;
113*0Sstevel@tonic-gate
114*0Sstevel@tonic-gate__END__
115*0Sstevel@tonic-gate
116*0Sstevel@tonic-gate=head1 NAME
117*0Sstevel@tonic-gate
118*0Sstevel@tonic-gateTie::Array - base class for tied arrays
119*0Sstevel@tonic-gate
120*0Sstevel@tonic-gate=head1 SYNOPSIS
121*0Sstevel@tonic-gate
122*0Sstevel@tonic-gate    package Tie::NewArray;
123*0Sstevel@tonic-gate    use Tie::Array;
124*0Sstevel@tonic-gate    @ISA = ('Tie::Array');
125*0Sstevel@tonic-gate
126*0Sstevel@tonic-gate    # mandatory methods
127*0Sstevel@tonic-gate    sub TIEARRAY { ... }
128*0Sstevel@tonic-gate    sub FETCH { ... }
129*0Sstevel@tonic-gate    sub FETCHSIZE { ... }
130*0Sstevel@tonic-gate
131*0Sstevel@tonic-gate    sub STORE { ... }        # mandatory if elements writeable
132*0Sstevel@tonic-gate    sub STORESIZE { ... }    # mandatory if elements can be added/deleted
133*0Sstevel@tonic-gate    sub EXISTS { ... }       # mandatory if exists() expected to work
134*0Sstevel@tonic-gate    sub DELETE { ... }       # mandatory if delete() expected to work
135*0Sstevel@tonic-gate
136*0Sstevel@tonic-gate    # optional methods - for efficiency
137*0Sstevel@tonic-gate    sub CLEAR { ... }
138*0Sstevel@tonic-gate    sub PUSH { ... }
139*0Sstevel@tonic-gate    sub POP { ... }
140*0Sstevel@tonic-gate    sub SHIFT { ... }
141*0Sstevel@tonic-gate    sub UNSHIFT { ... }
142*0Sstevel@tonic-gate    sub SPLICE { ... }
143*0Sstevel@tonic-gate    sub EXTEND { ... }
144*0Sstevel@tonic-gate    sub DESTROY { ... }
145*0Sstevel@tonic-gate
146*0Sstevel@tonic-gate    package Tie::NewStdArray;
147*0Sstevel@tonic-gate    use Tie::Array;
148*0Sstevel@tonic-gate
149*0Sstevel@tonic-gate    @ISA = ('Tie::StdArray');
150*0Sstevel@tonic-gate
151*0Sstevel@tonic-gate    # all methods provided by default
152*0Sstevel@tonic-gate
153*0Sstevel@tonic-gate    package main;
154*0Sstevel@tonic-gate
155*0Sstevel@tonic-gate    $object = tie @somearray,Tie::NewArray;
156*0Sstevel@tonic-gate    $object = tie @somearray,Tie::StdArray;
157*0Sstevel@tonic-gate    $object = tie @somearray,Tie::NewStdArray;
158*0Sstevel@tonic-gate
159*0Sstevel@tonic-gate
160*0Sstevel@tonic-gate
161*0Sstevel@tonic-gate=head1 DESCRIPTION
162*0Sstevel@tonic-gate
163*0Sstevel@tonic-gateThis module provides methods for array-tying classes. See
164*0Sstevel@tonic-gateL<perltie> for a list of the functions required in order to tie an array
165*0Sstevel@tonic-gateto a package. The basic B<Tie::Array> package provides stub C<DESTROY>,
166*0Sstevel@tonic-gateand C<EXTEND> methods that do nothing, stub C<DELETE> and C<EXISTS>
167*0Sstevel@tonic-gatemethods that croak() if the delete() or exists() builtins are ever called
168*0Sstevel@tonic-gateon the tied array, and implementations of C<PUSH>, C<POP>, C<SHIFT>,
169*0Sstevel@tonic-gateC<UNSHIFT>, C<SPLICE> and C<CLEAR> in terms of basic C<FETCH>, C<STORE>,
170*0Sstevel@tonic-gateC<FETCHSIZE>, C<STORESIZE>.
171*0Sstevel@tonic-gate
172*0Sstevel@tonic-gateThe B<Tie::StdArray> package provides efficient methods required for tied arrays
173*0Sstevel@tonic-gatewhich are implemented as blessed references to an "inner" perl array.
174*0Sstevel@tonic-gateIt inherits from B<Tie::Array>, and should cause tied arrays to behave exactly
175*0Sstevel@tonic-gatelike standard arrays, allowing for selective overloading of methods.
176*0Sstevel@tonic-gate
177*0Sstevel@tonic-gateFor developers wishing to write their own tied arrays, the required methods
178*0Sstevel@tonic-gateare briefly defined below. See the L<perltie> section for more detailed
179*0Sstevel@tonic-gatedescriptive, as well as example code:
180*0Sstevel@tonic-gate
181*0Sstevel@tonic-gate=over 4
182*0Sstevel@tonic-gate
183*0Sstevel@tonic-gate=item TIEARRAY classname, LIST
184*0Sstevel@tonic-gate
185*0Sstevel@tonic-gateThe class method is invoked by the command C<tie @array, classname>. Associates
186*0Sstevel@tonic-gatean array instance with the specified class. C<LIST> would represent
187*0Sstevel@tonic-gateadditional arguments (along the lines of L<AnyDBM_File> and compatriots) needed
188*0Sstevel@tonic-gateto complete the association. The method should return an object of a class which
189*0Sstevel@tonic-gateprovides the methods below.
190*0Sstevel@tonic-gate
191*0Sstevel@tonic-gate=item STORE this, index, value
192*0Sstevel@tonic-gate
193*0Sstevel@tonic-gateStore datum I<value> into I<index> for the tied array associated with
194*0Sstevel@tonic-gateobject I<this>. If this makes the array larger then
195*0Sstevel@tonic-gateclass's mapping of C<undef> should be returned for new positions.
196*0Sstevel@tonic-gate
197*0Sstevel@tonic-gate=item FETCH this, index
198*0Sstevel@tonic-gate
199*0Sstevel@tonic-gateRetrieve the datum in I<index> for the tied array associated with
200*0Sstevel@tonic-gateobject I<this>.
201*0Sstevel@tonic-gate
202*0Sstevel@tonic-gate=item FETCHSIZE this
203*0Sstevel@tonic-gate
204*0Sstevel@tonic-gateReturns the total number of items in the tied array associated with
205*0Sstevel@tonic-gateobject I<this>. (Equivalent to C<scalar(@array)>).
206*0Sstevel@tonic-gate
207*0Sstevel@tonic-gate=item STORESIZE this, count
208*0Sstevel@tonic-gate
209*0Sstevel@tonic-gateSets the total number of items in the tied array associated with
210*0Sstevel@tonic-gateobject I<this> to be I<count>. If this makes the array larger then
211*0Sstevel@tonic-gateclass's mapping of C<undef> should be returned for new positions.
212*0Sstevel@tonic-gateIf the array becomes smaller then entries beyond count should be
213*0Sstevel@tonic-gatedeleted.
214*0Sstevel@tonic-gate
215*0Sstevel@tonic-gate=item EXTEND this, count
216*0Sstevel@tonic-gate
217*0Sstevel@tonic-gateInformative call that array is likely to grow to have I<count> entries.
218*0Sstevel@tonic-gateCan be used to optimize allocation. This method need do nothing.
219*0Sstevel@tonic-gate
220*0Sstevel@tonic-gate=item EXISTS this, key
221*0Sstevel@tonic-gate
222*0Sstevel@tonic-gateVerify that the element at index I<key> exists in the tied array I<this>.
223*0Sstevel@tonic-gate
224*0Sstevel@tonic-gateThe B<Tie::Array> implementation is a stub that simply croaks.
225*0Sstevel@tonic-gate
226*0Sstevel@tonic-gate=item DELETE this, key
227*0Sstevel@tonic-gate
228*0Sstevel@tonic-gateDelete the element at index I<key> from the tied array I<this>.
229*0Sstevel@tonic-gate
230*0Sstevel@tonic-gateThe B<Tie::Array> implementation is a stub that simply croaks.
231*0Sstevel@tonic-gate
232*0Sstevel@tonic-gate=item CLEAR this
233*0Sstevel@tonic-gate
234*0Sstevel@tonic-gateClear (remove, delete, ...) all values from the tied array associated with
235*0Sstevel@tonic-gateobject I<this>.
236*0Sstevel@tonic-gate
237*0Sstevel@tonic-gate=item DESTROY this
238*0Sstevel@tonic-gate
239*0Sstevel@tonic-gateNormal object destructor method.
240*0Sstevel@tonic-gate
241*0Sstevel@tonic-gate=item PUSH this, LIST
242*0Sstevel@tonic-gate
243*0Sstevel@tonic-gateAppend elements of LIST to the array.
244*0Sstevel@tonic-gate
245*0Sstevel@tonic-gate=item POP this
246*0Sstevel@tonic-gate
247*0Sstevel@tonic-gateRemove last element of the array and return it.
248*0Sstevel@tonic-gate
249*0Sstevel@tonic-gate=item SHIFT this
250*0Sstevel@tonic-gate
251*0Sstevel@tonic-gateRemove the first element of the array (shifting other elements down)
252*0Sstevel@tonic-gateand return it.
253*0Sstevel@tonic-gate
254*0Sstevel@tonic-gate=item UNSHIFT this, LIST
255*0Sstevel@tonic-gate
256*0Sstevel@tonic-gateInsert LIST elements at the beginning of the array, moving existing elements
257*0Sstevel@tonic-gateup to make room.
258*0Sstevel@tonic-gate
259*0Sstevel@tonic-gate=item SPLICE this, offset, length, LIST
260*0Sstevel@tonic-gate
261*0Sstevel@tonic-gatePerform the equivalent of C<splice> on the array.
262*0Sstevel@tonic-gate
263*0Sstevel@tonic-gateI<offset> is optional and defaults to zero, negative values count back
264*0Sstevel@tonic-gatefrom the end of the array.
265*0Sstevel@tonic-gate
266*0Sstevel@tonic-gateI<length> is optional and defaults to rest of the array.
267*0Sstevel@tonic-gate
268*0Sstevel@tonic-gateI<LIST> may be empty.
269*0Sstevel@tonic-gate
270*0Sstevel@tonic-gateReturns a list of the original I<length> elements at I<offset>.
271*0Sstevel@tonic-gate
272*0Sstevel@tonic-gate=back
273*0Sstevel@tonic-gate
274*0Sstevel@tonic-gate=head1 CAVEATS
275*0Sstevel@tonic-gate
276*0Sstevel@tonic-gateThere is no support at present for tied @ISA. There is a potential conflict
277*0Sstevel@tonic-gatebetween magic entries needed to notice setting of @ISA, and those needed to
278*0Sstevel@tonic-gateimplement 'tie'.
279*0Sstevel@tonic-gate
280*0Sstevel@tonic-gateVery little consideration has been given to the behaviour of tied arrays
281*0Sstevel@tonic-gatewhen C<$[> is not default value of zero.
282*0Sstevel@tonic-gate
283*0Sstevel@tonic-gate=head1 AUTHOR
284*0Sstevel@tonic-gate
285*0Sstevel@tonic-gateNick Ing-Simmons E<lt>nik@tiuk.ti.comE<gt>
286*0Sstevel@tonic-gate
287*0Sstevel@tonic-gate=cut
288