void LZ4Segment<T>::_decompress_block_to_bytes(const size_t block_index, std::vector<char>& decompressed_data, const size_t write_offset) const { const auto decompressed_block_size = block_index + 1 != _lz4_blocks.size() ? _block_size : _last_block_size; auto& compressed_block = _lz4_blocks[block_index]; const auto compressed_block_size = compressed_block.size(); int decompressed_result; if (_dictionary.empty()) { /** * If the dictionary is empty, we either have only a single block or had not enough data for a dictionary. * When decoding without a dictionary LZ4 needs a stream decode pointer (which would be used to decode the * following blocks). * A new decoder needs to be created for every block (in the case of multiple blocks being compressed without a * dictionary) since the blocks were compressed independently. * This decoder needs to be reset via LZ4_setStreamDecode since LZ4 reuses the previous state instead. */ LZ4_streamDecode_t lz4_stream_decoder; auto lz4_stream_decoder_ptr = std::make_unique<LZ4_streamDecode_t>(lz4_stream_decoder); const auto reset_decoder_status = LZ4_setStreamDecode(lz4_stream_decoder_ptr.get(), nullptr, 0); Assert(reset_decoder_status == 1, "LZ4 decompression failed to reset stream decoder."); decompressed_result = LZ4_decompress_safe_continue( lz4_stream_decoder_ptr.get(), compressed_block.data(), decompressed_data.data() + write_offset, static_cast<int>(compressed_block_size), static_cast<int>(decompressed_block_size)); } else { decompressed_result = LZ4_decompress_safe_usingDict( compressed_block.data(), decompressed_data.data() + write_offset, static_cast<int>(compressed_block_size), static_cast<int>(decompressed_block_size), _dictionary.data(), static_cast<int>(_dictionary.size())); } Assert(decompressed_result > 0, "LZ4 stream decompression failed"); DebugAssert(static_cast<size_t>(decompressed_result) == decompressed_block_size, "Decompressed LZ4 block has different size than the initial source data."); }
LZ4Decompressor::LZ4Decompressor(StreamReader *read, Ownership own) : Decompressor(read, own) { m_Page[0] = AllocAlignedBuffer(lz4BlockSize); m_Page[1] = AllocAlignedBuffer(lz4BlockSize); m_CompressBuffer = AllocAlignedBuffer(LZ4_COMPRESSBOUND(lz4BlockSize)); m_PageOffset = 0; m_PageLength = 0; LZ4_setStreamDecode(&m_LZ4Decomp, NULL, 0); }
void lz4_unpack(void * in, const size_t * const compSize, void * const out, int * const size, const int * const ierr) { size_t offset=0; size_t offset_in=0; decBufIndex=0; LZ4_resetStream(lz4Stream); LZ4_setStreamDecode(lz4StreamDecode,NULL,0); for(;;) { char cmpBuf[LZ4_COMPRESSBOUND(BLOCK_BYTES)]; int cmpBytes = 0; /*printf("offset_in+sizeof(cmpBytes): %d\n",offset_in+sizeof(cmpBytes));*/ /*printf("compSize: %d\n",*compSize);*/ int tmp=offset_in+sizeof(cmpBytes); /*printf("tmp: %d\n", tmp);*/ /*printf("compSize: %d\n", *compSize);*/ if(tmp > (int) *compSize) { break; } memcpy(&cmpBytes, in+offset_in, sizeof(cmpBytes)); /*printf("cmpBytes: %d\n",cmpBytes);*/ if(cmpBytes <= 0) { /*printf("cmpBytes %d\n", cmpBytes);*/ break; } /*printf("lz4 cmpBytes %d\n", cmpBytes);*/ memcpy(&cmpBuf, in+offset_in+sizeof(cmpBytes), cmpBytes); const size_t readCount1=0; offset_in=offset_in+sizeof(cmpBytes)+cmpBytes; /*printf("new offset_in: %zu\n", offset_in);*/ { char* decPtr = decBuf[decBufIndex]; int decBytes = LZ4_decompress_safe_continue( lz4StreamDecode, cmpBuf, decPtr, cmpBytes, BLOCK_BYTES); if(decBytes <= 0) { /*printf("lz4 decBytes: %d\n", decBytes);*/ break; } memcpy(out+offset, decPtr, (size_t) decBytes); offset=offset+(size_t) decBytes; } decBufIndex = (decBufIndex + 1) % 2; } *size=offset; }
void test_decompress(FILE* outFp, FILE* inpFp) { LZ4_streamDecode_t lz4StreamDecode_body; LZ4_streamDecode_t* lz4StreamDecode = &lz4StreamDecode_body; char decBuf[2][BLOCK_BYTES]; int decBufIndex = 0; LZ4_setStreamDecode(lz4StreamDecode, NULL, 0); for(;;) { char cmpBuf[LZ4_COMPRESSBOUND(BLOCK_BYTES)]; int cmpBytes = 0; { const size_t readCount0 = read_int(inpFp, &cmpBytes); if(readCount0 != 1 || cmpBytes <= 0) { break; } const size_t readCount1 = read_bin(inpFp, cmpBuf, (size_t) cmpBytes); if(readCount1 != (size_t) cmpBytes) { break; } } { char* const decPtr = decBuf[decBufIndex]; const int decBytes = LZ4_decompress_safe_continue( lz4StreamDecode, cmpBuf, decPtr, cmpBytes, BLOCK_BYTES); if(decBytes <= 0) { break; } write_bin(outFp, decPtr, (size_t) decBytes); } decBufIndex = (decBufIndex + 1) % 2; } }
void decompressFile(FILE* outFp, FILE* inpFp) { LZ4_streamDecode_t lz4StreamDecode_body; LZ4_streamDecode_t* lz4StreamDecode = &lz4StreamDecode_body; char decBuf[2][BLOCK_BYTES]; int decBufIndex = 0; LZ4_setStreamDecode(lz4StreamDecode, NULL, 0); while(1) { char cmpBuf[LZ4_COMPRESSBOUND(BLOCK_BYTES)]; int cmpBytes = 0; { const size_t readCount0 = intRead(inpFp, &cmpBytes); if((readCount0 != 1) || (cmpBytes <= 0)) { break; } const size_t readCount1 = binRead(inpFp, cmpBuf, (size_t) cmpBytes); if(readCount1 != (size_t) cmpBytes) { break; } } { char* const decPtr = decBuf[decBufIndex]; const int decBytes = LZ4_decompress_safe_continue(lz4StreamDecode, cmpBuf, decPtr, cmpBytes, BLOCK_BYTES); if(decBytes <= 0) { break; } binWrite(outFp, decPtr, (size_t) decBytes); } decBufIndex = (decBufIndex + 1) % 2; } }