~ubuntu-branches/ubuntu/saucy/golang/saucy

« back to all changes in this revision

Viewing changes to src/pkg/net/http/httputil/chunked.go

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2013-07-08 05:52:37 UTC
  • mfrom: (29.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20130708055237-at01839e0hp8z3ni
Tags: 2:1.1-1ubuntu1
016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
 
14
14
import (
15
15
        "bufio"
16
 
        "bytes"
17
16
        "errors"
 
17
        "fmt"
18
18
        "io"
19
 
        "strconv"
20
19
)
21
20
 
22
21
const maxLineLength = 4096 // assumed <= bufio.defaultBufSize
24
23
var ErrLineTooLong = errors.New("header line too long")
25
24
 
26
25
// NewChunkedReader returns a new chunkedReader that translates the data read from r
27
 
// out of HTTP "chunked" format before returning it. 
 
26
// out of HTTP "chunked" format before returning it.
28
27
// The chunkedReader returns io.EOF when the final 0-length chunk is read.
29
28
//
30
29
// NewChunkedReader is not needed by normal applications. The http package
41
40
        r   *bufio.Reader
42
41
        n   uint64 // unread bytes in chunk
43
42
        err error
 
43
        buf [2]byte
44
44
}
45
45
 
46
46
func (cr *chunkedReader) beginChunk() {
47
47
        // chunk-size CRLF
48
 
        var line string
 
48
        var line []byte
49
49
        line, cr.err = readLine(cr.r)
50
50
        if cr.err != nil {
51
51
                return
52
52
        }
53
 
        cr.n, cr.err = strconv.ParseUint(line, 16, 64)
 
53
        cr.n, cr.err = parseHexUint(line)
54
54
        if cr.err != nil {
55
55
                return
56
56
        }
76
76
        cr.n -= uint64(n)
77
77
        if cr.n == 0 && cr.err == nil {
78
78
                // end of chunk (CRLF)
79
 
                b := make([]byte, 2)
80
 
                if _, cr.err = io.ReadFull(cr.r, b); cr.err == nil {
81
 
                        if b[0] != '\r' || b[1] != '\n' {
 
79
                if _, cr.err = io.ReadFull(cr.r, cr.buf[:]); cr.err == nil {
 
80
                        if cr.buf[0] != '\r' || cr.buf[1] != '\n' {
82
81
                                cr.err = errors.New("malformed chunked encoding")
83
82
                        }
84
83
                }
90
89
// Give up if the line exceeds maxLineLength.
91
90
// The returned bytes are a pointer into storage in
92
91
// the bufio, so they are only valid until the next bufio read.
93
 
func readLineBytes(b *bufio.Reader) (p []byte, err error) {
 
92
func readLine(b *bufio.Reader) (p []byte, err error) {
94
93
        if p, err = b.ReadSlice('\n'); err != nil {
95
94
                // We always know when EOF is coming.
96
95
                // If the caller asked for a line, there should be a line.
104
103
        if len(p) >= maxLineLength {
105
104
                return nil, ErrLineTooLong
106
105
        }
107
 
 
108
 
        // Chop off trailing white space.
109
 
        p = bytes.TrimRight(p, " \r\t\n")
110
 
 
111
 
        return p, nil
 
106
        return trimTrailingWhitespace(p), nil
112
107
}
113
108
 
114
 
// readLineBytes, but convert the bytes into a string.
115
 
func readLine(b *bufio.Reader) (s string, err error) {
116
 
        p, e := readLineBytes(b)
117
 
        if e != nil {
118
 
                return "", e
 
109
func trimTrailingWhitespace(b []byte) []byte {
 
110
        for len(b) > 0 && isASCIISpace(b[len(b)-1]) {
 
111
                b = b[:len(b)-1]
119
112
        }
120
 
        return string(p), nil
 
113
        return b
 
114
}
 
115
 
 
116
func isASCIISpace(b byte) bool {
 
117
        return b == ' ' || b == '\t' || b == '\n' || b == '\r'
121
118
}
122
119
 
123
120
// NewChunkedWriter returns a new chunkedWriter that translates writes into HTTP
149
146
                return 0, nil
150
147
        }
151
148
 
152
 
        head := strconv.FormatInt(int64(len(data)), 16) + "\r\n"
153
 
 
154
 
        if _, err = io.WriteString(cw.Wire, head); err != nil {
 
149
        if _, err = fmt.Fprintf(cw.Wire, "%x\r\n", len(data)); err != nil {
155
150
                return 0, err
156
151
        }
157
152
        if n, err = cw.Wire.Write(data); err != nil {
170
165
        _, err := io.WriteString(cw.Wire, "0\r\n")
171
166
        return err
172
167
}
 
168
 
 
169
func parseHexUint(v []byte) (n uint64, err error) {
 
170
        for _, b := range v {
 
171
                n <<= 4
 
172
                switch {
 
173
                case '0' <= b && b <= '9':
 
174
                        b = b - '0'
 
175
                case 'a' <= b && b <= 'f':
 
176
                        b = b - 'a' + 10
 
177
                case 'A' <= b && b <= 'F':
 
178
                        b = b - 'A' + 10
 
179
                default:
 
180
                        return 0, errors.New("invalid byte in chunk length")
 
181
                }
 
182
                n |= uint64(b)
 
183
        }
 
184
        return
 
185
}