mirror of https://github.com/k3s-io/k3s
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
98 lines
2.1 KiB
98 lines
2.1 KiB
// +build !amd64 appengine !gc noasm |
|
|
|
package lz4 |
|
|
|
func decodeBlock(dst, src []byte) (ret int) { |
|
const hasError = -2 |
|
defer func() { |
|
if recover() != nil { |
|
ret = hasError |
|
} |
|
}() |
|
|
|
var si, di int |
|
for { |
|
// Literals and match lengths (token). |
|
b := int(src[si]) |
|
si++ |
|
|
|
// Literals. |
|
if lLen := b >> 4; lLen > 0 { |
|
switch { |
|
case lLen < 0xF && si+16 < len(src): |
|
// Shortcut 1 |
|
// if we have enough room in src and dst, and the literals length |
|
// is small enough (0..14) then copy all 16 bytes, even if not all |
|
// are part of the literals. |
|
copy(dst[di:], src[si:si+16]) |
|
si += lLen |
|
di += lLen |
|
if mLen := b & 0xF; mLen < 0xF { |
|
// Shortcut 2 |
|
// if the match length (4..18) fits within the literals, then copy |
|
// all 18 bytes, even if not all are part of the literals. |
|
mLen += 4 |
|
if offset := int(src[si]) | int(src[si+1])<<8; mLen <= offset { |
|
i := di - offset |
|
end := i + 18 |
|
if end > len(dst) { |
|
// The remaining buffer may not hold 18 bytes. |
|
// See https://github.com/pierrec/lz4/issues/51. |
|
end = len(dst) |
|
} |
|
copy(dst[di:], dst[i:end]) |
|
si += 2 |
|
di += mLen |
|
continue |
|
} |
|
} |
|
case lLen == 0xF: |
|
for src[si] == 0xFF { |
|
lLen += 0xFF |
|
si++ |
|
} |
|
lLen += int(src[si]) |
|
si++ |
|
fallthrough |
|
default: |
|
copy(dst[di:di+lLen], src[si:si+lLen]) |
|
si += lLen |
|
di += lLen |
|
} |
|
} |
|
if si >= len(src) { |
|
return di |
|
} |
|
|
|
offset := int(src[si]) | int(src[si+1])<<8 |
|
if offset == 0 { |
|
return hasError |
|
} |
|
si += 2 |
|
|
|
// Match. |
|
mLen := b & 0xF |
|
if mLen == 0xF { |
|
for src[si] == 0xFF { |
|
mLen += 0xFF |
|
si++ |
|
} |
|
mLen += int(src[si]) |
|
si++ |
|
} |
|
mLen += minMatch |
|
|
|
// Copy the match. |
|
expanded := dst[di-offset:] |
|
if mLen > offset { |
|
// Efficiently copy the match dst[di-offset:di] into the dst slice. |
|
bytesToCopy := offset * (mLen / offset) |
|
for n := offset; n <= bytesToCopy+offset; n *= 2 { |
|
copy(expanded[n:], expanded[:n]) |
|
} |
|
di += bytesToCopy |
|
mLen -= bytesToCopy |
|
} |
|
di += copy(dst[di:di+mLen], expanded[:mLen]) |
|
} |
|
}
|
|
|