#
# $Id: Iolist.pm,v 1.1.1.1 1998/02/25 21:13:00 schwartz Exp $
#
# Iolist
#
# Copyright (C) 1997, 1998 Martin Schwartz
#
# (POD documentation at end of file)
#
# Contact: schwartz@cs.tu-berlin.de
#
package OLE::Storage::Iolist;
use strict;
my $VERSION=do{my@R=('$Revision: 1.1.1.1 $'=~/\d+/g);sprintf"%d."."%d"x$#R,@R};
sub new {
my ($proto, $oR, $lR) = @_;
my $class = ref($proto) || $proto;
my $S = {
O => $oR || [],
L => $lR || []
};
bless ($S, $class);
}
sub dump {
my ($S) = @_;
if (@{$S->{O}}) {
print "Iolist = \n";
for (0..$#{$S->{O}}) {
printf " %03x: O=%6x L=%x\n", $_, $S->{O}->[$_], $S->{L}->[$_];
}
} else {
print "No Iolist.\n";
}
print "\n";
1}
sub append {
my ($S, $o, $l) = @_;
my $max = max($S);
my ($o1, $l1) = entry($S, $max) if $max!=-1;
if (($max==-1) || (($o1+$l1) != $o)) {
push ( @{$$S{O}}, $o );
push ( @{$$S{L}}, $l );
} else {
entry($S, $max, $o1, $l1+$l);
}
}
sub push {
my ($S, $sR) = @_;
if ($sR && $S) {
push ( @{$$S{O}}, @{$$sR{O}} );
push ( @{$$S{L}}, @{$$sR{L}} );
}
1}
sub entry {
my ($S, $i) = (shift, shift);
($$S{O}[$i], $$S{L}[$i]) = (shift, shift) if @_;
($$S{O}[$i], $$S{L}[$i]);
}
sub length {my ($S, $i) = (shift, shift); $$S{L}[$i] = shift if @_; $$S{L}[$i]}
sub offset {my ($S, $i) = (shift, shift); $$S{O}[$i] = shift if @_; $$S{O}[$i]}
sub max {my $S = shift; $#{$$S{O}} }
#
# ----- aggregate methods -----
#
sub sumlen {
my $S = shift;
my $size = 0;
for (@{$$S{L}}) {
$size += $_;
}
$size;
}
sub aggregate {
#
# $iolistO = aggregate (method)
#
# method:
# 1 @offsets shall be sorted, no overlap allowed
# 2 @offsets shall be sorted, overlap is allowed
# 3 @offsets are sorted, no overlap allowed
# 4 @offsets are sorted, overlap is allowed
#
my ($S, $method) = @_;
my $empty = $S->new();
return $empty if ($method<1)||($method>4); # Don't know method!
my ($o, $o1, $l, $l1);
my %o_in = ();
my $o_in = $S->new();
my $o_out = $S->new();
#
# Sort
#
if ( ($method==1) || ($method==2)) {
# sort offsets
for (0 .. $S->max()) {
($o, $l) = $S->entry($_);
next if !$l;
if (defined $o_in{$o}) {
return $empty if $method==1; # Data chunks overlap!
$o_in{$o}=$_ if $l>$o_in{$o};
} else {
$o_in{$o}=$_;
}
}
for (sort {$a <=> $b} keys %o_in) {
$o_in->append($S->entry($o_in{$_}));
}
} else {
$o_in = $S;
}
#
# Aggregate
#
($o, $l) = $o_in->entry(0);
for (1 .. $o_in->max()+1) {
($o1, $l1) = $o_in->entry($_);
if ( ($_==($o_in->max()+1))
|| ( $o1 < $o )
|| ( $o1 > ($o+$l) )
) {
$o_out->append($o, $l);
($o, $l) = ($o1, $l1);
} elsif ( $o1 < ($o+$l) ) {
return $empty if ($method==1 || $method==3); # Data chunks overlap!
if ( ($o1+$l1) > ($o+$l) ) {
$l=$o1+$l1-$o;
}
} else {
$l += $l1;
}
}
$o_out;
}
"Atomkraft? Nein, danke!"
__END__
=head1 NAME
OLE::Storage::Iolist - Data management for OLE::Storage::Io (I<alpha>)
=head1 SYNOPSIS
use OLE::Storage::Iolist();
s.b.
=head1 DESCRIPTION
B<Note>: OLE::Storage uses Iolists in conjuntion with Io interface for IO
operations. An IO entry is a two element list like (I<$offset>, I<$length>).
=over 4
=item aggregate
I<$NewIolist> = I<$IoL> -> aggregate (I<$method>)
Sorts and merges Iolist I<$IoL>, returns the new packed Iolist
I<$NewIolist>. Returns an empty Iolist on errors (!B<to be changed>!).
I<$method> can be:
method sort offsets allow offset overlaps
1 yes no
2 yes yes
3 no no
4 no yes
=item append
(I<$o1>, I<$l1>) == I<$IoL> -> append (I<$o>, I<$l>)
Appends an entry to Iolist. Tries to merge the Iolists last entry
with the new one. Returns the new last entry of Iolist.
=item entry
(I<$o>, I<$l>) = I<$IoL> -> entry (I<$i>)
rval: Get entry number I<$i>.
(I<$o>, I<$l>) == I<$IoL> -> entry (I<$i>, I<$o>, I<$l>)
lval: Set entry number I<$i> to (I<$o>, I<$l>).
Returns this entry.
=item length
(I<$l>) = I<$IoL> -> length (I<$i>)
rval: Get length of entry number I<$i>.
I<$l> == I<$IoL> -> length (I<$i>, I<$l>)
lval: Set length of entry number I<$i> to I<$l>. Returns I<$l>.
=item S<max >
I<$num> = I<$IoL> -> max ()
Returns number of I<$IoL>'s entries.
=item S<new >
I<$IoL> = new Iolist ([I<\@offset>, I<\@length>])
Iolist constructor. Returns an Iolist handle. Can be initialized with
references to corresponding offset and length lists.
=item offset
(I<$o>) = I<$IoL> -> offset (I<$i>)
rval: Get offset of entry number I<$i>.
I<$o> == I<$IoL> -> offset (I<$i>, I<$o>)
lval: Set offset of entry number I<$i> to I<$o>. Returns I<$o>.
=item push
C<1> == I<$IoL> -> push (I<$AnotherIolist>)
Appends all entries of I<$AnotherIolist> to I<$IoL>.
=item sumlen
I<$length> = I<$IoL> -> sumlen ()
Returns total length of I<$IoL>'s entries.
=back
=head1 SEE ALSO
L<OLE::Storage::Io>
=head1 AUTHOR
Martin Schwartz E<lt>F<schwartz@cs.tu-berlin.de>E<gt>
=cut