/usr/local/CPAN/WAIT/WAIT/Document/Split.pm
# -*- Mode: Cperl -*-
# Split.pm --
# ITIID : $ITI$ $Header $__Header$
# Author : Ulrich Pfeifer
# Created On : Sun Sep 15 14:42:09 1996
# Last Modified By: Ulrich Pfeifer
# Last Modified On: Sun Nov 22 18:44:47 1998
# Language : CPerl
# Update Count : 66
# Status : Unknown, Use with caution!
#
# Copyright (c) 1996-1997, Ulrich Pfeifer
#
package WAIT::Document::Split;
@ISA = qw(WAIT::Document::Base);
require WAIT::Document::Base;
use FileHandle;
use strict;
#use diagnostics;
use Carp;
sub TIEHASH {
my $type = shift;
my $mode = shift;
my $regexp = shift;
my @files = grep -f $_, @_;
my $self = {Regexp => $regexp,
Mode => $mode,
Files => \@files};
bless $self, ref($type) || $type;
}
sub FETCH {
my $self = shift;
my $key = shift;
# cached ?
if (defined $self->{Key} and $self->{Key} eq $key) {
return $self->{Value};
}
my ($file, $start, $length) = split ' ', $key;
unless (defined $self->{File} and $self->{File} eq $file) {
$self->openfile($file) or return;
}
#$fh->seek($start, 0); #SEEK_SET);
$self->seek($start);
$self->{Key} = $key;
$self->{Value} = '';
$length = $self->{Fh}->read($self->{Value}, $length);
$self->{_pos} += $length;
$self->{Value};
}
# Emulate seek on gziped files.
sub seek {
my $self = shift;
my $pos = shift;
if ($self->{File} =~ /\.gz$/) {
my $buf = '';
if ($self->{_pos} < $pos) {
$self->{Fh}->read($buf,$pos - $self->{_pos});
$self->{_pos} = $pos;
} elsif ($self->{_pos} > $pos) {
my $file = $self->{File};
$self->closefile;
$self->openfile($file);
$self->{Fh}->read($buf,$pos);
$self->{_pos} = $pos;
} else {
1;
}
} else {
$self->{Fh}->seek($pos, 0); #SEEK_SET);
}
}
sub FIRSTKEY {
my $self = shift;
$self->{have} = [@{$self->{Files}}];
return undef unless $self->nextfile();
$self->NEXTKEY;
}
sub isopen {
my $self = shift;
exists $self->{Fh};
}
sub closefile {
my $self = shift;
if ($self->{Line}) {
delete $self->{Line};
}
if ($self->{Fh}) {
$self->{Fh}->close;
delete $self->{Fh};
delete $self->{File};
$self->{_pos} = 0;
}
}
sub openfile {
my $self = shift;
my $file = shift;
my $fh;
$self->closefile;
if ($file =~ /\.gz$/) {
$fh = new FileHandle "gzip -cd $file|";
} else {
$fh = new FileHandle "< $file";
}
unless (defined $fh) {
return undef;
}
$self->{_pos} = 0;
$self->{File} = $file;
$self->{Fh} = $fh;
}
sub close {
my $self = shift;
$self->closefile;
for (qw(have Key Value File)) {
delete $self->{$_} if exists $self->{$_};
}
}
sub nextfile {
my $self = shift;
my $file = shift @{$self->{have}};
return undef unless defined $file;
$self->openfile($file);
}
sub NEXTKEY {
my $self = shift;
my $line;
my $match;
$self->isopen || $self->nextfile || return(undef);
my $start = $self->{Fh}->tell;
if (defined $self->{Line}) {
$start -= length($self->{Line});
$self->{Value} = $self->{Line};
} else {
$self->{Value} = '';
}
my $fh = $self->{Fh};
while (defined($line = <$fh>)) {
if ($line =~ /$self->{Regexp}/) {
$match = 1;
if ($self->{Mode} =~ /end/i) {
$self->{Value} .= $line;
} elsif ($self->{Mode} =~ /start/i) {
$self->{Line} = $line;
}
last;
}
$self->{Value} .= $line;
}
my $length = length($self->{Value});
$self->{Key} = "$self->{File} $start $length";
unless ($match) { # EOF
$self->closefile;
}
$self->{Key};
}
1;