coppit has asked for the wisdom of the Perl Monks concerning the following question:

According to IO::Handle, ungetc is only promised to work for 1 character. What's the best way to implement ungetstring? Here are my requirements:

- needs to be compatible with FileHandle
- needs to work if the file handle is a pipe (I use open('-|') to decompress data from STDIN using an external decompression program)
- needs to work if I happen to accidentally read eof (I've found that FreeBSD won't let me ungetc if I already read past EOF)
- takes an already opened handle

I'll obviously need to store the previously read (and unget'd) bytes. Should I tie a filehandle? Or should I implement a wrapper class for FileHandle? Or IO::Handle? As I understand it, I can't inherit from FileHandle because it doesn't really inherit from IO::*...

Lastly, if some kind soul wouldn't mind sharing an initial implementation with me, I would appreciate it.

Thanks!

Replies are listed 'Best First'.
Re: Best way to implement ungetstring?
by Abigail-II (Bishop) on Aug 19, 2003 at 20:50 UTC
    Probably best done as a PerlIO layer. See man PerlIO and man PerlIO::via.

    Abigail

Re: Best way to implement ungetstring?
by thor (Priest) on Aug 19, 2003 at 21:08 UTC
    In general, you could have a buffer associated with each file handle. You could then overload any get* routines to look at your buffer first, and if that's empty do the operation on the file. Ungetting at that point is just filling that buffer. Looking at what we have, it looks like you'd want to implement this as a wrapper to IO::Handle. Also, from what I recall, seek clears EOF...

    thor

Re: Best way to implement ungetstring?
by waswas-fng (Curate) on Aug 19, 2003 at 22:03 UTC
    I have never understood why unget was used except for networking code where you want to peak at some data to see where you want to send it to, maybe I am missing something but what are you doing where you want to reinsert chars into the buffer?

    -Waswas
      Simple--first, test whether a stream is binary. You can't use -B on a stream because it consumes the bytes. If it is binary, see if it is a known compressed file type. Then redirect the stream to an appropriate decompressor program.

      Yes, I *could* store the bytes I've read, but things would be much simpler if I could unget them. I could also write an external file, but I don't want to risk a security flaw. (This is for email.)