File Coverage

blib/lib/Tie/CArray.pm
Criterion Covered Total %
statement 103 135 76.3
branch 2 20 10.0
condition 2 5 40.0
subroutine 32 38 84.2
pod 4 5 80.0
total 143 203 70.4


line stmt bran cond sub pod time code
1             package Tie::CArray;
2             #
3             # "Better to do it in Perl than C." - from C::Dynalib.pm
4             #
5             # "Better do it in C than in Perl." - Tie::CArray.pm
6             #
7 4     4   36044 use strict;
  4         8  
  4         174  
8             local $^W = 1;
9 4     4   23 use Carp;
  4         8  
  4         664  
10 4     4   26 use vars qw( $VERSION @ISA );
  4         12  
  4         641  
11             require DynaLoader;
12             $VERSION = sprintf("%d.%02d", q$Revision: 0.15 $ =~ /(\d+)\.(\d+)/);
13             @ISA = qw( DynaLoader );
14              
15             =head1 NAME
16              
17             Tie::CArray - Space-efficient, typed, external C Arrays (Alpha)
18              
19             =head1 SYNOPSIS
20              
21             use Tie::CArray;
22             $dblarr = new Tie::CDoubleArray(10000);
23              
24             @values = (0..10000);
25             $dblarr = new Tie::CIntArray(10000,\@values);
26             ref $dblarr eq 'Tie::CIntArray' and
27             $dblarr->set(0,1) and
28             $dblarr->get(0) == 1;
29              
30             tie @array, 'Tie::CDoubleArray', 10000, \@values;
31             print $array[0], join ', ', @dbl[1..20];
32              
33             =head1 DESCRIPTION
34              
35             Several XS classes and methods to deal with typed, space-efficient
36             C arrays are provided. Range checked and tieable.
37              
38             There are hand-optimized, fast XS versions for the three basic C-types
39             array of I, I and I and some sequential aggregate types
40             int[2][], int[3][], int[4][], double[2][] and double[3][].
41              
42             This roughly reflects to:
43              
44             CArray
45             CIntArray int[]
46             CInt2Array int[][2]
47             CInt3Array int[][3]
48             CInt4Array int[][4]
49             CDoubleArray double[]
50             CDouble2Array double[][2]
51             CDouble3Array double[][3]
52             CStringArray *char[]
53              
54             Typed C arrays need about three times less space then untyped perl arrays.
55             Such as various computional geometry modules dealing with 10.000 - 200.000
56             double[3]. Modification is done in-place and preferably in bulk.
57              
58             It might also be easier to write XSUBs by converting the data to CArray's
59             before, pass this pointer to the C func, and handle the results in Perl
60             then.
61              
62             The Fetch/Store operations with tied arrays copy the scalars to perl
63             and back, so it shouldn't be abused for BIG data.
64              
65             Perl's safemalloc/safefree is used.
66              
67             =head1 EFFICIENT GROW
68              
69             CArray's are efficiently growable, which is needed for several
70             algorithms, such as placing extra sentinels at the end, adding
71             three points for a super-triangle for Delaunay triangulation, ...
72              
73             Extra space is always allocated to fit nicely into the page boundary,
74             defined by the system granularity.
75             For now it's 2048, half of the usual 4096, but this can be tweaked (e.g. for
76             many small arrays) in the C function freesize().
77              
78             =cut
79             bootstrap Tie::CArray $VERSION;
80              
81             # Preloaded methods go here.
82             package Tie::CArray;
83             require 5.006;
84 4     4   4328 use Tie::Array;
  4         6263  
  4         121  
85 4     4   27 use strict;
  4         9  
  4         139  
86 4     4   23 use vars qw(@ISA);
  4         6  
  4         152  
87 4     4   19 use Carp;
  4         8  
  4         315  
88             @ISA = qw(Tie::Array);
89              
90             # Mandatory methods defined only for the abstract class Tie::CArray,
91             # in terms of the autoloaded spezialized methods
92              
93             =pod
94              
95             =head1 CLASS METHODS
96              
97             =over 4
98              
99             =item new ( size, [ template, [ values ]] )
100              
101             The new method is provided for all classes, the optional arrayref initarg
102             applies only to the base C classes, not the aggregate.
103              
104             The constructor creates a new C object. For the C
105             classes the second optional argument is used to initialize it with an
106             array. The second argument may also be used by a seperate init call.
107             If the optionally provided values arrayref is shorter that the
108             allocated size, the rest will stay uninitialized.
109              
110             $D = new Tie::CDoubleArray( 1000, ,[0..999] );
111              
112             =cut
113              
114             # the whole rawclass issue is gone.
115             # only needed for Tie::CArray and the aggregate classes
116             # 0.12 added templates
117             sub new {
118 4     4   19 no strict 'refs';
  4         7  
  4         3025  
119 0     0 1 0 my $class = shift;
120             # Tie::CArray::new as virtual baseclass needs an additional second type arg.
121 0 0       0 $class = shift if $class eq 'Tie::CArray';
122 0         0 my $size = shift;
123             # the Tie::CArray arg initializer not, we have copy instead
124 0 0       0 confess "usage: new $class (size, [template, [values]])"
125             if $size =~ /\D/;
126 0         0 my $template = shift;
127 0         0 my $initval = shift;
128 0         0 $class =~ /(.*)(\d)(.*)/;
129 0 0       0 if ($2) {
130 0         0 $initval
131 0         0 ? bless( &{$1 . $3 . '::new'}($size * $2, $initval), $class)
132 0 0       0 : bless( &{$1 . $3 . '::new'}($size * $2), $class);
133             } else {
134 0         0 $initval
135 0         0 ? bless( &{$class . '::new'}($size, $initval), $class)
136 0 0       0 : bless( &{$class . '::new'}($size), $class);
137             }
138             }
139              
140             =pod
141              
142             =item len ()
143              
144             The len method returns the length of the array, 1+ the index of the
145             last element. To enlarge the array grow() should be used.
146              
147             $D = new Tie::CDoubleArray(5000);
148             for my $j (0 .. $D->len-1) { $D->set($_, 0.0)); }
149             $D->len; # => 5000
150              
151             =item get ( index )
152              
153             get returns the value at the given index, which will be scalar or a list.
154             Croaks with "index out of range" on wrong index.
155              
156             $I = new Tie::CIntArray(2,[0,1]);
157             print $I->get(1); # => 1
158             print $I->get(2);
159             => croak "index out of range"
160              
161             $I2 = new Tie::CInt2Array(2,[[0,1]]);
162             print $I->get(0); # => (0 1)
163              
164             =item set ( index, value )
165              
166             The set method is provided for all classes.
167             It changes the value at the given index.
168             The value should be either a scalar or an arrayref.
169             Croaks with "index out of range" on wrong index.
170             Returns nothing.
171              
172             $I = new Tie::CIntArray(100);
173             map { $I->set($_,$i[$_]) } (0..99);
174             $I->set(99,-1);
175             $I->set(100);
176             => "index out of range"
177              
178             $I2 = Tie::CInt2Array->new(2);
179             $I2->set(0, [1,0]);
180             $I2->set(1, [0,1]);
181              
182             =item list ()
183              
184             Returns the content of the flat array representation as arrayref.
185              
186             =item init ( ARRAYREF )
187              
188             Initializes the array with the values from the arrayref.
189             Returns nothing.
190              
191             This is the same as the second new argument.
192             If the provided values arrayref is shorter that the allocated size,
193             the rest will stay uninitialized.
194              
195             $I = Tie::CIntArray::new(100) ;
196             $I->init( [0..99] );
197              
198             =item grow ( n )
199              
200             Adds room for n elements to the array. These elements must be initialized
201             extra with set.
202             To support faster grow() a certain number of already pre-allocated items
203             at the end of the array will be used. (see free)
204             Returns nothing.
205              
206             =item delete ( index )
207              
208             Deletes the item at the given index. free is incremented and the remaining
209             array items are shifted.
210             Returns nothing.
211              
212             =item get_grouped_by ( size, index )
213              
214             Returns a list of subsequent values.
215             It returns a list of size indices starting at size * index.
216             This is useful to abuse the unstructured array as typed array of the
217             same type, such as *double[3] or *int[2].
218              
219             But this is normally not used since fast get methods are provided for the
220             sequential classes, and those methods can be used on flat arrays as well.
221             (Internally all sequential arrays are flat).
222              
223             Tie::CInt3Array::get($I,0) == $I->get_grouped_by(3,0)
224              
225             $ptr->get_grouped_by(2,4) returns the 4-th pair if the array is seen
226             as list of pairs.
227              
228             $ptr->get_grouped_by(3,$i) => (ptr[i*3] ptr[i*3+1] ptr[i*3+2] )
229              
230             =cut
231              
232             # support for structured data, such as typedef int[3] Triangle
233             # returns the i-th slice of length by
234             sub get_grouped_by ($$$) { #22.11.99 13:14
235 3     3 1 657 my $self = shift;
236 3         8 my $by = shift;
237 3         7 my $i = shift;
238 3         7 $i *= $by;
239 3         12 map { $self->get($i++) } (1 .. $by);
  6         88  
240             }
241              
242             # c++ like slice operator: start, size, stride
243             # => list of size items with stride interim offsets, matrix rows and cols
244             sub slice ($$$;$) {
245 8     8 1 73 my $self = shift;
246 8         12 my $start = shift;
247 8         10 my $size = shift;
248 8   100     34 my $stride = shift || 1;
249             # absolute offsets
250 20         95 map { $self->get($_) }
  20         31  
251 8         20 map { $start + ($_ * $stride) }
252             (0 .. $size-1);
253             }
254              
255             # SPLICE this, offset, length, LIST
256             # TIEARRAY perl slice operator
257             sub SLICE ($$$;$) {
258 0     0 0 0 my $self = shift;
259 0         0 my $offset = shift;
260 0         0 my $length = shift;
261 0         0 my @LIST = @_;
262 0 0       0 if (@_) {
263             # store
264 0         0 map { $self->set($offset + $_, $LIST[$_]) }
  0         0  
265             (0 .. $length-1);
266             } else {
267             # fetch
268 0         0 map { $self->get($offset + $_) } (0 .. $length-1);
  0         0  
269             }
270             }
271              
272             =pod
273              
274             =item slice ( start, size, [ stride=1 ] )
275              
276             C++ like slice operator on a flat array. - In contrast to get_grouped_by()
277             which semantics are as on a grouped array.
278              
279             Returns a list of size items, starting at start,
280             with interim offsets of stride which defaults to 1.
281             This is useful to return columns or rows of a flat matrix.
282              
283             $I = new Tie::CIntArray (9, [0..8]);
284             $I->slice ( 0, 3, 3 ); # 1st column
285             => (0 3 6)
286             $I->slice ( 0, 3, 1 ); # 1st row
287             => (0 1 2)
288             $I->get_grouped_by(3, 0);
289             => (0 1 2)
290              
291             =item isort ( [ cmpfunc ] )
292              
293             "Indirect sort" (numerically ascending only for now)
294              
295             Returns a fresh sorted index list of integers (0 .. len-1) resp. a
296             CIntArray object in scalar context.
297              
298             The optional cmpfunc argument is not yet implemented.
299              
300             =cut
301              
302             #03.12.99 12:00 init
303             sub isort {
304 3     3 1 10568 sort { $_[0]->get($a) <=> $_[0]->get($b) }
  417         1317  
305             (0 .. $_[0]->len()-1);
306             }
307              
308             =pod
309              
310             =item nreverse ()
311              
312             "Reverse in place". (The name comes from lisp, where `n' denotes the
313             destructive version).
314             Destructively swaps all array items. Returns nothing.
315              
316             To perform a copying reverse define
317              
318             sub reverse { nreverse($_[0]->copy()) }
319              
320             =back
321              
322             =head1 SOME SEQUENTIAL CLASSES and CONVERSION
323              
324             To mix and change parallel and sequential data structures, some sequential
325             types (int[2],int[3],int[4],double[2],double[3]) are derived from their
326             base classes with fast, hand-optimized get and set methods to return and
327             accept lists instead of scalars.
328              
329             The input argument must be an arrayref, the result will be an array in list
330             context and an arrayref in scalar context.
331              
332             Conversion
333              
334             The Arrays for Int2, Int3, Int4, Double2 and Double3
335             can also be converted from and to parallel base arrays with fast XS methods.
336             Parallel arrays are sometimes preferred over structured arrays, but delete/
337             insert of structures in parallel arrays is costly.
338              
339             # three parallel CIntArray's
340             $X = new Tie::CIntArray(1000);
341             $Y = new Tie::CIntArray(1000);
342             $Z = new Tie::CIntArray(1000);
343              
344             # copy to one sequential *int[3], new memory
345             $I = $X->ToInt3($Y,$Z);
346              
347             # or to an existing array
348             $I = new Tie::CIntArray(3000);
349             $I = $X->ToInt3($Y,$Z,$I);
350              
351             # copies back with allocating new memory
352             ($X, $Y, $Z) = $I->ToPar();
353              
354             # copies back with reusing some existing memory (not checked!)
355             ($X, $Y, $Z) = $I->ToPar($X,$Z); # Note: I3 will be fresh.
356              
357             =over 4
358              
359             =item ToPar ( SeqArray, [ Tie::CArray,... ] )
360              
361             This returns a list of Tie::CArray objects, copied from the sequential
362             object to plain parallel CArray objects. This is a fast slice.
363              
364             *int[2] => (*int, *int)
365              
366             Tie::CInt2Array::ToPar
367             Tie::CInt3Array::ToPar
368             Tie::CInt4Array::ToPar
369             Tie::CDouble2Array::ToPar
370             Tie::CDouble3Array::ToPar
371              
372             If the optional CArray args are given the memory for the returned objects are
373             not new allocated, the space from the given objects is used instead.
374              
375             =item To$Type$Num ( CArray, ..., [ CArray ] )
376              
377             This returns a sequential CArray object copied from the parallel objects
378             given as arguments to one sequential CArray. This is a fast map.
379              
380             *int, *int => *int[2]
381              
382             Tie::CIntArray::ToInt2
383             Tie::CIntArray::ToInt3
384             Tie::CIntArray::ToInt4
385             Tie::CDoubleArray::ToDouble2
386             Tie::CDoubleArray::ToDouble3
387              
388             If the last optional CArray arg is defined the memory for the returned
389             object is not new allocated, the space from the given object is used instead.
390              
391             =back
392              
393             =head1 ARBITRARY STRUCTURED ARRAYS, PACK-STYLE TEMPLATES (not yet)
394              
395             Some special sequential arrays are hand-optimized for speed but can hold only
396             limited data types (int[2] .. double[3]).
397              
398             To support arbitrary structured arrays a second template argument may be
399             provided which must be a arrayref of a hash, where its keys name the accessor
400             and the values pack-style letters.
401              
402             This does not work yet!
403              
404             tie @A, 'Tie::CArray', 200,
405             [ x => 'd',
406             y => 'd',
407             z => 'd',
408             attr => [ age => 'i',
409             dirty => 'i',
410             owner => 's' ],
411             refcount => 'i' ];
412             $A->init ...
413              
414             for (my $i = 0; $i < @A; $i++) {
415             printf("x,y,z: (%d %d %d),\nattr: (age=%d, dirty=%d, owner=%s)\nrefcount=%d",
416             $A[$i]->{x}, $A[$i]->{y}, $A[$i]->{z},
417             $A[$i]->{attr}->{age}, $A[$i]->{attr}->{dirty}, $A[$i]->{attr}->{owner},
418             $A[$i]->{refcount}
419             );
420             }
421              
422             tie @utmp, 'Tie::CArray', 100,
423             [ ut_type => 's',
424             ut_pid => 'i',
425             ut_line => 'a12',
426             ut_id => 'a4',
427             ut_user => 'a32',
428             ut_host => 'a256',
429             ut_exit => [ # struct exit_status
430             e_termination => 's',
431             e_exit => 's' ],
432             ut_session => 'l',
433             ut_tv => [ # struct timeval
434             tv_sec => 'l'
435             tv_usec => 'l' ],
436             ut_addr_v6 => 'l4',
437             pad => 'a20' ];
438              
439             The following subset of L template letters is supported:
440              
441             =over 4
442              
443             =item i
444              
445             signed integer (default)
446              
447             =item I
448              
449             unsigned integer
450              
451             =item c
452              
453             signed character (one byte integer)
454              
455             =item c
456              
457             unsigned character (one byte integer)
458              
459             =item s
460              
461             signed short integer
462              
463             =item S
464              
465             unsigned short integer
466              
467             =item n
468              
469             unsigned short integer in network byte order
470              
471             =item l
472              
473             signed long integer
474              
475             =item L
476              
477             unsigned long integer
478              
479             =item N
480              
481             unsigned long integer in network byte order
482              
483             =item q
484              
485             signed long long integer (long long/int64)
486              
487             (only if the system has quads and perl was compiled for 64 bit)
488              
489             =item Q
490              
491             unsigned long long integer (unsigned long long/uint64)
492              
493             (only if the system has quads and perl was compiled for 64 bit)
494              
495             =item L
496              
497             unsigned long integer
498              
499             =item f
500              
501             float
502              
503             =item d
504              
505             double
506              
507             =item aI
508              
509             fixed-length, null-padded ASCII string of length I
510              
511             =item AI
512              
513             fixed-length, space-padded ASCII string of length I
514              
515             =item ZI
516              
517             fixed-length, null-terminated ASCII string of length I
518              
519             =back
520              
521             =head1 INTERNAL METHODS
522              
523             =over 4
524              
525             =item DESTROY ()
526              
527             This used to crash on certain DEBUGGING perl's, but seems
528             to be okay now.
529             Returns nothing.
530              
531             =item Tie::CArray::itemsize ( )
532              
533             =item Tie::CStringArray::itemsize ( [index] )
534              
535             Returns the size in bytes per item stored in the array. This is only
536             used internally to optimize memory allocation and the free list.
537              
538             A CStringArray object accepts the optional index argument, which returns the
539             string length at the given index. Without argument it returns the size in
540             bytes of a char * pointer (which is 4 on 32 bit systems).
541              
542             =item copy ()
543              
544             Returns a freshly allocated copy of the array with the same contents.
545              
546             =item _freelen ()
547              
548             Internal only.
549             Returns the number of free elements at the end of the array.
550             If grow() needs less or equal than free elements to be added,
551             no new room will be allocated.
552              
553             This is primarly for performance measures.
554              
555             =back
556              
557             =cut
558              
559             # the specialized Array classes go here
560             # the Ptr classes are defined in the XS
561             package Tie::CIntArray;
562 4     4   25 use strict;
  4         7  
  4         133  
563 4     4   4448 use integer;
  4         47  
  4         165  
564 4     4   121 use vars qw(@ISA);
  4         9  
  4         158  
565 4     4   21 use Carp;
  4         8  
  4         303  
566             @ISA = qw( Tie::CArray );
567              
568             package Tie::CDoubleArray;
569 4     4   19 use strict;
  4         6  
  4         121  
570 4     4   34 no integer;
  4         6  
  4         16  
571 4     4   95 use vars qw(@ISA);
  4         6  
  4         153  
572 4     4   23 use Carp;
  4         6  
  4         261  
573             @ISA = qw( Tie::CArray );
574              
575             package Tie::CStringArray;
576 4     4   21 use strict;
  4         7  
  4         115  
577 4     4   19 use vars qw(@ISA);
  4         5  
  4         137  
578 4     4   18 use Carp;
  4         7  
  4         281  
579             @ISA = qw( Tie::CArray );
580              
581             # These will be autoloaded after testing.
582             # Autoload methods go after __END__, and are processed by the autosplit program.
583              
584             # Base aggregate class, purely virtual.
585             # get and set via get_grouped_by was 24 times slower than the XS version
586             # now. This is for the not so time-critical functions.
587             package Tie::CArray::CSeqBase;
588 4     4   28 use vars qw(@ISA);
  4         6  
  4         159  
589             @ISA = qw( Tie::CArray );
590 4     4   26 use Carp;
  4         6  
  4         3819  
591              
592 3     3   11 sub by { $_[0] =~ /(\d)/;
593 3         40 return $1; }
594 3     3   16 sub base { $_[0] =~ /^(Tie::.*)\d(.*)/;
595 3         27 return $1 . $2; }
596              
597             # size of item in bytes. this should be exported by the XS
598             # last resort, normally not needed
599             sub itemsize {
600 0   0 0   0 my $class = ref($_[0]) || $_[0];
601 0         0 $class =~ /^Tie::(.*)\d/;
602 0 0       0 if ($1 eq 'CInt') { $class->by * 4; }
  0 0       0  
603 0         0 elsif ($1 eq 'CDouble') { $class->by * 8; }
604 0         0 else { 0 }
605             }
606              
607 0     0   0 sub len () { $_[0]->SUPER::len / $_[0]->by };
608 0     0   0 sub free () { $_[0]->SUPER::free / $_[0]->by };
609              
610             sub new ($$;$) {
611 3     3   5860 my $class = shift;
612 3         7 my $n = shift;
613 3         5 my $init = shift;
614 3 50       15 croak "cannot call new Tie::CArray::CSeqBase"
615             if $class eq 'Tie::CArray::CSeqBase';
616 3 50       8 warn "cannot initialize Tie::CArray::CSeqBase: ignored" if $init;
617 3         23 bless ($class->base->new($n * $class->by), $class);
618             }
619              
620             # 24 times faster XSUB versions provided
621             #sub get ($$){
622             # my ($self,$i, $class) = @_;
623             # $class = ref $self;
624             # my $by = $self->by();
625             # bless ($self,$self->base); # downgrade to flat
626             # my @array = $self->get_grouped_by( $by, $i );
627             # bless ($self,$class); # upgrade it back
628             # return @array;
629             #}
630             #sub set ($$$){
631             # my ($self,$i,$val,$class) = @_;
632             # $class = ref $self;
633             # my $by = $self->by; $i *= $by;
634             # $self = bless ($self,$self->base);
635             # my @array = map { $self->set( $i++, $val->[$_] ) } (0 .. $by);
636             # $self = bless ($self,$class);
637             # return @array;
638             #}
639              
640             # the aggregate classes: just override the base methods
641             package Tie::CInt2Array;
642 4     4   28 use vars qw(@ISA);
  4         6  
  4         286  
643             @ISA = qw( Tie::CArray::CSeqBase Tie::CIntArray );
644              
645             package Tie::CInt3Array;
646 4     4   24 use vars qw(@ISA);
  4         8  
  4         195  
647             @ISA = qw( Tie::CArray::CSeqBase Tie::CIntArray );
648              
649             package Tie::CInt4Array;
650 4     4   18 use vars qw(@ISA);
  4         5  
  4         225  
651             @ISA = qw( Tie::CArray::CSeqBase Tie::CIntArray );
652              
653             package Tie::CDouble2Array;
654 4     4   18 use vars qw(@ISA);
  4         7  
  4         196  
655             @ISA = qw( Tie::CArray::CSeqBase Tie::CDoubleArray );
656              
657             package Tie::CDouble3Array;
658 4     4   19 use vars qw(@ISA);
  4         5  
  4         401  
659             @ISA = qw( Tie::CArray::CSeqBase Tie::CDoubleArray );
660              
661             #
662             ############################################################################
663              
664             =pod
665              
666             =head1 TIEARRAY METHODS
667              
668             B
669              
670             =over 4
671              
672             =item tie (var, type, size)
673              
674             After tying a array variable to an C class the variable can
675             be used just as any normal perl array.
676              
677             tie @array, 'Tie::CDoubleArray', 200;
678             print $array[200];
679             => croak "index out of range"
680              
681             =back
682              
683             =cut
684              
685             # The TIEARRAY stuff should be autoloaded (after testing)
686             package Tie::CArray;
687              
688 0     0     sub TIEARRAY { $_[0]->new(@_) }
689             #sub FETCH { $_[0]->get(@_) }
690             #sub FETCHSIZE { $_[0]->len() }
691             #sub STORE { $_[0]->set(@_) }
692              
693             # mandatory if elements can be added/deleted
694             # Note: we have a fast grow and delete method now
695             #sub STORESIZE {
696             # no strict 'refs';
697             # my $self = shift;
698             # my $newsize = shift;
699             # my $size = $self->len();
700             # my $rawclass = $self->rawclass();
701             # # or $self->PTR->set()
702             # my $setfunc = \&{"${rawclass}\:\:set"}();
703             # my $arrayptr = $self->PTR();
704             # if ($newsize > $size) {
705             # my $new = $self->new($size);
706             # my $newarray = $new->PTR();
707             # my $getfunc = \&{"${rawclass}\:\:get"}();
708             # # or $self->PTR->get()
709             # for my $i (0 .. $size-1) {
710             # &$setfunc($newarray, $i, &$getfunc($arrayptr,$i));
711             # }
712             # # or $self->PTR->DESTROY()
713             # $self->DESTROY();
714             # return $new;
715             # } else {
716             # for my $j ($newsize .. $size-1) { &$setfunc($arrayptr, $j, 0); }
717             # $self->len($newsize);
718             # return $self;
719             # }
720             #}
721              
722             1;
723             __END__