2019-02-13 14:47:24 +00:00
|
|
|
#include <Common/config.h>
|
|
|
|
#if USE_BROTLI
|
|
|
|
|
2019-02-04 22:15:08 +00:00
|
|
|
#include "BrotliReadBuffer.h"
|
2019-02-27 16:52:08 +00:00
|
|
|
#include <brotli/decode.h> // Y_IGNORE
|
2019-02-04 22:15:08 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
2019-02-11 20:42:46 +00:00
|
|
|
|
|
|
|
class BrotliReadBuffer::BrotliStateWrapper
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
BrotliStateWrapper()
|
|
|
|
: state(BrotliDecoderCreateInstance(nullptr, nullptr, nullptr))
|
|
|
|
, result(BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
~BrotliStateWrapper()
|
|
|
|
{
|
|
|
|
BrotliDecoderDestroyInstance(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
BrotliDecoderState * state;
|
|
|
|
BrotliDecoderResult result;
|
|
|
|
};
|
|
|
|
|
2019-02-04 22:15:08 +00:00
|
|
|
BrotliReadBuffer::BrotliReadBuffer(ReadBuffer &in_, size_t buf_size, char *existing_memory, size_t alignment)
|
|
|
|
: BufferWithOwnMemory<ReadBuffer>(buf_size, existing_memory, alignment)
|
|
|
|
, in(in_)
|
2019-02-11 20:42:46 +00:00
|
|
|
, brotli(new BrotliStateWrapper())
|
2019-02-05 23:12:31 +00:00
|
|
|
, in_available(0)
|
|
|
|
, in_data(nullptr)
|
|
|
|
, out_capacity(0)
|
|
|
|
, out_data(nullptr)
|
2019-02-04 22:15:08 +00:00
|
|
|
, eof(false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
BrotliReadBuffer::~BrotliReadBuffer()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BrotliReadBuffer::nextImpl()
|
|
|
|
{
|
|
|
|
if (eof)
|
|
|
|
return false;
|
|
|
|
|
2019-02-05 23:12:31 +00:00
|
|
|
if (!in_available)
|
|
|
|
{
|
|
|
|
in.nextIfAtEnd();
|
|
|
|
in_available = in.buffer().end() - in.position();
|
|
|
|
in_data = reinterpret_cast<uint8_t *>(in.position());
|
|
|
|
}
|
|
|
|
|
2019-02-11 20:42:46 +00:00
|
|
|
if (brotli->result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT && (!in_available || in.eof()))
|
2019-02-05 23:12:31 +00:00
|
|
|
{
|
|
|
|
throw Exception(std::string("brotli decode error"), ErrorCodes::CANNOT_READ_ALL_DATA);
|
|
|
|
}
|
2019-02-04 22:15:08 +00:00
|
|
|
|
2019-02-05 23:12:31 +00:00
|
|
|
out_capacity = internal_buffer.size();
|
|
|
|
out_data = reinterpret_cast<uint8_t *>(internal_buffer.begin());
|
2019-02-04 22:15:08 +00:00
|
|
|
|
2019-02-11 20:42:46 +00:00
|
|
|
brotli->result = BrotliDecoderDecompressStream(brotli->state, &in_available, &in_data, &out_capacity, &out_data, nullptr);
|
2019-02-04 22:15:08 +00:00
|
|
|
|
2019-02-05 23:12:31 +00:00
|
|
|
in.position() = in.buffer().end() - in_available;
|
|
|
|
working_buffer.resize(internal_buffer.size() - out_capacity);
|
|
|
|
|
2019-02-11 20:42:46 +00:00
|
|
|
if (brotli->result == BROTLI_DECODER_RESULT_SUCCESS)
|
2019-02-05 23:12:31 +00:00
|
|
|
{
|
|
|
|
if (in.eof())
|
|
|
|
{
|
|
|
|
eof = true;
|
|
|
|
return working_buffer.size() != 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw Exception(std::string("brotli decode error"), ErrorCodes::CANNOT_READ_ALL_DATA);
|
|
|
|
}
|
|
|
|
}
|
2019-02-04 22:15:08 +00:00
|
|
|
|
2019-02-11 20:42:46 +00:00
|
|
|
if (brotli->result == BROTLI_DECODER_RESULT_ERROR)
|
2019-02-05 23:12:31 +00:00
|
|
|
{
|
|
|
|
throw Exception(std::string("brotli decode error"), ErrorCodes::CANNOT_READ_ALL_DATA);
|
2019-02-04 22:15:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2019-02-06 06:05:41 +00:00
|
|
|
}
|
|
|
|
|
2019-02-13 14:47:24 +00:00
|
|
|
#endif
|