From a386a9ff068071aab19e6dcb0452e72784d84267 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 3 Aug 2012 11:57:49 +0300 Subject: [PATCH] The EOF logic wasn't quite correct If the underlying object reported EOF after reading the last byte, then ZlibCompressed would report EOF itself before giving out all data from the buffers. --- source/io/base.h | 4 +++- source/io/zlibcompressed.cpp | 10 +++++++--- source/io/zlibcompressed.h | 1 + 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/source/io/base.h b/source/io/base.h index 3d86216..394a2c2 100644 --- a/source/io/base.h +++ b/source/io/base.h @@ -87,7 +87,9 @@ protected: void set_eof(); public: - /** Returns the end-of-file flag. */ + /** Returns the end-of-file flag. Note that some types of objects won't + indicate end-of-file until you try to read at least one byte past the actual + end, while others indicate it when you've read the last byte. */ bool eof() const { return eof_flag; } /** Returns the system-level handle for the object. Used by Console to diff --git a/source/io/zlibcompressed.cpp b/source/io/zlibcompressed.cpp index ea5e803..90b54a2 100644 --- a/source/io/zlibcompressed.cpp +++ b/source/io/zlibcompressed.cpp @@ -42,6 +42,7 @@ ZlibCompressed::ZlibCompressed(Base &b, unsigned level): buffer_size(1024), in_buffer(0), out_buffer(0), + stream_end(false), priv(0) { #ifdef WITH_ZLIB @@ -219,7 +220,7 @@ unsigned ZlibCompressed::do_read(char *data, unsigned size) { int ret = inflate(&priv->stream, Z_NO_FLUSH); if(ret==Z_STREAM_END) - set_eof(); + stream_end = true; else if(ret!=Z_OK) throw zlib_error("inflate", ret); need_more_input = (priv->stream.next_out==out_buffer); @@ -227,7 +228,7 @@ unsigned ZlibCompressed::do_read(char *data, unsigned size) if(need_more_input) { - if(eof_flag) + if(stream_end) break; if(priv->stream.next_in>in_buffer) @@ -237,9 +238,12 @@ unsigned ZlibCompressed::do_read(char *data, unsigned size) unsigned len = below.read(reinterpret_cast(priv->stream.next_in), in_buffer+buffer_size-priv->stream.next_in); priv->stream.avail_in += len; if(!len && below.eof()) - set_eof(); + stream_end = true; } } + + if(size>0 && processed==0 && stream_end) + set_eof(); #else (void)data; (void)size; diff --git a/source/io/zlibcompressed.h b/source/io/zlibcompressed.h index 1ee4274..feb21c6 100644 --- a/source/io/zlibcompressed.h +++ b/source/io/zlibcompressed.h @@ -36,6 +36,7 @@ private: unsigned buffer_size; unsigned char *in_buffer; unsigned char *out_buffer; + bool stream_end; Private *priv; public: -- 2.43.0