| OLE-Storage documentation | Contained in the OLE-Storage distribution. |
OLE::Storage::Iolist - Data management for OLE::Storage::Io (alpha)
use OLE::Storage::Iolist();
s.b.
Note: OLE::Storage uses Iolists in conjuntion with Io interface for IO operations. An IO entry is a two element list like ($offset, $length).
$NewIolist = $IoL -> aggregate ($method)
Sorts and merges Iolist $IoL, returns the new packed Iolist $NewIolist. Returns an empty Iolist on errors (!to be changed!). $method can be:
method sort offsets allow offset overlaps 1 yes no 2 yes yes 3 no no 4 no yes
($o1, $l1) == $IoL -> append ($o, $l)
Appends an entry to Iolist. Tries to merge the Iolists last entry with the new one. Returns the new last entry of Iolist.
($o, $l) = $IoL -> entry ($i)
rval: Get entry number $i.
($o, $l) == $IoL -> entry ($i, $o, $l)
lval: Set entry number $i to ($o, $l). Returns this entry.
($l) = $IoL -> length ($i)
rval: Get length of entry number $i.
$l == $IoL -> length ($i, $l)
lval: Set length of entry number $i to $l. Returns $l.
$num = $IoL -> max ()
Returns number of $IoL's entries.
$IoL = new Iolist ([\@offset, \@length])
Iolist constructor. Returns an Iolist handle. Can be initialized with references to corresponding offset and length lists.
($o) = $IoL -> offset ($i)
rval: Get offset of entry number $i.
$o == $IoL -> offset ($i, $o)
lval: Set offset of entry number $i to $o. Returns $o.
1 == $IoL -> push ($AnotherIolist)
Appends all entries of $AnotherIolist to $IoL.
$length = $IoL -> sumlen ()
Returns total length of $IoL's entries.
Martin Schwartz <schwartz@cs.tu-berlin.de>
| OLE-Storage documentation | Contained in the OLE-Storage distribution. |
# # $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__