2017-04-01 09:19:00 +00:00
|
|
|
#include <IO/ZlibInflatingReadBuffer.h>
|
2017-01-07 16:11:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
ZlibInflatingReadBuffer::ZlibInflatingReadBuffer(
|
2017-04-01 07:20:54 +00:00
|
|
|
ReadBuffer & in_,
|
2019-02-13 20:54:12 +00:00
|
|
|
CompressionMethod compression_method,
|
2017-04-01 07:20:54 +00:00
|
|
|
size_t buf_size,
|
|
|
|
char * existing_memory,
|
|
|
|
size_t alignment)
|
|
|
|
: BufferWithOwnMemory<ReadBuffer>(buf_size, existing_memory, alignment)
|
|
|
|
, in(in_)
|
|
|
|
, eof(false)
|
2017-01-07 16:11:30 +00:00
|
|
|
{
|
2018-11-26 00:56:50 +00:00
|
|
|
zstr.zalloc = nullptr;
|
|
|
|
zstr.zfree = nullptr;
|
|
|
|
zstr.opaque = nullptr;
|
|
|
|
zstr.next_in = nullptr;
|
|
|
|
zstr.avail_in = 0;
|
|
|
|
zstr.next_out = nullptr;
|
2017-04-01 07:20:54 +00:00
|
|
|
zstr.avail_out = 0;
|
2017-01-07 16:11:30 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
int window_bits = 15;
|
2019-02-13 20:54:12 +00:00
|
|
|
if (compression_method == CompressionMethod::Gzip)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
window_bits += 16;
|
|
|
|
}
|
2017-01-07 16:11:30 +00:00
|
|
|
|
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
2017-04-01 07:20:54 +00:00
|
|
|
int rc = inflateInit2(&zstr, window_bits);
|
2017-01-07 16:11:30 +00:00
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
if (rc != Z_OK)
|
2017-11-30 17:09:33 +00:00
|
|
|
throw Exception(std::string("inflateInit2 failed: ") + zError(rc) + "; zlib version: " + ZLIB_VERSION, ErrorCodes::ZLIB_INFLATE_FAILED);
|
2017-01-07 16:11:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ZlibInflatingReadBuffer::~ZlibInflatingReadBuffer()
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
inflateEnd(&zstr);
|
2017-01-07 16:11:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool ZlibInflatingReadBuffer::nextImpl()
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
if (eof)
|
|
|
|
return false;
|
2017-01-07 16:11:30 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
if (!zstr.avail_in)
|
|
|
|
{
|
|
|
|
in.nextIfAtEnd();
|
|
|
|
zstr.next_in = reinterpret_cast<unsigned char *>(in.position());
|
|
|
|
zstr.avail_in = in.buffer().end() - in.position();
|
|
|
|
}
|
|
|
|
zstr.next_out = reinterpret_cast<unsigned char *>(internal_buffer.begin());
|
|
|
|
zstr.avail_out = internal_buffer.size();
|
2017-01-07 16:11:30 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
int rc = inflate(&zstr, Z_NO_FLUSH);
|
2017-01-07 16:11:30 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
in.position() = in.buffer().end() - zstr.avail_in;
|
|
|
|
working_buffer.resize(internal_buffer.size() - zstr.avail_out);
|
2017-01-07 16:11:30 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
if (rc == Z_STREAM_END)
|
|
|
|
{
|
|
|
|
if (in.eof())
|
|
|
|
{
|
|
|
|
eof = true;
|
|
|
|
return working_buffer.size() != 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-08-26 02:13:41 +00:00
|
|
|
rc = inflateReset(&zstr);
|
2017-04-01 07:20:54 +00:00
|
|
|
if (rc != Z_OK)
|
|
|
|
throw Exception(std::string("inflateReset failed: ") + zError(rc), ErrorCodes::ZLIB_INFLATE_FAILED);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (rc != Z_OK)
|
|
|
|
throw Exception(std::string("inflate failed: ") + zError(rc), ErrorCodes::ZLIB_INFLATE_FAILED);
|
2017-01-07 16:11:30 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
return true;
|
2017-01-07 16:11:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|