ClickHouse/src/IO/BrotliReadBuffer.cpp

98 lines
2.3 KiB
C++
Raw Normal View History

#if !defined(ARCADIA_BUILD)
# include <Common/config.h>
#endif
2019-02-13 14:47:24 +00:00
#if USE_BROTLI
# include <brotli/decode.h>
# include "BrotliReadBuffer.h"
namespace DB
{
2019-02-11 20:42:46 +00:00
2019-04-10 16:12:31 +00:00
namespace ErrorCodes
{
extern const int BROTLI_READ_FAILED;
}
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);
}
BrotliDecoderState * state;
BrotliDecoderResult result;
};
2019-11-19 13:57:54 +00:00
BrotliReadBuffer::BrotliReadBuffer(std::unique_ptr<ReadBuffer> in_, size_t buf_size, char *existing_memory, size_t alignment)
: BufferWithOwnMemory<ReadBuffer>(buf_size, existing_memory, alignment)
2019-11-19 13:57:54 +00:00
, in(std::move(in_))
, brotli(std::make_unique<BrotliStateWrapper>())
, in_available(0)
, in_data(nullptr)
, out_capacity(0)
, out_data(nullptr)
, eof(false)
{
}
2020-03-08 21:18:53 +00:00
BrotliReadBuffer::~BrotliReadBuffer() = default;
bool BrotliReadBuffer::nextImpl()
{
if (eof)
return false;
if (!in_available)
{
2019-11-19 13:57:54 +00:00
in->nextIfAtEnd();
in_available = in->buffer().end() - in->position();
in_data = reinterpret_cast<uint8_t *>(in->position());
}
2019-11-19 13:57:54 +00:00
if (brotli->result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT && (!in_available || in->eof()))
{
2019-04-10 16:12:31 +00:00
throw Exception("brotli decode error", ErrorCodes::BROTLI_READ_FAILED);
}
out_capacity = internal_buffer.size();
out_data = reinterpret_cast<uint8_t *>(internal_buffer.begin());
2019-02-11 20:42:46 +00:00
brotli->result = BrotliDecoderDecompressStream(brotli->state, &in_available, &in_data, &out_capacity, &out_data, nullptr);
2019-11-19 13:57:54 +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-11-19 13:57:54 +00:00
if (in->eof())
{
eof = true;
2021-02-04 23:14:17 +00:00
return !working_buffer.empty();
}
else
{
2019-04-10 16:12:31 +00:00
throw Exception("brotli decode error", ErrorCodes::BROTLI_READ_FAILED);
}
}
2019-02-11 20:42:46 +00:00
if (brotli->result == BROTLI_DECODER_RESULT_ERROR)
{
2019-04-10 16:12:31 +00:00
throw Exception("brotli decode error", ErrorCodes::BROTLI_READ_FAILED);
}
return true;
}
2019-02-06 06:05:41 +00:00
}
2019-02-13 14:47:24 +00:00
#endif