2018-12-28 18:15:26 +00:00
# include "ICompressionCodec.h"
2020-07-09 01:00:16 +00:00
# include <cassert>
2020-08-26 08:59:02 +00:00
# include <Parsers/ASTFunction.h>
2018-10-11 02:57:48 +00:00
# include <common/unaligned.h>
2020-07-09 01:00:16 +00:00
# include <Common/Exception.h>
2018-10-11 02:57:48 +00:00
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
}
2020-08-26 08:59:02 +00:00
ASTPtr ICompressionCodec : : getFullCodecDesc ( ) const
{
std : : shared_ptr < ASTFunction > result = std : : make_shared < ASTFunction > ( ) ;
result - > name = " CODEC " ;
result - > arguments = getCodecDesc ( ) ;
return result ;
}
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
{
2020-06-05 12:02:38 +00:00
assert ( source ! = nullptr & & dest ! = nullptr ) ;
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
{
2020-06-05 12:02:38 +00:00
assert ( source ! = nullptr & & dest ! = nullptr ) ;
2019-12-19 19:23:49 +00:00
2020-06-05 12:02:38 +00:00
UInt8 header_size = getHeaderSize ( ) ;
2019-12-19 19:23:49 +00:00
if ( source_size < header_size )
2020-07-09 01:00:16 +00:00
throw Exception ( ErrorCodes : : CORRUPTED_DATA , " Can't decompress data: the compressed data size ({}) , this should include header size ) is less than the header size ( { } ) " , source_size, size_t(header_size));
2019-12-19 19:23:49 +00:00
2020-07-09 01:00:16 +00:00
uint8_t our_method = getMethodByte ( ) ;
2020-01-03 14:39:24 +00:00
uint8_t method = source [ 0 ] ;
2020-07-09 01:00:16 +00:00
if ( method ! = our_method )
throw Exception ( ErrorCodes : : CANNOT_DECOMPRESS , " Can't decompress data with codec byte {} using codec with byte {} " , method , our_method ) ;
2018-12-19 17:20:18 +00:00
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
}