2018-12-28 18:15:26 +00:00
|
|
|
#include "ICompressionCodec.h"
|
|
|
|
|
|
|
|
#include <Compression/LZ4_decompress_faster.h>
|
2018-10-11 02:57:48 +00:00
|
|
|
#include <common/unaligned.h>
|
|
|
|
#include <Common/hex.h>
|
|
|
|
#include <IO/WriteHelpers.h>
|
|
|
|
#include <IO/ReadBufferFromFileBase.h>
|
|
|
|
#include <Common/typeid_cast.h>
|
|
|
|
#include <Compression/CompressionFactory.h>
|
|
|
|
|
2019-12-19 19:23:49 +00:00
|
|
|
|
2018-10-11 02:57:48 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int CANNOT_DECOMPRESS;
|
2019-12-19 19:23:49 +00:00
|
|
|
extern const int CORRUPTED_DATA;
|
2018-10-11 02:57:48 +00:00
|
|
|
}
|
|
|
|
|
2018-12-19 17:20:18 +00:00
|
|
|
|
2019-06-13 14:04:38 +00:00
|
|
|
UInt32 ICompressionCodec::compress(const char * source, UInt32 source_size, char * dest) const
|
2018-10-11 02:57:48 +00:00
|
|
|
{
|
2018-12-19 17:20:18 +00:00
|
|
|
dest[0] = getMethodByte();
|
|
|
|
UInt8 header_size = getHeaderSize();
|
|
|
|
/// Write data from header_size
|
|
|
|
UInt32 compressed_bytes_written = doCompressData(source, source_size, &dest[header_size]);
|
|
|
|
unalignedStore<UInt32>(&dest[1], compressed_bytes_written + header_size);
|
|
|
|
unalignedStore<UInt32>(&dest[5], source_size);
|
|
|
|
return header_size + compressed_bytes_written;
|
2018-10-11 02:57:48 +00:00
|
|
|
}
|
|
|
|
|
2018-12-19 17:20:18 +00:00
|
|
|
|
2019-06-13 14:04:38 +00:00
|
|
|
UInt32 ICompressionCodec::decompress(const char * source, UInt32 source_size, char * dest) const
|
2018-10-11 02:57:48 +00:00
|
|
|
{
|
2019-12-19 19:23:49 +00:00
|
|
|
UInt8 header_size = getHeaderSize();
|
|
|
|
|
|
|
|
if (source_size < header_size)
|
|
|
|
throw Exception("Can't decompress data: the compressed data size (" + toString(source_size)
|
|
|
|
+ ", this should include header size) is less than the header size (" + toString(header_size) + ")", ErrorCodes::CORRUPTED_DATA);
|
|
|
|
|
2020-01-03 14:39:24 +00:00
|
|
|
uint8_t method = source[0];
|
2018-12-19 17:20:18 +00:00
|
|
|
if (method != getMethodByte())
|
|
|
|
throw Exception("Can't decompress data with codec byte " + toString(method) + " from codec with byte " + toString(method), ErrorCodes::CANNOT_DECOMPRESS);
|
|
|
|
|
2019-08-26 14:39:49 +00:00
|
|
|
UInt32 decompressed_size = readDecompressedBlockSize(source);
|
2018-12-19 17:20:18 +00:00
|
|
|
doDecompressData(&source[header_size], source_size - header_size, dest, decompressed_size);
|
|
|
|
|
2019-08-11 08:01:02 +00:00
|
|
|
return decompressed_size;
|
2018-10-11 02:57:48 +00:00
|
|
|
}
|
|
|
|
|
2018-12-19 17:20:18 +00:00
|
|
|
UInt32 ICompressionCodec::readCompressedBlockSize(const char * source)
|
2018-10-11 02:57:48 +00:00
|
|
|
{
|
2018-12-19 17:20:18 +00:00
|
|
|
return unalignedLoad<UInt32>(&source[1]);
|
2018-10-11 02:57:48 +00:00
|
|
|
}
|
|
|
|
|
2018-12-19 17:20:18 +00:00
|
|
|
|
|
|
|
UInt32 ICompressionCodec::readDecompressedBlockSize(const char * source)
|
|
|
|
{
|
|
|
|
return unalignedLoad<UInt32>(&source[5]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-01-03 14:39:24 +00:00
|
|
|
uint8_t ICompressionCodec::readMethod(const char * source)
|
2018-12-19 17:20:18 +00:00
|
|
|
{
|
2020-01-03 14:39:24 +00:00
|
|
|
return static_cast<uint8_t>(source[0]);
|
2018-12-19 17:20:18 +00:00
|
|
|
}
|
|
|
|
|
2018-10-11 02:57:48 +00:00
|
|
|
}
|