-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
Signed-off-by: bwplotka <[email protected]>
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
Copyright (c) 2012 The Go Authors. All rights reserved. | ||
Copyright (c) 2019 Klaus Post. All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are | ||
met: | ||
|
||
* Redistributions of source code must retain the above copyright | ||
notice, this list of conditions and the following disclaimer. | ||
* Redistributions in binary form must reproduce the above | ||
copyright notice, this list of conditions and the following disclaimer | ||
in the documentation and/or other materials provided with the | ||
distribution. | ||
* Neither the name of Google Inc. nor the names of its | ||
contributors may be used to endorse or promote products derived from | ||
this software without specific prior written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
This source code is a stripped down version of zstd from the https://github.com/klauspost/compress/tree/517288e9a6e1dd4dea10ad42ffe2829c58dadf51/zstd. | ||
|
||
Motivation: https://github.com/kubernetes/kubernetes/pull/130569#discussion_r1981503174 | ||
|
||
Changes: | ||
* Remove all but things necessary to use and create zstd.NewWriter for SpeedFastest mode. | ||
* Use github.com/cespare/xxhash/v2 instead of vendored copy. | ||
|
||
The goal is to remove this once stdlib will support zstd. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
// Copyright 2018 Klaus Post. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. | ||
|
||
package fse | ||
|
||
import ( | ||
"encoding/binary" | ||
"errors" | ||
"io" | ||
) | ||
|
||
// bitReader reads a bitstream in reverse. | ||
// The last set bit indicates the start of the stream and is used | ||
// for aligning the input. | ||
type bitReader struct { | ||
in []byte | ||
off uint // next byte to read is at in[off - 1] | ||
value uint64 | ||
bitsRead uint8 | ||
} | ||
|
||
// init initializes and resets the bit reader. | ||
func (b *bitReader) init(in []byte) error { | ||
if len(in) < 1 { | ||
return errors.New("corrupt stream: too short") | ||
} | ||
b.in = in | ||
b.off = uint(len(in)) | ||
// The highest bit of the last byte indicates where to start | ||
v := in[len(in)-1] | ||
if v == 0 { | ||
return errors.New("corrupt stream, did not find end of stream") | ||
} | ||
b.bitsRead = 64 | ||
b.value = 0 | ||
if len(in) >= 8 { | ||
b.fillFastStart() | ||
} else { | ||
b.fill() | ||
b.fill() | ||
} | ||
b.bitsRead += 8 - uint8(highBits(uint32(v))) | ||
return nil | ||
} | ||
|
||
// getBits will return n bits. n can be 0. | ||
func (b *bitReader) getBits(n uint8) uint16 { | ||
Check failure on line 49 in internal/github.com/klauspost/compress/fse/bitreader.go
|
||
if n == 0 || b.bitsRead >= 64 { | ||
return 0 | ||
} | ||
return b.getBitsFast(n) | ||
} | ||
|
||
// getBitsFast requires that at least one bit is requested every time. | ||
// There are no checks if the buffer is filled. | ||
func (b *bitReader) getBitsFast(n uint8) uint16 { | ||
Check failure on line 58 in internal/github.com/klauspost/compress/fse/bitreader.go
|
||
const regMask = 64 - 1 | ||
v := uint16((b.value << (b.bitsRead & regMask)) >> ((regMask + 1 - n) & regMask)) | ||
b.bitsRead += n | ||
return v | ||
} | ||
|
||
// fillFast() will make sure at least 32 bits are available. | ||
// There must be at least 4 bytes available. | ||
func (b *bitReader) fillFast() { | ||
Check failure on line 67 in internal/github.com/klauspost/compress/fse/bitreader.go
|
||
if b.bitsRead < 32 { | ||
return | ||
} | ||
// 2 bounds checks. | ||
v := b.in[b.off-4:] | ||
v = v[:4] | ||
low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) | ||
b.value = (b.value << 32) | uint64(low) | ||
b.bitsRead -= 32 | ||
b.off -= 4 | ||
} | ||
|
||
// fill() will make sure at least 32 bits are available. | ||
func (b *bitReader) fill() { | ||
if b.bitsRead < 32 { | ||
return | ||
} | ||
if b.off > 4 { | ||
v := b.in[b.off-4:] | ||
v = v[:4] | ||
low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) | ||
b.value = (b.value << 32) | uint64(low) | ||
b.bitsRead -= 32 | ||
b.off -= 4 | ||
return | ||
} | ||
for b.off > 0 { | ||
b.value = (b.value << 8) | uint64(b.in[b.off-1]) | ||
b.bitsRead -= 8 | ||
b.off-- | ||
} | ||
} | ||
|
||
// fillFastStart() assumes the bitreader is empty and there is at least 8 bytes to read. | ||
func (b *bitReader) fillFastStart() { | ||
// Do single re-slice to avoid bounds checks. | ||
b.value = binary.LittleEndian.Uint64(b.in[b.off-8:]) | ||
b.bitsRead = 0 | ||
b.off -= 8 | ||
} | ||
|
||
// finished returns true if all bits have been read from the bit stream. | ||
func (b *bitReader) finished() bool { | ||
Check failure on line 110 in internal/github.com/klauspost/compress/fse/bitreader.go
|
||
return b.bitsRead >= 64 && b.off == 0 | ||
} | ||
|
||
// close the bitstream and returns an error if out-of-buffer reads occurred. | ||
func (b *bitReader) close() error { | ||
Check failure on line 115 in internal/github.com/klauspost/compress/fse/bitreader.go
|
||
// Release reference. | ||
b.in = nil | ||
if b.bitsRead > 64 { | ||
return io.ErrUnexpectedEOF | ||
} | ||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
// Copyright 2018 Klaus Post. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. | ||
|
||
package fse | ||
|
||
import "fmt" | ||
|
||
// bitWriter will write bits. | ||
// First bit will be LSB of the first byte of output. | ||
type bitWriter struct { | ||
bitContainer uint64 | ||
nBits uint8 | ||
out []byte | ||
} | ||
|
||
// bitMask16 is bitmasks. Has extra to avoid bounds check. | ||
var bitMask16 = [32]uint16{ | ||
0, 1, 3, 7, 0xF, 0x1F, | ||
0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, | ||
0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0xFFFF, | ||
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, | ||
0xFFFF, 0xFFFF} /* up to 16 bits */ | ||
|
||
// addBits16NC will add up to 16 bits. | ||
// It will not check if there is space for them, | ||
// so the caller must ensure that it has flushed recently. | ||
func (b *bitWriter) addBits16NC(value uint16, bits uint8) { | ||
b.bitContainer |= uint64(value&bitMask16[bits&31]) << (b.nBits & 63) | ||
b.nBits += bits | ||
} | ||
|
||
// addBits16Clean will add up to 16 bits. value may not contain more set bits than indicated. | ||
// It will not check if there is space for them, so the caller must ensure that it has flushed recently. | ||
func (b *bitWriter) addBits16Clean(value uint16, bits uint8) { | ||
b.bitContainer |= uint64(value) << (b.nBits & 63) | ||
b.nBits += bits | ||
} | ||
|
||
// addBits16ZeroNC will add up to 16 bits. | ||
// It will not check if there is space for them, | ||
// so the caller must ensure that it has flushed recently. | ||
// This is fastest if bits can be zero. | ||
func (b *bitWriter) addBits16ZeroNC(value uint16, bits uint8) { | ||
if bits == 0 { | ||
return | ||
} | ||
value <<= (16 - bits) & 15 | ||
value >>= (16 - bits) & 15 | ||
b.bitContainer |= uint64(value) << (b.nBits & 63) | ||
b.nBits += bits | ||
} | ||
|
||
// flush will flush all pending full bytes. | ||
// There will be at least 56 bits available for writing when this has been called. | ||
// Using flush32 is faster, but leaves less space for writing. | ||
func (b *bitWriter) flush() { | ||
v := b.nBits >> 3 | ||
switch v { | ||
case 0: | ||
case 1: | ||
b.out = append(b.out, | ||
byte(b.bitContainer), | ||
) | ||
case 2: | ||
b.out = append(b.out, | ||
byte(b.bitContainer), | ||
byte(b.bitContainer>>8), | ||
) | ||
case 3: | ||
b.out = append(b.out, | ||
byte(b.bitContainer), | ||
byte(b.bitContainer>>8), | ||
byte(b.bitContainer>>16), | ||
) | ||
case 4: | ||
b.out = append(b.out, | ||
byte(b.bitContainer), | ||
byte(b.bitContainer>>8), | ||
byte(b.bitContainer>>16), | ||
byte(b.bitContainer>>24), | ||
) | ||
case 5: | ||
b.out = append(b.out, | ||
byte(b.bitContainer), | ||
byte(b.bitContainer>>8), | ||
byte(b.bitContainer>>16), | ||
byte(b.bitContainer>>24), | ||
byte(b.bitContainer>>32), | ||
) | ||
case 6: | ||
b.out = append(b.out, | ||
byte(b.bitContainer), | ||
byte(b.bitContainer>>8), | ||
byte(b.bitContainer>>16), | ||
byte(b.bitContainer>>24), | ||
byte(b.bitContainer>>32), | ||
byte(b.bitContainer>>40), | ||
) | ||
case 7: | ||
b.out = append(b.out, | ||
byte(b.bitContainer), | ||
byte(b.bitContainer>>8), | ||
byte(b.bitContainer>>16), | ||
byte(b.bitContainer>>24), | ||
byte(b.bitContainer>>32), | ||
byte(b.bitContainer>>40), | ||
byte(b.bitContainer>>48), | ||
) | ||
case 8: | ||
b.out = append(b.out, | ||
byte(b.bitContainer), | ||
byte(b.bitContainer>>8), | ||
byte(b.bitContainer>>16), | ||
byte(b.bitContainer>>24), | ||
byte(b.bitContainer>>32), | ||
byte(b.bitContainer>>40), | ||
byte(b.bitContainer>>48), | ||
byte(b.bitContainer>>56), | ||
) | ||
default: | ||
panic(fmt.Errorf("bits (%d) > 64", b.nBits)) | ||
} | ||
b.bitContainer >>= v << 3 | ||
b.nBits &= 7 | ||
} | ||
|
||
// flush32 will flush out, so there are at least 32 bits available for writing. | ||
func (b *bitWriter) flush32() { | ||
if b.nBits < 32 { | ||
return | ||
} | ||
b.out = append(b.out, | ||
byte(b.bitContainer), | ||
byte(b.bitContainer>>8), | ||
byte(b.bitContainer>>16), | ||
byte(b.bitContainer>>24)) | ||
b.nBits -= 32 | ||
b.bitContainer >>= 32 | ||
} | ||
|
||
// flushAlign will flush remaining full bytes and align to next byte boundary. | ||
func (b *bitWriter) flushAlign() { | ||
nbBytes := (b.nBits + 7) >> 3 | ||
for i := uint8(0); i < nbBytes; i++ { | ||
b.out = append(b.out, byte(b.bitContainer>>(i*8))) | ||
} | ||
b.nBits = 0 | ||
b.bitContainer = 0 | ||
} | ||
|
||
// close will write the alignment bit and write the final byte(s) | ||
// to the output. | ||
func (b *bitWriter) close() { | ||
// End mark | ||
b.addBits16Clean(1, 1) | ||
// flush until next byte. | ||
b.flushAlign() | ||
} | ||
|
||
// reset and continue writing by appending to out. | ||
func (b *bitWriter) reset(out []byte) { | ||
b.bitContainer = 0 | ||
b.nBits = 0 | ||
b.out = out | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// Copyright 2018 Klaus Post. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. | ||
|
||
package fse | ||
|
||
// byteReader provides a byte reader that reads | ||
// little endian values from a byte stream. | ||
// The input stream is manually advanced. | ||
// The reader performs no bounds checks. | ||
type byteReader struct { | ||
b []byte | ||
off int | ||
} | ||
|
||
// init will initialize the reader and set the input. | ||
func (b *byteReader) init(in []byte) { | ||
b.b = in | ||
b.off = 0 | ||
} | ||
|
||
// advance the stream b n bytes. | ||
func (b *byteReader) advance(n uint) { | ||
Check failure on line 24 in internal/github.com/klauspost/compress/fse/bytereader.go
|
||
b.off += int(n) | ||
} | ||
|
||
// Uint32 returns a little endian uint32 starting at current offset. | ||
func (b byteReader) Uint32() uint32 { | ||
b2 := b.b[b.off:] | ||
b2 = b2[:4] | ||
v3 := uint32(b2[3]) | ||
v2 := uint32(b2[2]) | ||
v1 := uint32(b2[1]) | ||
v0 := uint32(b2[0]) | ||
return v0 | (v1 << 8) | (v2 << 16) | (v3 << 24) | ||
} | ||
|
||
// unread returns the unread portion of the input. | ||
func (b byteReader) unread() []byte { | ||
Check failure on line 40 in internal/github.com/klauspost/compress/fse/bytereader.go
|
||
return b.b[b.off:] | ||
} | ||
|
||
// remain will return the number of bytes remaining. | ||
func (b byteReader) remain() int { | ||
return len(b.b) - b.off | ||
} |