// Copyright 2016 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package flateimport ()const (// tableBits is the number of bits used in the hash table.tableBits = 15// tableSize is the size of the hash table.tableSize = 1 << tableBits// hashLongBytes is the number of bytes used for long table hashes.hashLongBytes = 7// baseMatchOffset is the smallest match offset.baseMatchOffset = 1// baseMatchLength is the smallest match length per RFC section 3.2.5.baseMatchLength = 3// maxMatchOffset is the largest match offset.maxMatchOffset = 1 << 15// allocHistory is the size to preallocate for history.allocHistory = maxStoreBlockSize * 5// bufferReset is the buffer offset at which the history is reset.bufferReset = (1 << 31) - allocHistory - maxStoreBlockSize - 1)// fastEncL1 to fastEncL6 provides specialized encoders for levels 1-6// that each provide a different speed/size/memory strategies.//// Level 1: Single small table, 5 byte hashes, sparse indexing.// Level 2: Single big table, 5 byte hashes, indexing ~ every 2 bytes.// Level 3: Single medium table, 5 byte hashes, 2 candidates per table entry.// Level 4: Two tables, 4/7 byte hashes, 1 candidate per table entry.// Level 5: Two tables, 4/7 byte hashes, 2 candidates per 7-byte table entry.// Level 6: Two tables, 4/7 byte hashes, full indexing, checks for repeats.//// Skipping on contiguous non-matches also decreases as levels go up.// fastEnc is the interface implemented by the level 1-6 fast encoders.typefastEncinterface {// encode src into dst.encode(dst *tokens, src []byte)// reset the encoder so matches are not made with previous data.reset()}// newFastEnc returns a fastEnc encoder for the given compression level (1-6).func ( int) fastEnc {switch {case1:return &fastEncL1{fastGen: fastGen{cur: maxStoreBlockSize}}case2:return &fastEncL2{fastGen: fastGen{cur: maxStoreBlockSize}}case3:return &fastEncL3{fastGen: fastGen{cur: maxStoreBlockSize}}case4:return &fastEncL4{fastGen: fastGen{cur: maxStoreBlockSize}}case5:return &fastEncL5{fastGen: fastGen{cur: maxStoreBlockSize}}case6:return &fastEncL6{fastGen: fastGen{cur: maxStoreBlockSize}}default:panic("invalid level specified") }}// fastGen maintains the table for matches,// and the previous byte block for level 1 and up.// This is the generic implementation.typefastGenstruct {hist []bytecurint32}// addBlock appends src to the history and returns the offset where src starts in e.hist.func ( *fastGen) ( []byte) int32 {// check if we have space alreadyiflen(.hist)+len() > cap(.hist) {ifcap(.hist) == 0 { .hist = make([]byte, 0, allocHistory) } else {ifcap(.hist) < maxMatchOffset*2 {panic("unexpected buffer size") }// Move down := int32(len(.hist)) - maxMatchOffsetcopy(.hist[0:maxMatchOffset], .hist[:+maxMatchOffset]) .cur += .hist = .hist[:maxMatchOffset] } } := int32(len(.hist)) .hist = append(.hist, ...)return}// matchLenLimited returns the match length between offsets s and t in src.// The maximum length returned is maxMatchLength - 4.// It is assumed that s > t, that t >= 0 and s < len(src).func ( *fastGen) (, int, []byte) int32 { := [:min(+maxMatchLength-4, len())] := [:]returnint32(matchLen(, ))}// matchLenLong returns the match length between offsets s and t in src.// It is assumed that s > t, that t >= 0 and s < len(src).func ( *fastGen) (, int, []byte) int32 {returnint32(matchLen([:], [:]))}// reset resets the encoding table to prepare for a new compression stream.func ( *fastGen) () {ifcap(.hist) < allocHistory { .hist = make([]byte, 0, allocHistory) }// We offset current position so everything will be out of reach. // If we are above the buffer reset it will be cleared anyway since len(hist) == 0.if .cur <= bufferReset { .cur += maxMatchOffset + int32(len(.hist)) } .hist = .hist[:0]}func ( *fastGen) () *fastGen { return }// tableEntry stores the offset of a hash match in the input history.typetableEntrystruct {offsetint32}// tableEntryPrev stores the current and previous offsets for a hash entry.typetableEntryPrevstruct {curtableEntryprevtableEntry}const (prime3bytes = 506832829prime4bytes = 2654435761prime5bytes = 889523592379prime6bytes = 227718039650203prime7bytes = 58295818150454627prime8bytes = 0xcf1bbcdcb7a56463)// hashLen returns a hash of the first n bytes of u, using b output bits.// It expects 3 <= n <= 8; other values are treated as n == 4.// The bit length b must be <= 32.// b and n should be constants in speed-critical use.func ( uint64, , uint8) uint32 {switch {case3:return (uint32(<<8) * prime3bytes) >> (32 - )case5:returnuint32((( << (64 - 40)) * prime5bytes) >> (64 - ))case6:returnuint32((( << (64 - 48)) * prime6bytes) >> (64 - ))case7:returnuint32((( << (64 - 56)) * prime7bytes) >> (64 - ))case8:returnuint32(( * prime8bytes) >> (64 - ))default:return (uint32() * prime4bytes) >> (32 - ) }}// matchLen returns the maximum common prefix length of a and b.// a must be the shortest of the two.func (, []byte) ( int) { := len()for >= 8 { := loadLE64(, ) ^ loadLE64(, )if != 0 {return + bits.TrailingZeros64()>>3 } += 8 -= 8 } = [:] = [:] = [:len()]for := range {if [] != [] {break } ++ }return}
The pages are generated with Goldsv0.8.4. (GOOS=linux GOARCH=amd64)