/* * 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; }