Interesting SEEK behavior on tied filehandle
GammaRay Rob
created: 2006-08-02 15:02:08
Hi Monks, my first post here; I've been lurking for some time, ever since I became a perl coder. I ran across something interesting today in the behavior of seek on a tied filehandle that I could not find in any documention or discussion on this wonderful site. A little background: I wrote a tied filehandle module to return records of binary science data. The records are indexed by time, so my SEEK function naturally accepts a time value; a *floating-point* time value: since the data are accumulated on millisecond scales. But things were not right; the seeks went awry. Why?

Because 'seek' is a perl function that magically accesses my own SEEK subroutine, but which *always* coerces its second argument (the first is the fh) to an integer! Do you doubt this? See the code below!

(btw: I fixed my little problem by multiplying the times in the argument list by 1000 and then dividing by same within SEEK.)

- GRR
#!/usr/bin/perl
use strict;
package myNull;

sub TIEHANDLE {
	my $class = shift;
	my $fh = local *FH;
	bless \$fh, $class;
}

sub SEEK {
	my $class = shift;
	my $offset = shift;
	my $whence = shift;
	print "SEEK: offset = $offset\n";
}
1;

perl -e 'use myNull; tie *null, "myNull"; seek null, 5.5, 0;'

SEEK: offset = 5

Re: Interesting SEEK behavior on tied filehandle
created: 2006-08-02 15:11:48

Call with an integer offset in ms rather than a float in seconds. Problem, if not solved, worked around fairly easily. :)

Re: Interesting SEEK behavior on tied filehandle
created: 2006-08-02 15:20:01
I noticed an interesting behavior with the READ function when you called read() on a tied filehandle. Since read() accepts 3 or 4 arguments, the code I was looking at (not mine) went something like:
sub READ {
  if ( @_ == 3 ) {
    # read into buffer
  } else {
    # read into buffer at offset
  }
It turned out that even if you called read() with 3 arguments, READ was always called with 4 arguments, and the 4th (the offset) was set to zero (which I admit makes sense, but it threw a warning about uninitialized value in [substr] in this particular case, and made the conditional pointless).
Re: Interesting SEEK behavior on tied filehandle (others)
tye
created: 2006-08-02 16:13:27

Many tie methods force their arguments into more regular forms. You can't get anything but non-negative integers for indices into tied arrays ($x[-1] calls $obj->FETCH( $obj->FETCHSIZE() -1 ), for example). You can't use nor return a list where you would usually have a scalar. And so on...

An exception appears to be that you can get more than just the string value for keys passed to tied hashes (and I suspect this was not always the case).

- tye        

Re^2: Interesting SEEK behavior on tied filehandle ($x[-@x-1])
created: 2006-08-02 16:29:16

I thought I might be able to pass a negative number to FETCH if the index was negative and bigger than the number of elements.

Turns out FETCH is not even called in that situation, even though FETCH *is* called for indexes greater than the highest existing index.

use Tie::Array qw( );
our @ISA = 'Tie::StdArray';

sub FETCH {
   my ($self, $idx) = @_;
   warn("Fetching index $idx\n");
   return $self->SUPER::FETCH($idx);
}

my @a;
tie @a, __PACKAGE__;
$#a = 4;

my $s;
$s = $a[-@a+1];  # Fetching index 1
$s = $a[-@a];    # Fetching index 0
$s = $a[-@a-1];  # FETCH not called!

$s = $a[@a];     # Fetching index 5

Perl 5.6.1 & 5.8.6

perlmonks.org content © perlmonks.org and Fletch, GammaRay Rob, ikegami, runrig, tye

prlmnks.org © 2006 edmund von der burg (eccles & toad)

v 0.03