Hi Robert,

Thanks for digging into the problem.  I find it difficult to believe
that tell, seek istream implementations are broken.  It might be worth
putting a tellg before and after the seek to see what values it's
using.

I did this:

    virtual bool matchString( const std::string& str )
    {
        std::string s; readString(s);
        if ( s==str ) return true;
        else
        {
            std::istream::pos_type pos_before = _in->tellg();
            _in->seekg( -(int)(s.length()), std::ios::cur );
            std::istream::pos_type pos_after = _in->tellg();
        }
        return false;
    }

What I get is pos_before = 148, pos_after = 140. However, next time matchString is called, the value of s is "1" instead of "Children", so it obviously didn't succeed...

Changing the function to:

    virtual bool matchString( const std::string& str )
    {
        std::string s; readString(s);
        if ( s==str ) return true;
        else
        {
            std::istream::pos_type pos_before = _in->tellg();
            for (unsigned int i = 0; i < s.length(); ++i)
                _in->unget();
            std::istream::pos_type pos_after = _in->tellg();
        }
        return false;
    }

(so instead of seeking back by 8 characters, we call unget() 8 times)

This works, i.e. the next time matchString is called the value of s is "Children", and the cow is read correctly. What's weird is that I kept the two tellg() calls, and they still return the same values (pos_before = 148 and pos_after = 140). There seems to be some inconsistency between how seekg and tellg work (or the underlying functions they eventually call to do their work).

So unless someone finds a better solution, I suggest changing matchString from this:

    virtual bool matchString( const std::string& str )
    {
        std::string s; readString(s);
        if ( s==str ) return true;
        else _in->seekg( -(int)(s.length()), std::ios::cur );
        return false;
    }

to this:

    virtual bool matchString( const std::string& str )
    {
        std::string s; readString(s);
        if ( s==str ) return true;
        else
        {
            for (unsigned int i = 0; i < s.length(); ++i)
                _in->unget();
        }
        return false;
    }

Or you can obfuscate it by removing newlines if you want :-)

It's really sad we need to avoid seekg for one particular platform (and I wonder if VC++ 2010 fixes this... I'm on 2008).

As for moving to binary mode, this is possible, nor sure of the
fallout though, but it terms of making sure we get the same results
across all platforms it might well be the best thing to do.  Off hand
I don't know how much of a fallout this would have.

As for the .osg plugin, I deliberately avoiding using seek and instead
implemented caching of strings within the FieldReaderIterator to hide
the fact that we'd read data in but then not use it directly.
Potentially would could do something similar with InputStream, but
again I'm not sure how much of a impact this might have.

For these two possible solutions I'll defer to you or others who might know about how stream i/o works on multiple platforms. I'm generally just a user of these things and hack at them until they work, I'm not well placed to say what will work and what the consequences will be...

J-S
--
______________________________________________________
Jean-Sebastien Guay    [email protected]
                               http://www.cm-labs.com/
                    http://whitestar02.dyndns-web.com/
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to