Updated transitive dependencies
This commit is contained in:
parent
173e1528be
commit
e4ade4532b
2
go.mod
2
go.mod
|
@ -5,7 +5,7 @@ go 1.21
|
||||||
require (
|
require (
|
||||||
github.com/alecthomas/chroma/v2 v2.9.1
|
github.com/alecthomas/chroma/v2 v2.9.1
|
||||||
github.com/julienschmidt/httprouter v1.3.0
|
github.com/julienschmidt/httprouter v1.3.0
|
||||||
github.com/klauspost/compress v1.16.7
|
github.com/klauspost/compress v1.17.0
|
||||||
github.com/spf13/cobra v1.7.0
|
github.com/spf13/cobra v1.7.0
|
||||||
github.com/yosssi/gohtml v0.0.0-20201013000340-ee4748c638f4
|
github.com/yosssi/gohtml v0.0.0-20201013000340-ee4748c638f4
|
||||||
golang.org/x/image v0.12.0
|
golang.org/x/image v0.12.0
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -13,8 +13,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
|
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
|
||||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||||
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
|
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
|
||||||
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
||||||
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
before:
|
before:
|
||||||
hooks:
|
hooks:
|
||||||
- ./gen.sh
|
- ./gen.sh
|
||||||
- go install mvdan.cc/garble@v0.9.3
|
- go install mvdan.cc/garble@v0.10.1
|
||||||
|
|
||||||
builds:
|
builds:
|
||||||
-
|
-
|
||||||
|
@ -92,16 +92,7 @@ builds:
|
||||||
archives:
|
archives:
|
||||||
-
|
-
|
||||||
id: s2-binaries
|
id: s2-binaries
|
||||||
name_template: "s2-{{ .Os }}_{{ .Arch }}_{{ .Version }}"
|
name_template: "s2-{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
|
||||||
replacements:
|
|
||||||
aix: AIX
|
|
||||||
darwin: OSX
|
|
||||||
linux: Linux
|
|
||||||
windows: Windows
|
|
||||||
386: i386
|
|
||||||
amd64: x86_64
|
|
||||||
freebsd: FreeBSD
|
|
||||||
netbsd: NetBSD
|
|
||||||
format_overrides:
|
format_overrides:
|
||||||
- goos: windows
|
- goos: windows
|
||||||
format: zip
|
format: zip
|
||||||
|
@ -125,7 +116,7 @@ changelog:
|
||||||
|
|
||||||
nfpms:
|
nfpms:
|
||||||
-
|
-
|
||||||
file_name_template: "s2_package_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
file_name_template: "s2_package__{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
|
||||||
vendor: Klaus Post
|
vendor: Klaus Post
|
||||||
homepage: https://github.com/klauspost/compress
|
homepage: https://github.com/klauspost/compress
|
||||||
maintainer: Klaus Post <klauspost@gmail.com>
|
maintainer: Klaus Post <klauspost@gmail.com>
|
||||||
|
@ -134,8 +125,3 @@ nfpms:
|
||||||
formats:
|
formats:
|
||||||
- deb
|
- deb
|
||||||
- rpm
|
- rpm
|
||||||
replacements:
|
|
||||||
darwin: Darwin
|
|
||||||
linux: Linux
|
|
||||||
freebsd: FreeBSD
|
|
||||||
amd64: x86_64
|
|
||||||
|
|
|
@ -16,6 +16,10 @@ This package provides various compression algorithms.
|
||||||
|
|
||||||
# changelog
|
# changelog
|
||||||
|
|
||||||
|
* July 1st, 2023 - [v1.16.7](https://github.com/klauspost/compress/releases/tag/v1.16.7)
|
||||||
|
* zstd: Fix default level first dictionary encode https://github.com/klauspost/compress/pull/829
|
||||||
|
* s2: add GetBufferCapacity() method by @GiedriusS in https://github.com/klauspost/compress/pull/832
|
||||||
|
|
||||||
* June 13, 2023 - [v1.16.6](https://github.com/klauspost/compress/releases/tag/v1.16.6)
|
* June 13, 2023 - [v1.16.6](https://github.com/klauspost/compress/releases/tag/v1.16.6)
|
||||||
* zstd: correctly ignore WithEncoderPadding(1) by @ianlancetaylor in https://github.com/klauspost/compress/pull/806
|
* zstd: correctly ignore WithEncoderPadding(1) by @ianlancetaylor in https://github.com/klauspost/compress/pull/806
|
||||||
* zstd: Add amd64 match length assembly https://github.com/klauspost/compress/pull/824
|
* zstd: Add amd64 match length assembly https://github.com/klauspost/compress/pull/824
|
||||||
|
@ -50,6 +54,9 @@ This package provides various compression algorithms.
|
||||||
* s2: Support io.ReaderAt in ReadSeeker. https://github.com/klauspost/compress/pull/747
|
* s2: Support io.ReaderAt in ReadSeeker. https://github.com/klauspost/compress/pull/747
|
||||||
* s2c/s2sx: Use concurrent decoding. https://github.com/klauspost/compress/pull/746
|
* s2c/s2sx: Use concurrent decoding. https://github.com/klauspost/compress/pull/746
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>See changes to v1.15.x</summary>
|
||||||
|
|
||||||
* Jan 21st, 2023 (v1.15.15)
|
* Jan 21st, 2023 (v1.15.15)
|
||||||
* deflate: Improve level 7-9 by @klauspost in https://github.com/klauspost/compress/pull/739
|
* deflate: Improve level 7-9 by @klauspost in https://github.com/klauspost/compress/pull/739
|
||||||
* zstd: Add delta encoding support by @greatroar in https://github.com/klauspost/compress/pull/728
|
* zstd: Add delta encoding support by @greatroar in https://github.com/klauspost/compress/pull/728
|
||||||
|
@ -176,6 +183,8 @@ Stream decompression is now faster on asynchronous, since the goroutine allocati
|
||||||
|
|
||||||
While the release has been extensively tested, it is recommended to testing when upgrading.
|
While the release has been extensively tested, it is recommended to testing when upgrading.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>See changes to v1.14.x</summary>
|
<summary>See changes to v1.14.x</summary>
|
||||||
|
|
||||||
|
@ -636,6 +645,7 @@ Here are other packages of good quality and pure Go (no cgo wrappers or autoconv
|
||||||
* [github.com/dsnet/compress](https://github.com/dsnet/compress) - brotli decompression, bzip2 writer.
|
* [github.com/dsnet/compress](https://github.com/dsnet/compress) - brotli decompression, bzip2 writer.
|
||||||
* [github.com/ronanh/intcomp](https://github.com/ronanh/intcomp) - Integer compression.
|
* [github.com/ronanh/intcomp](https://github.com/ronanh/intcomp) - Integer compression.
|
||||||
* [github.com/spenczar/fpc](https://github.com/spenczar/fpc) - Float compression.
|
* [github.com/spenczar/fpc](https://github.com/spenczar/fpc) - Float compression.
|
||||||
|
* [github.com/minio/zipindex](https://github.com/minio/zipindex) - External ZIP directory index.
|
||||||
|
|
||||||
# license
|
# license
|
||||||
|
|
||||||
|
|
|
@ -152,12 +152,11 @@ func (b *bitWriter) flushAlign() {
|
||||||
|
|
||||||
// close will write the alignment bit and write the final byte(s)
|
// close will write the alignment bit and write the final byte(s)
|
||||||
// to the output.
|
// to the output.
|
||||||
func (b *bitWriter) close() error {
|
func (b *bitWriter) close() {
|
||||||
// End mark
|
// End mark
|
||||||
b.addBits16Clean(1, 1)
|
b.addBits16Clean(1, 1)
|
||||||
// flush until next byte.
|
// flush until next byte.
|
||||||
b.flushAlign()
|
b.flushAlign()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset and continue writing by appending to out.
|
// reset and continue writing by appending to out.
|
||||||
|
|
|
@ -199,7 +199,8 @@ func (s *Scratch) compress(src []byte) error {
|
||||||
c2.flush(s.actualTableLog)
|
c2.flush(s.actualTableLog)
|
||||||
c1.flush(s.actualTableLog)
|
c1.flush(s.actualTableLog)
|
||||||
|
|
||||||
return s.bw.close()
|
s.bw.close()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeCount will write the normalized histogram count to header.
|
// writeCount will write the normalized histogram count to header.
|
||||||
|
|
|
@ -94,10 +94,9 @@ func (b *bitWriter) flushAlign() {
|
||||||
|
|
||||||
// close will write the alignment bit and write the final byte(s)
|
// close will write the alignment bit and write the final byte(s)
|
||||||
// to the output.
|
// to the output.
|
||||||
func (b *bitWriter) close() error {
|
func (b *bitWriter) close() {
|
||||||
// End mark
|
// End mark
|
||||||
b.addBits16Clean(1, 1)
|
b.addBits16Clean(1, 1)
|
||||||
// flush until next byte.
|
// flush until next byte.
|
||||||
b.flushAlign()
|
b.flushAlign()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,10 +227,10 @@ func EstimateSizes(in []byte, s *Scratch) (tableSz, dataSz, reuseSz int, err err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Scratch) compress1X(src []byte) ([]byte, error) {
|
func (s *Scratch) compress1X(src []byte) ([]byte, error) {
|
||||||
return s.compress1xDo(s.Out, src)
|
return s.compress1xDo(s.Out, src), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Scratch) compress1xDo(dst, src []byte) ([]byte, error) {
|
func (s *Scratch) compress1xDo(dst, src []byte) []byte {
|
||||||
var bw = bitWriter{out: dst}
|
var bw = bitWriter{out: dst}
|
||||||
|
|
||||||
// N is length divisible by 4.
|
// N is length divisible by 4.
|
||||||
|
@ -260,8 +260,8 @@ func (s *Scratch) compress1xDo(dst, src []byte) ([]byte, error) {
|
||||||
bw.encTwoSymbols(cTable, tmp[1], tmp[0])
|
bw.encTwoSymbols(cTable, tmp[1], tmp[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := bw.close()
|
bw.close()
|
||||||
return bw.out, err
|
return bw.out
|
||||||
}
|
}
|
||||||
|
|
||||||
var sixZeros [6]byte
|
var sixZeros [6]byte
|
||||||
|
@ -283,12 +283,8 @@ func (s *Scratch) compress4X(src []byte) ([]byte, error) {
|
||||||
}
|
}
|
||||||
src = src[len(toDo):]
|
src = src[len(toDo):]
|
||||||
|
|
||||||
var err error
|
|
||||||
idx := len(s.Out)
|
idx := len(s.Out)
|
||||||
s.Out, err = s.compress1xDo(s.Out, toDo)
|
s.Out = s.compress1xDo(s.Out, toDo)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if len(s.Out)-idx > math.MaxUint16 {
|
if len(s.Out)-idx > math.MaxUint16 {
|
||||||
// We cannot store the size in the jump table
|
// We cannot store the size in the jump table
|
||||||
return nil, ErrIncompressible
|
return nil, ErrIncompressible
|
||||||
|
@ -315,7 +311,6 @@ func (s *Scratch) compress4Xp(src []byte) ([]byte, error) {
|
||||||
|
|
||||||
segmentSize := (len(src) + 3) / 4
|
segmentSize := (len(src) + 3) / 4
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
var errs [4]error
|
|
||||||
wg.Add(4)
|
wg.Add(4)
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
toDo := src
|
toDo := src
|
||||||
|
@ -326,15 +321,12 @@ func (s *Scratch) compress4Xp(src []byte) ([]byte, error) {
|
||||||
|
|
||||||
// Separate goroutine for each block.
|
// Separate goroutine for each block.
|
||||||
go func(i int) {
|
go func(i int) {
|
||||||
s.tmpOut[i], errs[i] = s.compress1xDo(s.tmpOut[i][:0], toDo)
|
s.tmpOut[i] = s.compress1xDo(s.tmpOut[i][:0], toDo)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}(i)
|
}(i)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
if errs[i] != nil {
|
|
||||||
return nil, errs[i]
|
|
||||||
}
|
|
||||||
o := s.tmpOut[i]
|
o := s.tmpOut[i]
|
||||||
if len(o) > math.MaxUint16 {
|
if len(o) > math.MaxUint16 {
|
||||||
// We cannot store the size in the jump table
|
// We cannot store the size in the jump table
|
||||||
|
|
|
@ -17,7 +17,6 @@ import (
|
||||||
// for aligning the input.
|
// for aligning the input.
|
||||||
type bitReader struct {
|
type bitReader struct {
|
||||||
in []byte
|
in []byte
|
||||||
off uint // next byte to read is at in[off - 1]
|
|
||||||
value uint64 // Maybe use [16]byte, but shifting is awkward.
|
value uint64 // Maybe use [16]byte, but shifting is awkward.
|
||||||
bitsRead uint8
|
bitsRead uint8
|
||||||
}
|
}
|
||||||
|
@ -28,7 +27,6 @@ func (b *bitReader) init(in []byte) error {
|
||||||
return errors.New("corrupt stream: too short")
|
return errors.New("corrupt stream: too short")
|
||||||
}
|
}
|
||||||
b.in = in
|
b.in = in
|
||||||
b.off = uint(len(in))
|
|
||||||
// The highest bit of the last byte indicates where to start
|
// The highest bit of the last byte indicates where to start
|
||||||
v := in[len(in)-1]
|
v := in[len(in)-1]
|
||||||
if v == 0 {
|
if v == 0 {
|
||||||
|
@ -69,21 +67,19 @@ func (b *bitReader) fillFast() {
|
||||||
if b.bitsRead < 32 {
|
if b.bitsRead < 32 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 2 bounds checks.
|
v := b.in[len(b.in)-4:]
|
||||||
v := b.in[b.off-4:]
|
b.in = b.in[:len(b.in)-4]
|
||||||
v = v[:4]
|
|
||||||
low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
|
low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
|
||||||
b.value = (b.value << 32) | uint64(low)
|
b.value = (b.value << 32) | uint64(low)
|
||||||
b.bitsRead -= 32
|
b.bitsRead -= 32
|
||||||
b.off -= 4
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fillFastStart() assumes the bitreader is empty and there is at least 8 bytes to read.
|
// fillFastStart() assumes the bitreader is empty and there is at least 8 bytes to read.
|
||||||
func (b *bitReader) fillFastStart() {
|
func (b *bitReader) fillFastStart() {
|
||||||
// Do single re-slice to avoid bounds checks.
|
v := b.in[len(b.in)-8:]
|
||||||
b.value = binary.LittleEndian.Uint64(b.in[b.off-8:])
|
b.in = b.in[:len(b.in)-8]
|
||||||
|
b.value = binary.LittleEndian.Uint64(v)
|
||||||
b.bitsRead = 0
|
b.bitsRead = 0
|
||||||
b.off -= 8
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill() will make sure at least 32 bits are available.
|
// fill() will make sure at least 32 bits are available.
|
||||||
|
@ -91,25 +87,25 @@ func (b *bitReader) fill() {
|
||||||
if b.bitsRead < 32 {
|
if b.bitsRead < 32 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if b.off >= 4 {
|
if len(b.in) >= 4 {
|
||||||
v := b.in[b.off-4:]
|
v := b.in[len(b.in)-4:]
|
||||||
v = v[:4]
|
b.in = b.in[:len(b.in)-4]
|
||||||
low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
|
low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
|
||||||
b.value = (b.value << 32) | uint64(low)
|
b.value = (b.value << 32) | uint64(low)
|
||||||
b.bitsRead -= 32
|
b.bitsRead -= 32
|
||||||
b.off -= 4
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for b.off > 0 {
|
|
||||||
b.value = (b.value << 8) | uint64(b.in[b.off-1])
|
b.bitsRead -= uint8(8 * len(b.in))
|
||||||
b.bitsRead -= 8
|
for len(b.in) > 0 {
|
||||||
b.off--
|
b.value = (b.value << 8) | uint64(b.in[len(b.in)-1])
|
||||||
|
b.in = b.in[:len(b.in)-1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// finished returns true if all bits have been read from the bit stream.
|
// finished returns true if all bits have been read from the bit stream.
|
||||||
func (b *bitReader) finished() bool {
|
func (b *bitReader) finished() bool {
|
||||||
return b.off == 0 && b.bitsRead >= 64
|
return len(b.in) == 0 && b.bitsRead >= 64
|
||||||
}
|
}
|
||||||
|
|
||||||
// overread returns true if more bits have been requested than is on the stream.
|
// overread returns true if more bits have been requested than is on the stream.
|
||||||
|
@ -119,7 +115,7 @@ func (b *bitReader) overread() bool {
|
||||||
|
|
||||||
// remain returns the number of bits remaining.
|
// remain returns the number of bits remaining.
|
||||||
func (b *bitReader) remain() uint {
|
func (b *bitReader) remain() uint {
|
||||||
return b.off*8 + 64 - uint(b.bitsRead)
|
return 8*uint(len(b.in)) + 64 - uint(b.bitsRead)
|
||||||
}
|
}
|
||||||
|
|
||||||
// close the bitstream and returns an error if out-of-buffer reads occurred.
|
// close the bitstream and returns an error if out-of-buffer reads occurred.
|
||||||
|
|
|
@ -97,12 +97,11 @@ func (b *bitWriter) flushAlign() {
|
||||||
|
|
||||||
// close will write the alignment bit and write the final byte(s)
|
// close will write the alignment bit and write the final byte(s)
|
||||||
// to the output.
|
// to the output.
|
||||||
func (b *bitWriter) close() error {
|
func (b *bitWriter) close() {
|
||||||
// End mark
|
// End mark
|
||||||
b.addBits16Clean(1, 1)
|
b.addBits16Clean(1, 1)
|
||||||
// flush until next byte.
|
// flush until next byte.
|
||||||
b.flushAlign()
|
b.flushAlign()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset and continue writing by appending to out.
|
// reset and continue writing by appending to out.
|
||||||
|
|
|
@ -361,14 +361,21 @@ func (b *blockEnc) encodeLits(lits []byte, raw bool) error {
|
||||||
if len(lits) >= 1024 {
|
if len(lits) >= 1024 {
|
||||||
// Use 4 Streams.
|
// Use 4 Streams.
|
||||||
out, reUsed, err = huff0.Compress4X(lits, b.litEnc)
|
out, reUsed, err = huff0.Compress4X(lits, b.litEnc)
|
||||||
} else if len(lits) > 32 {
|
} else if len(lits) > 16 {
|
||||||
// Use 1 stream
|
// Use 1 stream
|
||||||
single = true
|
single = true
|
||||||
out, reUsed, err = huff0.Compress1X(lits, b.litEnc)
|
out, reUsed, err = huff0.Compress1X(lits, b.litEnc)
|
||||||
} else {
|
} else {
|
||||||
err = huff0.ErrIncompressible
|
err = huff0.ErrIncompressible
|
||||||
}
|
}
|
||||||
|
if err == nil && len(out)+5 > len(lits) {
|
||||||
|
// If we are close, we may still be worse or equal to raw.
|
||||||
|
var lh literalsHeader
|
||||||
|
lh.setSizes(len(out), len(lits), single)
|
||||||
|
if len(out)+lh.size() >= len(lits) {
|
||||||
|
err = huff0.ErrIncompressible
|
||||||
|
}
|
||||||
|
}
|
||||||
switch err {
|
switch err {
|
||||||
case huff0.ErrIncompressible:
|
case huff0.ErrIncompressible:
|
||||||
if debugEncoder {
|
if debugEncoder {
|
||||||
|
@ -503,7 +510,7 @@ func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error {
|
||||||
if len(b.literals) >= 1024 && !raw {
|
if len(b.literals) >= 1024 && !raw {
|
||||||
// Use 4 Streams.
|
// Use 4 Streams.
|
||||||
out, reUsed, err = huff0.Compress4X(b.literals, b.litEnc)
|
out, reUsed, err = huff0.Compress4X(b.literals, b.litEnc)
|
||||||
} else if len(b.literals) > 32 && !raw {
|
} else if len(b.literals) > 16 && !raw {
|
||||||
// Use 1 stream
|
// Use 1 stream
|
||||||
single = true
|
single = true
|
||||||
out, reUsed, err = huff0.Compress1X(b.literals, b.litEnc)
|
out, reUsed, err = huff0.Compress1X(b.literals, b.litEnc)
|
||||||
|
@ -511,6 +518,17 @@ func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error {
|
||||||
err = huff0.ErrIncompressible
|
err = huff0.ErrIncompressible
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err == nil && len(out)+5 > len(b.literals) {
|
||||||
|
// If we are close, we may still be worse or equal to raw.
|
||||||
|
var lh literalsHeader
|
||||||
|
lh.setSize(len(b.literals))
|
||||||
|
szRaw := lh.size()
|
||||||
|
lh.setSizes(len(out), len(b.literals), single)
|
||||||
|
szComp := lh.size()
|
||||||
|
if len(out)+szComp >= len(b.literals)+szRaw {
|
||||||
|
err = huff0.ErrIncompressible
|
||||||
|
}
|
||||||
|
}
|
||||||
switch err {
|
switch err {
|
||||||
case huff0.ErrIncompressible:
|
case huff0.ErrIncompressible:
|
||||||
lh.setType(literalsBlockRaw)
|
lh.setType(literalsBlockRaw)
|
||||||
|
@ -773,10 +791,7 @@ func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error {
|
||||||
ml.flush(mlEnc.actualTableLog)
|
ml.flush(mlEnc.actualTableLog)
|
||||||
of.flush(ofEnc.actualTableLog)
|
of.flush(ofEnc.actualTableLog)
|
||||||
ll.flush(llEnc.actualTableLog)
|
ll.flush(llEnc.actualTableLog)
|
||||||
err = wr.close()
|
wr.close()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
b.output = wr.out
|
b.output = wr.out
|
||||||
|
|
||||||
// Maybe even add a bigger margin.
|
// Maybe even add a bigger margin.
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package zstd
|
package zstd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/klauspost/compress/huff0"
|
"github.com/klauspost/compress/huff0"
|
||||||
)
|
)
|
||||||
|
@ -14,7 +17,6 @@ type dict struct {
|
||||||
|
|
||||||
litEnc *huff0.Scratch
|
litEnc *huff0.Scratch
|
||||||
llDec, ofDec, mlDec sequenceDec
|
llDec, ofDec, mlDec sequenceDec
|
||||||
//llEnc, ofEnc, mlEnc []*fseEncoder
|
|
||||||
offsets [3]int
|
offsets [3]int
|
||||||
content []byte
|
content []byte
|
||||||
}
|
}
|
||||||
|
@ -159,3 +161,374 @@ func InspectDictionary(b []byte) (interface {
|
||||||
d, err := loadDict(b)
|
d, err := loadDict(b)
|
||||||
return d, err
|
return d, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BuildDictOptions struct {
|
||||||
|
// Dictionary ID.
|
||||||
|
ID uint32
|
||||||
|
|
||||||
|
// Content to use to create dictionary tables.
|
||||||
|
Contents [][]byte
|
||||||
|
|
||||||
|
// History to use for all blocks.
|
||||||
|
History []byte
|
||||||
|
|
||||||
|
// Offsets to use.
|
||||||
|
Offsets [3]int
|
||||||
|
|
||||||
|
// CompatV155 will make the dictionary compatible with Zstd v1.5.5 and earlier.
|
||||||
|
// See https://github.com/facebook/zstd/issues/3724
|
||||||
|
CompatV155 bool
|
||||||
|
|
||||||
|
// Use the specified encoder level.
|
||||||
|
// The dictionary will be built using the specified encoder level,
|
||||||
|
// which will reflect speed and make the dictionary tailored for that level.
|
||||||
|
// If not set SpeedBestCompression will be used.
|
||||||
|
Level EncoderLevel
|
||||||
|
|
||||||
|
// DebugOut will write stats and other details here if set.
|
||||||
|
DebugOut io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildDict(o BuildDictOptions) ([]byte, error) {
|
||||||
|
initPredefined()
|
||||||
|
hist := o.History
|
||||||
|
contents := o.Contents
|
||||||
|
debug := o.DebugOut != nil
|
||||||
|
println := func(args ...interface{}) {
|
||||||
|
if o.DebugOut != nil {
|
||||||
|
fmt.Fprintln(o.DebugOut, args...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf := func(s string, args ...interface{}) {
|
||||||
|
if o.DebugOut != nil {
|
||||||
|
fmt.Fprintf(o.DebugOut, s, args...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print := func(args ...interface{}) {
|
||||||
|
if o.DebugOut != nil {
|
||||||
|
fmt.Fprint(o.DebugOut, args...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if int64(len(hist)) > dictMaxLength {
|
||||||
|
return nil, fmt.Errorf("dictionary of size %d > %d", len(hist), int64(dictMaxLength))
|
||||||
|
}
|
||||||
|
if len(hist) < 8 {
|
||||||
|
return nil, fmt.Errorf("dictionary of size %d < %d", len(hist), 8)
|
||||||
|
}
|
||||||
|
if len(contents) == 0 {
|
||||||
|
return nil, errors.New("no content provided")
|
||||||
|
}
|
||||||
|
d := dict{
|
||||||
|
id: o.ID,
|
||||||
|
litEnc: nil,
|
||||||
|
llDec: sequenceDec{},
|
||||||
|
ofDec: sequenceDec{},
|
||||||
|
mlDec: sequenceDec{},
|
||||||
|
offsets: o.Offsets,
|
||||||
|
content: hist,
|
||||||
|
}
|
||||||
|
block := blockEnc{lowMem: false}
|
||||||
|
block.init()
|
||||||
|
enc := encoder(&bestFastEncoder{fastBase: fastBase{maxMatchOff: int32(maxMatchLen), bufferReset: math.MaxInt32 - int32(maxMatchLen*2), lowMem: false}})
|
||||||
|
if o.Level != 0 {
|
||||||
|
eOpts := encoderOptions{
|
||||||
|
level: o.Level,
|
||||||
|
blockSize: maxMatchLen,
|
||||||
|
windowSize: maxMatchLen,
|
||||||
|
dict: &d,
|
||||||
|
lowMem: false,
|
||||||
|
}
|
||||||
|
enc = eOpts.encoder()
|
||||||
|
} else {
|
||||||
|
o.Level = SpeedBestCompression
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
remain [256]int
|
||||||
|
ll [256]int
|
||||||
|
ml [256]int
|
||||||
|
of [256]int
|
||||||
|
)
|
||||||
|
addValues := func(dst *[256]int, src []byte) {
|
||||||
|
for _, v := range src {
|
||||||
|
dst[v]++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addHist := func(dst *[256]int, src *[256]uint32) {
|
||||||
|
for i, v := range src {
|
||||||
|
dst[i] += int(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
seqs := 0
|
||||||
|
nUsed := 0
|
||||||
|
litTotal := 0
|
||||||
|
newOffsets := make(map[uint32]int, 1000)
|
||||||
|
for _, b := range contents {
|
||||||
|
block.reset(nil)
|
||||||
|
if len(b) < 8 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
nUsed++
|
||||||
|
enc.Reset(&d, true)
|
||||||
|
enc.Encode(&block, b)
|
||||||
|
addValues(&remain, block.literals)
|
||||||
|
litTotal += len(block.literals)
|
||||||
|
seqs += len(block.sequences)
|
||||||
|
block.genCodes()
|
||||||
|
addHist(&ll, block.coders.llEnc.Histogram())
|
||||||
|
addHist(&ml, block.coders.mlEnc.Histogram())
|
||||||
|
addHist(&of, block.coders.ofEnc.Histogram())
|
||||||
|
for i, seq := range block.sequences {
|
||||||
|
if i > 3 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
offset := seq.offset
|
||||||
|
if offset == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if offset > 3 {
|
||||||
|
newOffsets[offset-3]++
|
||||||
|
} else {
|
||||||
|
newOffsets[uint32(o.Offsets[offset-1])]++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Find most used offsets.
|
||||||
|
var sortedOffsets []uint32
|
||||||
|
for k := range newOffsets {
|
||||||
|
sortedOffsets = append(sortedOffsets, k)
|
||||||
|
}
|
||||||
|
sort.Slice(sortedOffsets, func(i, j int) bool {
|
||||||
|
a, b := sortedOffsets[i], sortedOffsets[j]
|
||||||
|
if a == b {
|
||||||
|
// Prefer the longer offset
|
||||||
|
return sortedOffsets[i] > sortedOffsets[j]
|
||||||
|
}
|
||||||
|
return newOffsets[sortedOffsets[i]] > newOffsets[sortedOffsets[j]]
|
||||||
|
})
|
||||||
|
if len(sortedOffsets) > 3 {
|
||||||
|
if debug {
|
||||||
|
print("Offsets:")
|
||||||
|
for i, v := range sortedOffsets {
|
||||||
|
if i > 20 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
printf("[%d: %d],", v, newOffsets[v])
|
||||||
|
}
|
||||||
|
println("")
|
||||||
|
}
|
||||||
|
|
||||||
|
sortedOffsets = sortedOffsets[:3]
|
||||||
|
}
|
||||||
|
for i, v := range sortedOffsets {
|
||||||
|
o.Offsets[i] = int(v)
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
println("New repeat offsets", o.Offsets)
|
||||||
|
}
|
||||||
|
|
||||||
|
if nUsed == 0 || seqs == 0 {
|
||||||
|
return nil, fmt.Errorf("%d blocks, %d sequences found", nUsed, seqs)
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
println("Sequences:", seqs, "Blocks:", nUsed, "Literals:", litTotal)
|
||||||
|
}
|
||||||
|
if seqs/nUsed < 512 {
|
||||||
|
// Use 512 as minimum.
|
||||||
|
nUsed = seqs / 512
|
||||||
|
}
|
||||||
|
copyHist := func(dst *fseEncoder, src *[256]int) ([]byte, error) {
|
||||||
|
hist := dst.Histogram()
|
||||||
|
var maxSym uint8
|
||||||
|
var maxCount int
|
||||||
|
var fakeLength int
|
||||||
|
for i, v := range src {
|
||||||
|
if v > 0 {
|
||||||
|
v = v / nUsed
|
||||||
|
if v == 0 {
|
||||||
|
v = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v > maxCount {
|
||||||
|
maxCount = v
|
||||||
|
}
|
||||||
|
if v != 0 {
|
||||||
|
maxSym = uint8(i)
|
||||||
|
}
|
||||||
|
fakeLength += v
|
||||||
|
hist[i] = uint32(v)
|
||||||
|
}
|
||||||
|
dst.HistogramFinished(maxSym, maxCount)
|
||||||
|
dst.reUsed = false
|
||||||
|
dst.useRLE = false
|
||||||
|
err := dst.normalizeCount(fakeLength)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
println("RAW:", dst.count[:maxSym+1], "NORM:", dst.norm[:maxSym+1], "LEN:", fakeLength)
|
||||||
|
}
|
||||||
|
return dst.writeCount(nil)
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
print("Literal lengths: ")
|
||||||
|
}
|
||||||
|
llTable, err := copyHist(block.coders.llEnc, &ll)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
print("Match lengths: ")
|
||||||
|
}
|
||||||
|
mlTable, err := copyHist(block.coders.mlEnc, &ml)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
print("Offsets: ")
|
||||||
|
}
|
||||||
|
ofTable, err := copyHist(block.coders.ofEnc, &of)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Literal table
|
||||||
|
avgSize := litTotal
|
||||||
|
if avgSize > huff0.BlockSizeMax/2 {
|
||||||
|
avgSize = huff0.BlockSizeMax / 2
|
||||||
|
}
|
||||||
|
huffBuff := make([]byte, 0, avgSize)
|
||||||
|
// Target size
|
||||||
|
div := litTotal / avgSize
|
||||||
|
if div < 1 {
|
||||||
|
div = 1
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
println("Huffman weights:")
|
||||||
|
}
|
||||||
|
for i, n := range remain[:] {
|
||||||
|
if n > 0 {
|
||||||
|
n = n / div
|
||||||
|
// Allow all entries to be represented.
|
||||||
|
if n == 0 {
|
||||||
|
n = 1
|
||||||
|
}
|
||||||
|
huffBuff = append(huffBuff, bytes.Repeat([]byte{byte(i)}, n)...)
|
||||||
|
if debug {
|
||||||
|
printf("[%d: %d], ", i, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if o.CompatV155 && remain[255]/div == 0 {
|
||||||
|
huffBuff = append(huffBuff, 255)
|
||||||
|
}
|
||||||
|
scratch := &huff0.Scratch{TableLog: 11}
|
||||||
|
for tries := 0; tries < 255; tries++ {
|
||||||
|
scratch = &huff0.Scratch{TableLog: 11}
|
||||||
|
_, _, err = huff0.Compress1X(huffBuff, scratch)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
printf("Try %d: Huffman error: %v\n", tries+1, err)
|
||||||
|
}
|
||||||
|
huffBuff = huffBuff[:0]
|
||||||
|
if tries == 250 {
|
||||||
|
if debug {
|
||||||
|
println("Huffman: Bailing out with predefined table")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bail out.... Just generate something
|
||||||
|
huffBuff = append(huffBuff, bytes.Repeat([]byte{255}, 10000)...)
|
||||||
|
for i := 0; i < 128; i++ {
|
||||||
|
huffBuff = append(huffBuff, byte(i))
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if errors.Is(err, huff0.ErrIncompressible) {
|
||||||
|
// Try truncating least common.
|
||||||
|
for i, n := range remain[:] {
|
||||||
|
if n > 0 {
|
||||||
|
n = n / (div * (i + 1))
|
||||||
|
if n > 0 {
|
||||||
|
huffBuff = append(huffBuff, bytes.Repeat([]byte{byte(i)}, n)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if o.CompatV155 && len(huffBuff) > 0 && huffBuff[len(huffBuff)-1] != 255 {
|
||||||
|
huffBuff = append(huffBuff, 255)
|
||||||
|
}
|
||||||
|
if len(huffBuff) == 0 {
|
||||||
|
huffBuff = append(huffBuff, 0, 255)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if errors.Is(err, huff0.ErrUseRLE) {
|
||||||
|
for i, n := range remain[:] {
|
||||||
|
n = n / (div * (i + 1))
|
||||||
|
// Allow all entries to be represented.
|
||||||
|
if n == 0 {
|
||||||
|
n = 1
|
||||||
|
}
|
||||||
|
huffBuff = append(huffBuff, bytes.Repeat([]byte{byte(i)}, n)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var out bytes.Buffer
|
||||||
|
out.Write([]byte(dictMagic))
|
||||||
|
out.Write(binary.LittleEndian.AppendUint32(nil, o.ID))
|
||||||
|
out.Write(scratch.OutTable)
|
||||||
|
if debug {
|
||||||
|
println("huff table:", len(scratch.OutTable), "bytes")
|
||||||
|
println("of table:", len(ofTable), "bytes")
|
||||||
|
println("ml table:", len(mlTable), "bytes")
|
||||||
|
println("ll table:", len(llTable), "bytes")
|
||||||
|
}
|
||||||
|
out.Write(ofTable)
|
||||||
|
out.Write(mlTable)
|
||||||
|
out.Write(llTable)
|
||||||
|
out.Write(binary.LittleEndian.AppendUint32(nil, uint32(o.Offsets[0])))
|
||||||
|
out.Write(binary.LittleEndian.AppendUint32(nil, uint32(o.Offsets[1])))
|
||||||
|
out.Write(binary.LittleEndian.AppendUint32(nil, uint32(o.Offsets[2])))
|
||||||
|
out.Write(hist)
|
||||||
|
if debug {
|
||||||
|
_, err := loadDict(out.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
i, err := InspectDictionary(out.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
println("ID:", i.ID())
|
||||||
|
println("Content size:", i.ContentSize())
|
||||||
|
println("Encoder:", i.LitEncoder() != nil)
|
||||||
|
println("Offsets:", i.Offsets())
|
||||||
|
var totalSize int
|
||||||
|
for _, b := range contents {
|
||||||
|
totalSize += len(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
encWith := func(opts ...EOption) int {
|
||||||
|
enc, err := NewWriter(nil, opts...)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer enc.Close()
|
||||||
|
var dst []byte
|
||||||
|
var totalSize int
|
||||||
|
for _, b := range contents {
|
||||||
|
dst = enc.EncodeAll(b, dst[:0])
|
||||||
|
totalSize += len(dst)
|
||||||
|
}
|
||||||
|
return totalSize
|
||||||
|
}
|
||||||
|
plain := encWith(WithEncoderLevel(o.Level))
|
||||||
|
withDict := encWith(WithEncoderLevel(o.Level), WithEncoderDict(out.Bytes()))
|
||||||
|
println("Input size:", totalSize)
|
||||||
|
println("Plain Compressed:", plain)
|
||||||
|
println("Dict Compressed:", withDict)
|
||||||
|
println("Saved:", plain-withDict, (plain-withDict)/len(contents), "bytes per input (rounded down)")
|
||||||
|
}
|
||||||
|
return out.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
|
@ -227,10 +227,7 @@ func (e *Encoder) nextBlock(final bool) error {
|
||||||
DictID: e.o.dict.ID(),
|
DictID: e.o.dict.ID(),
|
||||||
}
|
}
|
||||||
|
|
||||||
dst, err := fh.appendTo(tmp[:0])
|
dst := fh.appendTo(tmp[:0])
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
s.headerWritten = true
|
s.headerWritten = true
|
||||||
s.wWg.Wait()
|
s.wWg.Wait()
|
||||||
var n2 int
|
var n2 int
|
||||||
|
@ -483,7 +480,7 @@ func (e *Encoder) EncodeAll(src, dst []byte) []byte {
|
||||||
Checksum: false,
|
Checksum: false,
|
||||||
DictID: 0,
|
DictID: 0,
|
||||||
}
|
}
|
||||||
dst, _ = fh.appendTo(dst)
|
dst = fh.appendTo(dst)
|
||||||
|
|
||||||
// Write raw block as last one only.
|
// Write raw block as last one only.
|
||||||
var blk blockHeader
|
var blk blockHeader
|
||||||
|
@ -518,10 +515,7 @@ func (e *Encoder) EncodeAll(src, dst []byte) []byte {
|
||||||
if len(dst) == 0 && cap(dst) == 0 && len(src) < 1<<20 && !e.o.lowMem {
|
if len(dst) == 0 && cap(dst) == 0 && len(src) < 1<<20 && !e.o.lowMem {
|
||||||
dst = make([]byte, 0, len(src))
|
dst = make([]byte, 0, len(src))
|
||||||
}
|
}
|
||||||
dst, err := fh.appendTo(dst)
|
dst = fh.appendTo(dst)
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we can do everything in one block, prefer that.
|
// If we can do everything in one block, prefer that.
|
||||||
if len(src) <= e.o.blockSize {
|
if len(src) <= e.o.blockSize {
|
||||||
|
@ -581,6 +575,7 @@ func (e *Encoder) EncodeAll(src, dst []byte) []byte {
|
||||||
// Add padding with content from crypto/rand.Reader
|
// Add padding with content from crypto/rand.Reader
|
||||||
if e.o.pad > 0 {
|
if e.o.pad > 0 {
|
||||||
add := calcSkippableFrame(int64(len(dst)), int64(e.o.pad))
|
add := calcSkippableFrame(int64(len(dst)), int64(e.o.pad))
|
||||||
|
var err error
|
||||||
dst, err = skippableFrame(dst, add, rand.Reader)
|
dst, err = skippableFrame(dst, add, rand.Reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
|
@ -22,7 +22,7 @@ type frameHeader struct {
|
||||||
|
|
||||||
const maxHeaderSize = 14
|
const maxHeaderSize = 14
|
||||||
|
|
||||||
func (f frameHeader) appendTo(dst []byte) ([]byte, error) {
|
func (f frameHeader) appendTo(dst []byte) []byte {
|
||||||
dst = append(dst, frameMagic...)
|
dst = append(dst, frameMagic...)
|
||||||
var fhd uint8
|
var fhd uint8
|
||||||
if f.Checksum {
|
if f.Checksum {
|
||||||
|
@ -88,7 +88,7 @@ func (f frameHeader) appendTo(dst []byte) ([]byte, error) {
|
||||||
default:
|
default:
|
||||||
panic("invalid fcs")
|
panic("invalid fcs")
|
||||||
}
|
}
|
||||||
return dst, nil
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
const skippableFrameHeader = 4 + 4
|
const skippableFrameHeader = 4 + 4
|
||||||
|
|
|
@ -245,7 +245,7 @@ func (s *sequenceDecs) decodeSync(hist []byte) error {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
var ll, mo, ml int
|
var ll, mo, ml int
|
||||||
if br.off > 4+((maxOffsetBits+16+16)>>3) {
|
if len(br.in) > 4+((maxOffsetBits+16+16)>>3) {
|
||||||
// inlined function:
|
// inlined function:
|
||||||
// ll, mo, ml = s.nextFast(br, llState, mlState, ofState)
|
// ll, mo, ml = s.nextFast(br, llState, mlState, ofState)
|
||||||
|
|
||||||
|
@ -452,18 +452,13 @@ func (s *sequenceDecs) next(br *bitReader, llState, mlState, ofState decSymbol)
|
||||||
|
|
||||||
// extra bits are stored in reverse order.
|
// extra bits are stored in reverse order.
|
||||||
br.fill()
|
br.fill()
|
||||||
if s.maxBits <= 32 {
|
|
||||||
mo += br.getBits(moB)
|
|
||||||
ml += br.getBits(mlB)
|
|
||||||
ll += br.getBits(llB)
|
|
||||||
} else {
|
|
||||||
mo += br.getBits(moB)
|
mo += br.getBits(moB)
|
||||||
|
if s.maxBits > 32 {
|
||||||
br.fill()
|
br.fill()
|
||||||
|
}
|
||||||
// matchlength+literal length, max 32 bits
|
// matchlength+literal length, max 32 bits
|
||||||
ml += br.getBits(mlB)
|
ml += br.getBits(mlB)
|
||||||
ll += br.getBits(llB)
|
ll += br.getBits(llB)
|
||||||
|
|
||||||
}
|
|
||||||
mo = s.adjustOffset(mo, ll, moB)
|
mo = s.adjustOffset(mo, ll, moB)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
// func sequenceDecs_decode_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
// func sequenceDecs_decode_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
||||||
// Requires: CMOV
|
// Requires: CMOV
|
||||||
TEXT ·sequenceDecs_decode_amd64(SB), $8-32
|
TEXT ·sequenceDecs_decode_amd64(SB), $8-32
|
||||||
MOVQ br+8(FP), AX
|
MOVQ br+8(FP), CX
|
||||||
MOVQ 32(AX), DX
|
MOVQ 24(CX), DX
|
||||||
MOVBQZX 40(AX), BX
|
MOVBQZX 32(CX), BX
|
||||||
MOVQ 24(AX), SI
|
MOVQ (CX), AX
|
||||||
MOVQ (AX), AX
|
MOVQ 8(CX), SI
|
||||||
ADDQ SI, AX
|
ADDQ SI, AX
|
||||||
MOVQ AX, (SP)
|
MOVQ AX, (SP)
|
||||||
MOVQ ctx+16(FP), AX
|
MOVQ ctx+16(FP), AX
|
||||||
|
@ -301,9 +301,9 @@ sequenceDecs_decode_amd64_match_len_ofs_ok:
|
||||||
MOVQ R12, 152(AX)
|
MOVQ R12, 152(AX)
|
||||||
MOVQ R13, 160(AX)
|
MOVQ R13, 160(AX)
|
||||||
MOVQ br+8(FP), AX
|
MOVQ br+8(FP), AX
|
||||||
MOVQ DX, 32(AX)
|
MOVQ DX, 24(AX)
|
||||||
MOVB BL, 40(AX)
|
MOVB BL, 32(AX)
|
||||||
MOVQ SI, 24(AX)
|
MOVQ SI, 8(AX)
|
||||||
|
|
||||||
// Return success
|
// Return success
|
||||||
MOVQ $0x00000000, ret+24(FP)
|
MOVQ $0x00000000, ret+24(FP)
|
||||||
|
@ -336,11 +336,11 @@ error_overread:
|
||||||
// func sequenceDecs_decode_56_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
// func sequenceDecs_decode_56_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
||||||
// Requires: CMOV
|
// Requires: CMOV
|
||||||
TEXT ·sequenceDecs_decode_56_amd64(SB), $8-32
|
TEXT ·sequenceDecs_decode_56_amd64(SB), $8-32
|
||||||
MOVQ br+8(FP), AX
|
MOVQ br+8(FP), CX
|
||||||
MOVQ 32(AX), DX
|
MOVQ 24(CX), DX
|
||||||
MOVBQZX 40(AX), BX
|
MOVBQZX 32(CX), BX
|
||||||
MOVQ 24(AX), SI
|
MOVQ (CX), AX
|
||||||
MOVQ (AX), AX
|
MOVQ 8(CX), SI
|
||||||
ADDQ SI, AX
|
ADDQ SI, AX
|
||||||
MOVQ AX, (SP)
|
MOVQ AX, (SP)
|
||||||
MOVQ ctx+16(FP), AX
|
MOVQ ctx+16(FP), AX
|
||||||
|
@ -603,9 +603,9 @@ sequenceDecs_decode_56_amd64_match_len_ofs_ok:
|
||||||
MOVQ R12, 152(AX)
|
MOVQ R12, 152(AX)
|
||||||
MOVQ R13, 160(AX)
|
MOVQ R13, 160(AX)
|
||||||
MOVQ br+8(FP), AX
|
MOVQ br+8(FP), AX
|
||||||
MOVQ DX, 32(AX)
|
MOVQ DX, 24(AX)
|
||||||
MOVB BL, 40(AX)
|
MOVB BL, 32(AX)
|
||||||
MOVQ SI, 24(AX)
|
MOVQ SI, 8(AX)
|
||||||
|
|
||||||
// Return success
|
// Return success
|
||||||
MOVQ $0x00000000, ret+24(FP)
|
MOVQ $0x00000000, ret+24(FP)
|
||||||
|
@ -638,11 +638,11 @@ error_overread:
|
||||||
// func sequenceDecs_decode_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
// func sequenceDecs_decode_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
||||||
// Requires: BMI, BMI2, CMOV
|
// Requires: BMI, BMI2, CMOV
|
||||||
TEXT ·sequenceDecs_decode_bmi2(SB), $8-32
|
TEXT ·sequenceDecs_decode_bmi2(SB), $8-32
|
||||||
MOVQ br+8(FP), CX
|
MOVQ br+8(FP), BX
|
||||||
MOVQ 32(CX), AX
|
MOVQ 24(BX), AX
|
||||||
MOVBQZX 40(CX), DX
|
MOVBQZX 32(BX), DX
|
||||||
MOVQ 24(CX), BX
|
MOVQ (BX), CX
|
||||||
MOVQ (CX), CX
|
MOVQ 8(BX), BX
|
||||||
ADDQ BX, CX
|
ADDQ BX, CX
|
||||||
MOVQ CX, (SP)
|
MOVQ CX, (SP)
|
||||||
MOVQ ctx+16(FP), CX
|
MOVQ ctx+16(FP), CX
|
||||||
|
@ -892,9 +892,9 @@ sequenceDecs_decode_bmi2_match_len_ofs_ok:
|
||||||
MOVQ R11, 152(CX)
|
MOVQ R11, 152(CX)
|
||||||
MOVQ R12, 160(CX)
|
MOVQ R12, 160(CX)
|
||||||
MOVQ br+8(FP), CX
|
MOVQ br+8(FP), CX
|
||||||
MOVQ AX, 32(CX)
|
MOVQ AX, 24(CX)
|
||||||
MOVB DL, 40(CX)
|
MOVB DL, 32(CX)
|
||||||
MOVQ BX, 24(CX)
|
MOVQ BX, 8(CX)
|
||||||
|
|
||||||
// Return success
|
// Return success
|
||||||
MOVQ $0x00000000, ret+24(FP)
|
MOVQ $0x00000000, ret+24(FP)
|
||||||
|
@ -927,11 +927,11 @@ error_overread:
|
||||||
// func sequenceDecs_decode_56_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
// func sequenceDecs_decode_56_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
||||||
// Requires: BMI, BMI2, CMOV
|
// Requires: BMI, BMI2, CMOV
|
||||||
TEXT ·sequenceDecs_decode_56_bmi2(SB), $8-32
|
TEXT ·sequenceDecs_decode_56_bmi2(SB), $8-32
|
||||||
MOVQ br+8(FP), CX
|
MOVQ br+8(FP), BX
|
||||||
MOVQ 32(CX), AX
|
MOVQ 24(BX), AX
|
||||||
MOVBQZX 40(CX), DX
|
MOVBQZX 32(BX), DX
|
||||||
MOVQ 24(CX), BX
|
MOVQ (BX), CX
|
||||||
MOVQ (CX), CX
|
MOVQ 8(BX), BX
|
||||||
ADDQ BX, CX
|
ADDQ BX, CX
|
||||||
MOVQ CX, (SP)
|
MOVQ CX, (SP)
|
||||||
MOVQ ctx+16(FP), CX
|
MOVQ ctx+16(FP), CX
|
||||||
|
@ -1152,9 +1152,9 @@ sequenceDecs_decode_56_bmi2_match_len_ofs_ok:
|
||||||
MOVQ R11, 152(CX)
|
MOVQ R11, 152(CX)
|
||||||
MOVQ R12, 160(CX)
|
MOVQ R12, 160(CX)
|
||||||
MOVQ br+8(FP), CX
|
MOVQ br+8(FP), CX
|
||||||
MOVQ AX, 32(CX)
|
MOVQ AX, 24(CX)
|
||||||
MOVB DL, 40(CX)
|
MOVB DL, 32(CX)
|
||||||
MOVQ BX, 24(CX)
|
MOVQ BX, 8(CX)
|
||||||
|
|
||||||
// Return success
|
// Return success
|
||||||
MOVQ $0x00000000, ret+24(FP)
|
MOVQ $0x00000000, ret+24(FP)
|
||||||
|
@ -1797,11 +1797,11 @@ empty_seqs:
|
||||||
// func sequenceDecs_decodeSync_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
|
// func sequenceDecs_decodeSync_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
|
||||||
// Requires: CMOV, SSE
|
// Requires: CMOV, SSE
|
||||||
TEXT ·sequenceDecs_decodeSync_amd64(SB), $64-32
|
TEXT ·sequenceDecs_decodeSync_amd64(SB), $64-32
|
||||||
MOVQ br+8(FP), AX
|
MOVQ br+8(FP), CX
|
||||||
MOVQ 32(AX), DX
|
MOVQ 24(CX), DX
|
||||||
MOVBQZX 40(AX), BX
|
MOVBQZX 32(CX), BX
|
||||||
MOVQ 24(AX), SI
|
MOVQ (CX), AX
|
||||||
MOVQ (AX), AX
|
MOVQ 8(CX), SI
|
||||||
ADDQ SI, AX
|
ADDQ SI, AX
|
||||||
MOVQ AX, (SP)
|
MOVQ AX, (SP)
|
||||||
MOVQ ctx+16(FP), AX
|
MOVQ ctx+16(FP), AX
|
||||||
|
@ -2295,9 +2295,9 @@ handle_loop:
|
||||||
|
|
||||||
loop_finished:
|
loop_finished:
|
||||||
MOVQ br+8(FP), AX
|
MOVQ br+8(FP), AX
|
||||||
MOVQ DX, 32(AX)
|
MOVQ DX, 24(AX)
|
||||||
MOVB BL, 40(AX)
|
MOVB BL, 32(AX)
|
||||||
MOVQ SI, 24(AX)
|
MOVQ SI, 8(AX)
|
||||||
|
|
||||||
// Update the context
|
// Update the context
|
||||||
MOVQ ctx+16(FP), AX
|
MOVQ ctx+16(FP), AX
|
||||||
|
@ -2362,11 +2362,11 @@ error_not_enough_space:
|
||||||
// func sequenceDecs_decodeSync_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
|
// func sequenceDecs_decodeSync_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
|
||||||
// Requires: BMI, BMI2, CMOV, SSE
|
// Requires: BMI, BMI2, CMOV, SSE
|
||||||
TEXT ·sequenceDecs_decodeSync_bmi2(SB), $64-32
|
TEXT ·sequenceDecs_decodeSync_bmi2(SB), $64-32
|
||||||
MOVQ br+8(FP), CX
|
MOVQ br+8(FP), BX
|
||||||
MOVQ 32(CX), AX
|
MOVQ 24(BX), AX
|
||||||
MOVBQZX 40(CX), DX
|
MOVBQZX 32(BX), DX
|
||||||
MOVQ 24(CX), BX
|
MOVQ (BX), CX
|
||||||
MOVQ (CX), CX
|
MOVQ 8(BX), BX
|
||||||
ADDQ BX, CX
|
ADDQ BX, CX
|
||||||
MOVQ CX, (SP)
|
MOVQ CX, (SP)
|
||||||
MOVQ ctx+16(FP), CX
|
MOVQ ctx+16(FP), CX
|
||||||
|
@ -2818,9 +2818,9 @@ handle_loop:
|
||||||
|
|
||||||
loop_finished:
|
loop_finished:
|
||||||
MOVQ br+8(FP), CX
|
MOVQ br+8(FP), CX
|
||||||
MOVQ AX, 32(CX)
|
MOVQ AX, 24(CX)
|
||||||
MOVB DL, 40(CX)
|
MOVB DL, 32(CX)
|
||||||
MOVQ BX, 24(CX)
|
MOVQ BX, 8(CX)
|
||||||
|
|
||||||
// Update the context
|
// Update the context
|
||||||
MOVQ ctx+16(FP), AX
|
MOVQ ctx+16(FP), AX
|
||||||
|
@ -2885,11 +2885,11 @@ error_not_enough_space:
|
||||||
// func sequenceDecs_decodeSync_safe_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
|
// func sequenceDecs_decodeSync_safe_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
|
||||||
// Requires: CMOV, SSE
|
// Requires: CMOV, SSE
|
||||||
TEXT ·sequenceDecs_decodeSync_safe_amd64(SB), $64-32
|
TEXT ·sequenceDecs_decodeSync_safe_amd64(SB), $64-32
|
||||||
MOVQ br+8(FP), AX
|
MOVQ br+8(FP), CX
|
||||||
MOVQ 32(AX), DX
|
MOVQ 24(CX), DX
|
||||||
MOVBQZX 40(AX), BX
|
MOVBQZX 32(CX), BX
|
||||||
MOVQ 24(AX), SI
|
MOVQ (CX), AX
|
||||||
MOVQ (AX), AX
|
MOVQ 8(CX), SI
|
||||||
ADDQ SI, AX
|
ADDQ SI, AX
|
||||||
MOVQ AX, (SP)
|
MOVQ AX, (SP)
|
||||||
MOVQ ctx+16(FP), AX
|
MOVQ ctx+16(FP), AX
|
||||||
|
@ -3485,9 +3485,9 @@ handle_loop:
|
||||||
|
|
||||||
loop_finished:
|
loop_finished:
|
||||||
MOVQ br+8(FP), AX
|
MOVQ br+8(FP), AX
|
||||||
MOVQ DX, 32(AX)
|
MOVQ DX, 24(AX)
|
||||||
MOVB BL, 40(AX)
|
MOVB BL, 32(AX)
|
||||||
MOVQ SI, 24(AX)
|
MOVQ SI, 8(AX)
|
||||||
|
|
||||||
// Update the context
|
// Update the context
|
||||||
MOVQ ctx+16(FP), AX
|
MOVQ ctx+16(FP), AX
|
||||||
|
@ -3552,11 +3552,11 @@ error_not_enough_space:
|
||||||
// func sequenceDecs_decodeSync_safe_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
|
// func sequenceDecs_decodeSync_safe_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
|
||||||
// Requires: BMI, BMI2, CMOV, SSE
|
// Requires: BMI, BMI2, CMOV, SSE
|
||||||
TEXT ·sequenceDecs_decodeSync_safe_bmi2(SB), $64-32
|
TEXT ·sequenceDecs_decodeSync_safe_bmi2(SB), $64-32
|
||||||
MOVQ br+8(FP), CX
|
MOVQ br+8(FP), BX
|
||||||
MOVQ 32(CX), AX
|
MOVQ 24(BX), AX
|
||||||
MOVBQZX 40(CX), DX
|
MOVBQZX 32(BX), DX
|
||||||
MOVQ 24(CX), BX
|
MOVQ (BX), CX
|
||||||
MOVQ (CX), CX
|
MOVQ 8(BX), BX
|
||||||
ADDQ BX, CX
|
ADDQ BX, CX
|
||||||
MOVQ CX, (SP)
|
MOVQ CX, (SP)
|
||||||
MOVQ ctx+16(FP), CX
|
MOVQ ctx+16(FP), CX
|
||||||
|
@ -4110,9 +4110,9 @@ handle_loop:
|
||||||
|
|
||||||
loop_finished:
|
loop_finished:
|
||||||
MOVQ br+8(FP), CX
|
MOVQ br+8(FP), CX
|
||||||
MOVQ AX, 32(CX)
|
MOVQ AX, 24(CX)
|
||||||
MOVB DL, 40(CX)
|
MOVB DL, 32(CX)
|
||||||
MOVQ BX, 24(CX)
|
MOVQ BX, 8(CX)
|
||||||
|
|
||||||
// Update the context
|
// Update the context
|
||||||
MOVQ ctx+16(FP), AX
|
MOVQ ctx+16(FP), AX
|
||||||
|
|
|
@ -29,7 +29,7 @@ func (s *sequenceDecs) decode(seqs []seqVals) error {
|
||||||
}
|
}
|
||||||
for i := range seqs {
|
for i := range seqs {
|
||||||
var ll, mo, ml int
|
var ll, mo, ml int
|
||||||
if br.off > 4+((maxOffsetBits+16+16)>>3) {
|
if len(br.in) > 4+((maxOffsetBits+16+16)>>3) {
|
||||||
// inlined function:
|
// inlined function:
|
||||||
// ll, mo, ml = s.nextFast(br, llState, mlState, ofState)
|
// ll, mo, ml = s.nextFast(br, llState, mlState, ofState)
|
||||||
|
|
||||||
|
|
|
@ -95,10 +95,9 @@ func (r *SnappyConverter) Convert(in io.Reader, w io.Writer) (int64, error) {
|
||||||
var written int64
|
var written int64
|
||||||
var readHeader bool
|
var readHeader bool
|
||||||
{
|
{
|
||||||
var header []byte
|
header := frameHeader{WindowSize: snappyMaxBlockSize}.appendTo(r.buf[:0])
|
||||||
var n int
|
|
||||||
header, r.err = frameHeader{WindowSize: snappyMaxBlockSize}.appendTo(r.buf[:0])
|
|
||||||
|
|
||||||
|
var n int
|
||||||
n, r.err = w.Write(header)
|
n, r.err = w.Write(header)
|
||||||
if r.err != nil {
|
if r.err != nil {
|
||||||
return written, r.err
|
return written, r.err
|
||||||
|
|
|
@ -14,7 +14,7 @@ github.com/inconshreveable/mousetrap
|
||||||
# github.com/julienschmidt/httprouter v1.3.0
|
# github.com/julienschmidt/httprouter v1.3.0
|
||||||
## explicit; go 1.7
|
## explicit; go 1.7
|
||||||
github.com/julienschmidt/httprouter
|
github.com/julienschmidt/httprouter
|
||||||
# github.com/klauspost/compress v1.16.7
|
# github.com/klauspost/compress v1.17.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
github.com/klauspost/compress
|
github.com/klauspost/compress
|
||||||
github.com/klauspost/compress/fse
|
github.com/klauspost/compress/fse
|
||||||
|
|
Loading…
Reference in New Issue