[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: GCC 3.2 replacement for streammarker?

On Sun, Oct 27, 2002 at 12:53:28PM +0200, Ulrich Eckhardt wrote:
> On Sunday 27 October 2002 02:35, Steve M. Robbins wrote:
> > Hi,
> >
> > The geomview package needs the ability to seek backwards on
> > a file regardless of whether it is a pipe, socket, tty, etc.
> > Basically: fseek() that never fails.
> >
> > A pure C-code solution would be best.  Any suggestions?
> >
> >
> > The current solution is to link in some C++ code that uses
> > a streammarker object, which does exactly what is needed:
> >
> >     The GNU iostream library allows you to ask a streambuf to remember
>           ^^^^^^^^^^^^
> It's a non-portable extension, in other words. A quick grep revealed no such 
> thing as a streammarker in 3.2 (part of 'old' stuff are still available in 
> separated namespaces, but not that one).

Yes, more's the pity.  I speculate that streammarker was a casualty of
a code rewrite.  Anyone know the story?  Could the code be fished out
of the old libstdc++ sources and made to work?

> However, standard C++ IOstreams provide means to seek, though there is no 
> guarantee that the operation will not fail. The problem is especially when 
> using non-storage devices like pipes or ttys, cause those have no way to 
> seek.

Yes.  This is precisely the problem: the geomview parser needs to
backtrack occasionally, and it could be reading input from a pipe,
the tty, or a network socket.

> However, here is some code:
> istream::pos_type const pos = mystream.tellg();
> // do something with mystream
> mystream.clear();
> if(! mystream.seekg(pos))
>     ...// handle error

The trouble is that "handle error" means "give up the parse", 
which is a pretty serious failure.

> >     This allows you to go back to this position
> >     later, after reading further. You can back up arbitrary amounts,
> >     even on unbuffered files or multiple buffers' worth, as long as
> >     you tell the library in advance.
> Doesn't work with this method. Still, there is a simple way of doing that 
> which might be sufficient: copy parts of the istream to a stringstream and 
> read from that one. stringstream it probably seekable without limit. This 
> requires knowing in advance how many bytes are needed though ... 

The geomview code has some kind of a parser that reads in descriptions
of geometry from a FILE* (notwithstanding the C++ hackery, geomview is
written in C).  In certain situations, the parser needs to backtrack,
but the potential backtrack points are known in advance.
Specifically: if the parser reaches a point to which it *might* need
to return, a function stdio_setmark() is called, which returns a
marker object.  To backtrack, a function stdio_seekmark() is called
using the marker object.

There are some ways to fix this: maybe the parser can be improved, or
an extra layer of buffering could be implemented on top of the input

Either approach requires a lot of changes to geomview code for which
no-one has the energy, at the moment.  Thus my search for cheaper
hacks.  ;-)

> I just took a look at the sources. It seems that the only thing there that 
> uses C++ IOstreams is some weird way of wrapping access to a piece of memory 
> in a FILE*.

That, and the setmark/seekmark functions.

> It does so in a way that makes me cringe.

I agree.  Don't look at the code without a strong stomach :)

[Bear in mind, however, that this code dates from 10 years ago,
and was developed when stdio was a lot more standard, apparently.
They took a lot of liberties with poking about in the FILE structure]

> However, I don't think you should need that hack:

They used that hack because the always-successful-seek functionality
was available in the C++ library but not in the C library.

> in <stdio.h> is a function called fmemopen. This 
> function however requires that you #define __USE_GNU ( because it is 
> non-standard) to become visible. This should provide unlimited seeking.

This is a separate issue.  In addition to needing to seek backwards
on arbitrary streams, geomview *also* needs to operate on memory
buffers as files.  And, yes, fmemopen() is used when available.

> What I don't get is where/why geomview operates on pipes/ttys ... maybe it 
> doesn't and you're lucky? :)

Sadly, geomview is too general: it accepts input from many different
sources including over the net from a remote machine, the tty, a
pipe from another process, a memory buffer, or a bona-fide disk file.

In a perfect world, it needs to occasionally seek backwards on
any of those sources.


Reply to: