simgear/io/iostreams/zlibstream.*: improved support for reading compressed data.
Added support for seeking (forwards only) - in ZlibAbstractIStreambuf, added seekoff(). Also disabled assert that checked that we reach EOF compressed data at same time as EOF uncompressed data; was breaking things when using embedded compressed streams within fgtape recording. Added ZLibCompressionFormat::ZLIB_RAW, uses windowBits=-15, for zlib compressed streams without header or trailer. Fixed clang build error with std::min().
This commit is contained in:
parent
d01e9ca2e6
commit
95239fea87
@ -157,7 +157,6 @@ ZlibAbstractIStreambuf::ZlibAbstractIStreambuf(std::istream& iStream,
|
||||
_putbackSize(putbackSize)
|
||||
{
|
||||
assert(_inBufSize > 0);
|
||||
assert(_putbackSize >= 0); // guaranteed unless the type is changed...
|
||||
assert(_putbackSize < _outBufSize);
|
||||
|
||||
if (_inBuf == nullptr) {
|
||||
@ -249,6 +248,28 @@ int ZlibAbstractIStreambuf::underflow()
|
||||
return (gptr() == egptr()) ? traits::eof() : traits::to_int_type(*gptr());
|
||||
}
|
||||
|
||||
std::streampos ZlibAbstractIStreambuf::seekoff(std::streamoff off,
|
||||
std::ios_base::seekdir way,
|
||||
std::ios_base::openmode which)
|
||||
{
|
||||
if (way != std::ios_base::cur || off < 0) return -1;
|
||||
for(;;) {
|
||||
if (!off) break;
|
||||
char* g = gptr();
|
||||
char* eg = egptr();
|
||||
if (eg > g) {
|
||||
size_t delta = (off < eg - g) ? off : eg - g;
|
||||
setg(g + delta, g + delta, eg);
|
||||
off -= delta;
|
||||
}
|
||||
else {
|
||||
if (underflow() == EOF) return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Simple utility method for fillOutputBuffer(), used to improve readability.
|
||||
// Return the remaining space available in the output buffer, where zlib can
|
||||
// write.
|
||||
@ -320,7 +341,7 @@ char* ZlibAbstractIStreambuf::fillOutputBuffer()
|
||||
if (retCode == Z_BUF_ERROR) {
|
||||
handleZ_BUF_ERROR(); // doesn't return
|
||||
} else if (retCode == Z_STREAM_END) {
|
||||
assert(_zstream.avail_in == 0); // all of _inBuf must have been used
|
||||
//assert(_zstream.avail_in == 0); // all of _inBuf must have been used
|
||||
_allFinished = true;
|
||||
break;
|
||||
} else if (retCode < 0) { // negative codes are errors
|
||||
@ -481,7 +502,7 @@ std::streamsize ZlibAbstractIStreambuf::xsgetn(char* dest, std::streamsize n)
|
||||
if (retCode == Z_BUF_ERROR) {
|
||||
handleZ_BUF_ERROR(); // doesn't return
|
||||
} else if (retCode == Z_STREAM_END) {
|
||||
assert(_zstream.avail_in == 0); // all of _inBuf must have been used
|
||||
//assert(_zstream.avail_in == 0); // all of _inBuf must have been used
|
||||
_allFinished = true;
|
||||
break;
|
||||
} else if (retCode < 0) { // negative codes are errors
|
||||
@ -730,6 +751,9 @@ void ZlibDecompressorIStreambuf::zStreamInit(ZLibCompressionFormat format)
|
||||
case ZLibCompressionFormat::AUTODETECT:
|
||||
windowBits = 47; // 47 = 32 + 15
|
||||
break;
|
||||
case ZLibCompressionFormat::ZLIB_RAW:
|
||||
windowBits = -15;
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("Unexpected compression format: " +
|
||||
std::to_string(enumValue(format)));
|
||||
|
@ -103,7 +103,8 @@ namespace simgear
|
||||
enum class ZLibCompressionFormat {
|
||||
ZLIB = 0,
|
||||
GZIP,
|
||||
AUTODETECT
|
||||
AUTODETECT,
|
||||
ZLIB_RAW, // No zlib header or trailer.
|
||||
};
|
||||
|
||||
enum class ZLibMemoryStrategy {
|
||||
@ -196,6 +197,13 @@ private:
|
||||
// Callback whose role is to refill the output buffer when it's empty and
|
||||
// the “client” tries to read more.
|
||||
virtual int underflow() override;
|
||||
|
||||
// We only support seeking forwards, with way==std::ios_base::cur and
|
||||
// off>=0, returning 0. Otherwise we return -1.
|
||||
std::streampos seekoff(std::streamoff off,
|
||||
std::ios_base::seekdir way,
|
||||
std::ios_base::openmode which) override;
|
||||
|
||||
// Optional override when subclassing std::streambuf. This is the most
|
||||
// efficient way of reading several characters (as soon as we've emptied the
|
||||
// output buffer, data is written by zlib directly to the destination
|
||||
|
Loading…
Reference in New Issue
Block a user