#include "LZ77/LZLookupTable.hpp" #include LZLookupTable::LZLookupTable() : m_buffer(m_minimumMatch) {} LZLookupTable::LZLookupTable(int32_t minimumMatch, int32_t slidingWindow, int32_t lookAheadWindow) { if (minimumMatch > 0) m_minimumMatch = minimumMatch; else m_minimumMatch = 3; if (slidingWindow > 0) m_slidingWindow = slidingWindow; else m_slidingWindow = 4096; setLookAheadWindow(lookAheadWindow); m_buffer.reserve(m_minimumMatch); } LZLookupTable::~LZLookupTable() = default; void LZLookupTable::setLookAheadWindow(int32_t lookAheadWindow) { if (lookAheadWindow > 0) m_lookAheadWindow = lookAheadWindow; else m_lookAheadWindow = 18; } LZLengthOffset LZLookupTable::search(const uint8_t* curPos, const uint8_t* dataBegin, const uint8_t* dataEnd) { LZLengthOffset loPair = {0, 0}; // Returns negative 1 for search failures since the current position is passed the size to be compressed if (curPos >= dataEnd) { loPair.length = -1; return loPair; } std::copy(curPos, curPos + m_minimumMatch, m_buffer.begin()); int32_t currentOffset = static_cast(curPos - dataBegin); // Find code if (currentOffset > 0 && (dataEnd - curPos) >= m_minimumMatch) { auto elements = table.equal_range(m_buffer); elements.second--; elements.first--; // Iterate over keys in reverse order. C++11 guarantees that the relative order of elements is maintained for the // same key for (auto iter = elements.second; iter != elements.first; iter--) { int32_t matchLength = m_minimumMatch; int32_t lookAheadBufferLength = ((dataEnd - curPos) < m_lookAheadWindow) ? static_cast(dataEnd - curPos) : m_lookAheadWindow; for (; matchLength < lookAheadBufferLength; ++matchLength) { if (*(dataBegin + iter->second + matchLength) != *(curPos + matchLength)) break; } // Store the longest match found so far into length_offset struct. // When lengths are the same the closer offset to the lookahead buffer wins if (loPair.length < (uint32_t)matchLength) { loPair.length = matchLength; loPair.offset = currentOffset - iter->second; } // Found the longest match so break out of loop if (loPair.length == (uint32_t)m_lookAheadWindow) break; } } // end find code // Insert code table.insert(std::make_pair(m_buffer, currentOffset)); for (uint32_t i = 1; i < loPair.length; i++) { if (dataEnd - (curPos + i) < m_minimumMatch) break; std::copy(curPos + i, curPos + m_minimumMatch + i, m_buffer.begin()); table.insert(std::make_pair(m_buffer, currentOffset + i)); } // end insert code // Delete code int32_t slidingWindowOffset = std::max(0, currentOffset - m_slidingWindow); // Absolute offset int32_t tablesize = static_cast(table.size()); for (int32_t i = 0; i < tablesize - m_slidingWindow; ++i) { std::copy(dataBegin + slidingWindowOffset + i, dataBegin + slidingWindowOffset + m_minimumMatch + i, m_buffer.begin()); auto elements = table.equal_range(m_buffer); for (auto iter = elements.first; iter != elements.second; iter++) { if (slidingWindowOffset + i == iter->second) { table.erase(iter); // There should no occurance of the map with the same value break; } } } // end delete code return loPair; // break lookupTable.cpp:109 if table.size()> 4096 }