2013-04-16 23:59:37 -04:00
/* -*- mode: C; c-basic-offset: 4 -*- */
# ident "Copyright (c) 2011 Tokutek Inc. All rights reserved."
# ident "$Id$"
# include <zlib.h>
# include "compress.h"
# include "memory.h"
# include "quicklz.h"
# include "toku_assert.h"
size_t toku_compress_bound ( enum toku_compression_method a , size_t size )
// See compress.h for the specification of this function.
{
switch ( a ) {
case TOKU_QUICKLZ_METHOD :
return size + 400 + 1 ; // quicklz manual says 400 bytes is enough. We need one more byte for the rfc1950-style header byte. bits 0-3 are 9, bits 4-7 are the QLZ_COMPRESSION_LEVEL.
case TOKU_ZLIB_METHOD :
return compressBound ( size ) ;
}
// fall through for bad enum (thus compiler can warn us if we didn't use all the enums
2013-04-16 23:59:39 -04:00
assert ( 0 ) ; return 0 ;
2013-04-16 23:59:37 -04:00
}
static const int zlib_compression_level = 5 ;
void toku_compress ( enum toku_compression_method a ,
// the following types and naming conventions come from zlib.h
Bytef * dest , uLongf * destLen ,
const Bytef * source , uLong sourceLen )
// See compress.h for the specification of this function.
{
assert ( sourceLen < ( 1LL < < 32 ) ) ;
switch ( a ) {
case TOKU_ZLIB_METHOD : {
int r = compress2 ( dest , destLen , source , sourceLen , zlib_compression_level ) ;
assert ( r = = Z_OK ) ;
assert ( ( dest [ 0 ] & 0xF ) = = TOKU_ZLIB_METHOD ) ;
return ;
}
case TOKU_QUICKLZ_METHOD : {
if ( sourceLen = = 0 ) {
// quicklz requires at least one byte, so we handle this ourselves
assert ( 1 < = * destLen ) ;
* destLen = 1 ;
} else {
2013-04-16 23:59:37 -04:00
qlz_state_compress * XMALLOC ( qsc ) ;
2013-04-16 23:59:37 -04:00
size_t actual_destlen = qlz_compress ( source , ( char * ) ( dest + 1 ) , sourceLen , qsc ) ;
assert ( actual_destlen + 1 < = * destLen ) ;
* destLen = actual_destlen + 1 ; // add one for the rfc1950-style header byte.
toku_free ( qsc ) ;
}
// Fill in that first byte
dest [ 0 ] = TOKU_QUICKLZ_METHOD + ( QLZ_COMPRESSION_LEVEL < < 4 ) ;
return ;
} }
// default fall through to error.
assert ( 0 ) ;
}
void toku_decompress ( Bytef * dest , uLongf destLen ,
const Bytef * source , uLongf sourceLen )
// See compress.h for the specification of this function.
{
assert ( sourceLen > = 1 ) ; // need at least one byte for the RFC header.
switch ( source [ 0 ] & 0xF ) {
case TOKU_ZLIB_METHOD : {
uLongf actual_destlen = destLen ;
int r = uncompress ( dest , & actual_destlen , source , sourceLen ) ;
assert ( r = = Z_OK ) ;
assert ( actual_destlen = = destLen ) ;
return ;
}
case TOKU_QUICKLZ_METHOD :
if ( sourceLen > 1 ) {
2013-04-16 23:59:37 -04:00
qlz_state_decompress * XMALLOC ( qsd ) ;
2013-04-16 23:59:37 -04:00
uLongf actual_destlen = qlz_decompress ( ( char * ) source + 1 , dest , qsd ) ;
assert ( actual_destlen = = destLen ) ;
toku_free ( qsd ) ;
} else {
// length 1 means there is no data, so do nothing.
assert ( destLen = = 0 ) ;
}
return ;
}
// default fall through to error.
assert ( 0 ) ;
}