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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [compress/] [zlib/] [reader.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
/*
6
Package zlib implements reading and writing of zlib format compressed data,
7
as specified in RFC 1950.
8
 
9
The implementation provides filters that uncompress during reading
10
and compress during writing.  For example, to write compressed data
11
to a buffer:
12
 
13
        var b bytes.Buffer
14
        w, err := zlib.NewWriter(&b)
15
        w.Write([]byte("hello, world\n"))
16
        w.Close()
17
 
18
and to read that data back:
19
 
20
        r, err := zlib.NewReader(&b)
21
        io.Copy(os.Stdout, r)
22
        r.Close()
23
*/
24
package zlib
25
 
26
import (
27
        "bufio"
28
        "compress/flate"
29
        "errors"
30
        "hash"
31
        "hash/adler32"
32
        "io"
33
)
34
 
35
const zlibDeflate = 8
36
 
37
var ErrChecksum = errors.New("zlib checksum error")
38
var ErrHeader = errors.New("invalid zlib header")
39
var ErrDictionary = errors.New("invalid zlib dictionary")
40
 
41
type reader struct {
42
        r            flate.Reader
43
        decompressor io.ReadCloser
44
        digest       hash.Hash32
45
        err          error
46
        scratch      [4]byte
47
}
48
 
49
// NewReader creates a new io.ReadCloser that satisfies reads by decompressing data read from r.
50
// The implementation buffers input and may read more data than necessary from r.
51
// It is the caller's responsibility to call Close on the ReadCloser when done.
52
func NewReader(r io.Reader) (io.ReadCloser, error) {
53
        return NewReaderDict(r, nil)
54
}
55
 
56
// NewReaderDict is like NewReader but uses a preset dictionary.
57
// NewReaderDict ignores the dictionary if the compressed data does not refer to it.
58
func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) {
59
        z := new(reader)
60
        if fr, ok := r.(flate.Reader); ok {
61
                z.r = fr
62
        } else {
63
                z.r = bufio.NewReader(r)
64
        }
65
        _, err := io.ReadFull(z.r, z.scratch[0:2])
66
        if err != nil {
67
                return nil, err
68
        }
69
        h := uint(z.scratch[0])<<8 | uint(z.scratch[1])
70
        if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) {
71
                return nil, ErrHeader
72
        }
73
        if z.scratch[1]&0x20 != 0 {
74
                _, err = io.ReadFull(z.r, z.scratch[0:4])
75
                if err != nil {
76
                        return nil, err
77
                }
78
                checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
79
                if checksum != adler32.Checksum(dict) {
80
                        return nil, ErrDictionary
81
                }
82
                z.decompressor = flate.NewReaderDict(z.r, dict)
83
        } else {
84
                z.decompressor = flate.NewReader(z.r)
85
        }
86
        z.digest = adler32.New()
87
        return z, nil
88
}
89
 
90
func (z *reader) Read(p []byte) (n int, err error) {
91
        if z.err != nil {
92
                return 0, z.err
93
        }
94
        if len(p) == 0 {
95
                return 0, nil
96
        }
97
 
98
        n, err = z.decompressor.Read(p)
99
        z.digest.Write(p[0:n])
100
        if n != 0 || err != io.EOF {
101
                z.err = err
102
                return
103
        }
104
 
105
        // Finished file; check checksum.
106
        if _, err := io.ReadFull(z.r, z.scratch[0:4]); err != nil {
107
                z.err = err
108
                return 0, err
109
        }
110
        // ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
111
        checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
112
        if checksum != z.digest.Sum32() {
113
                z.err = ErrChecksum
114
                return 0, z.err
115
        }
116
        return
117
}
118
 
119
// Calling Close does not close the wrapped io.Reader originally passed to NewReader.
120
func (z *reader) Close() error {
121
        if z.err != nil {
122
                return z.err
123
        }
124
        z.err = z.decompressor.Close()
125
        return z.err
126
}

powered by: WebSVN 2.1.0

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