package flate
import (
)
const (
offsetCodeCount = 30
endBlockMarker = 256
lengthCodesStart = 257
codegenCodeCount = 19
badCode = 255
bufferFlushSize = 240
bufferSize = bufferFlushSize + 8
)
var lengthExtraBits = []int8{
0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
4, 5, 5, 5, 5, 0,
}
var lengthBase = []uint32{
0, 1, 2, 3, 4, 5, 6, 7, 8, 10,
12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
64, 80, 96, 112, 128, 160, 192, 224, 255,
}
var offsetExtraBits = []int8{
0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
}
var offsetBase = []uint32{
0x000000, 0x000001, 0x000002, 0x000003, 0x000004,
0x000006, 0x000008, 0x00000c, 0x000010, 0x000018,
0x000020, 0x000030, 0x000040, 0x000060, 0x000080,
0x0000c0, 0x000100, 0x000180, 0x000200, 0x000300,
0x000400, 0x000600, 0x000800, 0x000c00, 0x001000,
0x001800, 0x002000, 0x003000, 0x004000, 0x006000,
}
var codegenOrder = []uint32{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}
type huffmanBitWriter struct {
writer io.Writer
bits uint64
nbits uint
bytes [bufferSize]byte
codegenFreq [codegenCodeCount]int32
nbytes int
literalFreq []int32
offsetFreq []int32
codegen []uint8
literalEncoding *huffmanEncoder
offsetEncoding *huffmanEncoder
codegenEncoding *huffmanEncoder
err error
}
func ( io.Writer) *huffmanBitWriter {
return &huffmanBitWriter{
writer: ,
literalFreq: make([]int32, maxNumLit),
offsetFreq: make([]int32, offsetCodeCount),
codegen: make([]uint8, maxNumLit+offsetCodeCount+1),
literalEncoding: newHuffmanEncoder(maxNumLit),
codegenEncoding: newHuffmanEncoder(codegenCodeCount),
offsetEncoding: newHuffmanEncoder(offsetCodeCount),
}
}
func ( *huffmanBitWriter) ( io.Writer) {
.writer =
.bits, .nbits, .nbytes, .err = 0, 0, 0, nil
}
func ( *huffmanBitWriter) () {
if .err != nil {
.nbits = 0
return
}
:= .nbytes
for .nbits != 0 {
.bytes[] = byte(.bits)
.bits >>= 8
if .nbits > 8 {
.nbits -= 8
} else {
.nbits = 0
}
++
}
.bits = 0
.write(.bytes[:])
.nbytes = 0
}
func ( *huffmanBitWriter) ( []byte) {
if .err != nil {
return
}
_, .err = .writer.Write()
}
func ( *huffmanBitWriter) ( int32, uint) {
if .err != nil {
return
}
.bits |= uint64() << .nbits
.nbits +=
if .nbits >= 48 {
:= .bits
.bits >>= 48
.nbits -= 48
:= .nbytes
:= .bytes[ : +6]
[0] = byte()
[1] = byte( >> 8)
[2] = byte( >> 16)
[3] = byte( >> 24)
[4] = byte( >> 32)
[5] = byte( >> 40)
+= 6
if >= bufferFlushSize {
.write(.bytes[:])
= 0
}
.nbytes =
}
}
func ( *huffmanBitWriter) ( []byte) {
if .err != nil {
return
}
:= .nbytes
if .nbits&7 != 0 {
.err = InternalError("writeBytes with unfinished bits")
return
}
for .nbits != 0 {
.bytes[] = byte(.bits)
.bits >>= 8
.nbits -= 8
++
}
if != 0 {
.write(.bytes[:])
}
.nbytes = 0
.write()
}
func ( *huffmanBitWriter) ( int, int, , *huffmanEncoder) {
for := range .codegenFreq {
.codegenFreq[] = 0
}
:= .codegen
:= [:]
for := range {
[] = uint8(.codes[].len)
}
= [ : +]
for := range {
[] = uint8(.codes[].len)
}
[+] = badCode
:= [0]
:= 1
:= 0
for := 1; != badCode; ++ {
:= []
if == {
++
continue
}
if != 0 {
[] =
++
.codegenFreq[]++
--
for >= 3 {
:= 6
if > {
=
}
[] = 16
++
[] = uint8( - 3)
++
.codegenFreq[16]++
-=
}
} else {
for >= 11 {
:= 138
if > {
=
}
[] = 18
++
[] = uint8( - 11)
++
.codegenFreq[18]++
-=
}
if >= 3 {
[] = 17
++
[] = uint8( - 3)
++
.codegenFreq[17]++
= 0
}
}
--
for ; >= 0; -- {
[] =
++
.codegenFreq[]++
}
=
= 1
}
[] = badCode
}
func ( *huffmanBitWriter) (, *huffmanEncoder, int) (, int) {
= len(.codegenFreq)
for > 4 && .codegenFreq[codegenOrder[-1]] == 0 {
--
}
:= 3 + 5 + 5 + 4 + (3 * ) +
.codegenEncoding.bitLength(.codegenFreq[:]) +
int(.codegenFreq[16])*2 +
int(.codegenFreq[17])*3 +
int(.codegenFreq[18])*7
= +
.bitLength(.literalFreq) +
.bitLength(.offsetFreq) +
return ,
}
func ( *huffmanBitWriter) ( int) int {
return 3 +
fixedLiteralEncoding.bitLength(.literalFreq) +
fixedOffsetEncoding.bitLength(.offsetFreq) +
}
func ( *huffmanBitWriter) ( []byte) (int, bool) {
if == nil {
return 0, false
}
if len() <= maxStoreBlockSize {
return (len() + 5) * 8, true
}
return 0, false
}
func ( *huffmanBitWriter) ( hcode) {
if .err != nil {
return
}
.bits |= uint64(.code) << .nbits
.nbits += uint(.len)
if .nbits >= 48 {
:= .bits
.bits >>= 48
.nbits -= 48
:= .nbytes
:= .bytes[ : +6]
[0] = byte()
[1] = byte( >> 8)
[2] = byte( >> 16)
[3] = byte( >> 24)
[4] = byte( >> 32)
[5] = byte( >> 40)
+= 6
if >= bufferFlushSize {
.write(.bytes[:])
= 0
}
.nbytes =
}
}
func ( *huffmanBitWriter) ( int, int, int, bool) {
if .err != nil {
return
}
var int32 = 4
if {
= 5
}
.writeBits(, 3)
.writeBits(int32(-257), 5)
.writeBits(int32(-1), 5)
.writeBits(int32(-4), 4)
for := 0; < ; ++ {
:= uint(.codegenEncoding.codes[codegenOrder[]].len)
.writeBits(int32(), 3)
}
:= 0
for {
var int = int(.codegen[])
++
if == badCode {
break
}
.writeCode(.codegenEncoding.codes[uint32()])
switch {
case 16:
.writeBits(int32(.codegen[]), 2)
++
break
case 17:
.writeBits(int32(.codegen[]), 3)
++
break
case 18:
.writeBits(int32(.codegen[]), 7)
++
break
}
}
}
func ( *huffmanBitWriter) ( int, bool) {
if .err != nil {
return
}
var int32
if {
= 1
}
.writeBits(, 3)
.flush()
.writeBits(int32(), 16)
.writeBits(int32(^uint16()), 16)
}
func ( *huffmanBitWriter) ( bool) {
if .err != nil {
return
}
var int32 = 2
if {
= 3
}
.writeBits(, 3)
}
func ( *huffmanBitWriter) ( []token, bool, []byte) {
if .err != nil {
return
}
= append(, endBlockMarker)
, := .indexTokens()
var int
, := .storedSize()
if {
for := lengthCodesStart + 8; < ; ++ {
+= int(.literalFreq[]) * int(lengthExtraBits[-lengthCodesStart])
}
for := 4; < ; ++ {
+= int(.offsetFreq[]) * int(offsetExtraBits[])
}
}
var = fixedLiteralEncoding
var = fixedOffsetEncoding
var = .fixedSize()
var int
.generateCodegen(, , .literalEncoding, .offsetEncoding)
.codegenEncoding.generate(.codegenFreq[:], 7)
, := .dynamicSize(.literalEncoding, .offsetEncoding, )
if < {
=
= .literalEncoding
= .offsetEncoding
}
if && < {
.writeStoredHeader(len(), )
.writeBytes()
return
}
if == fixedLiteralEncoding {
.writeFixedHeader()
} else {
.writeDynamicHeader(, , , )
}
.writeTokens(, .codes, .codes)
}
func ( *huffmanBitWriter) ( []token, bool, []byte) {
if .err != nil {
return
}
= append(, endBlockMarker)
, := .indexTokens()
.generateCodegen(, , .literalEncoding, .offsetEncoding)
.codegenEncoding.generate(.codegenFreq[:], 7)
, := .dynamicSize(.literalEncoding, .offsetEncoding, 0)
if , := .storedSize(); && < (+>>4) {
.writeStoredHeader(len(), )
.writeBytes()
return
}
.writeDynamicHeader(, , , )
.writeTokens(, .literalEncoding.codes, .offsetEncoding.codes)
}
func ( *huffmanBitWriter) ( []token) (, int) {
for := range .literalFreq {
.literalFreq[] = 0
}
for := range .offsetFreq {
.offsetFreq[] = 0
}
for , := range {
if < matchType {
.literalFreq[.literal()]++
continue
}
:= .length()
:= .offset()
.literalFreq[lengthCodesStart+lengthCode()]++
.offsetFreq[offsetCode()]++
}
= len(.literalFreq)
for .literalFreq[-1] == 0 {
--
}
= len(.offsetFreq)
for > 0 && .offsetFreq[-1] == 0 {
--
}
if == 0 {
.offsetFreq[0] = 1
= 1
}
.literalEncoding.generate(.literalFreq, 15)
.offsetEncoding.generate(.offsetFreq, 15)
return
}
func ( *huffmanBitWriter) ( []token, , []hcode) {
if .err != nil {
return
}
for , := range {
if < matchType {
.writeCode([.literal()])
continue
}
:= .length()
:= lengthCode()
.writeCode([+lengthCodesStart])
:= uint(lengthExtraBits[])
if > 0 {
:= int32( - lengthBase[])
.writeBits(, )
}
:= .offset()
:= offsetCode()
.writeCode([])
:= uint(offsetExtraBits[])
if > 0 {
:= int32( - offsetBase[])
.writeBits(, )
}
}
}
var huffOffset *huffmanEncoder
func () {
:= make([]int32, offsetCodeCount)
[0] = 1
huffOffset = newHuffmanEncoder(offsetCodeCount)
huffOffset.generate(, 15)
}
func ( *huffmanBitWriter) ( bool, []byte) {
if .err != nil {
return
}
for := range .literalFreq {
.literalFreq[] = 0
}
histogram(, .literalFreq)
.literalFreq[endBlockMarker] = 1
const = endBlockMarker + 1
.offsetFreq[0] = 1
const = 1
.literalEncoding.generate(.literalFreq, 15)
var int
.generateCodegen(, , .literalEncoding, huffOffset)
.codegenEncoding.generate(.codegenFreq[:], 7)
, := .dynamicSize(.literalEncoding, huffOffset, 0)
if , := .storedSize(); && < (+>>4) {
.writeStoredHeader(len(), )
.writeBytes()
return
}
.writeDynamicHeader(, , , )
:= .literalEncoding.codes[:257]
:= .nbytes
for , := range {
:= []
.bits |= uint64(.code) << .nbits
.nbits += uint(.len)
if .nbits < 48 {
continue
}
:= .bits
.bits >>= 48
.nbits -= 48
:= .bytes[ : +6]
[0] = byte()
[1] = byte( >> 8)
[2] = byte( >> 16)
[3] = byte( >> 24)
[4] = byte( >> 32)
[5] = byte( >> 40)
+= 6
if < bufferFlushSize {
continue
}
.write(.bytes[:])
if .err != nil {
return
}
= 0
}
.nbytes =
.writeCode([endBlockMarker])
}
func ( []byte, []int32) {
= [:256]
for , := range {
[]++
}
}