source: code/trunk/vendor/github.com/andybalholm/brotli/reader.go@ 145

Last change on this file since 145 was 145, checked in by Izuru Yakumo, 22 months ago

Updated the Makefile and vendored depedencies

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 2.3 KB
RevLine 
[145]1package brotli
2
3import (
4 "errors"
5 "io"
6)
7
8type decodeError int
9
10func (err decodeError) Error() string {
11 return "brotli: " + string(decoderErrorString(int(err)))
12}
13
14var errExcessiveInput = errors.New("brotli: excessive input")
15var errInvalidState = errors.New("brotli: invalid state")
16
17// readBufSize is a "good" buffer size that avoids excessive round-trips
18// between C and Go but doesn't waste too much memory on buffering.
19// It is arbitrarily chosen to be equal to the constant used in io.Copy.
20const readBufSize = 32 * 1024
21
22// NewReader creates a new Reader reading the given reader.
23func NewReader(src io.Reader) *Reader {
24 r := new(Reader)
25 r.Reset(src)
26 return r
27}
28
29// Reset discards the Reader's state and makes it equivalent to the result of
30// its original state from NewReader, but writing to src instead.
31// This permits reusing a Reader rather than allocating a new one.
32// Error is always nil
33func (r *Reader) Reset(src io.Reader) error {
34 decoderStateInit(r)
35 r.src = src
36 if r.buf == nil {
37 r.buf = make([]byte, readBufSize)
38 }
39 return nil
40}
41
42func (r *Reader) Read(p []byte) (n int, err error) {
43 if !decoderHasMoreOutput(r) && len(r.in) == 0 {
44 m, readErr := r.src.Read(r.buf)
45 if m == 0 {
46 // If readErr is `nil`, we just proxy underlying stream behavior.
47 return 0, readErr
48 }
49 r.in = r.buf[:m]
50 }
51
52 if len(p) == 0 {
53 return 0, nil
54 }
55
56 for {
57 var written uint
58 in_len := uint(len(r.in))
59 out_len := uint(len(p))
60 in_remaining := in_len
61 out_remaining := out_len
62 result := decoderDecompressStream(r, &in_remaining, &r.in, &out_remaining, &p)
63 written = out_len - out_remaining
64 n = int(written)
65
66 switch result {
67 case decoderResultSuccess:
68 if len(r.in) > 0 {
69 return n, errExcessiveInput
70 }
71 return n, nil
72 case decoderResultError:
73 return n, decodeError(decoderGetErrorCode(r))
74 case decoderResultNeedsMoreOutput:
75 if n == 0 {
76 return 0, io.ErrShortBuffer
77 }
78 return n, nil
79 case decoderNeedsMoreInput:
80 }
81
82 if len(r.in) != 0 {
83 return 0, errInvalidState
84 }
85
86 // Calling r.src.Read may block. Don't block if we have data to return.
87 if n > 0 {
88 return n, nil
89 }
90
91 // Top off the buffer.
92 encN, err := r.src.Read(r.buf)
93 if encN == 0 {
94 // Not enough data to complete decoding.
95 if err == io.EOF {
96 return 0, io.ErrUnexpectedEOF
97 }
98 return 0, err
99 }
100 r.in = r.buf[:encN]
101 }
102}
Note: See TracBrowser for help on using the repository browser.