#include "DeflateBlock.h" #include "ByteUtils.h" #include "AbstractChecksumCalculator.h" #include #include #include DeflateBlock::DeflateBlock(BitStream* inputStream, BitStream* outputStream) : mInputStream(inputStream), mOutputStream(outputStream) { } std::string DeflateBlock::getMetaData() const { std::stringstream sstr; sstr << "DeflateBlock Metadata \n"; sstr << "Final block: " << mInFinalBlock << '\n'; sstr << "Compression method: " << Deflate::toString(mCompressionMethod) << '\n'; sstr << "Uncompressed block length: " << mUncompressedBlockLength << '\n'; return sstr.str(); } void DeflateBlock::setIsFinalBlock(bool isFinal) { mInFinalBlock = isFinal; } bool DeflateBlock::isFinalBlock() const { return mInFinalBlock; } bool DeflateBlock::read() { auto working_byte = *mInputStream->readNextByte(); std::cout << mInputStream->logNextNBytes(11); std::cout << "DeflateBlock::read location " << mInputStream->logLocation(); unsigned char final_block{0}; mInputStream->readNextNBits(1, final_block); mInFinalBlock = bool(final_block); unsigned char compression_type{0}; mInputStream->readNextNBits(2, compression_type); mCompressionMethod = static_cast(compression_type); if (mCompressionMethod == Deflate::CompressionMethod::NONE) { return readUncompressedStream(); } else if(mCompressionMethod == Deflate::CompressionMethod::FIXED_HUFFMAN) { return readFixedHuffmanStream(); } else if(mCompressionMethod == Deflate::CompressionMethod::DYNAMIC_HUFFMAN) { return readDynamicHuffmanStream(); } return false; } bool DeflateBlock::readUncompressedStream() { auto byte0 = *mInputStream->readNextByte(); auto byte1 = *mInputStream->readNextByte(); mUncompressedBlockLength = (byte0 << 8) | byte1; std::cout << "Check block 0: " << ByteUtils::toString(byte0) << std::endl; std::cout << "Check block 1: " << ByteUtils::toString(byte1) << std::endl; auto byte2 = *mInputStream->readNextByte(); auto byte3 = *mInputStream->readNextByte(); uint16_t len_check = (byte2 << 8) | byte3; std::cout << "Check block 2: " << ByteUtils::toString(byte2) << std::endl; std::cout << "Check block 3: " << ByteUtils::toString(byte3) << std::endl; //if (!(byte0 ==(~byte2) && byte1 ==(~byte3))) //{ //std::cout << "Uncompressed block length check failed - aborting." << std::endl; //return false; //} //else //{ for(unsigned idx=0; idxwriteByte(*mInputStream->readNextByte()); } //} return true; } bool DeflateBlock::readFixedHuffmanStream() { std::cout << "Reading fixed huffman stream" << std::endl; mHuffmanStream = std::make_unique(mInputStream, mOutputStream); mHuffmanStream->generateFixedCodeMapping(); return mHuffmanStream->decode(); } bool DeflateBlock::readDynamicHuffmanStream() { mHuffmanStream = std::make_unique(mInputStream, mOutputStream); return mHuffmanStream->decode(); } void DeflateBlock::write(uint16_t datalength) { mUncompressedBlockLength = datalength; unsigned char working_block{0}; working_block |= static_cast(mInFinalBlock); working_block |= (static_cast(mCompressionMethod) << 1); if (mCompressionMethod == Deflate::CompressionMethod::NONE) { writeUncompressedStream(working_block, datalength); } else if (mCompressionMethod == Deflate::CompressionMethod::FIXED_HUFFMAN) { mOutputStream->writeNBits(working_block, 3); while(auto byte = mInputStream->readNextByte()) { mOutputStream->writeByte(*byte); } if (const auto& remaining_bits = mInputStream->getRemainingBits(); remaining_bits.second > 0) { mOutputStream->writeNBits(remaining_bits.first, remaining_bits.second); } } } void DeflateBlock::writeUncompressedStream(unsigned char working_byte, uint16_t datalength) { std::cout << "Writing compression block header " << ByteUtils::toString(working_byte) << std::endl; mOutputStream->writeByte(working_byte); std::cout << "Writing data length " << mUncompressedBlockLength << " " << ByteUtils::toString(mUncompressedBlockLength) << std::endl; mOutputStream->writeWord(datalength); std::cout << "Writing iverse data length " << ~mUncompressedBlockLength << " " << ByteUtils::toString(~mUncompressedBlockLength) << std::endl; mOutputStream->writeWord(static_cast(~mUncompressedBlockLength)); for(unsigned idx=0; idxreadNextByte(); //std::cout << "Writing next byte " << static_cast(byte) << std::endl; mOutputStream->writeByte(byte); } }