From Colin McDonald, "The osgb file reader uses seek to position within the file.

But the nested stream implementation for osga archive files doesn't
support seeking.  So osgb files can't currently be used in an osga
archive e.g. if osgdem is used to output a osgb format database it
can't be packaged in an archive file, in the same manner that ive
files could.

I've added seek support to the osga nested stream implementation."
This commit is contained in:
Robert Osfield 2013-10-22 11:26:45 +00:00
parent 5ed399ca48
commit c34a8e4ddb

View File

@ -600,40 +600,90 @@ bool OSGA_Archive::addFileReference(pos_type position, size_type size, const std
}
// streambuffer class to give access to a portion of the archive stream, for numChars onwards
// from the current position in the archive.
class proxy_streambuf : public std::streambuf
{
public:
public:
proxy_streambuf(std::streambuf* streambuf, unsigned int numChars):
_streambuf(streambuf),
_numChars(numChars) {
setg(&oneChar, (&oneChar)+1, (&oneChar)+1);
proxy_streambuf(std::streambuf* streambuf, std::streamoff numChars):
_streambuf(streambuf),_curPos(0),_numChars(numChars)
{
_startPos = ARCHIVE_POS(_streambuf->pubseekoff(0, std::ios_base::cur, std::ios_base::in));
setg(&_oneChar, (&_oneChar)+1, (&_oneChar)+1);
}
/// Destructor deallocates no buffer space.
// Destructor deallocates no buffer space.
virtual ~proxy_streambuf() {}
std::streambuf* _streambuf;
std::streambuf* _streambuf; // Underlying archive stream
protected:
protected:
unsigned int _numChars;
char_type oneChar;
char_type _oneChar; // Single character buffer
std::streamoff _curPos, _numChars;
OSGA_Archive::pos_type _startPos;
// Set internal position pointer to relative position. Virtual function called by the public
// member function pubseekoff to alter the stream position.
virtual std::streampos seekoff (std::streamoff off, std::ios_base::seekdir way,
std::ios_base::openmode which = std::ios_base::in)
{
std::streamoff newpos;
if ( way == std::ios_base::beg )
{
newpos = off;
}
else if ( way == std::ios_base::cur )
{
newpos = _curPos + off;
}
else if ( way == std::ios_base::end )
{
newpos = _numChars + off;
}
else
{
return -1;
}
if ( newpos<0 || newpos>_numChars ) return -1;
if ( (std::streamoff)_streambuf->pubseekpos( STREAM_POS(_startPos+newpos), which) < 0 ) return -1;
_curPos = newpos;
return _curPos;
}
// Set internal position pointer to absolute position. Virtual function called by the public
// member function pubseekpos to alter the stream positions
virtual std::streampos seekpos (std::streampos sp, std::ios_base::openmode which = std::ios_base::in)
{
return seekoff(sp, std::ios_base::beg, which);
}
// Virtual function called by other member functions to get the current character. It is called
// by streambuf public member functions such as sgetc to request a new character when there are
// no read positions available at the get pointer (gptr).
virtual int_type underflow()
{
if ( gptr() == &oneChar ) return traits_type::to_int_type(oneChar);
// Return current character.
if ( _numChars==0 ) return traits_type::eof();
--_numChars;
if ( gptr() == &_oneChar ) return traits_type::to_int_type(_oneChar);
// Get another character from the archive stream, if available.
if ( _curPos==_numChars ) return traits_type::eof();
_curPos += 1;
int_type next_value = _streambuf->sbumpc();
if ( !traits_type::eq_int_type(next_value,traits_type::eof()) )
{
setg(&oneChar, &oneChar, (&oneChar)+1);
oneChar = traits_type::to_char_type(next_value);
setg(&_oneChar, &_oneChar, (&_oneChar)+1);
_oneChar = traits_type::to_char_type(next_value);
}
return next_value;