// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package bufio import "os" import "io" // TODO: // - maybe define an interface // - BufRead: ReadRune, UnreadRune ? // could make ReadRune generic if we dropped UnreadRune // - buffered output const ( DefaultBufSize = 4096 ) export var ( EndOfFile = os.NewError("end of file"); PhaseError = os.NewError("phase error"); BufferFull = os.NewError("buffer full"); InternalError = os.NewError("bufio internal error"); BadBufSize = os.NewError("bad bufio size"); ShortWrite = os.NewError("short write"); ) func CopySlice(dst *[]byte, src *[]byte) { for i := 0; i < len(dst); i++ { dst[i] = src[i] } } // Buffered input. export type BufRead struct { buf *[]byte; rd io.Read; r, w int; err *os.Error; } export func NewBufReadSize(rd io.Read, size int) (b *BufRead, err *os.Error) { if size <= 0 { return nil, BadBufSize } b = new(BufRead); b.buf = new([]byte, size); b.rd = rd; return b, nil } export func NewBufRead(rd io.Read) (b *BufRead, err *os.Error) { // 6g BUG return NewBufReadSize(rd, DefaultBufSize) r, e := NewBufReadSize(rd, DefaultBufSize); return r, e } // Read a new chunk into the buffer. func (b *BufRead) Fill() *os.Error { if b.err != nil { return b.err } // Slide existing data to beginning. if b.w > b.r { CopySlice(b.buf[0:b.w-b.r], b.buf[b.r:b.w]); b.w -= b.r; } else { b.w = 0 } b.r = 0; // Read new data. n, e := b.rd.Read(b.buf[b.w:len(b.buf)]); if e != nil { b.err = e; return e } b.w += n; return nil } // Read into p. // Returns the number of bytes read into p. // If nn < len(p), also returns an error explaining // why the read is short. func (b *BufRead) Read(p *[]byte) (nn int, err *os.Error) { nn = 0; for len(p) > 0 { n := len(p); if b.w == b.r { b.Fill(); if b.err != nil { return nn, b.err } if b.w == b.r { return nn, EndOfFile } } if n > b.w - b.r { n = b.w - b.r } CopySlice(p[0:n], b.buf[b.r:b.r+n]); p = p[n:len(p)]; b.r += n; nn += n } return nn, nil } // Read a single byte. // If no byte available, returns error. func (b *BufRead) ReadByte() (c byte, err *os.Error) { if b.w == b.r { b.Fill(); if b.err != nil { return 0, b.err } if b.w == b.r { return 0, EndOfFile } } c = b.buf[b.r]; b.r++; return c, nil } // Unread the last byte. Only guaranteed to be able to unread one byte. func (b *BufRead) UnreadByte() *os.Error { if b.err != nil { return b.err } if b.r <= 0 { return PhaseError } b.r--; return nil } // Helper function: look for byte c in array p, // returning its index or -1. func FindByte(p *[]byte, c byte) int { for i := 0; i < len(p); i++ { if p[i] == c { return i } } return -1 } // Returns the number of bytes that can be read. func (b *BufRead) Buffered() int { return b.w - b.r; } // Read until the first occurrence of delim in the input, // returning a slice pointing at the bytes in the buffer. // The bytes stop being valid at the next read call. // Fails if the line doesn't fit in the buffer. // For internal (or advanced) use only. // Use ReadLineString or ReadLineBytes instead. func (b *BufRead) ReadLineSlice(delim byte) (line *[]byte, err *os.Error) { if b.err != nil { return nil, b.err } // Look in buffer. if i := FindByte(b.buf[b.r:b.w], delim); i >= 0 { line1 := b.buf[b.r:b.r+i+1]; b.r += i+1; return line1, nil } // Read more into buffer, until buffer fills or we find delim. for { n := b.Buffered(); b.Fill(); if b.err != nil { return nil, b.err } if b.Buffered() == n { // no data added; end of file return nil, EndOfFile } // Search new part of buffer if i := FindByte(b.buf[n:b.w], delim); i >= 0 { line := b.buf[0:n+i+1]; b.r = n+i+1; return line, nil } // Buffer is full? if b.Buffered() >= len(b.buf) { return nil, BufferFull } } // BUG 6g bug100 return nil, nil } // Read until the first occurrence of delim in the input, // returning a new byte array containing the line. // If an error happens, returns the data (without a delimiter) // and the error. (Can't leave the data in the buffer because // we might have read more than the buffer size.) func (b *BufRead) ReadLineBytes(delim byte) (line *[]byte, err *os.Error) { if b.err != nil { return nil, b.err } // Use ReadLineSlice to look for array, // accumulating full buffers. var frag *[]byte; var full *[]*[]byte; nfull := 0; err = nil; for { var e *os.Error; frag, e = b.ReadLineSlice(delim); if e == nil { // got final fragment break } if e != BufferFull { // unexpected error err = e; break } // Read bytes out of buffer. buf := new([]byte, b.Buffered()); var n int; n, e = b.Read(buf); if e != nil { frag = buf[0:n]; err = e; break } if n != len(buf) { frag = buf[0:n]; err = InternalError; break } // Grow list if needed. if full == nil { full = new([]*[]byte, 16); } else if nfull >= len(full) { newfull := new([]*[]byte, len(full)*2); // BUG slice assignment for i := 0; i < len(full); i++ { newfull[i] = full[i]; } full = newfull } // Save buffer full[nfull] = buf; nfull++; } // Allocate new buffer to hold the full pieces and the fragment. n := 0; for i := 0; i < nfull; i++ { n += len(full[i]) } if frag != nil { n += len(frag); } // Copy full pieces and fragment in. buf := new([]byte, n); n = 0; for i := 0; i < nfull; i++ { CopySlice(buf[n:n+len(full[i])], full[i]); n += len(full[i]) } if frag != nil { CopySlice(buf[n:n+len(frag)], frag) } return buf, err } // BUG(bugs/bug102.go): string(empty bytes array) throws error func ToString(p *[]byte) string { if len(p) == 0 { return "" } return string(p) } // Read until the first occurrence of delim in the input, // returning a new string containing the line. // If savedelim, keep delim in the result; otherwise chop it off. func (b *BufRead) ReadLineString(delim byte, savedelim bool) (line string, err *os.Error) { bytes, e := b.ReadLineBytes(delim); if e != nil { return ToString(bytes), e } if !savedelim { bytes = bytes[0:len(bytes)-1] } return ToString(bytes), nil } // buffered output export type BufWrite struct { err *os.Error; buf *[]byte; n int; wr io.Write; } export func NewBufWriteSize(wr io.Write, size int) (b *BufWrite, err *os.Error) { if size <= 0 { return nil, BadBufSize } b = new(BufWrite); b.buf = new([]byte, size); b.wr = wr; return b, nil } export func NewBufWrite(wr io.Write) (b *BufWrite, err *os.Error) { // 6g BUG return NewBufWriteSize(wr, DefaultBufSize) r, e := NewBufWriteSize(wr, DefaultBufSize); return r, e } // Flush the output buffer. func (b *BufWrite) Flush() *os.Error { if b.err != nil { return b.err } n := 0; for n < b.n { m, e := b.wr.Write(b.buf[n:b.n]); n += m; if m == 0 && e == nil { e = ShortWrite } if e != nil { if n < b.n { CopySlice(b.buf[0:b.n-n], b.buf[n:b.n]) } b.n -= n; b.err = e; return e } } b.n = 0; return nil } func (b *BufWrite) Available() int { return len(b.buf) - b.n } func (b *BufWrite) Buffered() int { return b.n } func (b *BufWrite) 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 n > len(p) { n = len(p) } CopySlice(b.buf[b.n:b.n+n], p[0:n]); b.n += n; nn += n; p = p[n:len(p)] } return nn, b.err } func (b *BufWrite) WriteByte(c byte) *os.Error { if b.err != nil { return b.err } if b.Available() <= 0 && b.Flush() != nil { return b.err } b.buf[b.n] = c; b.n++; return nil }