170 lines
4.2 KiB
C++
170 lines
4.2 KiB
C++
#include "Lz77Encoder.h"
|
|
|
|
#include "StringUtils.h"
|
|
#include "BitStream.h"
|
|
|
|
Lz77Encoder::Lz77Encoder(BitStream* inputStream, BitStream* outputStream)
|
|
: AbstractEncoder(inputStream, outputStream)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
unsigned Lz77Encoder::lookAheadForMatchingChars(std::vector<char>& 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<mSearchBuffer.size(); idx++)
|
|
{
|
|
auto search_index = mSearchBuffer.size() - idx - 1;
|
|
|
|
if (auto buffer_char = mSearchBuffer[search_index]; buffer_char == searchChar)
|
|
{
|
|
std::vector<char> 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool Lz77Encoder::encode()
|
|
{
|
|
/*
|
|
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<hit_loc + hit_length; idx++)
|
|
{
|
|
mSearchBuffer.push_back(mSearchBuffer[idx]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ret += search_char;
|
|
mSearchBuffer.push_back(search_char);
|
|
loc++;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
*/
|
|
return false;
|
|
}
|
|
|
|
bool Lz77Encoder::decode()
|
|
{
|
|
/*
|
|
std::string ret;
|
|
|
|
unsigned loc{0};
|
|
while(loc < stream.size())
|
|
{
|
|
auto working_char = stream[loc];
|
|
if (working_char == '@')
|
|
{
|
|
unsigned loc_working = loc;
|
|
|
|
auto remainder = stream.size() - loc;
|
|
std::string offset;
|
|
|
|
unsigned length_loc{0};
|
|
for(unsigned jdx=0; jdx< remainder; jdx++)
|
|
{
|
|
loc++;
|
|
|
|
auto offset_char = stream[loc];
|
|
if (offset_char == 'L')
|
|
{
|
|
loc++;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
offset += offset_char;
|
|
}
|
|
}
|
|
unsigned offset_amount = std::stoul(offset);
|
|
|
|
std::string length;
|
|
remainder = stream.size() - loc;
|
|
|
|
for(unsigned jdx=0; jdx< remainder; jdx++)
|
|
{
|
|
auto length_char = stream[loc];
|
|
if (StringUtils::IsAlphabetical(length_char) || length_char == '@')
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
loc++;
|
|
length += length_char;
|
|
}
|
|
}
|
|
|
|
unsigned length_amount = std::stoul(length);
|
|
|
|
auto buffer_index = ret.size() - offset_amount;
|
|
for(unsigned jdx=buffer_index;jdx<buffer_index+length_amount; jdx++)
|
|
{
|
|
ret += ret[jdx];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
loc++;
|
|
ret += working_char;
|
|
}
|
|
}
|
|
return ret;
|
|
*/
|
|
return false;
|
|
}
|