2010-06-04 18:25:25 +00:00
|
|
|
#ifndef DBMS_COMMON_COMPRESSED_READBUFFER_H
|
|
|
|
#define DBMS_COMMON_COMPRESSED_READBUFFER_H
|
|
|
|
|
2010-06-07 12:48:32 +00:00
|
|
|
#include <vector>
|
2010-06-04 18:25:25 +00:00
|
|
|
#include <algorithm>
|
|
|
|
|
2011-06-17 20:44:10 +00:00
|
|
|
#include <snappy.h>
|
2010-06-04 18:25:25 +00:00
|
|
|
|
|
|
|
#include <DB/Core/Exception.h>
|
|
|
|
#include <DB/Core/ErrorCodes.h>
|
|
|
|
#include <DB/IO/ReadBuffer.h>
|
2011-06-17 20:44:10 +00:00
|
|
|
#include <DB/IO/VarInt.h>
|
|
|
|
|
|
|
|
|
|
|
|
/// Если сжатый кусок больше 1GB - значит ошибка
|
|
|
|
#define DB_COMPRESSED_BUFFER_MAX_COMPRESSED_SIZE 0x40000000
|
2010-06-04 18:25:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
class CompressedReadBuffer : public ReadBuffer
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
ReadBuffer & in;
|
|
|
|
|
|
|
|
std::vector<char> compressed_buffer;
|
|
|
|
|
|
|
|
public:
|
|
|
|
CompressedReadBuffer(ReadBuffer & in_)
|
2011-06-17 20:44:10 +00:00
|
|
|
: in(in_)
|
2010-06-04 18:25:25 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-06-17 20:44:10 +00:00
|
|
|
bool next()
|
2010-06-04 18:25:25 +00:00
|
|
|
{
|
2011-06-17 20:44:10 +00:00
|
|
|
if (in.eof())
|
|
|
|
return false;
|
2010-06-04 18:25:25 +00:00
|
|
|
|
2011-06-17 20:44:10 +00:00
|
|
|
size_t size_compressed = 0;
|
|
|
|
readVarUInt(size_compressed, in);
|
|
|
|
if (size_compressed == 0)
|
|
|
|
throw Exception("Too small size_compressed", ErrorCodes::TOO_SMALL_SIZE_COMPRESSED);
|
|
|
|
if (size_compressed > DB_COMPRESSED_BUFFER_MAX_COMPRESSED_SIZE)
|
|
|
|
throw Exception("Too large size_compressed", ErrorCodes::TOO_LARGE_SIZE_COMPRESSED);
|
2010-06-04 18:25:25 +00:00
|
|
|
|
|
|
|
compressed_buffer.resize(size_compressed);
|
2011-06-17 20:44:10 +00:00
|
|
|
in.readStrict(&compressed_buffer[0], size_compressed);
|
2010-06-07 12:48:32 +00:00
|
|
|
|
2011-06-17 20:44:10 +00:00
|
|
|
size_t size_decompressed = 0;
|
|
|
|
if (!snappy::GetUncompressedLength(&compressed_buffer[0], size_compressed, &size_decompressed))
|
|
|
|
throw Exception("Cannot decompress corrupted data", ErrorCodes::CANNOT_DECOMPRESS_CORRUPTED_DATA);
|
2010-06-07 17:14:13 +00:00
|
|
|
|
2011-06-17 20:44:10 +00:00
|
|
|
internal_buffer.resize(size_decompressed);
|
2010-06-07 12:48:32 +00:00
|
|
|
|
2011-06-17 20:44:10 +00:00
|
|
|
if (!snappy::RawUncompress(&compressed_buffer[0], size_compressed, &internal_buffer[0]))
|
|
|
|
throw Exception("Cannot decompress corrupted data", ErrorCodes::CANNOT_DECOMPRESS_CORRUPTED_DATA);
|
2010-06-04 18:25:25 +00:00
|
|
|
|
2011-06-17 20:44:10 +00:00
|
|
|
working_buffer = Buffer(working_buffer.begin(), working_buffer.begin() + size_decompressed);
|
2011-05-13 19:40:56 +00:00
|
|
|
pos = working_buffer.begin();
|
2010-06-04 18:25:25 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-06-17 20:44:10 +00:00
|
|
|
#undef DB_COMPRESSED_BUFFER_MAX_COMPRESSED_SIZE
|
|
|
|
|
2010-06-04 18:25:25 +00:00
|
|
|
#endif
|