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
streams.
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.
Cheers,
-Steve
Reply to: