Code Examples
package main
import (
"bytes"
"compress/flate"
"fmt"
"io"
"log"
"os"
"strings"
)
func main() {
// The dictionary is a string of bytes. When compressing some input data,
// the compressor will attempt to substitute substrings with matches found
// in the dictionary. As such, the dictionary should only contain substrings
// that are expected to be found in the actual data stream.
const dict = `<?xml version="1.0"?>` + `<book>` + `<data>` + `<meta name="` + `" content="`
// The data to compress should (but is not required to) contain frequent
// substrings that match those in the dictionary.
const data = `<?xml version="1.0"?>
<book>
<meta name="title" content="The Go Programming Language"/>
<meta name="authors" content="Alan Donovan and Brian Kernighan"/>
<meta name="published" content="2015-10-26"/>
<meta name="isbn" content="978-0134190440"/>
<data>...</data>
</book>
`
var b bytes.Buffer
// Compress the data using the specially crafted dictionary.
zw, err := flate.NewWriterDict(&b, flate.DefaultCompression, []byte(dict))
if err != nil {
log.Fatal(err)
}
if _, err := io.Copy(zw, strings.NewReader(data)); err != nil {
log.Fatal(err)
}
if err := zw.Close(); err != nil {
log.Fatal(err)
}
// The decompressor must use the same dictionary as the compressor.
// Otherwise, the input may appear as corrupted.
fmt.Println("Decompressed output using the dictionary:")
zr := flate.NewReaderDict(bytes.NewReader(b.Bytes()), []byte(dict))
if _, err := io.Copy(os.Stdout, zr); err != nil {
log.Fatal(err)
}
if err := zr.Close(); err != nil {
log.Fatal(err)
}
fmt.Println()
// Substitute all of the bytes in the dictionary with a '#' to visually
// demonstrate the approximate effectiveness of using a preset dictionary.
fmt.Println("Substrings matched by the dictionary are marked with #:")
hashDict := []byte(dict)
for i := range hashDict {
hashDict[i] = '#'
}
zr = flate.NewReaderDict(&b, hashDict)
if _, err := io.Copy(os.Stdout, zr); err != nil {
log.Fatal(err)
}
if err := zr.Close(); err != nil {
log.Fatal(err)
}
}
package main
import (
"bytes"
"compress/flate"
"io"
"log"
"os"
"strings"
)
func main() {
proverbs := []string{
"Don't communicate by sharing memory, share memory by communicating.\n",
"Concurrency is not parallelism.\n",
"The bigger the interface, the weaker the abstraction.\n",
"Documentation is for users.\n",
}
var r strings.Reader
var b bytes.Buffer
buf := make([]byte, 32<<10)
zw, err := flate.NewWriter(nil, flate.DefaultCompression)
if err != nil {
log.Fatal(err)
}
zr := flate.NewReader(nil)
for _, s := range proverbs {
r.Reset(s)
b.Reset()
// Reset the compressor and encode from some input stream.
zw.Reset(&b)
if _, err := io.CopyBuffer(zw, &r, buf); err != nil {
log.Fatal(err)
}
if err := zw.Close(); err != nil {
log.Fatal(err)
}
// Reset the decompressor and decode to some output stream.
if err := zr.(flate.Resetter).Reset(&b, nil); err != nil {
log.Fatal(err)
}
if _, err := io.CopyBuffer(os.Stdout, zr, buf); err != nil {
log.Fatal(err)
}
if err := zr.Close(); err != nil {
log.Fatal(err)
}
}
}
package main
import (
"compress/flate"
"fmt"
"io"
"log"
"strings"
"sync"
)
func main() {
var wg sync.WaitGroup
defer wg.Wait()
// Use io.Pipe to simulate a network connection.
// A real network application should take care to properly close the
// underlying connection.
rp, wp := io.Pipe()
// Start a goroutine to act as the transmitter.
wg.Add(1)
go func() {
defer wg.Done()
zw, err := flate.NewWriter(wp, flate.BestSpeed)
if err != nil {
log.Fatal(err)
}
b := make([]byte, 256)
for m := range strings.FieldsSeq("A long time ago in a galaxy far, far away...") {
// We use a simple framing format where the first byte is the
// message length, followed the message itself.
b[0] = uint8(copy(b[1:], m))
if _, err := zw.Write(b[:1+len(m)]); err != nil {
log.Fatal(err)
}
// Flush ensures that the receiver can read all data sent so far.
if err := zw.Flush(); err != nil {
log.Fatal(err)
}
}
if err := zw.Close(); err != nil {
log.Fatal(err)
}
}()
// Start a goroutine to act as the receiver.
wg.Add(1)
go func() {
defer wg.Done()
zr := flate.NewReader(rp)
b := make([]byte, 256)
for {
// Read the message length.
// This is guaranteed to return for every corresponding
// Flush and Close on the transmitter side.
if _, err := io.ReadFull(zr, b[:1]); err != nil {
if err == io.EOF {
break // The transmitter closed the stream
}
log.Fatal(err)
}
// Read the message content.
n := int(b[0])
if _, err := io.ReadFull(zr, b[:n]); err != nil {
log.Fatal(err)
}
fmt.Printf("Received %d bytes: %s\n", n, b[:n])
}
fmt.Println()
if err := zr.Close(); err != nil {
log.Fatal(err)
}
}()
}
Package-Level Type Names (total 31, in which 7 are exported)
/* sort exporteds by: | */
A CorruptInputError reports the presence of corrupt input at a given offset.( CorruptInputError) Error() string
CorruptInputError : error
An InternalError reports an error in the flate code itself.( InternalError) Error() string
InternalError : error
The actual read interface needed by [NewReader].
If the passed in [io.Reader] does not also have ReadByte,
the [NewReader] will introduce its own buffering.( Reader) Read(p []byte) (n int, err error)( Reader) ReadByte() (byte, error)
*bufio.Reader
bufio.ReadWriter
*bytes.Buffer
*bytes.Reader
*google.golang.org/grpc/mem.Reader
*strings.Reader
golang.org/x/net/internal/httpcommon.eofReader
golang.org/x/tools/internal/gcimporter.intReader
*golang.org/x/tools/internal/gcimporter.intWriter
math/big.byteReader
net/http.eofReader
net/http/internal/http2.eofReader
Reader : io.ByteReader
Reader : io.Reader
A ReadError reports an error encountered while reading input.
Deprecated: No longer returned. // error returned by underlying Read // byte offset where error occurred(*ReadError) Error() string
*ReadError : error
Resetter resets a ReadCloser returned by [NewReader] or [NewReaderDict]
to switch to a new underlying [Reader]. This permits reusing a ReadCloser
instead of allocating a new one. Reset discards any buffered data and resets the Resetter as if it was
newly initialized with the given reader.
*decompressor
A WriteError reports an error encountered while writing output.
Deprecated: No longer returned. // error returned by underlying Read // byte offset where error occurred(*WriteError) Error() string
*WriteError : error
A Writer takes data written to it and writes the compressed
form of that data to an underlying writer (see [NewWriter]).dcompressordict[]byte Close flushes and closes the writer. Flush flushes any pending data to the underlying writer.
It is useful mainly in compressed network protocols, to ensure that
a remote reader has enough data to reconstruct a packet.
Flush does not return until the data has been written.
Calling Flush when there is no pending data still causes the [Writer]
to emit a sync marker of at least 4 bytes.
If the underlying writer returns an error, Flush returns that error.
In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH. Reset discards the writer's state and makes it equivalent to
the result of NewWriter or NewWriterDict called with dst
and w's level and dictionary. Write writes data to w, which will eventually write the
compressed form of data to its underlying writer.
*Writer : internal/bisect.Writer
*Writer : io.Closer
*Writer : io.WriteCloser
*Writer : io.Writer
*Writer : crypto/tls.transcriptHash
func NewWriter(w io.Writer, level int) (*Writer, error)
func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, error)
advancedState contains state for levels 7-9, with bigger hash tables, etc.chainHeadint32 Input hash chains
hashHead[hashValue] contains the largest inputIndex with the specified hash value
If hashHead[hashValue] is within the current window, then
hashPrev[hashHead[hashValue] & windowMask] contains the previous index
with the same hash value.hashMatch[262]uint32hashOffsetint32hashPrev[32768]int32 input window: unprocessed data is window[index:windowEnd] deflate state // consecutive literal count; overflows to reset after 64KB.maxInsertIndexint32offsetint32
compressionLevel holds the parameters for levels 7-9. // maximum number of hash chain entries to search // "good enough" match length // don't try to find a later, better match above this lengthlevelint // stop looking for a better match above this length
// window index where current tokens start // if true, still need to process window[index-1].compressionLevelcompressionLevel // maximum number of hash chain entries to search // "good enough" match length // don't try to find a later, better match above this lengthcompressionLevel.levelint // stop looking for a better match above this length // stateful error // encoder to use for blocks compression algorithm // copy data to window // huffman encoder, with state // chained encoder for level 7-9 // process window // requesting flush queued output tokens // tokens store for each block // writer for blocks // current window - size depends on encoder level // filled bytes in window close flushes any uncompressed data and writes an EOF block. deflateFast encodes the current window
if it has filled or if we are doing sync/flush.
It uses the level 1-6 fast encoding. deflateHuff compresses and stores the current window
(if it has filled or if we are in sync or flush).
It uses Huffman-only encoding. deflateLazy encodes the current window using lazy matching.
Lazy matching defers emitting a match to see if the next position yields a better one.
Unique to levels 7-9 is that more than 2 matches are potentially checked
until a good/nice one is found. fillBlock appends b to d.window, returning the number of bytes copied.
If n < len(b), the window is filled. fillDeflate will add b to the current window for levels 7-9. fillWindow will fill the current window with the supplied
dictionary and calculate all hashes.
This is much faster than doing a full encode.
Should only be used after a start/reset. findMatch finds the longest match starting at pos in the hash chain starting
at prevHead. It searches up to d.chain entries in the chain. init a new encode with new writer and compression level. initDeflate initializes d for levels 7-9. reset resets the compressor with a new output writer. skipLiterals emits extra literal bytes during long runs of incompressible data,
skipping ahead to avoid futile match searches. Returns false on write error. store will store the current window if it has filled or if we are in sync. syncFlush will flush the compressor by writing
any remaining window and writing a stored block
to byte-align the output. tryBetterMatchAtEnd checks whether a better match exists at the end of the
previous match and, if so, emits the skipped literals and adjusts the match.
Returns the (possibly updated) prevLength and prevOffset. write adds b to the compressor.
It can only return a short length if an error occurs. writeBlock will write tokens to output.
The provided index is where the block starts in d.window. writeBlockSkip writes the current block and uses the number of tokens
to determine if the block should be stored when there are no matches, or
only Huffman encoded. writeStoredBlock writes an uncompressed block to the stream.
Decompress state. Input bits, in top of b. Length arrays used to define Huffman codes. Temporary buffer (avoids repeated allocation).codebits*[19]intcopyDistintcopyLenint Output history, buffer.errerrorfinalbool Huffman decoders for literal/length, distance. Huffman decoders for literal/length, distance.hd*huffmanDecoderhl*huffmanDecodernbuint Input source. // created if provided io.Reader does not implement io.ByteReaderroffsetint64 Next step in the decompression,
and decompression state.stepStateinttoRead[]byte(*decompressor) Close() error(*decompressor) Read(b []byte) (int, error)(*decompressor) Reset(r io.Reader, dict []byte) error copyData copies f.copyLen bytes from the underlying reader into f.hist.
It pauses for reads when f.hist is full. Copy a single uncompressed data block from input to output.(*decompressor) finishBlock() Read the next Huffman-encoded symbol from f according to h. Decode a single Huffman block from f.
hl and hd are the Huffman states for the lit/length values
and the distance values, respectively. If hd == nil, using the
fixed distance encoding associated with fixed Huffman blocks.(*decompressor) makeReader(r io.Reader)(*decompressor) moreBits() error(*decompressor) nextBlock()(*decompressor) readHuffman() error
*decompressor : Resetter
*decompressor : io.Closer
*decompressor : io.ReadCloser
*decompressor : io.Reader
dictDecoder implements the LZ77 sliding dictionary as used in decompression.
LZ77 decompresses data through sequences of two forms of commands:
- Literal insertions: Runs of one or more symbols are inserted into the data
stream as is. This is accomplished through the writeByte method for a
single symbol, or combinations of writeSlice/writeMark for multiple symbols.
Any valid stream must start with a literal insertion if no preset dictionary
is used.
- Backward copies: Runs of one or more symbols are copied from previously
emitted data. Backward copies come as the tuple (dist, length) where dist
determines how far back in the stream to copy from and length determines how
many bytes to copy. Note that it is valid for the length to be greater than
the distance. Since LZ77 uses forward copies, that situation is used to
perform a form of run-length encoding on repeated runs of symbols.
The writeCopy and tryWriteCopy are used to implement this command.
For performance reasons, this implementation performs little to no sanity
checks about the arguments. As such, the invariants documented for each
method call must be respected. // Has a full window length been written yet? // Sliding window history // Have emitted hist[:rdPos] already Invariant: 0 <= rdPos <= wrPos <= len(hist) // Current output position in buffer availRead reports the number of bytes that can be flushed by readFlush. availWrite reports the available amount of output buffer space. histSize reports the total amount of historical data in the dictionary. init initializes dictDecoder to have a sliding window dictionary of the given
size. If a preset dict is provided, it will initialize the dictionary with
the contents of dict. readFlush returns a slice of the historical buffer that is ready to be
emitted to the user. The data returned by readFlush must be fully consumed
before calling any other dictDecoder methods. tryWriteCopy tries to copy a string at a given (distance, length) to the
output. This specialized version is optimized for short distances.
This method is designed to be inlined for performance reasons.
This invariant must be kept: 0 < dist <= histSize() writeByte writes a single byte to the dictionary.
This invariant must be kept: 0 < availWrite() writeCopy copies a string at a given (dist, length) to the output.
This returns the number of bytes copied and may be less than the requested
length if the available space in the output buffer is too small.
This invariant must be kept: 0 < dist <= histSize() writeMark advances the writer pointer by cnt.
This invariant must be kept: 0 <= cnt <= availWrite() writeSlice returns a slice of the available buffer to write data to.
This invariant will be kept: len(s) <= availWrite()
Level 1 uses a single small table with 5 byte hashes.fastGenfastGenfastGen.curint32fastGen.hist[]bytetable[32768]tableEntry addBlock appends src to the history and returns the offset where src starts in e.hist.(*fastEncL1) encode(dst *tokens, src []byte)(*fastEncL1) getFastGen() *fastGen 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). 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). reset resets the encoding table to prepare for a new compression stream.
*fastEncL1 : fastEnc
Level 2 uses a similar algorithm to level 1, but with a larger table.fastGenfastGenfastGen.curint32fastGen.hist[]bytetable[131072]tableEntry addBlock appends src to the history and returns the offset where src starts in e.hist.(*fastEncL2) encode(dst *tokens, src []byte)(*fastEncL2) getFastGen() *fastGen 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). 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). reset resets the encoding table to prepare for a new compression stream.
*fastEncL2 : fastEnc
Level 3 uses a similar algorithm to level 2, with a smaller table,
but will check up two candidates for each iteration with more
entries added to the table.fastGenfastGenfastGen.curint32fastGen.hist[]bytetable[65536]tableEntryPrev addBlock appends src to the history and returns the offset where src starts in e.hist.(*fastEncL3) encode(dst *tokens, src []byte)(*fastEncL3) getFastGen() *fastGen 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). 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). reset resets the encoding table to prepare for a new compression stream.
*fastEncL3 : fastEnc
Level 4 uses two tables, one for short (4 bytes) and one for long (7 bytes) matches.bTable[32768]tableEntryfastGenfastGenfastGen.curint32fastGen.hist[]bytetable[32768]tableEntry addBlock appends src to the history and returns the offset where src starts in e.hist.(*fastEncL4) encode(dst *tokens, src []byte)(*fastEncL4) getFastGen() *fastGen 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). 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). reset resets the encoding table to prepare for a new compression stream.
*fastEncL4 : fastEnc
Level 5 is similar to level 4, but for long matches two candidates are tested.
Once a match is found, when it stops it will attempt to find a match that extends further.bTable[32768]tableEntryPrevfastGenfastGenfastGen.curint32fastGen.hist[]bytetable[32768]tableEntry addBlock appends src to the history and returns the offset where src starts in e.hist.(*fastEncL5) encode(dst *tokens, src []byte)(*fastEncL5) getFastGen() *fastGen 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). 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). reset resets the encoding table to prepare for a new compression stream.
*fastEncL5 : fastEnc
Level 6 extends level 5, but does "repeat offset" check,
as well as adding more hash entries to the tables.bTable[32768]tableEntryPrevfastGenfastGenfastGen.curint32fastGen.hist[]bytetable[32768]tableEntry addBlock appends src to the history and returns the offset where src starts in e.hist.(*fastEncL6) encode(dst *tokens, src []byte)(*fastEncL6) getFastGen() *fastGen 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). 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). reset resets the encoding table to prepare for a new compression stream.
*fastEncL6 : fastEnc
fastGen maintains the table for matches,
and the previous byte block for level 1 and up.
This is the generic implementation.curint32hist[]byte addBlock appends src to the history and returns the offset where src starts in e.hist.(*fastGen) getFastGen() *fastGen 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). 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). reset resets the encoding table to prepare for a new compression stream.
hcode is a huffman code with a bit code and bit length. code64 returns the code as a uint64. len returns the length of the code in bits. set sets the code and length of an hcode. zero returns true if the code is unset.
func newhcode(code uint16, length uint8) hcode
huffmanBitWriter encodes tokens and values to a stream.
The huffmanBitWriter supports reusing huffman tables and will combine
blocks, if compression is less than creating a new table.
An incoming block estimates the output size of a new table using a
'fresh' by calculating the optimal size and adding a penalty.
A Huffman table is not optimal, which is why we add a penalty,
and generating a new table is slower for both compression and decompression. Data waiting to be written is bytes[0:nbytes]
and then the low nbits of bits.bytes[264]byte codegen must have an extra space for the final symbol.codegenEncoding*huffmanEncodercodegenFreq[19]uint16errerrorliteralEncoding*huffmanEncoderliteralFreq[289]uint16 logNewTablePenalty is a log2 penalty reduction for creating new tables.
The initial penalty is 100%.
Adding 1 will cut the penalty in half.nbitsuint8nbytesuint8offsetEncoding*huffmanEncoderoffsetFreq[32]uint16 If prevHeader is non-zero the Huffman table can be reused.
It also indicates that an EOB has not yet been emitted, so if a new table
is generated, an EOB with the previous table must be written.tmpLitEncoding*huffmanEncoder writer is the underlying writer.
Do not use it directly; use the write method, which ensures
that Write errors are sticky. If wroteHuffman is set, a table for outputting only literals
has been generated and offsets are invalid. canReuse checks if the current generated tables can be
reused for the provided tokens. codegens returns current number of non-zero codegens. dynamicSize returns the size of dynamically encoded data in bits. dynamicSize returns the size of dynamically encoded data in bits. extraBitSize returns the number of bits that will be written
as "extra" bits on matches. fixedSize returns the size of dynamically encoded data in bits. flush flushes the currently encoded data.
An EOB will be written if the current block hasn't been ended. flushBits writes accumulated bits to the byte buffer. generate literalEncoding and offsetEncoding based on respective histograms. RFC 1951 3.2.7 specifies a special run-length encoding for specifying
the literal and offset lengths arrays (which are concatenated into a single
array). This method generates that run-length encoding.
The result is written into the codegen array, and the frequencies
of each code is written into the codegenFreq array.
Codes 0-15 are single byte codes. Codes 16-18 are followed by additional
information. Code badCode is an end marker
numLiterals The number of literals in literalEncoding
numOffsets The number of offsets in offsetEncoding
litenc, offenc The literal and offset encoder to use headerSize returns the size of the header with the current encodings. indexTokens indexes a slice of tokens, updates literalFreq and offsetFreq,
and generates literalEncoding and offsetEncoding.
It returns the number of literal and offset tokens. reset the huffmanBitWriter state and replace the output. storedSize calculates the stored size, including header.
The function returns the size in bits and whether the block
fits inside a single block. write writes the provided bytes directly to the output,
ignoring all queued bytes. writeBits writes nb bits from b to the stream. writeBlock writes a block of tokens using the smallest encoding.
The original input can be supplied, and if the Huffman-encoded data
is larger than the original bytes, the data will be written as a
stored block.
If the input is nil, the tokens will always be Huffman encoded. writeBlockDynamic encodes a block using a dynamic Huffman table.
This should be used if the symbols used have a disproportionate
histogram distribution. writeBlockHuff encodes a block of bytes as either
Huffman-encoded literals or uncompressed bytes if the
results gain very little from compression. writeBytes writes the provided bytes to the stream. writeCode writes 'c' to the stream. writeDynamicHeader writes the header of a dynamic Huffman block to the output stream.
numLiterals is the number of literals specified in codegen.
numOffsets is the number of offsets specified in codegen.
numCodegens is the number of codegens used in codegen. writeFixedHeader writes a fixed encoding header to the output stream. writeStoredHeader writes a stored header.
If the stored block is only used for EOF,
it is replaced with a fixed huffman block. writeTokens writes a slice of tokens to the output.
Codes for literal and offset encoding must be supplied.
func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter
// chunks as described above // mask the width of the link table // overflow links // the minimum code length Initialize Huffman decoding tables from array of code lengths.
Following this function, h is guaranteed to be initialized into a complete
tree (i.e., neither over-subscribed nor under-subscribed). The exception is a
degenerate case where the tree has only a single symbol with length 1. Empty
trees are permitted.
var fixedHuffmanDecoder
huffmanEncoder provides a fast way to generate Huffman codes for a given
frequency table. It is based on the algorithm described in RFC 1951,
section 3.2.2.bitCount[17]int32codes[]hcode freqcache is a reusable buffer with the longest possible frequency table.
Possible lengths are codegenCodeCount, offsetCodeCount and literalCount.
The largest of these is literalCount, so we allocate for that case. assignEncodingAndSize assigns bit counts and encodings to the leaves
as specified in RFC 1951 3.2.2. bitCounts returns an integer slice in which slice[i] is the number
of literals that should be encoded using i bits.
This method is only called when len(list) >= 3.
The cases of 0, 1, and 2 literals are handled by special case code.
list is an array of the literals with non-zero frequencies
and their associated frequencies. The array is in order of increasing
frequency and has as its last element a special element with frequency
MaxInt32.
maxBits is the maximum number of bits that should be used to encode any literal.
It must be less than 16. bitLength returns the number of bits needed to encode freq. bitLengthRaw will return the number of bits needed to encode b.
For unset codes 1 bit/entry will be added. canEncodeLen returns the number of bits to encode freq.
It returns math.MaxInt32 if freq cannot be encoded. generate rewrites h to be the Huffman code for the given frequency count.
freq[i] is the frequency of literal i, and maxBits is the maximum number
of bits to use for any literal.
func generateFixedLiteralEncoding() *huffmanEncoder
func generateFixedOffsetEncoding() *huffmanEncoder
func newHuffmanEncoder(size int) *huffmanEncoder
A levelInfo describes the state of the constructed tree for a given depth. The frequency of the last node at this level Our level. for better printing The number of chains remaining to generate for this level before moving
up to the next level The frequency of the next character to add to this level The frequency of the next pair (from level below) to add to this level.
Only valid if the "needed" value of the next lower level is 0.
A token is a token that will be written to output stream.
It is either a literal or a match with offset and length. length returns the length of a match token. literal returns the literal value of t. offset returns the offset of a match token. typ returns the type of a token.
func indexTokens(in []token) tokens
tokens are compound values as described above.
Histograms are created as tokens are added.
A full block is allocated. // codes 256->maxnumlit // codes 0->255 // Must be able to contain maxStoreBlockSizenFilledint // offset codestokens[65536]token AddEOB adds an end of block marker to the tokens. AddLiteral adds a single literal to the tokens. AddMatch adds a match to the tokens.
This function is very sensitive to inlining and right on the border. AddMatchLong adds a match to the tokens, potentially longer than max match length.
Length should NOT have the base subtracted, only offset should. EstimatedBits returns an estimated minimum size for the
optimal compression of t.
Minimum 1 bit is assigned per symbol.
Maximum 15 bits are assigned per symbol. Reset resets the tokens and histograms. Slice returns a slice of the tokens that references the tokens in t. indexTokens clears and sets t from a slice of unindexed tokens.
func indexTokens(in []token) tokens
func emitLiterals(dst *tokens, lit []byte)
Package-Level Functions (total 30, in which 4 are exported)
NewReader returns a new ReadCloser that can be used
to read the uncompressed version of r.
If r does not also implement [io.ByteReader],
the decompressor may read more data than necessary from r.
The reader returns [io.EOF] after the final block in the DEFLATE stream has
been encountered. Any trailing data after the final block is ignored.
The [io.ReadCloser] returned by NewReader also implements [Resetter].
NewReaderDict is like [NewReader] but initializes the reader
with a preset dictionary. The returned reader behaves as if
the uncompressed data stream started with the given dictionary,
which has already been read. NewReaderDict is typically used
to read data compressed by [NewWriterDict].
The ReadCloser returned by NewReaderDict also implements [Resetter].
NewWriter returns a new [Writer] compressing data at the given level.
Following zlib, levels range from 1 ([BestSpeed]) to 9 ([BestCompression]);
higher levels typically run slower but compress more. Level 0
([NoCompression]) does not attempt any compression; it only adds the
necessary DEFLATE framing.
Level -1 ([DefaultCompression]) uses the default compression level.
Level -2 ([HuffmanOnly]) will use Huffman compression only, giving
a very fast compression for all types of input, but sacrificing considerable
compression efficiency.
If level is in the range [-2, 9] then the error returned will be nil.
Otherwise the error returned will be non-nil.
Note that the exact bytes written to w are not covered by the Go 1
compatibility promise. Callers, including tests, should not depend on the
exact written bytes.
NewWriterDict is like [NewWriter] but initializes the new
[Writer] with a preset dictionary. The returned [Writer] behaves
as if the dictionary had been written to it without producing
any compressed output. The compressed data written to w
can only be decompressed by a reader initialized with the
same dictionary (see [NewReaderDict]).
Note that the exact bytes written to w are not covered by the Go 1
compatibility promise. Callers, including tests, should not depend on the
exact written bytes.
bulkHash4 sets dst[i] = hash4(b[i:i+4]) for all i <= len(b)-4.
emitLiterals writes a literal chunk and returns the number of bytes written.
hash4 returns a hash representation of the first 4 bytes
of the supplied slice.
The caller must ensure that len(b) >= 4.
hash4 returns the hash of u to fit in a hash table with h bits.
Preferably h should be a constant and should always be <32.
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.
HuffmanOnly disables Lempel-Ziv match searching and only performs Huffman
entropy encoding. This mode is useful in compressing data that has
already been compressed with an LZ style algorithm (e.g. Snappy or LZ4)
that lacks an entropy encoder. Compression gains are achieved when
certain bytes in the input stream occur more frequently than others.
Note that HuffmanOnly produces a compressed output that is
RFC 1951 compliant. That is, any valid DEFLATE decompressor will
continue to be able to decompress this output.
baseMatchLength is the smallest match length per RFC section 3.2.5.
baseMatchOffset is the smallest match offset.
bufferFlushSize indicates the buffer size
after which bytes are flushed to the writer.
Should preferably be a multiple of 6, since
we accumulate 6 bytes between writes to the buffer.
bufferReset is the buffer offset at which the history is reset.
The maximum number of tokens we will encode at the time.
Smaller sizes usually creates less optimal blocks.
Bigger can make context switching slow.
We use this for levels 7-9, so we make it big.
The next three numbers come from the RFC section 3.2.7, with the
additional proviso in section 3.2.5 which implies that distance codes
30 and 31 should never occur in compressed data.
maxPredefinedTokens is the maximum number of tokens
where we check if fixed size is smaller.