/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include "FlateDecode.h"
#include "zlib.h"
#include "Utils.h"
#include
#include "core/memcheck.h"
using namespace merge_lib;
#define ZLIB_MEM_DELTA 65535
#define ZLIB_CHECK_ERR(err,msg) \
if( err != Z_OK) {\
std::cout<getHeader(head);
if( head.find(FilterPredictor::DECODE_PARAM_TOKEN) != -1 )
{
_predict = new FilterPredictor();
_predict->initialize(objectWithStream);
}
}
}
/** @brief encode
*
* @todo:
document this function
*/
bool FlateDecode::encode(std::string &decoded)
{
z_stream stream;
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
stream.opaque = (voidpf)0;
size_t out_len = 0;
unsigned char *out_p = NULL;
stream.next_out = out_p;
stream.avail_out = (uInt)out_len;
stream.next_in = (unsigned char*)decoded.c_str();
stream.avail_in = (uInt)decoded.size();
int err = deflateInit(&stream, Z_DEFAULT_COMPRESSION);
ZLIB_CHECK_ERR(err, "deflateInit");
if ( err != Z_OK )
{
return false;
}
bool toContinue = false;
int flush = Z_NO_FLUSH;
do
{
toContinue = false;
flush = (stream.avail_in == 0)?Z_FINISH:Z_NO_FLUSH;
if ( !stream.avail_out )
{
// increase the space
out_p = (unsigned char*)realloc(out_p,out_len + ZLIB_MEM_DELTA);
// init new memory
unsigned char *new_out_start = out_p + out_len;
memset(new_out_start,0,ZLIB_MEM_DELTA);
// Point next_out to the next unused byte
stream.next_out = new_out_start;
// Update the size of the buffer
stream.avail_out = (uInt)ZLIB_MEM_DELTA;
out_len += ZLIB_MEM_DELTA;
}
err = deflate(&stream,flush);
if ( err == Z_OK && stream.avail_out == 0 )
{
toContinue = true;
}
}
while ( toContinue || flush == Z_NO_FLUSH );
err = deflateEnd(&stream);
ZLIB_CHECK_ERR(err, "deflateEnd");
if( err != Z_OK )
{
free(out_p);
return false;
}
decoded = std::string((char*)out_p,stream.total_out);
free(out_p);
return true;
}
/** @brief decode
*
* @todo: document this function
*/
bool FlateDecode::decode(std::string & encoded)
{
z_stream stream;
//some initialization of ZLIB stuff
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
stream.opaque = (voidpf)0;
//trace_hex((char*)encoded.c_str(),encoded.size());
stream.next_in = (unsigned char*)encoded.c_str();
stream.avail_in = (uInt)encoded.size();
int err = inflateInit(&stream);
ZLIB_CHECK_ERR(err,"InflateInit");
if ( err != Z_OK )
{
return false;
}
unsigned char *out_p = NULL;
int out_len = 0;
stream.next_out = out_p;
stream.avail_out = out_len;
for (;;)
{
if ( !stream.avail_out)
{
// there is no more space for deallocation - increase the space
out_p = (unsigned char*)realloc(out_p,out_len + ZLIB_MEM_DELTA);
// init new memory
unsigned char *new_out_start = out_p + out_len;
memset(new_out_start,0,ZLIB_MEM_DELTA);
// Point next_out to the next unused byte
stream.next_out = new_out_start;
// Update the size of the uncompressed buffer
stream.avail_out = (uInt)ZLIB_MEM_DELTA;
out_len += ZLIB_MEM_DELTA;
}
err = inflate(&stream,Z_NO_FLUSH);
if ( err == Z_STREAM_END)
{
break;
}
ZLIB_CHECK_ERR(err,"Deflate");
if ( err != Z_OK )
{
if( out_p )
{
free(out_p);
}
return false;
}
}
err = inflateEnd(&stream);
ZLIB_CHECK_ERR(err,"InflateEnd");
if( err != Z_OK )
{
if( out_p )
{
free(out_p);
}
return false;
}
encoded = std::string((char*)out_p,stream.total_out);
free(out_p);
// trace_hex((char*)encoded.c_str(),encoded.size());
// if predictor exists for that object, then lets decode it
if( _predict )
{
_predict->decode(encoded);
}
return true;
}