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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [compress/] [zlib/] [writer.go] - Blame information for rev 747

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2009 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 zlib
6
 
7
import (
8
        "compress/flate"
9
        "errors"
10
        "hash"
11
        "hash/adler32"
12
        "io"
13
)
14
 
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".
17
const (
18
        NoCompression      = flate.NoCompression
19
        BestSpeed          = flate.BestSpeed
20
        BestCompression    = flate.BestCompression
21
        DefaultCompression = flate.DefaultCompression
22
)
23
 
24
// A Writer takes data written to it and writes the compressed
25
// form of that data to an underlying writer (see NewWriter).
26
type Writer struct {
27
        w          io.Writer
28
        compressor *flate.Writer
29
        digest     hash.Hash32
30
        err        error
31
        scratch    [4]byte
32
}
33
 
34
// NewWriter calls NewWriterLevel with the default compression level.
35
func NewWriter(w io.Writer) (*Writer, error) {
36
        return NewWriterLevel(w, DefaultCompression)
37
}
38
 
39
// NewWriterLevel calls NewWriterDict with no dictionary.
40
func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
41
        return NewWriterDict(w, level, nil)
42
}
43
 
44
// NewWriterDict creates a new io.WriteCloser that satisfies writes by compressing data written to w.
45
// It is the caller's responsibility to call Close on the WriteCloser when done.
46
// level is the compression level, which can be DefaultCompression, NoCompression,
47
// or any integer value between BestSpeed and BestCompression (inclusive).
48
// dict is the preset dictionary to compress with, or nil to use no dictionary.
49
func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, error) {
50
        z := new(Writer)
51
        // ZLIB has a two-byte header (as documented in RFC 1950).
52
        // The first four bits is the CINFO (compression info), which is 7 for the default deflate window size.
53
        // The next four bits is the CM (compression method), which is 8 for deflate.
54
        z.scratch[0] = 0x78
55
        // The next two bits is the FLEVEL (compression level). The four values are:
56
        // 0=fastest, 1=fast, 2=default, 3=best.
57
        // The next bit, FDICT, is set if a dictionary is given.
58
        // The final five FCHECK bits form a mod-31 checksum.
59
        switch level {
60
        case 0, 1:
61
                z.scratch[1] = 0 << 6
62
        case 2, 3, 4, 5:
63
                z.scratch[1] = 1 << 6
64
        case 6, -1:
65
                z.scratch[1] = 2 << 6
66
        case 7, 8, 9:
67
                z.scratch[1] = 3 << 6
68
        default:
69
                return nil, errors.New("level out of range")
70
        }
71
        if dict != nil {
72
                z.scratch[1] |= 1 << 5
73
        }
74
        z.scratch[1] += uint8(31 - (uint16(z.scratch[0])<<8+uint16(z.scratch[1]))%31)
75
        _, err := w.Write(z.scratch[0:2])
76
        if err != nil {
77
                return nil, err
78
        }
79
        if dict != nil {
80
                // The next four bytes are the Adler-32 checksum of the dictionary.
81
                checksum := adler32.Checksum(dict)
82
                z.scratch[0] = uint8(checksum >> 24)
83
                z.scratch[1] = uint8(checksum >> 16)
84
                z.scratch[2] = uint8(checksum >> 8)
85
                z.scratch[3] = uint8(checksum >> 0)
86
                _, err = w.Write(z.scratch[0:4])
87
                if err != nil {
88
                        return nil, err
89
                }
90
        }
91
        z.w = w
92
        z.compressor = flate.NewWriterDict(w, level, dict)
93
        z.digest = adler32.New()
94
        return z, nil
95
}
96
 
97
func (z *Writer) Write(p []byte) (n int, err error) {
98
        if z.err != nil {
99
                return 0, z.err
100
        }
101
        if len(p) == 0 {
102
                return 0, nil
103
        }
104
        n, err = z.compressor.Write(p)
105
        if err != nil {
106
                z.err = err
107
                return
108
        }
109
        z.digest.Write(p)
110
        return
111
}
112
 
113
// Flush flushes the underlying compressor.
114
func (z *Writer) Flush() error {
115
        if z.err != nil {
116
                return z.err
117
        }
118
        z.err = z.compressor.Flush()
119
        return z.err
120
}
121
 
122
// Calling Close does not close the wrapped io.Writer originally passed to NewWriter.
123
func (z *Writer) Close() error {
124
        if z.err != nil {
125
                return z.err
126
        }
127
        z.err = z.compressor.Close()
128
        if z.err != nil {
129
                return z.err
130
        }
131
        checksum := z.digest.Sum32()
132
        // ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
133
        z.scratch[0] = uint8(checksum >> 24)
134
        z.scratch[1] = uint8(checksum >> 16)
135
        z.scratch[2] = uint8(checksum >> 8)
136
        z.scratch[3] = uint8(checksum >> 0)
137
        _, z.err = z.w.Write(z.scratch[0:4])
138
        return z.err
139
}

powered by: WebSVN 2.1.0

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