diff options
Diffstat (limited to 'src/pkg/net/textproto/reader.go')
-rw-r--r-- | src/pkg/net/textproto/reader.go | 62 |
1 files changed, 42 insertions, 20 deletions
diff --git a/src/pkg/net/textproto/reader.go b/src/pkg/net/textproto/reader.go index e65374903..ce0ddc73f 100644 --- a/src/pkg/net/textproto/reader.go +++ b/src/pkg/net/textproto/reader.go @@ -7,7 +7,6 @@ package textproto import ( "bufio" "bytes" - "container/vector" "io" "io/ioutil" "os" @@ -33,22 +32,25 @@ func NewReader(r *bufio.Reader) *Reader { // ReadLine reads a single line from r, // eliding the final \n or \r\n from the returned string. func (r *Reader) ReadLine() (string, os.Error) { - line, err := r.ReadLineBytes() + line, err := r.readLineSlice() return string(line), err } // ReadLineBytes is like ReadLine but returns a []byte instead of a string. func (r *Reader) ReadLineBytes() ([]byte, os.Error) { - r.closeDot() - line, err := r.R.ReadBytes('\n') - n := len(line) - if n > 0 && line[n-1] == '\n' { - n-- - if n > 0 && line[n-1] == '\r' { - n-- - } + line, err := r.readLineSlice() + if line != nil { + buf := make([]byte, len(line)) + copy(buf, line) + line = buf } - return line[0:n], err + return line, err +} + +func (r *Reader) readLineSlice() ([]byte, os.Error) { + r.closeDot() + line, _, err := r.R.ReadLine() + return line, err } // ReadContinuedLine reads a possibly continued line from r, @@ -71,7 +73,7 @@ func (r *Reader) ReadLineBytes() ([]byte, os.Error) { // A line consisting of only white space is never continued. // func (r *Reader) ReadContinuedLine() (string, os.Error) { - line, err := r.ReadContinuedLineBytes() + line, err := r.readContinuedLineSlice() return string(line), err } @@ -92,8 +94,18 @@ func trim(s []byte) []byte { // ReadContinuedLineBytes is like ReadContinuedLine but // returns a []byte instead of a string. func (r *Reader) ReadContinuedLineBytes() ([]byte, os.Error) { + line, err := r.readContinuedLineSlice() + if line != nil { + buf := make([]byte, len(line)) + copy(buf, line) + line = buf + } + return line, err +} + +func (r *Reader) readContinuedLineSlice() ([]byte, os.Error) { // Read the first line. - line, err := r.ReadLineBytes() + line, err := r.readLineSlice() if err != nil { return line, err } @@ -102,6 +114,13 @@ func (r *Reader) ReadContinuedLineBytes() ([]byte, os.Error) { } line = trim(line) + copied := false + if r.R.Buffered() < 1 { + // ReadByte will flush the buffer; make a copy of the slice. + copied = true + line = append([]byte(nil), line...) + } + // Look for a continuation line. c, err := r.R.ReadByte() if err != nil { @@ -114,6 +133,11 @@ func (r *Reader) ReadContinuedLineBytes() ([]byte, os.Error) { return line, nil } + if !copied { + // The next readLineSlice will invalidate the previous one. + line = append(make([]byte, 0, len(line)*2), line...) + } + // Read continuation lines. for { // Consume leading spaces; one already gone. @@ -128,7 +152,7 @@ func (r *Reader) ReadContinuedLineBytes() ([]byte, os.Error) { } } var cont []byte - cont, err = r.ReadLineBytes() + cont, err = r.readLineSlice() cont = trim(cont) line = append(line, ' ') line = append(line, cont...) @@ -375,7 +399,7 @@ func (r *Reader) ReadDotLines() ([]string, os.Error) { // We could use ReadDotBytes and then Split it, // but reading a line at a time avoids needing a // large contiguous block of memory and is simpler. - var v vector.StringVector + var v []string var err os.Error for { var line string @@ -394,7 +418,7 @@ func (r *Reader) ReadDotLines() ([]string, os.Error) { } line = line[1:] } - v.Push(line) + v = append(v, line) } return v, err } @@ -422,7 +446,7 @@ func (r *Reader) ReadDotLines() ([]string, os.Error) { func (r *Reader) ReadMIMEHeader() (MIMEHeader, os.Error) { m := make(MIMEHeader) for { - kv, err := r.ReadContinuedLineBytes() + kv, err := r.readContinuedLineSlice() if len(kv) == 0 { return m, err } @@ -441,9 +465,7 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, os.Error) { } value := string(kv[i:]) - v := vector.StringVector(m[key]) - v.Push(value) - m[key] = v + m[key] = append(m[key], value) if err != nil { return m, err |