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 package zlib | 5 package zlib |
6 | 6 |
7 import ( | 7 import ( |
8 » "compress/flate"; | 8 » "compress/flate" |
9 » "hash"; | 9 » "hash" |
10 » "hash/adler32"; | 10 » "hash/adler32" |
11 » "io"; | 11 » "io" |
12 » "os"; | 12 » "os" |
13 ) | 13 ) |
14 | 14 |
15 // These constants are copied from the flate package, so that code that imports | 15 // These constants are copied from the flate package, so that code that imports |
16 // "compress/zlib" does not also have to import "compress/flate". | 16 // "compress/zlib" does not also have to import "compress/flate". |
17 const ( | 17 const ( |
18 » NoCompression» » = flate.NoCompression; | 18 » NoCompression = flate.NoCompression |
19 » BestSpeed» » = flate.BestSpeed; | 19 » BestSpeed = flate.BestSpeed |
20 » BestCompression»» = flate.BestCompression; | 20 » BestCompression = flate.BestCompression |
21 » DefaultCompression» = flate.DefaultCompression; | 21 » DefaultCompression = flate.DefaultCompression |
22 ) | 22 ) |
23 | 23 |
24 type writer struct { | 24 type writer struct { |
25 » w» » io.Writer; | 25 » w io.Writer |
26 » deflater» io.WriteCloser; | 26 » deflater io.WriteCloser |
27 » digest» » hash.Hash32; | 27 » digest hash.Hash32 |
28 » err» » os.Error; | 28 » err os.Error |
29 » scratch»» [4]byte; | 29 » scratch [4]byte |
30 } | 30 } |
31 | 31 |
32 // NewDeflater calls NewDeflaterLevel with the default compression level. | 32 // NewDeflater calls NewDeflaterLevel with the default compression level. |
33 func NewDeflater(w io.Writer) (io.WriteCloser, os.Error) { | 33 func NewDeflater(w io.Writer) (io.WriteCloser, os.Error) { |
34 return NewDeflaterLevel(w, DefaultCompression) | 34 return NewDeflaterLevel(w, DefaultCompression) |
35 } | 35 } |
36 | 36 |
37 // NewDeflater creates a new io.WriteCloser that satisfies writes by compressing
data written to w. | 37 // NewDeflater creates a new io.WriteCloser that satisfies writes by compressing
data written to w. |
38 // It is the caller's responsibility to call Close on the WriteCloser when done. | 38 // It is the caller's responsibility to call Close on the WriteCloser when done. |
39 // level is the compression level, which can be DefaultCompression, NoCompressio
n, | 39 // level is the compression level, which can be DefaultCompression, NoCompressio
n, |
40 // or any integer value between BestSpeed and BestCompression (inclusive). | 40 // or any integer value between BestSpeed and BestCompression (inclusive). |
41 func NewDeflaterLevel(w io.Writer, level int) (io.WriteCloser, os.Error) { | 41 func NewDeflaterLevel(w io.Writer, level int) (io.WriteCloser, os.Error) { |
42 » z := new(writer); | 42 » z := new(writer) |
43 // ZLIB has a two-byte header (as documented in RFC 1950). | 43 // ZLIB has a two-byte header (as documented in RFC 1950). |
44 // The first four bits is the CINFO (compression info), which is 7 for t
he default deflate window size. | 44 // The first four bits is the CINFO (compression info), which is 7 for t
he default deflate window size. |
45 // The next four bits is the CM (compression method), which is 8 for def
late. | 45 // The next four bits is the CM (compression method), which is 8 for def
late. |
46 » z.scratch[0] = 0x78; | 46 » z.scratch[0] = 0x78 |
47 // The next two bits is the FLEVEL (compression level). The four values
are: | 47 // The next two bits is the FLEVEL (compression level). The four values
are: |
48 // 0=fastest, 1=fast, 2=default, 3=best. | 48 // 0=fastest, 1=fast, 2=default, 3=best. |
49 // The next bit, FDICT, is unused, in this implementation. | 49 // The next bit, FDICT, is unused, in this implementation. |
50 // The final five FCHECK bits form a mod-31 checksum. | 50 // The final five FCHECK bits form a mod-31 checksum. |
51 switch level { | 51 switch level { |
52 case 0, 1: | 52 case 0, 1: |
53 z.scratch[1] = 0x01 | 53 z.scratch[1] = 0x01 |
54 case 2, 3, 4, 5: | 54 case 2, 3, 4, 5: |
55 z.scratch[1] = 0x5e | 55 z.scratch[1] = 0x5e |
56 case 6, -1: | 56 case 6, -1: |
57 z.scratch[1] = 0x9c | 57 z.scratch[1] = 0x9c |
58 case 7, 8, 9: | 58 case 7, 8, 9: |
59 z.scratch[1] = 0xda | 59 z.scratch[1] = 0xda |
60 default: | 60 default: |
61 return nil, os.NewError("level out of range") | 61 return nil, os.NewError("level out of range") |
62 } | 62 } |
63 » _, err := w.Write(z.scratch[0:2]); | 63 » _, err := w.Write(z.scratch[0:2]) |
64 if err != nil { | 64 if err != nil { |
65 return nil, err | 65 return nil, err |
66 } | 66 } |
67 » z.w = w; | 67 » z.w = w |
68 » z.deflater = flate.NewDeflater(w, level); | 68 » z.deflater = flate.NewDeflater(w, level) |
69 » z.digest = adler32.New(); | 69 » z.digest = adler32.New() |
70 » return z, nil; | 70 » return z, nil |
71 } | 71 } |
72 | 72 |
73 func (z *writer) Write(p []byte) (n int, err os.Error) { | 73 func (z *writer) Write(p []byte) (n int, err os.Error) { |
74 if z.err != nil { | 74 if z.err != nil { |
75 return 0, z.err | 75 return 0, z.err |
76 } | 76 } |
77 if len(p) == 0 { | 77 if len(p) == 0 { |
78 return 0, nil | 78 return 0, nil |
79 } | 79 } |
80 » n, err = z.deflater.Write(p); | 80 » n, err = z.deflater.Write(p) |
81 if err != nil { | 81 if err != nil { |
82 » » z.err = err; | 82 » » z.err = err |
83 » » return; | 83 » » return |
84 } | 84 } |
85 » z.digest.Write(p); | 85 » z.digest.Write(p) |
86 » return; | 86 » return |
87 } | 87 } |
88 | 88 |
89 // Calling Close does not close the wrapped io.Writer originally passed to NewDe
flater. | 89 // Calling Close does not close the wrapped io.Writer originally passed to NewDe
flater. |
90 func (z *writer) Close() os.Error { | 90 func (z *writer) Close() os.Error { |
91 if z.err != nil { | 91 if z.err != nil { |
92 return z.err | 92 return z.err |
93 } | 93 } |
94 » z.err = z.deflater.Close(); | 94 » z.err = z.deflater.Close() |
95 if z.err != nil { | 95 if z.err != nil { |
96 return z.err | 96 return z.err |
97 } | 97 } |
98 » checksum := z.digest.Sum32(); | 98 » checksum := z.digest.Sum32() |
99 // ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952). | 99 // ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952). |
100 » z.scratch[0] = uint8(checksum >> 24); | 100 » z.scratch[0] = uint8(checksum >> 24) |
101 » z.scratch[1] = uint8(checksum >> 16); | 101 » z.scratch[1] = uint8(checksum >> 16) |
102 » z.scratch[2] = uint8(checksum >> 8); | 102 » z.scratch[2] = uint8(checksum >> 8) |
103 » z.scratch[3] = uint8(checksum >> 0); | 103 » z.scratch[3] = uint8(checksum >> 0) |
104 » _, z.err = z.w.Write(z.scratch[0:4]); | 104 » _, z.err = z.w.Write(z.scratch[0:4]) |
105 » return z.err; | 105 » return z.err |
106 } | 106 } |
OLD | NEW |