# # $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) =head1 SYNOPSIS use OLE::Storage::Iolist(); s.b. =head1 DESCRIPTION B: 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!). 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 I<$num> = I<$IoL> -> max () Returns number of I<$IoL>'s entries. =item S 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 =head1 AUTHOR Martin Schwartz EFE =cut