Mailing List Archive

Ken's SimpleFileHandle
OK, to try and cut through some of the FileHandle arguments, here is a
simple FileHandle module that I just wrote up. Extract to simpleFH.pm, and
try some code like this:

use simpleFH;

$f = new FileHandle;
$f->open(">foo");
print $f->opened(),"\n";
print $f "Hello, world!";
close($f);

I've had some specific goals in mind for this code: it is to be as simple
as possible, use as _little_ of the current POSIX/FileHandle mess as
possible, and be useful as an extensible starting point. Chip, I apologize
for not basing this on your patches, but I wanted to start with a
completely clean slate.

Folks, please take a look through the code below, and shout if you think
you couldn't live with it, or if things could be done better. (Please
excuse the missing seek(), tell(), incomplete open(), etc.)

---------------- simpleFH.pm ------------

package simpleFH;

sub import {};

package FileHandle;

# Symbolic utilities

$gensym = "SYM000";

sub gensym {
*{"FileHandle::" . $gensym++};
}

sub ungensym {
local($x) = shift;
$x =~ s/.*:://;
delete $FileHandle::{$x};
}


# Constructors/destructors

sub new {
my($type,@args) = @_;

local($glob) = gensym();
my($fh) = bless \$glob, $type;
local(*hash) = *$fh;

if(@args) {
$fh->open(@args);
}
return $fh;
}

sub DESTROY {
my($self) = @_;
local(*hash) = *$self;

$self->close() if $self->opened();
}


# Status members
sub opened {
my($self) = @_;
return 0+defined fileno $self;
}

sub filename {
my($self) = @_;
local(*hash) = *$self;

return $hash{filename};
}

sub mode {
my($self) = @_;
local(*hash) = *$self;

return $hash{mode};
}

sub deleteonclose {
my($self,@new) = @_;
local(*hash) = *$self;

my($result) = 0+ $hash{DeleteOnClose};

$hash{DeleteOnClose} = $new[0] if @new;

return $result;
}


# FileHandle operations

sub open {
my($self,@args) = @_;
local(*hash) = *$self;

if(@args == 1) {
my($n) = $args[0];
$n =~ s/^\+?(<|>|>>)//;
my($m) = $args[0];
$m = "write" if $m =~ /^>/;
$m = "read" if $m =~ /^</;
$m = "append" if $m =~ /^>>/;
$m = "update" if $m =~ /^\+>/;

$hash{filename} = $n;
$hash{mode} = $m;

return open($self,$args[0]);
} else {
die "Unknown calling style of FileHandle::Open";
}
}

sub close {
my($self) = @_;
local(*hash) = *$self;

close($self);

if( $hash{DeleteOnClose} ) {
unlink($hash{filename});
$hash{DeleteOnClose} = 0;
}
}

sub read {
my($self,$len) = @_;
my($result);

read($self,$result,$len) or return undef;

return $result;
}

sub print {
my($self,@args) = @_;

return (print $self @args);
}

sub socket {
my($self,@args) = @_;

return (socket($self,@args));
}

package File::Temporary;

$path = "/tmp/";

@ISA = qw(FileHandle);

sub new {
my($type) = @_;

my($self) = FileHandle::new($type);
local(*hash) = *$self;

my($file) = $path . $$ . "000";

do {
$file++ while -e $file;

# This is a kludge, and needs to be changed to proper atomic file
# creation

} while -e $file;

$self->open("+>$file");

$hash{DeleteOnClose} = 1;

return $self;
}

1;


--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
Re: Ken's SimpleFileHandle [ In reply to ]
: Folks, please take a look through the code below, and shout if you think
: you couldn't live with it, or if things could be done better. (Please
: excuse the missing seek(), tell(), incomplete open(), etc.)

You will never get DESTROY called unless you use the delete-immediately
trick. Here's what my POSIX.pm uses at the moment. Chip's Symbol patch
does something similar.

sub gensym {
my $pkg = @_ ? ref($_[0]) || $_[0] : "";
local *{$pkg . "::GLOB" . ++$seq};
\delete ${$pkg . "::"}{'GLOB' . $seq};
}

sub ungensym {
}

Note this generates a reference to a symbol, not a symbol. The ungensym
is there only for backward compatibility.

Larry
Re: Ken's SimpleFileHandle [ In reply to ]
On Wed, 25 Oct 1995, Larry Wall wrote:

> : Folks, please take a look through the code below, and shout if you think
> : you couldn't live with it, or if things could be done better. (Please
> : excuse the missing seek(), tell(), incomplete open(), etc.)
>
> You will never get DESTROY called unless you use the delete-immediately
> trick. Here's what my POSIX.pm uses at the moment. Chip's Symbol patch
> does something similar.

Ah, right, silly me.

> Larry
>

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
Re: Ken's SimpleFileHandle [ In reply to ]
On Wed, 25 Oct 1995, Tom Christiansen wrote:

> > OK, to try and cut through some of the FileHandle arguments, here is a
> > simple FileHandle module that I just wrote up. Extract to simpleFH.pm, and
> > try some code like this:
>
> just a quick initial reaction: let's not propogate a "simple" or "partial"
> solution too widely, and get the stuff in there that does sysopen and
> named args stuff before it makes it to the real world. i'm talkin about
> the 1, 2, 3, etc argument contstructors for new/open.

Fair enough.

> hm.. what about the aliases for
>
> -f is_regular_file
> -t is_tty
> -d is_directory
> -l is_symlink
> -S is_socket
> -p is_fifo
> -c is_block_device
> -c is_char_device
> -z is_zero_length
>
> -s file_size
> -e does_exist (silly on a filehandle?)

Yes. But this could shill for is_open(). I don't think -s will have a
rational meaning.

> -T is_text
> -B is_binary (better than isn't_text, eh? :-)

Agreed.

> -M modify_age
> -A access_age
> -C change_age

> -r i_can_read
> -w i_can_write
> -x i_can_execute
>
> -R I_can_read (or can_really_read)
> -W I_can_write
> -X I_can_execute
>
> -o am_owner
> -O Am_owner (or am_really_owner)
>
>
> should they be there too?

Likewise, they could tie into the mode, at least -r and -w. Past that...
I don't see any good point in them.

Now, what are we going to call these?

1. $f->-e(); #nix, bad syntax
2. $f->test_e();
3. $f->test_exist();
4. $f->test("e");
5. $f->_e();
6. -e $f
7. $f->does_exist();
8. $f->exist();

Any others?

#6 gets grandfathered in. #1 is right out. #7 is verbose enough, but with
a dozen of these things, they'll get very cluttered. I'm somewhat in
favor of having both #2 and #3.

> --tom
>

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
Re: Ken's SimpleFileHandle [ In reply to ]
> OK, to try and cut through some of the FileHandle arguments, here is a
> simple FileHandle module that I just wrote up. Extract to simpleFH.pm, and
> try some code like this:

just a quick initial reaction: let's not propogate a "simple" or "partial"
solution too widely, and get the stuff in there that does sysopen and
named args stuff before it makes it to the real world. i'm talkin about
the 1, 2, 3, etc argument contstructors for new/open.

hm.. what about the aliases for

-f is_regular_file
-t is_tty
-d is_directory
-l is_symlink
-S is_socket
-p is_fifo
-c is_block_device
-c is_char_device
-z is_zero_length

-s file_size
-e does_exist (silly on a filehandle?)

-T is_text
-B is_binary (better than isn't_text, eh? :-)

-M modify_age
-A access_age
-C change_age

-r i_can_read
-w i_can_write
-x i_can_execute

-R I_can_read (or can_really_read)
-W I_can_write
-X I_can_execute

-o am_owner
-O Am_owner (or am_really_owner)


should they be there too?

--tom
Re: Ken's SimpleFileHandle [ In reply to ]
On Thu, 26 Oct 1995, Kenneth Albanowski wrote:

> > -e does_exist (silly on a filehandle?)
>
> Yes. But this could shill for is_open(). I don't think -s will have a
> rational meaning.
>
> > should they be there too?
>
> Likewise, they could tie into the mode, at least -r and -w. Past that...
> I don't see any good point in them.

As Tye has pointed out to me, all of this stuff is provided on
filehandles by fstat(), whether it makes sense or not, and it would
probably make sense to continue that style.

-e would then mean something like (is_open() && fstat_successful).


--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
Re: Ken's SimpleFileHandle [ In reply to ]
Strange sunspot activity caused Tom Christiansen <tchrist@mox.perl.com> to writ
e:
| I'm wondering whether
|
| $fh->is_plain_file
|
| shouldn't be
|
| sub FileHandle::is_plain_file {
| local $_ = shift;
| -f && -T;
| }

If is_plain_file is the same as is_file (like is_directory), then no, it
shouldn't be -f && -T. is_plain_file should be just that... it's a file.
There are quite often times when you want everything that's a file, whether
it's text or not. Besides, doesn't that make is_text (-T) redundant?

-spp
Re: Ken's SimpleFileHandle [ In reply to ]
> > -f is_regular_file
> > -t is_tty
> > -d is_directory
> > -l is_symlink
> > -S is_socket
> > -p is_fifo
> > -c is_block_device
> > -c is_char_device
> > -z is_zero_length

> Now, what are we going to call these?

> 1. $f->-e(); #nix, bad syntax
> 2. $f->test_e();
> 3. $f->test_exist();
> 4. $f->test("e");
> 5. $f->_e();
> 6. -e $f
> 7. $f->does_exist();
> 8. $f->exist();


Perhaps you misunderstood. I intended

$fh->is_directory()
$fh->is_fifo()

etc, exactly as I listed.

I'm wondering whether

$fh->is_plain_file

shouldn't be

sub FileHandle::is_plain_file {
local $_ = shift;
-f && -T;
}

rather than just


sub FileHandle::is_plain_file { -f shift }

--tom
Re: Ken's SimpleFileHandle [ In reply to ]
> | I'm wondering whether
> |
> | $fh->is_plain_file
> |
> | shouldn't be
> |
> | sub FileHandle::is_plain_file {
> | local $_ = shift;
> | -f && -T;
> | }

> If is_plain_file is the same as is_file (like is_directory), then no, it
> shouldn't be -f && -T. is_plain_file should be just that... it's a file.
> There are quite often times when you want everything that's a file, whether
> it's text or not. Besides, doesn't that make is_text (-T) redundant?

Duh, me make typo/braino.

I meant for is_text, not is_regular. the real is whether is_text should
do the direct mapping (-T) or the more realisitically expected one
(-f && -T). If they want the real -T and not -f, they could code that.

So what should these methods look like? will

sub FileHandle::is_whatever {
-xxx shift;
}

always work? Apparently not. Is this the Chip patches for internal
handling of file globs? Consider this bug:

% perl -le 'print "isatty: ", -t STDERR'
isatty: 1

% perl -le 'print "isatty: ", -t "STDERR"'
isatty: 1

%perl -le 'print "isatty: ", -t *STDERR'
isatty:

%perl -le 'print "isatty: ", -t \*STDERR'
isatty:

So the ones we most want it to work on it doesn't work on. Darn it.

--tom
Re: Ken's SimpleFileHandle [ In reply to ]
In <Pine.LNX.3.91.951026013824.353G-100000@kjahds.com>
On Thu, 26 Oct 1995 01:44:39 -0400 (EDT)
Kenneth Albanowski <kjahds@kjahds.com> writes:
>Now, what are we going to call these?
>
> 1. $f->-e(); #nix, bad syntax
> 2. $f->test_e();
> 3. $f->test_exist();
> 4. $f->test("e");
> 5. $f->_e();
> 6. -e $f
> 7. $f->does_exist();
> 8. $f->exist();
>
>Any others?

9. $f->e

>#6 gets grandfathered in.

Neat.
Re: Ken's SimpleFileHandle [ In reply to ]
NI> In <Pine.LNX.3.91.951026013824.353G-100000@kjahds.com>
NI> On Thu, 26 Oct 1995 01:44:39 -0400 (EDT)
NI> Kenneth Albanowski <kjahds@kjahds.com> writes:
>> Now, what are we going to call these?
>>
>> 1. $f->-e(); #nix, bad syntax
>> 2. $f->test_e();
>> 3. $f->test_exist();
>> 4. $f->test("e");
>> 5. $f->_e();
>> 6. -e $f
>> 7. $f->does_exist();
>> 8. $f->exist();
>>
>> Any others?

NI> 9. $f->e

$f->exists_p, of course :)

I'd prefer $f->exists over $f->exist, since it reads better

&foo if $f->exists;

P.
Re: Ken's SimpleFileHandle [ In reply to ]
: I meant for is_text, not is_regular. the real is whether is_text should
: do the direct mapping (-T) or the more realisitically expected one
: (-f && -T). If they want the real -T and not -f, they could code that.

It's always been my take that we have to provide the simple test. If
they want to guard against opening "/dev/whatever", they'd better do
that themselves. Otherwise there's no easy way to write the other thing.

: So what should these methods look like? will
:
: sub FileHandle::is_whatever {
: -xxx shift;
: }
:
: always work? Apparently not. Is this the Chip patches for internal
: handling of file globs? Consider this bug:
:
: % perl -le 'print "isatty: ", -t STDERR'
: isatty: 1
:
: % perl -le 'print "isatty: ", -t "STDERR"'
: isatty: 1
:
: %perl -le 'print "isatty: ", -t *STDERR'
: isatty:
:
: %perl -le 'print "isatty: ", -t \*STDERR'
: isatty:
:
: So the ones we most want it to work on it doesn't work on. Darn it.

That's simply a bug. I've installed a bug report.

Larry
Re: Ken's SimpleFileHandle [ In reply to ]
Strange sunspot activity caused Tom Christiansen <tchrist@mox.perl.com> to writ
e:
|
| -f $fh be $fh->is_plain
|

I don't particularly like either is_plain or is_regular. Plain or regular
what? What's wrong with is_file?

| I guess I was looking for a higher level mapping so
| people wouldn't always have to use
|
| $fh->is_plain && $fh->is_regular
|
| the way they now must always (or SHOULD always but sadly don't)
| use
|
| -f $fh && -T $fh

$fh->is_text_file

sub is_text_file {
my($file) = shift;
-f $file && -T _;
}

-spp
Re: Ken's SimpleFileHandle [ In reply to ]
>: I meant for is_text, not is_regular. the real is whether is_text should
>: do the direct mapping (-T) or the more realisitically expected one
>: (-f && -T). If they want the real -T and not -f, they could code that.

>It's always been my take that we have to provide the simple test. If
>they want to guard against opening "/dev/whatever", they'd better do
>that themselves. Otherwise there's no easy way to write the other thing.


So you would prefer that

-T $fh be $fh->is_text
and
-f $fh be $fh->is_regular

or maybe

-f $fh be $fh->is_plain

I guess I was looking for a higher level mapping so
people wouldn't always have to use

$fh->is_plain && $fh->is_regular

the way they now must always (or SHOULD always but sadly don't)
use

-f $fh && -T $fh

--tom
Re: Ken's SimpleFileHandle [ In reply to ]
On Thu, 26 Oct 1995, Tom Christiansen wrote:

> Perhaps you misunderstood. I intended
>
> $fh->is_directory()
> $fh->is_fifo()
>
> etc, exactly as I listed.

No, no misunderstanding, I just didn't make myself clear. Sorry about
that. My meaning was that the "is_directory" and "does_exist" style,
while verbose and nice to read, is rather hard to guess at if you
normally use "-d" and "-e". If the names chosen aren't easily guessable,
then they aren't that much of a help. "is_directory" seems quite
reasonable. "does_exist" is much less clear. This could just as well be
"exists", and some of the other tests are far easier to pin down.

Aliases should be relatively cheap, though, so this isn't a major worry.

> I'm wondering whether
>
> $fh->is_plain_file
>
> shouldn't be
>
> sub FileHandle::is_plain_file {
> local $_ = shift;
> -f && -T;
> }
>
> rather than just
>
>
> sub FileHandle::is_plain_file { -f shift }

Hmm... I somewhat like the idea of both -T and -B returning 0 for
non-files, myself. Yes, this bears some thought. But there is the
alternate point of naming, and keeping consistent behaviour between -T
and is_text, etc.

> --tom
>

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
Re: Ken's SimpleFileHandle [ In reply to ]
On Thu, 26 Oct 1995, Paul Hudson wrote:

> $f->exists_p, of course :)

Heretic. :-)

> I'd prefer $f->exists over $f->exist, since it reads better
>
> &foo if $f->exists;

Noted.

> P.

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
Re: Ken's SimpleFileHandle [ In reply to ]
On Thu, 26 Oct 1995, Tom Christiansen wrote:

> I guess I was looking for a higher level mapping so
> people wouldn't always have to use
>
> $fh->is_plain && $fh->is_regular
>
> the way they now must always (or SHOULD always but sadly don't)
> use
>
> -f $fh && -T $fh

My view on this is that since -T and -B are already "magic", and not just
simple fstat() tests, they really should take care of this in the first
place, maybe both returning 0 for non-files.

This breaks nastily if you are in the habit of saying this, though:

if( -T $foo) {
# text file
} else {
# binary file
}

It's a judgement call, I'm afraid. I don't see a good argument one way or
the other.

> --tom

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
Re: Ken's SimpleFileHandle [ In reply to ]
On Thu, 26 Oct 1995, Tom Christiansen wrote:

> >This breaks nastily if you are in the habit of saying this, though:
>
> > if( -T $foo) {
> > # text file
> > } else {
> > # binary file
> > }
>
> >It's a judgement call, I'm afraid. I don't see a good argument one way or
> >the other.
>
> I've usually held Ken's position, and Larry's always help the
> other one. But he is the author, after all. And it does make
> a good bit of sense to provide minimal primitives instead
> of only high-level things without any low-level access.

We are in definite agreement here. It just so happens that -T and -B are
hardly "minimal" by themselves. But that's just my opinion.

> I'm just currently questioning the 1:1 mapping.

Fair enough. Since this bit of FileHandle isn't written yet, I don't mind
leaving it till later to work this out. Since you want verbose names, I
doubt there will be a perfect 1:1 mapping anyhow, what with aliases.

Hmm. Maybe -B should just return -1 if the file isn't a file, 0 if it's
text, and 1 if it's binary.

> --tom

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
Re: Ken's SimpleFileHandle [ In reply to ]
>This breaks nastily if you are in the habit of saying this, though:

> if( -T $foo) {
> # text file
> } else {
> # binary file
> }

>It's a judgement call, I'm afraid. I don't see a good argument one way or
>the other.

I've usually held Ken's position, and Larry's always help the
other one. But he is the author, after all. And it does make
a good bit of sense to provide minimal primitives instead
of only high-level things without any low-level access.

I'm just currently questioning the 1:1 mapping.

--tom
Re: Ken's SimpleFileHandle [ In reply to ]
Excerpts from the mail message of Kenneth Albanowski:
)
) On Thu, 26 Oct 1995, Tom Christiansen wrote:
)
) > I guess I was looking for a higher level mapping so
) > people wouldn't always have to use
) >
) > $fh->is_plain && $fh->is_regular
) >
) > the way they now must always (or SHOULD always but sadly don't)
) > use
) >
) > -f $fh && -T $fh
)
) My view on this is that since -T and -B are already "magic", and not just
) simple fstat() tests, they really should take care of this in the first
) place, maybe both returning 0 for non-files.

I don't see why you think I wouldn't want -T and -B to work when I do:

cat file | perl -e '-T STDIN'
perl -e '-T STDIN' </dev/rdsk/fd0t #Read a floppy

Who says that non-ordinary files don't come in both text and binary
varieties?

Whose going to write the FAQ about useless uses of "cat" being the
cause of -T not working anymore? At least it will add some weight
to the arguments against UUoCs on comp.unix.questions. (:
--
Tye McQueen tye@metronet.com || tye@doober.usu.edu
Nothing is obvious unless you are overlooking something
http://www.metronet.com/~tye/ (scripts, links, nothing fancy)
Re: Ken's SimpleFileHandle [ In reply to ]
On Fri, 27 Oct 1995, Tye McQueen wrote:

> I don't see why you think I wouldn't want -T and -B to work when I do:
>
> cat file | perl -e '-T STDIN'
> perl -e '-T STDIN' </dev/rdsk/fd0t #Read a floppy
>
> Who says that non-ordinary files don't come in both text and binary
> varieties?

Yes, but if -T and -B each eat up some of the incoming data, then is it
really working properly? Looking through the source, yes, they work in
some instances, but they don't try to get to the beginning of the file,
and only use what's lying around in the STDIO buffers.

> Whose going to write the FAQ about useless uses of "cat" being the
> cause of -T not working anymore? At least it will add some weight
> to the arguments against UUoCs on comp.unix.questions. (:

OK, I surrender, -T is fine as it is. :-)

> --
> Tye McQueen tye@metronet.com || tye@doober.usu.edu
> Nothing is obvious unless you are overlooking something
> http://www.metronet.com/~tye/ (scripts, links, nothing fancy)
>

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
Re: Ken's SimpleFileHandle [ In reply to ]
WRT $f->filetest:

How about making a single test method for a filehandle object with
and-able attributes passed in as a list? This would allow efficient
reuse of the currently cached stat and only requires a single method
invocation.

if ( $f->test(is_text, is_writable, (size > 512)) ) { do_something; }

tog

Terry Greenlaw (on-site @ Lockheed Martin) Encompass Technologies
z50816@mip.lasc.lockheed.com terry@encompass.is.net



[ ...thread head chopped dead ]

> > $f->exists_p, of course :)

> Heretic. :-)

> > I'd prefer $f->exists over $f->exist, since it reads better
> >
> > &foo if $f->exists;

> Noted.
>
> > P.
Re: Ken's SimpleFileHandle [ In reply to ]
TG> How about making a single test method for a filehandle object with
TG> and-able attributes passed in as a list? This would allow efficient
TG> reuse of the currently cached stat and only requires a single method
TG> invocation.

TG> if ( $f->test(is_text, is_writable, (size > 512)) ) { do_something; }

Yuk :)

Also, I often want to do different further tests depending on the
outcome of the first. I'ld like caching to work then, too, so the
above doesn't help much.

P.
Re: Ken's SimpleFileHandle [ In reply to ]
On Mon, 30 Oct 1995, Terry Greenlaw wrote:

>
> WRT $f->filetest:
>
> How about making a single test method for a filehandle object with
> and-able attributes passed in as a list? This would allow efficient
> reuse of the currently cached stat and only requires a single method
> invocation.
>
> if ( $f->test(is_text, is_writable, (size > 512)) ) { do_something; }

That syntax isn't too feasible as it stands. Though, it's an interesting
idea, and could be implemented with closures:

if ( $f->test sub {$text or $writable or $size >512} ) { do_something; }

> tog
>
> Terry Greenlaw (on-site @ Lockheed Martin) Encompass Technologies
> z50816@mip.lasc.lockheed.com terry@encompass.is.net

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)