use strict;
use warnings;
use Tie::Handle ();
package Tie::Handle::TimeStamp;
our @ISA = 'Tie::Handle';
sub wrap {
my ($class, $globref) = @_;
tie *$globref, $class, ">&=".fileno($globref);
}
sub TIEHANDLE {
my $class = shift;
my $fh = \do { local *HANDLE };
my $self = bless({
fh => $fh,
nl => 1,
}, $class);
$self->OPEN(@_) if (@_);
return $self;
}
sub EOF { return eof($_[0]{fh}) }
sub TELL { return tell($_[0]{fh}) }
sub FILENO { return fileno($_[0]{fh}) }
sub SEEK { return seek($_[0]{fh}, $_[1], $_[2]) } # hum...
sub CLOSE { return close($_[0]{fh}) }
sub BINMODE { return binmode($_[0]{fh}) }
sub OPEN {
my $self = $_[0];
$self->CLOSE if defined($self->FILENO);
return (@_ == 2
? open($self->{fh}, $_[1])
: open($self->{fh}, $_[1], $_[2])
);
}
sub WRITE {
my $self = $_[0];
my $len = $_[2];
my $text = substr($_[1], 0, $len);
return 1 unless $len;
my $fh = $self->{fh};
my $nl = $self->{nl};
my $lt;
local ($,, $\);
my $qsep = quotemeta($/);
while ($text =~ /((?:(?!$qsep).)*(?:($qsep)|(?!$qsep).))/gs) {
if ($nl) {
$lt ||= "[" . localtime() . "] ";
print $fh ($lt)
or return 0;
}
print $fh $1
or return 0;
$nl = !!$2;
}
$self->{nl} = $nl;
return 1;
}
1;
Note: Prints the time at which the caller started printing the line, not the time at which the caller finished printing the line.
Bug: Doesn't support zero length or undefined $/.
Bug: Doesn't properly detect the line ending if it's split over multiple prints.
Bug: Uses more memory than in should.
local $/ = '||'
print('a|'); print('|b||'); # [timestamp] a||b||
print('a||b||'); # [timestamp] a||[timestamp] b||
Update: Added paren that was accidently deleted after testing.
Update: Simplified through the use of regexp. Tested to be safe.
Update: Changed $/ to $\.
Update: Added error checking, but I'm not sure that I'm returning the right value on error.
Update: Re-added support for $len which was accidently removed when I switched to regexps. Unfortunately, a copy is now made of the text to print.
Update: Switched from "\n" to $\ for splitting.
|