From ff5f1b037c4df5e453c60d86bbb60dacf5fd8877 Mon Sep 17 00:00:00 2001 From: greatroar <61184462+greatroar@users.noreply.github.com> Date: Sun, 30 Jan 2022 12:18:40 +0100 Subject: [PATCH] internal/lz4block: Simplify portable decoder --- internal/lz4block/decode_other.go | 40 +++++++++---------------------- internal/lz4block/decode_test.go | 6 +++++ 2 files changed, 17 insertions(+), 29 deletions(-) diff --git a/internal/lz4block/decode_other.go b/internal/lz4block/decode_other.go index 2ecce682..73598ce8 100644 --- a/internal/lz4block/decode_other.go +++ b/internal/lz4block/decode_other.go @@ -1,3 +1,4 @@ +//go:build (!amd64 && !arm && !arm64) || appengine || !gc || noasm // +build !amd64,!arm,!arm64 appengine !gc noasm package lz4block @@ -10,7 +11,6 @@ func decodeBlock(dst, src, dict []byte) (ret int) { // Restrict capacities so we don't read or write out of bounds. dst = dst[:len(dst):len(dst)] src = src[:len(src):len(src)] - dictLen := uint(len(dict)) const hasError = -2 defer func() { @@ -102,35 +102,17 @@ func decodeBlock(dst, src, dict []byte) (ret int) { // Copy the match. if di < offset { - // The match is beyond our block, meaning in the dictionary - if offset-di > mLen { - // The match is entirely contained in the dictionary. Just copy! - copy(dst[di:di+mLen], dict[dictLen+di-offset:dictLen+di-offset+mLen]) - di = di + mLen - } else { - // The match stretches over the dictionary and our block - copySize := offset - di - restSize := mLen - copySize - - copy(dst[di:di+copySize], dict[dictLen-copySize:]) - di = di + copySize - - if di < restSize { - // Overlap - we want to copy more than what we have available, - // so copy byte per byte. - copyFrom := 0 - endOfMatch := di + restSize - for di < endOfMatch { - dst[di] = dst[copyFrom] - di = di + 1 - copyFrom = copyFrom + 1 - } - } else { - copy(dst[di:di+restSize], dst[0:restSize]) - di = di + restSize - } + // The match is beyond our block, meaning the first part + // is in the dictionary. + fromDict := dict[uint(len(dict))+di-offset:] + n := uint(copy(dst[di:di+mLen], fromDict)) + di += n + if mLen -= n; mLen == 0 { + continue } - continue + // We copied n = offset-di bytes from the dictionary, + // then set di = di+n = offset, so the following code + // copies from dst[di-offset:] = dst[0:]. } expanded := dst[di-offset:] diff --git a/internal/lz4block/decode_test.go b/internal/lz4block/decode_test.go index 02282af5..554643fa 100644 --- a/internal/lz4block/decode_test.go +++ b/internal/lz4block/decode_test.go @@ -228,6 +228,12 @@ func TestDecodeWithDict(t *testing.T) { // First part in dictionary, rest in dst. {"\x35foo\x09\x00\x401234", "0barbaz", "foobarbazfoo1234"}, + // Copy end of dictionary three times, then a literal. + {"\x08\x04\x00\x50abcde", "---1234", "123412341234abcde"}, + + // First part in dictionary, rest in dst, copied multiple times. + {"\x1a1\x05\x00\x50abcde", "---2345", "123451234512345abcde"}, + // Same, but >16 bytes before the end, // to test the short match shortcut in the amd64 decoder. {"\x35abc\x09\x00\xf0\x0f0123456789abcdefghijklmnopqrst", "012defghi",