OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [compress/] [gzip/] [gzip.go] - Blame information for rev 774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2010 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4
 
5
package gzip
6
 
7
import (
8
        "compress/flate"
9
        "errors"
10
        "hash"
11
        "hash/crc32"
12
        "io"
13
)
14
 
15
// These constants are copied from the flate package, so that code that imports
16
// "compress/gzip" does not also have to import "compress/flate".
17
const (
18
        NoCompression      = flate.NoCompression
19
        BestSpeed          = flate.BestSpeed
20
        BestCompression    = flate.BestCompression
21
        DefaultCompression = flate.DefaultCompression
22
)
23
 
24
// A Compressor is an io.WriteCloser that satisfies writes by compressing data written
25
// to its wrapped io.Writer.
26
type Compressor struct {
27
        Header
28
        w          io.Writer
29
        level      int
30
        compressor io.WriteCloser
31
        digest     hash.Hash32
32
        size       uint32
33
        closed     bool
34
        buf        [10]byte
35
        err        error
36
}
37
 
38
// NewWriter calls NewWriterLevel with the default compression level.
39
func NewWriter(w io.Writer) (*Compressor, error) {
40
        return NewWriterLevel(w, DefaultCompression)
41
}
42
 
43
// NewWriterLevel creates a new Compressor writing to the given writer.
44
// Writes may be buffered and not flushed until Close.
45
// Callers that wish to set the fields in Compressor.Header must
46
// do so before the first call to Write or Close.
47
// It is the caller's responsibility to call Close on the WriteCloser when done.
48
// level is the compression level, which can be DefaultCompression, NoCompression,
49
// or any integer value between BestSpeed and BestCompression (inclusive).
50
func NewWriterLevel(w io.Writer, level int) (*Compressor, error) {
51
        z := new(Compressor)
52
        z.OS = 255 // unknown
53
        z.w = w
54
        z.level = level
55
        z.digest = crc32.NewIEEE()
56
        return z, nil
57
}
58
 
59
// GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950).
60
func put2(p []byte, v uint16) {
61
        p[0] = uint8(v >> 0)
62
        p[1] = uint8(v >> 8)
63
}
64
 
65
func put4(p []byte, v uint32) {
66
        p[0] = uint8(v >> 0)
67
        p[1] = uint8(v >> 8)
68
        p[2] = uint8(v >> 16)
69
        p[3] = uint8(v >> 24)
70
}
71
 
72
// writeBytes writes a length-prefixed byte slice to z.w.
73
func (z *Compressor) writeBytes(b []byte) error {
74
        if len(b) > 0xffff {
75
                return errors.New("gzip.Write: Extra data is too large")
76
        }
77
        put2(z.buf[0:2], uint16(len(b)))
78
        _, err := z.w.Write(z.buf[0:2])
79
        if err != nil {
80
                return err
81
        }
82
        _, err = z.w.Write(b)
83
        return err
84
}
85
 
86
// writeString writes a string (in ISO 8859-1 (Latin-1) format) to z.w.
87
func (z *Compressor) writeString(s string) error {
88
        // GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
89
        var err error
90
        needconv := false
91
        for _, v := range s {
92
                if v == 0 || v > 0xff {
93
                        return errors.New("gzip.Write: non-Latin-1 header string")
94
                }
95
                if v > 0x7f {
96
                        needconv = true
97
                }
98
        }
99
        if needconv {
100
                b := make([]byte, 0, len(s))
101
                for _, v := range s {
102
                        b = append(b, byte(v))
103
                }
104
                _, err = z.w.Write(b)
105
        } else {
106
                _, err = io.WriteString(z.w, s)
107
        }
108
        if err != nil {
109
                return err
110
        }
111
        // GZIP strings are NUL-terminated.
112
        z.buf[0] = 0
113
        _, err = z.w.Write(z.buf[0:1])
114
        return err
115
}
116
 
117
func (z *Compressor) Write(p []byte) (int, error) {
118
        if z.err != nil {
119
                return 0, z.err
120
        }
121
        var n int
122
        // Write the GZIP header lazily.
123
        if z.compressor == nil {
124
                z.buf[0] = gzipID1
125
                z.buf[1] = gzipID2
126
                z.buf[2] = gzipDeflate
127
                z.buf[3] = 0
128
                if z.Extra != nil {
129
                        z.buf[3] |= 0x04
130
                }
131
                if z.Name != "" {
132
                        z.buf[3] |= 0x08
133
                }
134
                if z.Comment != "" {
135
                        z.buf[3] |= 0x10
136
                }
137
                put4(z.buf[4:8], uint32(z.ModTime.Unix()))
138
                if z.level == BestCompression {
139
                        z.buf[8] = 2
140
                } else if z.level == BestSpeed {
141
                        z.buf[8] = 4
142
                } else {
143
                        z.buf[8] = 0
144
                }
145
                z.buf[9] = z.OS
146
                n, z.err = z.w.Write(z.buf[0:10])
147
                if z.err != nil {
148
                        return n, z.err
149
                }
150
                if z.Extra != nil {
151
                        z.err = z.writeBytes(z.Extra)
152
                        if z.err != nil {
153
                                return n, z.err
154
                        }
155
                }
156
                if z.Name != "" {
157
                        z.err = z.writeString(z.Name)
158
                        if z.err != nil {
159
                                return n, z.err
160
                        }
161
                }
162
                if z.Comment != "" {
163
                        z.err = z.writeString(z.Comment)
164
                        if z.err != nil {
165
                                return n, z.err
166
                        }
167
                }
168
                z.compressor = flate.NewWriter(z.w, z.level)
169
        }
170
        z.size += uint32(len(p))
171
        z.digest.Write(p)
172
        n, z.err = z.compressor.Write(p)
173
        return n, z.err
174
}
175
 
176
// Calling Close does not close the wrapped io.Writer originally passed to NewWriter.
177
func (z *Compressor) Close() error {
178
        if z.err != nil {
179
                return z.err
180
        }
181
        if z.closed {
182
                return nil
183
        }
184
        z.closed = true
185
        if z.compressor == nil {
186
                z.Write(nil)
187
                if z.err != nil {
188
                        return z.err
189
                }
190
        }
191
        z.err = z.compressor.Close()
192
        if z.err != nil {
193
                return z.err
194
        }
195
        put4(z.buf[0:4], z.digest.Sum32())
196
        put4(z.buf[4:8], z.size)
197
        _, z.err = z.w.Write(z.buf[0:8])
198
        return z.err
199
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.