package StringHandle;
use strict;
use warnings;
use Carp;
## NOTE: This is basically just a proof-of-concept. It implements
## just enough to allow a StringHandle to be used as the filehandle
## argument to SVN::Client::cat without getting bogged down in
## annoying questions of robustness. Use at your own risk.
## WARNING: Although as currently implemented, this code seems to
## allow or even encourage mixed WRITES and reads, don't do that (see
## the comments in the implementation of READLINE).
## The comments prefixed with "#*" are quoted from the perltie
## manpage, which should be consulted for the details.
#*TIEHANDLE classname, LIST
#* This is the constructor for the class. That means it is expected
#* to return a blessed reference of some sort. The reference can be
#* used to hold some internal information.
sub TIEHANDLE {
my $class = shift;
my $self = {
lines => [],
buffer => undef,
};
return bless $self, $class;
}
#*WRITE this, LIST
#* This method will be called when the handle is written to via the
#* "syswrite" function.
sub WRITE {
my $self = shift;
my $buf = shift;
my $len = shift;
my $off = shift || 0;
my $data = substr($buf, $off, $len);
$self->{buffer} .= $data;
return length $data;
}
#*PRINT this, LIST
#* This method will be triggered every time the tied handle is
#* printed to with the "print()" function. Beyond its self reference
#* it also expects the list that was passed to the print function.
sub PRINT {
my $self = shift;
my $data = join($,, @_) . $\;
$self->{buffer} .= $data;
return 1;
}
#*PRINTF this, LIST
#* This method will be triggered every time the tied handle is
#* printed to with the "printf()" function. Beyond its self refer-
#* ence it also expects the format and list that was passed to the
#* printf function.
sub PRINTF {
my $self = shift;
my $fmt = shift;
my $data = sprintf($fmt, @_);
$self->{buffer} .= $data;
return 1;
}
#*READ this, LIST
#* This method will be called when the handle is read from via the
#* "read" or "sysread" functions.
sub READ {
my $self = shift;
croak "READ not implemented";
}
#*READLINE this
#* This method will be called when the handle is read from via <HAN-
#* DLE>. The method should return undef when there is no more data.
sub READLINE {
my $self = shift;
if (defined $self->{buffer}) {
## BUG: If the buffer doesn't end in a record separator, this
## will result in a line getting broken in two. But as long
## as you write all data to the filehandle before trying to
## read, you should be ok.
push @{ $self->{lines} }, split $/, $self->{buffer};
$self->{buffer} = undef;
}
return wantarray ? @{ $self->{lines} } : shift @{ $self->{lines} };
}
#*GETC this
#* This method will be called when the "getc" function is called.
sub GETC {
croak "GETC not implemented";
}
#*CLOSE this
#* This method will be called when the handle is closed via the
#* "close" function.
sub CLOSE {
return 1;
}
#*UNTIE this
#* As with the other types of ties, this method will be called when
#* "untie" happens. It may be appropriate to "auto CLOSE" when this
#* occurs. See "The "untie" Gotcha" below.
#*DESTROY this
#* As with the other types of ties, this method will be called when
#* the tied handle is about to be destroyed. This is useful for
#* debugging and possibly cleaning up.
sub DESTROY {
my $self = shift;
}
1;
__END__
> Mailing-List: contact users-help@subversion.tigris.org; run by ezmlm
> Date: Thu, 18 May 2006 15:12:55 +0300
> From: Saku Ytti <saku+svn@ytti.fi>
> Content-Disposition: inline
>
> On (2006-05-18 13:47 +0200), Anders J. Munch wrote:
>
> > So what's a FILEHANDLE in perl? Can it be some sort of virtual file
> > that when written to builds up a string (like stringstream in C++ or
> > StringIO in python)? If it absolutely has to be an integer that
> > refers to some OS-level resource, you could perhaps create a pipe for
> > that, using a second thread to read from the pipe.
>
> I asked this from some of our perl guys, they couldn't immediately
> think of a way how to get that FILEHANDLE to an array instead.
Perl filehandles are just barely object-oriented enough to allow this
to be done via the tie mechanism (see the perltie manpage). I
expected there to be something like this on CPAN, but a quick search
didn't turn anything up. So, I've attached a very simple class that
allows something like this to work:
#!/usr/bin/perl -w
use strict;
use warnings;
use StringHandle;
use SVN::Client;
my $SVN = SVN::Client->new();
tie(*FH, 'StringHandle');
my $target = 'http://svn.collab.net/repos/svn/trunk/README';
$SVN->cat(\*FH, $target, 'HEAD');
## This works:
my @lines = <FH>;
for my $line (@lines) {
print $line, "\n";
}
## and so does this:
## while (my $line = <FH>) {
## print $line, "\n";
## }
__END__
I doubt this will solve the entire problem for you, but hopefully it
will give you some ideas of how to proceed.
Cheers,
David.
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org
Received on Thu May 18 20:19:43 2006