#include "Lz77Encoder.h" #include "StringUtils.h" #include "BitStream.h" #include "ByteUtils.h" #include "HuffmanEncoder.h" #include Lz77Encoder::Lz77Encoder(BitStream* inputStream, BitStream* outputStream) : AbstractEncoder(inputStream, outputStream) { } unsigned Lz77Encoder::lookAheadForMatchingChars(std::vector& matchBuffer, unsigned searchIndex, unsigned hitOffset, const std::string& stream, unsigned streamLoc) { auto remaining_size = stream.size() - streamLoc; unsigned num_hits{1}; for (unsigned jdx=1; jdx< remaining_size; jdx++) { char buffer_char{0}; if (searchIndex + jdx < mSearchBuffer.size()) { buffer_char = mSearchBuffer[searchIndex + jdx]; } else { buffer_char = stream[jdx - hitOffset]; } auto lookahead_char = stream[streamLoc + jdx]; if (lookahead_char == buffer_char) { matchBuffer.push_back(buffer_char); num_hits++; } else { break; } } return num_hits; } void Lz77Encoder::lookThroughSearchBuffer(char searchChar, unsigned& hitLength, unsigned& hitOffset, const std::string& stream, unsigned streamLoc) { for(unsigned idx=0; idx match_buffer{buffer_char}; auto num_hits = lookAheadForMatchingChars(match_buffer, search_index, idx, stream, streamLoc); if (num_hits >= hitLength) { hitLength = num_hits; hitOffset = idx + 1; } } } } void Lz77Encoder::setPrefixCodeGenerator(std::unique_ptr generator) { mCodeGenerator = std::move(generator); } bool Lz77Encoder::encode() { if (!mCodeGenerator) { auto code_generator = std::make_unique(); auto huffman_encoder = code_generator.get(); mCodeGenerator = std::move(code_generator); huffman_encoder->setUseFixedCode(true); huffman_encoder->initializeLiteralLengthTable(); } while(auto byte = mInputStream->readNextByte()) { const auto code = mCodeGenerator->getLiteralValue(*byte); std::cout << "Writing value " << static_cast(*byte) << " with code " << ByteUtils::toString(code.getData(), code.getLength()) << "\n"; mOutputStream->writeNBits(code.getData(), code.getLength()); } auto eos_code = mCodeGenerator->getEndOfStreamValue(); std::cout << "Writing EOS value with code " << ByteUtils::toString(eos_code.getData(), eos_code.getLength()) << "\n"; mOutputStream->writeNBits(eos_code.getData(), eos_code.getLength()); /* unsigned loc{0}; std::string ret; while(!mInputStream->isFinished()) { auto search_char = stream[loc]; unsigned hit_length{0}; unsigned hit_offset{0}; lookThroughSearchBuffer(search_char, hit_length, hit_offset, stream, loc); if (hit_length > 0) { ret += "@" + std::to_string(hit_offset) + "L" + std::to_string(hit_length); loc+=hit_length; auto hit_loc = mSearchBuffer.size() - hit_offset; for(unsigned idx=hit_loc; idx