summaryrefslogtreecommitdiff
path: root/src/pkg/bufio/bufio.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/bufio/bufio.go')
-rw-r--r--src/pkg/bufio/bufio.go95
1 files changed, 54 insertions, 41 deletions
diff --git a/src/pkg/bufio/bufio.go b/src/pkg/bufio/bufio.go
index eae5c5ce9..32a25afae 100644
--- a/src/pkg/bufio/bufio.go
+++ b/src/pkg/bufio/bufio.go
@@ -282,6 +282,33 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err os.Error) {
panic("not reached")
}
+// ReadLine tries to return a single line, not including the end-of-line bytes.
+// If the line was too long for the buffer then isPrefix is set and the
+// beginning of the line is returned. The rest of the line will be returned
+// from future calls. isPrefix will be false when returning the last fragment
+// of the line. The returned buffer is only valid until the next call to
+// ReadLine. ReadLine either returns a non-nil line or it returns an error,
+// never both.
+func (b *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) {
+ line, err = b.ReadSlice('\n')
+ if err == ErrBufferFull {
+ return line, true, nil
+ }
+
+ if len(line) == 0 {
+ return
+ }
+ err = nil
+
+ if line[len(line)-1] == '\n' {
+ line = line[:len(line)-1]
+ }
+ if len(line) > 0 && line[len(line)-1] == '\r' {
+ line = line[:len(line)-1]
+ }
+ return
+}
+
// ReadBytes reads until the first occurrence of delim in the input,
// returning a slice containing the data up to and including the delimiter.
// If ReadBytes encounters an error before finding a delimiter,
@@ -415,38 +442,27 @@ func (b *Writer) Buffered() int { return b.n }
// If nn < len(p), it also returns an error explaining
// why the write is short.
func (b *Writer) Write(p []byte) (nn int, err os.Error) {
- if b.err != nil {
- return 0, b.err
- }
- nn = 0
- for len(p) > 0 {
- n := b.Available()
- if n <= 0 {
- if b.Flush(); b.err != nil {
- break
- }
- n = b.Available()
- }
- if b.Buffered() == 0 && len(p) >= len(b.buf) {
+ for len(p) > b.Available() && b.err == nil {
+ var n int
+ if b.Buffered() == 0 {
// Large write, empty buffer.
// Write directly from p to avoid copy.
n, b.err = b.wr.Write(p)
- nn += n
- p = p[n:]
- if b.err != nil {
- break
- }
- continue
+ } else {
+ n = copy(b.buf[b.n:], p)
+ b.n += n
+ b.Flush()
}
- if n > len(p) {
- n = len(p)
- }
- copy(b.buf[b.n:b.n+n], p[0:n])
- b.n += n
nn += n
p = p[n:]
}
- return nn, b.err
+ if b.err != nil {
+ return nn, b.err
+ }
+ n := copy(b.buf[b.n:], p)
+ b.n += n
+ nn += n
+ return nn, nil
}
// WriteByte writes a single byte.
@@ -496,24 +512,21 @@ func (b *Writer) WriteRune(rune int) (size int, err os.Error) {
// If the count is less than len(s), it also returns an error explaining
// why the write is short.
func (b *Writer) WriteString(s string) (int, os.Error) {
- if b.err != nil {
- return 0, b.err
- }
- // Common case, worth making fast.
- if b.Available() >= len(s) || len(b.buf) >= len(s) && b.Flush() == nil {
- for i := 0; i < len(s); i++ { // loop over bytes, not runes.
- b.buf[b.n] = s[i]
- b.n++
- }
- return len(s), nil
+ nn := 0
+ for len(s) > b.Available() && b.err == nil {
+ n := copy(b.buf[b.n:], s)
+ b.n += n
+ nn += n
+ s = s[n:]
+ b.Flush()
}
- for i := 0; i < len(s); i++ { // loop over bytes, not runes.
- b.WriteByte(s[i])
- if b.err != nil {
- return i, b.err
- }
+ if b.err != nil {
+ return nn, b.err
}
- return len(s), nil
+ n := copy(b.buf[b.n:], s)
+ b.n += n
+ nn += n
+ return nn, nil
}
// buffered input and output