summaryrefslogtreecommitdiff
path: root/src/pkg/net/textproto/reader.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/net/textproto/reader.go')
-rw-r--r--src/pkg/net/textproto/reader.go62
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