blob: ef1d49a009cc75e73a9519495b1dab05e6bdcfb9 [file] [log] [blame]
kesavandc71914f2022-03-25 11:19:03 +05301// Package zstd provides decompression of zstandard files.
2//
3// For advanced usage and examples, go to the README: https://github.com/klauspost/compress/tree/master/zstd#zstd
4package zstd
5
6import (
7 "bytes"
8 "encoding/binary"
9 "errors"
10 "log"
11 "math"
12 "math/bits"
13)
14
15// enable debug printing
16const debug = false
17
18// enable encoding debug printing
19const debugEncoder = debug
20
21// enable decoding debug printing
22const debugDecoder = debug
23
24// Enable extra assertions.
25const debugAsserts = debug || false
26
27// print sequence details
28const debugSequences = false
29
30// print detailed matching information
31const debugMatches = false
32
33// force encoder to use predefined tables.
34const forcePreDef = false
35
36// zstdMinMatch is the minimum zstd match length.
37const zstdMinMatch = 3
38
39// Reset the buffer offset when reaching this.
40const bufferReset = math.MaxInt32 - MaxWindowSize
41
42var (
43 // ErrReservedBlockType is returned when a reserved block type is found.
44 // Typically this indicates wrong or corrupted input.
45 ErrReservedBlockType = errors.New("invalid input: reserved block type encountered")
46
47 // ErrCompressedSizeTooBig is returned when a block is bigger than allowed.
48 // Typically this indicates wrong or corrupted input.
49 ErrCompressedSizeTooBig = errors.New("invalid input: compressed size too big")
50
51 // ErrBlockTooSmall is returned when a block is too small to be decoded.
52 // Typically returned on invalid input.
53 ErrBlockTooSmall = errors.New("block too small")
54
55 // ErrMagicMismatch is returned when a "magic" number isn't what is expected.
56 // Typically this indicates wrong or corrupted input.
57 ErrMagicMismatch = errors.New("invalid input: magic number mismatch")
58
59 // ErrWindowSizeExceeded is returned when a reference exceeds the valid window size.
60 // Typically this indicates wrong or corrupted input.
61 ErrWindowSizeExceeded = errors.New("window size exceeded")
62
63 // ErrWindowSizeTooSmall is returned when no window size is specified.
64 // Typically this indicates wrong or corrupted input.
65 ErrWindowSizeTooSmall = errors.New("invalid input: window size was too small")
66
67 // ErrDecoderSizeExceeded is returned if decompressed size exceeds the configured limit.
68 ErrDecoderSizeExceeded = errors.New("decompressed size exceeds configured limit")
69
70 // ErrUnknownDictionary is returned if the dictionary ID is unknown.
71 // For the time being dictionaries are not supported.
72 ErrUnknownDictionary = errors.New("unknown dictionary")
73
74 // ErrFrameSizeExceeded is returned if the stated frame size is exceeded.
75 // This is only returned if SingleSegment is specified on the frame.
76 ErrFrameSizeExceeded = errors.New("frame size exceeded")
77
78 // ErrCRCMismatch is returned if CRC mismatches.
79 ErrCRCMismatch = errors.New("CRC check failed")
80
81 // ErrDecoderClosed will be returned if the Decoder was used after
82 // Close has been called.
83 ErrDecoderClosed = errors.New("decoder used after Close")
84
85 // ErrDecoderNilInput is returned when a nil Reader was provided
86 // and an operation other than Reset/DecodeAll/Close was attempted.
87 ErrDecoderNilInput = errors.New("nil input provided as reader")
88)
89
90func println(a ...interface{}) {
91 if debug || debugDecoder || debugEncoder {
92 log.Println(a...)
93 }
94}
95
96func printf(format string, a ...interface{}) {
97 if debug || debugDecoder || debugEncoder {
98 log.Printf(format, a...)
99 }
100}
101
102// matchLenFast does matching, but will not match the last up to 7 bytes.
103func matchLenFast(a, b []byte) int {
104 endI := len(a) & (math.MaxInt32 - 7)
105 for i := 0; i < endI; i += 8 {
106 if diff := load64(a, i) ^ load64(b, i); diff != 0 {
107 return i + bits.TrailingZeros64(diff)>>3
108 }
109 }
110 return endI
111}
112
113// matchLen returns the maximum length.
114// a must be the shortest of the two.
115// The function also returns whether all bytes matched.
116func matchLen(a, b []byte) int {
117 b = b[:len(a)]
118 for i := 0; i < len(a)-7; i += 8 {
119 if diff := load64(a, i) ^ load64(b, i); diff != 0 {
120 return i + (bits.TrailingZeros64(diff) >> 3)
121 }
122 }
123
124 checked := (len(a) >> 3) << 3
125 a = a[checked:]
126 b = b[checked:]
127 for i := range a {
128 if a[i] != b[i] {
129 return i + checked
130 }
131 }
132 return len(a) + checked
133}
134
135func load3232(b []byte, i int32) uint32 {
136 return binary.LittleEndian.Uint32(b[i:])
137}
138
139func load6432(b []byte, i int32) uint64 {
140 return binary.LittleEndian.Uint64(b[i:])
141}
142
143func load64(b []byte, i int) uint64 {
144 return binary.LittleEndian.Uint64(b[i:])
145}
146
147type byter interface {
148 Bytes() []byte
149 Len() int
150}
151
152var _ byter = &bytes.Buffer{}