aboutsummaryrefslogtreecommitdiff
path: root/src/lzss/lzssencoder.nim
diff options
context:
space:
mode:
Diffstat (limited to 'src/lzss/lzssencoder.nim')
-rw-r--r--src/lzss/lzssencoder.nim27
1 files changed, 14 insertions, 13 deletions
diff --git a/src/lzss/lzssencoder.nim b/src/lzss/lzssencoder.nim
index 36e0c7e..72f5081 100644
--- a/src/lzss/lzssencoder.nim
+++ b/src/lzss/lzssencoder.nim
@@ -14,36 +14,37 @@
14# You should have received a copy of the GNU Affero General Public License 14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <https://www.gnu.org/licenses/>. 15# along with this program. If not, see <https://www.gnu.org/licenses/>.
16 16
17import matchtable, lzssnode, lzsschain 17import matchring, matchtable, lzssnode, lzsschain
18 18
19const matchGroupLength* = 3 19const matchGroupLength* = 3
20const maxRefByteLength = high(uint8).int + matchGroupLength 20const maxRefByteLength = high(uint8).int + matchGroupLength
21 21
22proc commonPrefixLength*(a, b: openArray[uint8], skipFirst, maxLength: int): int = 22proc matchGroup(buf: openArray[uint8], startIndex: int): array[matchGroupLength, uint8] =
23 result = skipFirst 23 [buf[startIndex], buf[startIndex + 1], buf[startIndex + 2]]
24
25proc commonPrefixLength*(a, b: openArray[uint8], maxLength: int): int =
24 let maxPrefixLength = min(min(a.len, b.len), maxLength) 26 let maxPrefixLength = min(min(a.len, b.len), maxLength)
25 while result < maxPrefixLength and a[result] == b[result]: result += 1 27 while result < maxPrefixLength and a[result] == b[result]: result += 1
26 28
27proc longestPrefix*(candidatePos: openArray[int], searchBuf, lookAheadBuf: openArray[uint8]): tuple[length, pos: int] = 29proc longestPrefix*(candidatePos: MatchRing, searchBuf, lookAheadBuf: openArray[uint8]): tuple[length, pos: int] =
28 for startIndex in candidatePos: 30 for startIndex in candidatePos.items:
29 let prefixLength = commonPrefixLength( 31 let prefixLength = commonPrefixLength(
30 searchBuf.toOpenArray(startIndex, searchBuf.len - 1), lookAheadBuf, matchGroupLength, maxRefByteLength) 32 searchBuf.toOpenArray(startIndex, searchBuf.len - 1), lookAheadBuf, maxRefByteLength)
31 if prefixLength > result.length: result = (prefixLength, startIndex) 33 if prefixLength > result.length: result = (prefixLength, startIndex)
32 if prefixLength >= maxRefByteLength: return 34 if prefixLength >= maxRefByteLength: return
33 35
34proc addGroups*(matchTable: MatchTable[seq[uint8], int], buffer: openArray[uint8], fromPosIncl, toPosExcl: int) = 36proc addGroups*(matchTable: var MatchTable, buf: openArray[uint8], fromPosIncl, toPosExcl: int) =
35 for cursor in fromPosIncl..(toPosExcl - matchGroupLength): 37 for cursor in fromPosIncl..(toPosExcl - matchGroupLength):
36 let group = buffer[cursor..<(cursor + matchGroupLength)] 38 matchTable.addMatch(buf.matchGroup(cursor), cursor)
37 matchTable.addMatch(group, cursor)
38 39
39proc lzssEncode*(buf: openArray[uint8]): LzssChain = 40proc lzssEncode*(buf: openArray[uint8]): LzssChain =
40 result = newSeqOfCap[LzssNode](buf.len) 41 result = newSeqOfCap[LzssNode](buf.len)
41 let matchTable = initMatchTable(seq[uint8], int) 42 var matchTable = initMatchTable()
42 var cursor = 0 43 var cursor = 0
43 while cursor < buf.len() - matchGroupLength: 44 while cursor < buf.len() - matchGroupLength:
44 let matches = matchTable.matchList(buf[cursor..<(cursor + matchGroupLength)]) 45 let probableMatches = matchTable.candidates(buf.matchGroup(cursor))
45 let prefix = matches.longestPrefix(buf.toOpenArray(0, cursor - 1), buf.toOpenArray(cursor, buf.len - 1)) 46 let prefix = probableMatches.longestPrefix(buf.toOpenArray(0, cursor - 1), buf.toOpenArray(cursor, buf.len - 1))
46 if prefix.length > 0: 47 if prefix.length >= matchGroupLength:
47 result.add(lzssReference(prefix.length, cursor - prefix.pos)) 48 result.add(lzssReference(prefix.length, cursor - prefix.pos))
48 cursor += prefix.length 49 cursor += prefix.length
49 else: 50 else: