From be9ac57b9d2e27697262489002ee9334d4db61d2 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 15 Aug 2019 23:19:24 -0400 Subject: [PATCH 1/9] LZBase: Mark functions as const where applicable Most of the interface can be const qualified except for the setters. While we're at it, we can also make the private member functions internally linked helper functions, given they don't depend on instance state at all. --- include/LZ77/LZBase.hpp | 17 ++-- src/LZ77/LZBase.cpp | 180 ++++++++++++++++++++-------------------- 2 files changed, 97 insertions(+), 100 deletions(-) diff --git a/include/LZ77/LZBase.hpp b/include/LZ77/LZBase.hpp index 74d244e..b4d1c06 100644 --- a/include/LZ77/LZBase.hpp +++ b/include/LZ77/LZBase.hpp @@ -13,23 +13,18 @@ public: virtual atUint32 decompress(const atUint8* src, atUint8** dest, atUint32 srcLength) = 0; void setSlidingWindow(atInt32 SlidingWindow); - atInt32 slidingWindow(); + atInt32 slidingWindow() const; void setReadAheadBuffer(atInt32 ReadAheadBuffer); - atInt32 readAheadBuffer(); + atInt32 readAheadBuffer() const; void setMinMatch(atInt32 minimumMatch); - atInt32 minMatch(); + atInt32 minMatch() const; void setBlockSize(atInt32 BlockSize); - atInt32 blockSize(); + atInt32 blockSize() const; void setMinimumOffset(atUint32 minimumOffset); - atUint32 minimumOffset(); - -private: - atInt32 subMatch(const atUint8* str1, const uint8_t* str2, const atInt32 len); - LZLengthOffset windowSearch(atUint8* beginSearchPtr, atUint8* searchPosPtr, atUint8* endLABufferPtr, - atUint8* startLBPtr); + atUint32 minimumOffset() const; protected: - LZLengthOffset search(atUint8* posPtr, atUint8* dataBegin, atUint8* dataEnd); + LZLengthOffset search(const atUint8* posPtr, const atUint8* dataBegin, const atUint8* dataEnd) const; atInt32 m_slidingWindow; atInt32 m_readAheadBuffer; diff --git a/src/LZ77/LZBase.cpp b/src/LZ77/LZBase.cpp index c404f1c..461eb7e 100644 --- a/src/LZ77/LZBase.cpp +++ b/src/LZ77/LZBase.cpp @@ -1,75 +1,10 @@ #include "LZ77/LZLookupTable.hpp" #include "LZ77/LZBase.hpp" -LZBase::LZBase(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimumMatch, atInt32 blockSize) -: m_slidingWindow(slidingWindow) -, m_readAheadBuffer(minimumMatch) -, m_minMatch(minimumMatch) -, m_blockSize(blockSize) -, m_minOffset(minimumOffset) {} - -void LZBase::setSlidingWindow(atInt32 slidingWindow) { m_slidingWindow = slidingWindow; } - -atInt32 LZBase::slidingWindow() { return m_slidingWindow; } - -void LZBase::setReadAheadBuffer(atInt32 readAheadBuffer) { m_readAheadBuffer = readAheadBuffer; } - -atInt32 LZBase::readAheadBuffer() { return m_readAheadBuffer; } - -void LZBase::setMinMatch(atInt32 minimumMatch) { m_minMatch = minimumMatch; } - -atInt32 LZBase::minMatch() { return m_minMatch; } - -void LZBase::setBlockSize(atInt32 blockSize) { m_blockSize = blockSize; } - -atInt32 LZBase::blockSize() { return m_blockSize; } - -void LZBase::setMinimumOffset(atUint32 minimumOffset) { m_minOffset = minimumOffset; } - -atUint32 LZBase::minimumOffset() { return m_minOffset; } - -/* - DerricMc: - This search function is my own work and is no way affilated with any one else - I use the my own window_search function to drastically speed up the search function - Normally a search for one byte is matched, then two, then three, all the way up - to the size of the LookAheadBuffer. So I decided to skip the incremental search - and search for the entire LookAheadBuffer and if I don't find the bytes are equal I return - the next best match(which means if I look for 18 bytes and they are not found 18 bytess did not match, - and 17 bytes did match then 17 bytes match is return). - -*/ -LZLengthOffset LZBase::search(atUint8* posPtr, atUint8* dataBegin, atUint8* dataEnd) { - LZLengthOffset results = {0, 0}; - - // Returns negative 1 for Search failures since the current position is passed the size to be compressed - if (posPtr >= dataEnd) { - results.length = -1; - return results; - } - - atUint8* searchWindow; - // LookAheadBuffer is ReadAheadBuffer Size if there are more bytes than ReadAheadBufferSize waiting - // to be compressed else the number of remaining bytes is the LookAheadBuffer - int lookAheadBuffer_len = ((int)(dataEnd - posPtr) < m_readAheadBuffer) ? (int)(dataEnd - posPtr) : m_readAheadBuffer; - int slidingBuffer = (int)(posPtr - dataBegin) - m_slidingWindow; - - if (slidingBuffer > 0) - searchWindow = dataBegin + slidingBuffer; - else - searchWindow = dataBegin; - - atUint8* endPos = posPtr + lookAheadBuffer_len; - - if (!((posPtr - dataBegin < 1) || (dataEnd - posPtr < m_minMatch))) - results = windowSearch(searchWindow, posPtr, endPos, posPtr - m_minOffset); - - return results; -} - +namespace { // Returns the full length of string2 if they are equal else // Return the number of characters that were equal before they weren't equal -int LZBase::subMatch(const uint8_t* str1, const uint8_t* str2, const int len) { +int subMatch(const uint8_t* str1, const uint8_t* str2, const int len) { for (int i = 0; i < len; ++i) if (str1[i] != str2[i]) return i; @@ -77,24 +12,22 @@ int LZBase::subMatch(const uint8_t* str1, const uint8_t* str2, const int len) { return len; } -/* -Normally a search for one byte is matched, then two, then three, all the way up - to the size of the LookAheadBuffer. So I decided to skip the incremental search - and search for the entire LookAheadBuffer and if the function doesn't find the bytes are - equal the function return the next best match(which means if the function look for 18 bytes and they are not found, -return the number of bytes that did match before it failed to match. The submatch is function returns the number of -bytes that were equal, which can result up to the bytes total length if both byte strings are equal. - - - ...[][][][][][][][][][][][]|[][][][][][][][][][][][][][] - | - Search Window Current Pos LookAheadBuffer - Up to 4096 bytes Up to 18 bytes - Sliding Window - Up to 4114 bytes -*/ -LZLengthOffset LZBase::windowSearch(atUint8* beginSearchPtr, atUint8* searchPosPtr, atUint8* endLABufferPtr, - atUint8* startLBPtr) { +// Normally a search for one byte is matched, then two, then three, all the way up +// to the size of the LookAheadBuffer. So I decided to skip the incremental search +// and search for the entire LookAheadBuffer and if the function doesn't find the bytes are +// equal the function return the next best match(which means if the function look for 18 bytes and they are not found, +// return the number of bytes that did match before it failed to match. The submatch is function returns the number of +// bytes that were equal, which can result up to the bytes total length if both byte strings are equal. +// +// +// ...[][][][][][][][][][][][]|[][][][][][][][][][][][][][] +// | +// Search Window Current Pos LookAheadBuffer +// Up to 4096 bytes Up to 18 bytes +// Sliding Window +// Up to 4114 bytes +LZLengthOffset windowSearch(const atUint8* beginSearchPtr, const atUint8* searchPosPtr, const atUint8* endLABufferPtr, + const atUint8* startLBPtr) { atInt32 size = (atUint32)(endLABufferPtr - beginSearchPtr); // Size of the entire sliding window atInt32 n = (atUint32)(endLABufferPtr - searchPosPtr); LZLengthOffset result = {0, 0}; @@ -103,10 +36,10 @@ LZLengthOffset LZBase::windowSearch(atUint8* beginSearchPtr, atUint8* searchPosP if (n > size) // If the string that is being looked for is bigger than the string that is being searched return result; - /*This makes sure that search for the searchPosPtr can be searched if an invalid position is given - An invalid position occurs if the amount of characters to search in_beginSearchPtr is less than the size - of searchPosPtr. In other words there has to be at least n characters left in the string - to have a chance to find n characters*/ + // This makes sure that search for the searchPosPtr can be searched if an invalid position is given + // An invalid position occurs if the amount of characters to search in_beginSearchPtr is less than the size + // of searchPosPtr. In other words there has to be at least n characters left in the string + // to have a chance to find n characters do { temp = subMatch(startLBPtr, searchPosPtr, n); @@ -125,3 +58,72 @@ LZLengthOffset LZBase::windowSearch(atUint8* beginSearchPtr, atUint8* searchPosP return result; } +} // Anonymous namespace + +LZBase::LZBase(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimumMatch, atInt32 blockSize) +: m_slidingWindow(slidingWindow) +, m_readAheadBuffer(minimumMatch) +, m_minMatch(minimumMatch) +, m_blockSize(blockSize) +, m_minOffset(minimumOffset) {} + +void LZBase::setSlidingWindow(atInt32 slidingWindow) { m_slidingWindow = slidingWindow; } + +atInt32 LZBase::slidingWindow() const { return m_slidingWindow; } + +void LZBase::setReadAheadBuffer(atInt32 readAheadBuffer) { m_readAheadBuffer = readAheadBuffer; } + +atInt32 LZBase::readAheadBuffer() const { return m_readAheadBuffer; } + +void LZBase::setMinMatch(atInt32 minimumMatch) { m_minMatch = minimumMatch; } + +atInt32 LZBase::minMatch() const { return m_minMatch; } + +void LZBase::setBlockSize(atInt32 blockSize) { m_blockSize = blockSize; } + +atInt32 LZBase::blockSize() const { return m_blockSize; } + +void LZBase::setMinimumOffset(atUint32 minimumOffset) { m_minOffset = minimumOffset; } + +atUint32 LZBase::minimumOffset() const { return m_minOffset; } + +/* + DerricMc: + This search function is my own work and is no way affiliated with any one else + I use the my own window_search function to drastically speed up the search function + Normally a search for one byte is matched, then two, then three, all the way up + to the size of the LookAheadBuffer. So I decided to skip the incremental search + and search for the entire LookAheadBuffer and if I don't find the bytes are equal I return + the next best match(which means if I look for 18 bytes and they are not found 18 bytes did not match, + and 17 bytes did match then 17 bytes match is return). + +*/ +LZLengthOffset LZBase::search(const atUint8* posPtr, const atUint8* dataBegin, const atUint8* dataEnd) const { + LZLengthOffset results = {0, 0}; + + // Returns negative 1 for Search failures since the current position is passed the size to be compressed + if (posPtr >= dataEnd) { + results.length = -1; + return results; + } + + const atUint8* searchWindow; + // LookAheadBuffer is ReadAheadBuffer Size if there are more bytes than ReadAheadBufferSize waiting + // to be compressed else the number of remaining bytes is the LookAheadBuffer + const int lookAheadBuffer_len = + ((int)(dataEnd - posPtr) < m_readAheadBuffer) ? (int)(dataEnd - posPtr) : m_readAheadBuffer; + const int slidingBuffer = (int)(posPtr - dataBegin) - m_slidingWindow; + + if (slidingBuffer > 0) + searchWindow = dataBegin + slidingBuffer; + else + searchWindow = dataBegin; + + const atUint8* endPos = posPtr + lookAheadBuffer_len; + + if (!((posPtr - dataBegin < 1) || (dataEnd - posPtr < m_minMatch))) + results = windowSearch(searchWindow, posPtr, endPos, posPtr - m_minOffset); + + return results; +} + From 50936ab1a9069e53a007de8ef8fe093a58cabde1 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 15 Aug 2019 23:31:02 -0400 Subject: [PATCH 2/9] LZBase: Default virtual destructor --- include/LZ77/LZBase.hpp | 2 +- src/LZ77/LZBase.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/LZ77/LZBase.hpp b/include/LZ77/LZBase.hpp index b4d1c06..45e31a6 100644 --- a/include/LZ77/LZBase.hpp +++ b/include/LZ77/LZBase.hpp @@ -7,7 +7,7 @@ class LZBase { public: explicit LZBase(atInt32 minimumOffset = 1, atInt32 slidingWindow = 4096, atInt32 minimumMatch = 3, atInt32 blockSize = 8); - virtual ~LZBase() {} + virtual ~LZBase(); virtual atUint32 compress(const atUint8* src, atUint8** dest, atUint32 srcLength) = 0; virtual atUint32 decompress(const atUint8* src, atUint8** dest, atUint32 srcLength) = 0; diff --git a/src/LZ77/LZBase.cpp b/src/LZ77/LZBase.cpp index 461eb7e..1713114 100644 --- a/src/LZ77/LZBase.cpp +++ b/src/LZ77/LZBase.cpp @@ -67,6 +67,8 @@ LZBase::LZBase(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimumMatc , m_blockSize(blockSize) , m_minOffset(minimumOffset) {} +LZBase::~LZBase() = default; + void LZBase::setSlidingWindow(atInt32 slidingWindow) { m_slidingWindow = slidingWindow; } atInt32 LZBase::slidingWindow() const { return m_slidingWindow; } From 48ae0d32fe8732e053f13ceb44b3bcd541747609 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 15 Aug 2019 23:33:14 -0400 Subject: [PATCH 3/9] LZBase: Remove unused include --- include/LZ77/LZBase.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/LZ77/LZBase.hpp b/include/LZ77/LZBase.hpp index 45e31a6..cd78e8a 100644 --- a/include/LZ77/LZBase.hpp +++ b/include/LZ77/LZBase.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include "LZ77/LZLookupTable.hpp" class LZBase { From 663696fe7219c43612ecde4439a8fa9d9e672f8c Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 15 Aug 2019 23:39:43 -0400 Subject: [PATCH 4/9] LZLookupTable: Make member functions const where applicable While we're at it, we can convert compare_equal into an operator== operator!= pair, and make the curPos argument to search() const as well. --- include/LZ77/LZLookupTable.hpp | 5 +++-- src/LZ77/LZLookupTable.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/LZ77/LZLookupTable.hpp b/include/LZ77/LZLookupTable.hpp index 61bfb9e..bd66516 100644 --- a/include/LZ77/LZLookupTable.hpp +++ b/include/LZ77/LZLookupTable.hpp @@ -9,7 +9,8 @@ struct LZLengthOffset { atUint32 length; // The number of bytes compressed atUint16 offset; // How far back in sliding window where bytes that match the lookAheadBuffer is located - bool compare_equal(const LZLengthOffset& lo_pair) { return length == lo_pair.length && offset == lo_pair.offset; } + bool operator==(const LZLengthOffset& lo_pair) const { return length == lo_pair.length && offset == lo_pair.offset; } + bool operator!=(const LZLengthOffset& lo_pair) const { return !operator==(lo_pair); } }; class LZLookupTable { @@ -17,7 +18,7 @@ public: LZLookupTable(); LZLookupTable(atInt32 minimumMatch, atInt32 slidingWindow = 4096, atInt32 lookAheadWindow = 18); ~LZLookupTable(); - LZLengthOffset search(atUint8* curPos, const atUint8* dataBegin, const atUint8* dataEnd); + LZLengthOffset search(const atUint8* curPos, const atUint8* dataBegin, const atUint8* dataEnd); void setLookAheadWindow(atInt32 lookAheadWindow); private: diff --git a/src/LZ77/LZLookupTable.cpp b/src/LZ77/LZLookupTable.cpp index 0809c84..e7b7ba6 100644 --- a/src/LZ77/LZLookupTable.cpp +++ b/src/LZ77/LZLookupTable.cpp @@ -36,7 +36,7 @@ void LZLookupTable::setLookAheadWindow(atInt32 lookAheadWindow) { m_lookAheadWindow = 18; } -LZLengthOffset LZLookupTable::search(atUint8* curPos, const atUint8* dataBegin, const atUint8* dataEnd) { +LZLengthOffset LZLookupTable::search(const atUint8* curPos, const atUint8* dataBegin, const atUint8* dataEnd) { LZLengthOffset loPair = {0, 0}; // Returns negative 1 for search failures since the current position is passed the size to be compressed From 3092dc79e7dfc7b0406ba99f289b1dc38cee9583 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 15 Aug 2019 23:41:10 -0400 Subject: [PATCH 5/9] LZLookupTable: Default destructor --- src/LZ77/LZLookupTable.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LZ77/LZLookupTable.cpp b/src/LZ77/LZLookupTable.cpp index e7b7ba6..f2fcea5 100644 --- a/src/LZ77/LZLookupTable.cpp +++ b/src/LZ77/LZLookupTable.cpp @@ -27,7 +27,7 @@ LZLookupTable::LZLookupTable(atInt32 minimumMatch, atInt32 slidingWindow, atInt3 m_buffer.reserve(m_minimumMatch); } -LZLookupTable::~LZLookupTable() {} +LZLookupTable::~LZLookupTable() = default; void LZLookupTable::setLookAheadWindow(atInt32 lookAheadWindow) { if (lookAheadWindow > 0) From f7b8c33ed29825fbd33278b3f2faab2537324b98 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 15 Aug 2019 23:45:14 -0400 Subject: [PATCH 6/9] LZLookupTable: Default-initialize class members directly in the class Same thing without the need to duplicate the variable name. --- include/LZ77/LZLookupTable.hpp | 6 +++--- src/LZ77/LZLookupTable.cpp | 7 +------ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/include/LZ77/LZLookupTable.hpp b/include/LZ77/LZLookupTable.hpp index bd66516..6fb4df0 100644 --- a/include/LZ77/LZLookupTable.hpp +++ b/include/LZ77/LZLookupTable.hpp @@ -24,8 +24,8 @@ public: private: typedef std::multimap, int32_t> LookupTable; LookupTable table; - atInt32 m_minimumMatch; - atInt32 m_slidingWindow; - atInt32 m_lookAheadWindow; + atInt32 m_minimumMatch = 3; + atInt32 m_slidingWindow = 4096; + atInt32 m_lookAheadWindow = 18; std::vector m_buffer; }; diff --git a/src/LZ77/LZLookupTable.cpp b/src/LZ77/LZLookupTable.cpp index f2fcea5..83d346d 100644 --- a/src/LZ77/LZLookupTable.cpp +++ b/src/LZ77/LZLookupTable.cpp @@ -1,12 +1,7 @@ #include "LZ77/LZLookupTable.hpp" #include -LZLookupTable::LZLookupTable() { - m_minimumMatch = 3; - m_slidingWindow = 4096; - m_lookAheadWindow = 18; - m_buffer.resize(m_minimumMatch); -} +LZLookupTable::LZLookupTable() : m_buffer(m_minimumMatch) {} LZLookupTable::LZLookupTable(atInt32 minimumMatch, atInt32 slidingWindow, atInt32 lookAheadWindow) { if (minimumMatch > 0) From 70aeed342fac19cbb715dc3c0e77464226a58660 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 15 Aug 2019 23:47:06 -0400 Subject: [PATCH 7/9] LZLookupTable: Convert typedef into a using alias --- include/LZ77/LZLookupTable.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/LZ77/LZLookupTable.hpp b/include/LZ77/LZLookupTable.hpp index 6fb4df0..9f3017b 100644 --- a/include/LZ77/LZLookupTable.hpp +++ b/include/LZ77/LZLookupTable.hpp @@ -22,7 +22,7 @@ public: void setLookAheadWindow(atInt32 lookAheadWindow); private: - typedef std::multimap, int32_t> LookupTable; + using LookupTable = std::multimap, int32_t>; LookupTable table; atInt32 m_minimumMatch = 3; atInt32 m_slidingWindow = 4096; From a3a6e3b42aa47f2d0ca2865de45ccef02c833201 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 15 Aug 2019 23:48:47 -0400 Subject: [PATCH 8/9] LZLookupTable: Reuse setLookAheadWindow within constructor Provides the same behavior without duplicating code. --- src/LZ77/LZLookupTable.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/LZ77/LZLookupTable.cpp b/src/LZ77/LZLookupTable.cpp index 83d346d..805c123 100644 --- a/src/LZ77/LZLookupTable.cpp +++ b/src/LZ77/LZLookupTable.cpp @@ -14,10 +14,7 @@ LZLookupTable::LZLookupTable(atInt32 minimumMatch, atInt32 slidingWindow, atInt3 else m_slidingWindow = 4096; - if (lookAheadWindow > 0) - m_lookAheadWindow = lookAheadWindow; - else - m_lookAheadWindow = 18; + setLookAheadWindow(lookAheadWindow); m_buffer.reserve(m_minimumMatch); } From c524a9caa2b6645b5968936e315dced30ba85ca1 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 15 Aug 2019 23:51:59 -0400 Subject: [PATCH 9/9] LZLookupTable: Remove unused include This header and the matching cpp file make no use of std::deque, so this can be removed. --- include/LZ77/LZLookupTable.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/LZ77/LZLookupTable.hpp b/include/LZ77/LZLookupTable.hpp index 9f3017b..b157eb0 100644 --- a/include/LZ77/LZLookupTable.hpp +++ b/include/LZ77/LZLookupTable.hpp @@ -1,9 +1,8 @@ #pragma once -#include -#include -#include #include +#include +#include #include struct LZLengthOffset {