Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(394)

Side by Side Diff: src/compress/zlib/reader.go

Issue 97140043: code review 97140043: compress/flate: add Reset() to allow reusing large buffers to compress multipl
Patch Set: diff -r e1a081e6ddf8a77b267eb0d2b9747b2181524106 https://code.google.com/p/go Created 9 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compress/gzip/gunzip_test.go ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « src/compress/gzip/gunzip_test.go ('k') | no next file » | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b