Left: | ||
Right: |
OLD | NEW |
---|---|
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 /* | 5 /* |
6 Package zlib implements reading and writing of zlib format compressed data, | 6 Package zlib implements reading and writing of zlib format compressed data, |
7 as specified in RFC 1950. | 7 as specified in RFC 1950. |
8 | 8 |
9 The implementation provides filters that uncompress during reading | 9 The implementation provides filters that uncompress during reading |
10 and compress during writing. For example, to write compressed data | 10 and compress during writing. For example, to write compressed data |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
44 ) | 44 ) |
45 | 45 |
46 type reader struct { | 46 type reader struct { |
47 r flate.Reader | 47 r flate.Reader |
48 decompressor io.ReadCloser | 48 decompressor io.ReadCloser |
49 digest hash.Hash32 | 49 digest hash.Hash32 |
50 err error | 50 err error |
51 scratch [4]byte | 51 scratch [4]byte |
52 } | 52 } |
53 | 53 |
54 // NewReader creates a new io.ReadCloser. | 54 // Resetter resets a ReadCloser returned by NewReader or NewReaderDict to |
55 // Reads from the returned io.ReadCloser read and decompress data from r. | 55 // to switch to a new underlying Reader. This permits reusing a ReadCloser |
56 // instead of allocating a new one. | |
57 type Resetter interface { | |
58 » // Reset discards any buffered data and attempts to reset the Resetter a s | |
59 » // if it was newly initialized with the given reader. | |
60 » Reset(r io.Reader, dict []byte) error | |
61 } | |
62 | |
63 // NewReader creates a new ReadCloser. | |
64 // Reads from the returned ReadCloser read and decompress data from r. | |
56 // The implementation buffers input and may read more data than necessary from r . | 65 // The implementation buffers input and may read more data than necessary from r . |
57 // It is the caller's responsibility to call Close on the ReadCloser when done. | 66 // It is the caller's responsibility to call Close on the ReadCloser when done. |
67 // | |
68 // The ReadCloser returned by NewReader also implements Resetter. | |
58 func NewReader(r io.Reader) (io.ReadCloser, error) { | 69 func NewReader(r io.Reader) (io.ReadCloser, error) { |
59 return NewReaderDict(r, nil) | 70 return NewReaderDict(r, nil) |
60 } | 71 } |
61 | 72 |
62 // NewReaderDict is like NewReader but uses a preset dictionary. | 73 // NewReaderDict is like NewReader but uses a preset dictionary. |
63 // NewReaderDict ignores the dictionary if the compressed data does not refer to it. | 74 // NewReaderDict ignores the dictionary if the compressed data does not refer to it. |
75 // | |
76 // The ReadCloser returned by NewReaderDict also implements Resetter. | |
64 func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) { | 77 func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) { |
65 z := new(reader) | 78 z := new(reader) |
66 » if fr, ok := r.(flate.Reader); ok { | 79 » err := z.reset(r, dict) |
67 » » z.r = fr | |
68 » } else { | |
69 » » z.r = bufio.NewReader(r) | |
70 » } | |
71 » _, err := io.ReadFull(z.r, z.scratch[0:2]) | |
72 if err != nil { | 80 if err != nil { |
73 return nil, err | 81 return nil, err |
74 } | 82 } |
75 h := uint(z.scratch[0])<<8 | uint(z.scratch[1]) | |
76 if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) { | |
77 return nil, ErrHeader | |
78 } | |
79 if z.scratch[1]&0x20 != 0 { | |
80 _, err = io.ReadFull(z.r, z.scratch[0:4]) | |
81 if err != nil { | |
82 return nil, err | |
83 } | |
84 checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3]) | |
85 if checksum != adler32.Checksum(dict) { | |
86 return nil, ErrDictionary | |
87 } | |
88 z.decompressor = flate.NewReaderDict(z.r, dict) | |
89 } else { | |
90 z.decompressor = flate.NewReader(z.r) | |
91 } | |
92 z.digest = adler32.New() | |
93 return z, nil | 83 return z, nil |
94 } | 84 } |
95 | 85 |
96 func (z *reader) Read(p []byte) (n int, err error) { | 86 func (z *reader) Read(p []byte) (n int, err error) { |
97 if z.err != nil { | 87 if z.err != nil { |
98 return 0, z.err | 88 return 0, z.err |
99 } | 89 } |
100 if len(p) == 0 { | 90 if len(p) == 0 { |
101 return 0, nil | 91 return 0, nil |
102 } | 92 } |
(...skipping 20 matching lines...) Expand all Loading... | |
123 } | 113 } |
124 | 114 |
125 // Calling Close does not close the wrapped io.Reader originally passed to NewRe ader. | 115 // Calling Close does not close the wrapped io.Reader originally passed to NewRe ader. |
126 func (z *reader) Close() error { | 116 func (z *reader) Close() error { |
127 if z.err != nil { | 117 if z.err != nil { |
128 return z.err | 118 return z.err |
129 } | 119 } |
130 z.err = z.decompressor.Close() | 120 z.err = z.decompressor.Close() |
131 return z.err | 121 return z.err |
132 } | 122 } |
123 | |
124 func (z *reader) reset(r io.Reader, dict []byte) error { | |
125 if fr, ok := r.(flate.Reader); ok { | |
126 z.r = fr | |
127 } else { | |
128 z.r = bufio.NewReader(r) | |
129 } | |
130 _, err := io.ReadFull(z.r, z.scratch[0:2]) | |
131 if err != nil { | |
132 return err | |
133 } | |
134 h := uint(z.scratch[0])<<8 | uint(z.scratch[1]) | |
135 if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) { | |
136 return ErrHeader | |
137 } | |
138 haveDict := z.scratch[1]&0x20 != 0 | |
139 if haveDict { | |
140 _, err = io.ReadFull(z.r, z.scratch[0:4]) | |
141 if err != nil { | |
142 return err | |
143 } | |
144 checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3]) | |
145 if checksum != adler32.Checksum(dict) { | |
146 return ErrDictionary | |
147 } | |
148 } | |
149 if z.decompressor == nil { | |
150 if haveDict { | |
151 z.decompressor = flate.NewReaderDict(z.r, dict) | |
152 } else { | |
153 z.decompressor = flate.NewReader(z.r) | |
154 } | |
155 } else { | |
156 z.decompressor.(flate.Resetter).Reset(z.r, dict) | |
157 } | |
158 z.digest = adler32.New() | |
159 return nil | |
160 } | |
161 | |
162 func (z *reader) Reset(r io.Reader, dict []byte) error { | |
kortschak
2014/10/03 04:53:52
I missed this before, but it seems to me that this
james.robinson
2014/10/03 05:06:57
Oh, right you are. Fixed.
| |
163 return z.reset(r, dict) | |
164 } | |
OLD | NEW |