--- /dev/null
+// 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
+)
+
+func NewError(s string) *os.Error {
+ // BUG return &os.Error{s};
+ e := new(os.Error);
+ e.s = s;
+ return e
+}
+
+export var (
+ EndOfFile = NewError("end of file");
+ PhaseError = NewError("phase error");
+ BufferFull = NewError("buffer full");
+ InternalError = NewError("bufio internal error");
+ BadBufSize = NewError("bad bufio size");
+ ShortWrite = 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 {
+ err *os.Error;
+ buf *[]byte;
+ r, w int;
+ rd io.Read;
+}
+
+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
+}
+
+// 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 string(bytes), e
+ }
+ if !savedelim {
+ bytes = bytes[0:len(bytes)-1]
+ }
+ return string(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
+}
+
--- /dev/null
+// 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 io
+import os "os"
+
+export func StringToBytes(b *[]byte, s string) bool {
+ if len(s) >= len(b) {
+ return false
+ }
+ for i := 0; i < len(s); i++ {
+ b[i] = s[i]
+ }
+ b[len(s)] = '\000'; // not necessary - memory is zeroed - but be explicit
+ return true
+}
+
+export type Read interface {
+ Read(p *[]byte) (n int, err *os.Error);
+}
+
+export type Write interface {
+ Write(p *[]byte) (n int, err *os.Error);
+}
+
+export func WriteString(w Write, s string) (n int, err *os.Error) {
+ b := new([]byte, len(s)+1)
+ if !StringToBytes(b, s) {
+ return -1, os.EINVAL
+ }
+ // BUG return w.Write(b[0:len(s)])
+ r, e := w.Write(b[0:len(s)])
+ return r, e
+}
+
done
rm -f *.6
-for i in fmt.go flag.go container/vector.go rand.go sort.go strings.go
+for i in fmt.go flag.go container/vector.go rand.go sort.go io.go bufio.go strings.go
do
base=$(basename $i .go)
echo 6g -o $GOROOT/pkg/$base.6 $i
O_TRUNC = syscall.O_TRUNC;
)
-export func Open(name string, mode int64, flags int64) (fd *FD, err *Error) {
- r, e := syscall.open(name, mode, flags);
+export func Open(name string, mode int, flags int) (fd *FD, err *Error) {
+ r, e := syscall.open(name, int64(mode), int64(flags));
return NewFD(r), ErrnoToError(e)
}
return ErrnoToError(e)
}
-func (fd *FD) Read(b *[]byte) (ret int64, err *Error) {
+func (fd *FD) Read(b *[]byte) (ret int, err *Error) {
if fd == nil {
return -1, EINVAL
}
r, e := syscall.read(fd.fd, &b[0], int64(len(b)));
- return r, ErrnoToError(e)
+ return int(r), ErrnoToError(e)
}
-func (fd *FD) Write(b *[]byte) (ret int64, err *Error) {
+func (fd *FD) Write(b *[]byte) (ret int, err *Error) {
if fd == nil {
return -1, EINVAL
}
r, e := syscall.write(fd.fd, &b[0], int64(len(b)));
- return r, ErrnoToError(e)
+ return int(r), ErrnoToError(e)
}
-func (fd *FD) WriteString(s string) (ret int64, err *Error) {
+func (fd *FD) WriteString(s string) (ret int, err *Error) {
if fd == nil {
return -1, EINVAL
}
return -1, EINVAL
}
r, e := syscall.write(fd.fd, &b[0], int64(len(s)));
- return r, ErrnoToError(e)
+ return int(r), ErrnoToError(e)
}
--- /dev/null
+// 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.
+
+// $G $F.go && $L $F.$A && ./$A.out
+
+package main
+
+import (
+ "os";
+ "io";
+ "bufio";
+ "syscall";
+ "rand"
+)
+
+func StringToBytes(s string) *[]byte {
+ b := new([]byte, len(s));
+ for i := 0; i < len(s); i++ {
+ b[i] = s[i]
+ }
+ return b
+}
+
+// Should be in language!
+func Copy(p *[]byte, q *[]byte) {
+ for i := 0; i < len(p); i++ {
+ p[i] = q[i]
+ }
+}
+
+// Reads from p.
+type ByteReader struct {
+ p *[]byte
+}
+
+func NewByteReader(p *[]byte) io.Read {
+ b := new(ByteReader);
+ b.p = p
+ return b
+}
+
+func (b *ByteReader) Read(p *[]byte) (int, *os.Error) {
+ n := len(p)
+ if n > len(b.p) {
+ n = len(b.p)
+ }
+ Copy(p[0:n], b.p[0:n]);
+ b.p = b.p[n:len(b.p)]
+ return n, nil
+}
+
+
+// Reads from p but only returns half of what you asked for.
+type HalfByteReader struct {
+ p *[]byte
+}
+
+func NewHalfByteReader(p *[]byte) io.Read {
+ b := new(HalfByteReader);
+ b.p = p
+ return b
+}
+
+func (b *HalfByteReader) Read(p *[]byte) (int, *os.Error) {
+ n := len(p)/2
+ if n == 0 && len(p) > 0 {
+ n = 1
+ }
+ if n > len(b.p) {
+ n = len(b.p)
+ }
+ Copy(p[0:n], b.p[0:n]);
+ b.p = b.p[n:len(b.p)]
+ return n, nil
+}
+
+// Reads from a reader and rot13s the result.
+type Rot13Reader struct {
+ r io.Read
+}
+
+func NewRot13Reader(r io.Read) *Rot13Reader {
+ r13 := new(Rot13Reader);
+ r13.r = r
+ return r13
+}
+
+func (r13 *Rot13Reader) Read(p *[]byte) (int, *os.Error) {
+ n, e := r13.r.Read(p)
+ if e != nil {
+ return n, e
+ }
+ for i := 0; i < n; i++ {
+ if 'a' <= p[i] && p[i] <= 'z' || 'A' <= p[i] && p[i] <= 'Z' {
+ if 'a' <= p[i] && p[i] <= 'm' || 'A' <= p[i] && p[i] <= 'M' {
+ p[i] += 13;
+ } else {
+ p[i] -= 13;
+ }
+ }
+ }
+ return n, nil
+}
+
+func MakeByteReader(p *[]byte) io.Read {
+ return NewByteReader(p)
+}
+func MakeHalfByteReader(p *[]byte) io.Read {
+ return NewHalfByteReader(p)
+}
+
+var readmakers = []*(p *[]byte) io.Read {
+ &NewByteReader,
+ &NewHalfByteReader
+}
+
+
+// Call ReadLineString (which ends up calling everything else)
+// to accumulate the text of a file.
+func ReadLines(b *bufio.BufRead) string {
+ s := ""
+ for {
+ s1, e := b.ReadLineString('\n', false)
+ if e == bufio.EndOfFile {
+ break
+ }
+ if e != nil {
+ panic("GetLines: "+e.String())
+ }
+ s += s1
+ }
+ return s
+}
+
+// Call ReadByte to accumulate the text of a file
+func ReadBytes(buf *bufio.BufRead) string {
+ var b [1000]byte;
+ nb := 0
+ for {
+ c, e := buf.ReadByte()
+ if e == bufio.EndOfFile {
+ break
+ }
+ if e != nil {
+ panic("GetBytes: "+e.String())
+ }
+ b[nb] = c;
+ nb++
+ }
+ // BUG return string(b[0:nb]) ?
+ return string(b)[0:nb]
+}
+
+// Call Read to accumulate the text of a file
+func Reads(buf *bufio.BufRead, m int) string {
+ var b [1000]byte;
+ nb := 0
+ for {
+ // BUG parens around (&b) should not be needed
+ n, e := buf.Read((&b)[nb:nb+m]);
+ nb += n
+ if e == bufio.EndOfFile {
+ break
+ }
+ }
+ // BUG 6g bug102 - out of bounds error on empty byte array -> string
+ if nb == 0 { return "" }
+ return string((&b)[0:nb])
+}
+
+func Read1(b *bufio.BufRead) string { return Reads(b, 1) }
+func Read2(b *bufio.BufRead) string { return Reads(b, 2) }
+func Read3(b *bufio.BufRead) string { return Reads(b, 3) }
+func Read4(b *bufio.BufRead) string { return Reads(b, 4) }
+func Read5(b *bufio.BufRead) string { return Reads(b, 5) }
+func Read7(b *bufio.BufRead) string { return Reads(b, 7) }
+
+var bufreaders = []*(b *bufio.BufRead) string {
+ &Read1, &Read2, &Read3, &Read4, &Read5, &Read7,
+ &ReadBytes, &ReadLines
+}
+
+var bufsizes = []int {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 23, 32, 46, 64, 93, 128, 1024, 4096
+}
+
+func TestBufRead() {
+ // work around 6g bug101
+ readmakers[0] = &NewByteReader;
+ readmakers[1] = &NewHalfByteReader;
+
+ bufreaders[0] = &Read1;
+ bufreaders[1] = &Read2;
+ bufreaders[2] = &Read3;
+ bufreaders[3] = &Read4;
+ bufreaders[4] = &Read5;
+ bufreaders[5] = &Read7;
+ bufreaders[6] = &ReadBytes;
+ bufreaders[7] = &ReadLines;
+
+ bufsizes[0] = 1;
+ bufsizes[1] = 2;
+ bufsizes[2] = 3;
+ bufsizes[3] = 4;
+ bufsizes[4] = 5;
+ bufsizes[5] = 6;
+ bufsizes[6] = 7;
+ bufsizes[7] = 8;
+ bufsizes[8] = 9;
+ bufsizes[9] = 10;
+ bufsizes[10] = 23;
+ bufsizes[11] = 32;
+ bufsizes[12] = 46;
+ bufsizes[13] = 64;
+ bufsizes[14] = 93;
+ bufsizes[15] = 128;
+ bufsizes[16] = 1024;
+ bufsizes[17] = 4096;
+
+ var texts [31]string
+ str := "";
+ all := ""
+ for i := 0; i < len(texts)-1; i++ {
+ texts[i] = str + "\n";
+ all += texts[i];
+ str += string(i%26+'a')
+ }
+ texts[len(texts)-1] = all;
+
+ // BUG 6g should not need nbr temporary (bug099)
+ nbr := NewByteReader(StringToBytes("hello world"));
+ b, e := bufio.NewBufRead(nbr);
+ if ReadBytes(b) != "hello world" { panic("hello world") }
+
+ // BUG 6g should not need nbr nor nbr1 (bug009)
+ nbr = NewByteReader(StringToBytes("hello world"));
+ nbr1 := NewRot13Reader(nbr);
+ b, e = bufio.NewBufRead(nbr1);
+ if ReadBytes(b) != "uryyb jbeyq" { panic("hello world") }
+
+ for h := 0; h < len(texts); h++ {
+ text := texts[h];
+ textbytes := StringToBytes(text)
+ for i := 0; i < len(readmakers); i++ {
+ readmaker := readmakers[i]
+ for j := 0; j < len(bufreaders); j++ {
+ bufreader := bufreaders[j]
+ for k := 0; k < len(bufsizes); k++ {
+ bufsize := bufsizes[k];
+ read := readmaker(textbytes);
+ buf, e := bufio.NewBufReadSize(read, bufsize);
+ s := bufreader(buf);
+ if s != text {
+ print("Failed: ", h, " ", i, " ", j, " ", k, " ", len(s), " ", len(text), "\n");
+ print("<", s, ">\nshould be <", text, ">\n");
+ panic("bufio result")
+ }
+ }
+ }
+ }
+ }
+}
+
+
+type WriteBuffer interface {
+ Write(p *[]byte) (int, *os.Error);
+ GetBytes() *[]byte
+}
+
+// Accumulates bytes into a byte array.
+type ByteWriter struct {
+ p *[]byte;
+ n int
+}
+
+func NewByteWriter() WriteBuffer {
+ return new(ByteWriter)
+}
+
+func (w *ByteWriter) Write(p *[]byte) (int, *os.Error) {
+ if w.p == nil {
+ w.p = new([]byte, len(p)+100)
+ } else if w.n + len(p) >= len(w.p) {
+ newp := new([]byte, len(w.p)*2 + len(p));
+ Copy(newp[0:w.n], w.p[0:w.n]);
+ w.p = newp
+ }
+ Copy(w.p[w.n:w.n+len(p)], p);
+ w.n += len(p)
+ return len(p), nil
+}
+
+func (w *ByteWriter) GetBytes() *[]byte {
+ return w.p[0:w.n]
+}
+
+// Accumulates bytes written into a byte array
+// but Write only takes half of what you give it.
+type HalfByteWriter struct {
+ bw WriteBuffer
+}
+
+func NewHalfByteWriter() WriteBuffer {
+ w := new(HalfByteWriter);
+ w.bw = NewByteWriter()
+ return w
+}
+
+func (w *HalfByteWriter) Write(p *[]byte) (int, *os.Error) {
+ n := (len(p)+1) / 2;
+ // BUG return w.bw.Write(p[0:n])
+ r, e := w.bw.Write(p[0:n])
+ return r, e
+}
+
+func (w *HalfByteWriter) GetBytes() *[]byte {
+ return w.bw.GetBytes()
+}
+
+func TestBufWrite() {
+ var data [8192]byte
+
+ var writers [2]*()WriteBuffer;
+ writers[0] = &NewByteWriter;
+ writers[1] = &NewHalfByteWriter;
+
+ for i := 0; i < len(data); i++ {
+ data[i] = byte(rand.rand())
+ }
+ for i := 0; i < len(bufsizes); i++ {
+ for j := 0; j < len(bufsizes); j++ {
+ for k := 0; k < len(writers); k++ {
+ nwrite := bufsizes[i];
+ bs := bufsizes[j];
+
+ // Write nwrite bytes using buffer size bs.
+ // Check that the right amount makes it out
+ // and that the data is correct.
+
+ write := writers[k]();
+ buf, e := bufio.NewBufWriteSize(write, bs);
+ if e != nil {
+ panic("NewBufWriteSize error: "+e.String())
+ }
+ n, e1 := buf.Write((&data)[0:nwrite])
+ if e1 != nil {
+ panic("buf.Write error "+e1.String())
+ }
+ if n != nwrite {
+ panic("buf.Write wrong count")
+ }
+ e = buf.Flush()
+ if e != nil {
+ panic("buf.Flush error "+e.String())
+ }
+
+ written := write.GetBytes();
+ if len(written) != nwrite {
+ panic("wrong amount written")
+ }
+ for l := 0; l < len(written); l++ {
+ if written[i] != data[i] {
+ panic("wrong bytes written")
+ }
+ }
+ }
+ }
+ }
+}
+
+
+func main() {
+ TestBufRead();
+ TestBufWrite()
+}