diff options
Diffstat (limited to 'zen/zlib_wrap.h')
-rw-r--r-- | zen/zlib_wrap.h | 33 |
1 files changed, 16 insertions, 17 deletions
diff --git a/zen/zlib_wrap.h b/zen/zlib_wrap.h index c8647baf..fbe26193 100644 --- a/zen/zlib_wrap.h +++ b/zen/zlib_wrap.h @@ -8,31 +8,30 @@ #define ZLIB_WRAP_H_428597064566 #include "serialize.h" +#include "sys_error.h" namespace zen { -class ZlibInternalError {}; - // compression level must be between 0 and 9: // 0: no compression // 9: best compression template <class BinContainer> //as specified in serialize.h -BinContainer compress(const BinContainer& stream, int level); //throw ZlibInternalError +BinContainer compress(const BinContainer& stream, int level); //throw SysError //caveat: output stream is physically larger than input! => strip additional reserved space if needed: "BinContainer(output.begin(), output.end())" template <class BinContainer> -BinContainer decompress(const BinContainer& stream); //throw ZlibInternalError +BinContainer decompress(const BinContainer& stream); //throw SysError class InputStreamAsGzip //convert input stream into gzip on the fly { public: - InputStreamAsGzip( //throw ZlibInternalError + InputStreamAsGzip( //throw SysError const std::function<size_t(void* buffer, size_t bytesToRead)>& readBlock /*throw X*/); //returning 0 signals EOF: Posix read() semantics ~InputStreamAsGzip(); - size_t read(void* buffer, size_t bytesToRead); //throw ZlibInternalError, X; return "bytesToRead" bytes unless end of stream! + size_t read(void* buffer, size_t bytesToRead); //throw SysError, X; return "bytesToRead" bytes unless end of stream! private: class Impl; @@ -49,13 +48,13 @@ private: namespace impl { size_t zlib_compressBound(size_t len); -size_t zlib_compress (const void* src, size_t srcLen, void* trg, size_t trgLen, int level); //throw ZlibInternalError -size_t zlib_decompress(const void* src, size_t srcLen, void* trg, size_t trgLen); //throw ZlibInternalError +size_t zlib_compress (const void* src, size_t srcLen, void* trg, size_t trgLen, int level); //throw SysError +size_t zlib_decompress(const void* src, size_t srcLen, void* trg, size_t trgLen); //throw SysError } template <class BinContainer> -BinContainer compress(const BinContainer& stream, int level) //throw ZlibInternalError +BinContainer compress(const BinContainer& stream, int level) //throw SysError { BinContainer contOut; if (!stream.empty()) //don't dereference iterator into empty container! @@ -73,7 +72,7 @@ BinContainer compress(const BinContainer& stream, int level) //throw ZlibInterna stream.size(), &*contOut.begin() + contOut.size() - bufferEstimate, bufferEstimate, - level); //throw ZlibInternalError + level); //throw SysError if (bytesWritten < bufferEstimate) contOut.resize(contOut.size() - (bufferEstimate - bytesWritten)); //caveat: unsigned arithmetics //caveat: physical memory consumption still *unchanged*! @@ -83,7 +82,7 @@ BinContainer compress(const BinContainer& stream, int level) //throw ZlibInterna template <class BinContainer> -BinContainer decompress(const BinContainer& stream) //throw ZlibInternalError +BinContainer decompress(const BinContainer& stream) //throw SysError { BinContainer contOut; if (!stream.empty()) //don't dereference iterator into empty container! @@ -91,30 +90,30 @@ BinContainer decompress(const BinContainer& stream) //throw ZlibInternalError //retrieve size of uncompressed data uint64_t uncompressedSize = 0; //use portable number type! if (stream.size() < sizeof(uncompressedSize)) - throw ZlibInternalError(); + throw SysError(L"zlib error: stream size < 8"); std::memcpy(&uncompressedSize, &*stream.begin(), sizeof(uncompressedSize)); //attention: contOut MUST NOT be empty! Else it will pass a nullptr to zlib_decompress() => Z_STREAM_ERROR although "uncompressedSize == 0"!!! //secondary bug: don't dereference iterator into empty container! if (uncompressedSize == 0) //cannot be 0: compress() directly maps empty -> empty container skipping zlib! - throw ZlibInternalError(); + throw SysError(L"zlib error: uncompressed size == 0"); try { contOut.resize(static_cast<size_t>(uncompressedSize)); //throw std::bad_alloc } - catch (std::bad_alloc&) //most likely due to data corruption! + catch (const std::bad_alloc& e) //most likely due to data corruption! { - throw ZlibInternalError(); + throw SysError(L"zlib error: " + _("Out of memory.") + L" " + utfTo<std::wstring>(e.what())); } const size_t bytesWritten = impl::zlib_decompress(&*stream.begin() + sizeof(uncompressedSize), stream.size() - sizeof(uncompressedSize), &*contOut.begin(), - static_cast<size_t>(uncompressedSize)); //throw ZlibInternalError + static_cast<size_t>(uncompressedSize)); //throw SysError if (bytesWritten != static_cast<size_t>(uncompressedSize)) - throw ZlibInternalError(); + throw SysError(L"zlib error: bytes written != uncompressed size"); } return contOut; } |