assorted cleanup and fixes
R=r
DELTA=209 (109 added, 79 deleted, 21 changed)
OCL=20930
CL=20934
diff --git a/src/lib/bufio.go b/src/lib/bufio.go
index 11813d6..77563be 100644
--- a/src/lib/bufio.go
+++ b/src/lib/bufio.go
@@ -210,7 +210,9 @@
return nil, b.err
}
if b.Buffered() == n { // no data added; end of file
- return nil, EndOfFile
+ line := b.buf[b.r:b.w];
+ b.r = b.w;
+ return line, EndOfFile
}
// Search new part of buffer
diff --git a/src/lib/fmt/print.go b/src/lib/fmt/print.go
index 12da7d6..c05067e 100644
--- a/src/lib/fmt/print.go
+++ b/src/lib/fmt/print.go
@@ -275,7 +275,7 @@
func getPtr(v reflect.Value) (val uintptr, ok bool) {
switch v.Kind() {
case reflect.PtrKind:
- return uintptr(v.(reflect.PtrValue)), true;
+ return uintptr(v.(reflect.PtrValue).Get()), true;
}
return 0, false;
}
diff --git a/src/lib/http/url.go b/src/lib/http/url.go
index 741ee0b..8df18eb 100644
--- a/src/lib/http/url.go
+++ b/src/lib/http/url.go
@@ -3,11 +3,13 @@
// license that can be found in the LICENSE file.
// Parse URLs (actually URIs, but that seems overly pedantic).
+// TODO(rsc): Add tests.
package http
import (
- "os"
+ "os";
+ "strings"
)
export var (
@@ -150,13 +152,19 @@
// Maybe path is //authority/path
if len(path) > 2 && path[0:2] == "//" {
- url.authority, path = Split(path[2:len(path)], '/', false)
+ url.authority, path = Split(path[2:len(path)], '/', false);
}
- url.userinfo, url.host = Split(url.authority, '@', true);
+
+ // If there's no @, Split's default is wrong. Check explicitly.
+ if strings.index(url.authority, "@") < 0 {
+ url.host = url.authority;
+ } else {
+ url.userinfo, url.host = Split(url.authority, '@', true);
+ }
// What's left is the path.
// TODO: Canonicalize (remove . and ..)?
- if url.path, err = URLUnescape(url.path); err != nil {
+ if url.path, err = URLUnescape(path); err != nil {
return nil, err
}
diff --git a/src/lib/net/net.go b/src/lib/net/net.go
index 5db5909..79d6488 100644
--- a/src/lib/net/net.go
+++ b/src/lib/net/net.go
@@ -359,72 +359,20 @@
// TCP connections.
export type ConnTCP struct {
- base ConnBase
+ ConnBase
}
-// New TCP methods
func (c *ConnTCP) SetNoDelay(nodelay bool) *os.Error {
if c == nil {
return os.EINVAL
}
- return setsockopt_int((&c.base).FD(), syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(nodelay))
-}
-
-// Wrappers
-func (c *ConnTCP) Read(b *[]byte) (n int, err *os.Error) {
- n, err = (&c.base).Read(b);
- return n, err
-}
-func (c *ConnTCP) Write(b *[]byte) (n int, err *os.Error) {
- n, err = (&c.base).Write(b);
- return n, err
-}
-func (c *ConnTCP) ReadFrom(b *[]byte) (n int, raddr string, err *os.Error) {
- n, raddr, err = (&c.base).ReadFrom(b);
- return n, raddr, err
-}
-func (c *ConnTCP) WriteTo(raddr string, b *[]byte) (n int, err *os.Error) {
- n, err = (&c.base).WriteTo(raddr, b);
- return n, err
-}
-func (c *ConnTCP) Close() *os.Error {
- return (&c.base).Close()
-}
-func (c *ConnTCP) SetReadBuffer(bytes int) *os.Error {
- return (&c.base).SetReadBuffer(bytes)
-}
-func (c *ConnTCP) SetWriteBuffer(bytes int) *os.Error {
- return (&c.base).SetWriteBuffer(bytes)
-}
-func (c *ConnTCP) SetTimeout(nsec int64) *os.Error {
- return (&c.base).SetTimeout(nsec)
-}
-func (c *ConnTCP) SetReadTimeout(nsec int64) *os.Error {
- return (&c.base).SetReadTimeout(nsec)
-}
-func (c *ConnTCP) SetWriteTimeout(nsec int64) *os.Error {
- return (&c.base).SetWriteTimeout(nsec)
-}
-func (c *ConnTCP) SetLinger(sec int) *os.Error {
- return (&c.base).SetLinger(sec)
-}
-func (c *ConnTCP) SetReuseAddr(reuseaddr bool) *os.Error {
- return (&c.base).SetReuseAddr(reuseaddr)
-}
-func (c *ConnTCP) BindToDevice(dev string) *os.Error {
- return (&c.base).BindToDevice(dev)
-}
-func (c *ConnTCP) SetDontRoute(dontroute bool) *os.Error {
- return (&c.base).SetDontRoute(dontroute)
-}
-func (c *ConnTCP) SetKeepAlive(keepalive bool) *os.Error {
- return (&c.base).SetKeepAlive(keepalive)
+ return setsockopt_int(c.FD(), syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(nodelay))
}
func NewConnTCP(fd *FD, raddr string) *ConnTCP {
c := new(ConnTCP);
- c.base.fd = fd;
- c.base.raddr = raddr;
+ c.fd = fd;
+ c.raddr = raddr;
c.SetNoDelay(true);
return c
}
@@ -441,7 +389,31 @@
}
-// TODO: UDP connections
+// UDP connections.
+
+// TODO(rsc): UDP headers mode
+
+export type ConnUDP struct {
+ ConnBase
+}
+
+func NewConnUDP(fd *FD, raddr string) *ConnUDP {
+ c := new(ConnUDP);
+ c.fd = fd;
+ c.raddr = raddr;
+ return c
+}
+
+export func DialUDP(net, laddr, raddr string) (c *ConnUDP, err *os.Error) {
+ if raddr == "" {
+ return nil, MissingAddress
+ }
+ fd, e := InternetSocket(net, laddr, raddr, syscall.SOCK_DGRAM);
+ if e != nil {
+ return nil, e
+ }
+ return NewConnUDP(fd, raddr), nil
+}
// TODO: raw IP connections
@@ -468,24 +440,6 @@
BindToDevice(dev string) *os.Error;
}
-type NoConn struct { unused int }
-func (c *NoConn) Read(b *[]byte) (n int, err *os.Error) { return -1, os.EINVAL }
-func (c *NoConn) Write(b *[]byte) (n int, err *os.Error) { return -1, os.EINVAL }
-func (c *NoConn) ReadFrom(b *[]byte) (n int, addr string, err *os.Error) { return -1, "", os.EINVAL }
-func (c *NoConn) WriteTo(addr string, b *[]byte) (n int, err *os.Error) { return -1, os.EINVAL }
-func (c *NoConn) Close() *os.Error { return nil }
-func (c *NoConn) SetReadBuffer(bytes int) *os.Error { return os.EINVAL }
-func (c *NoConn) SetWriteBuffer(bytes int) *os.Error { return os.EINVAL }
-func (c *NoConn) SetTimeout(nsec int64) *os.Error { return os.EINVAL }
-func (c *NoConn) SetReadTimeout(nsec int64) *os.Error { return os.EINVAL }
-func (c *NoConn) SetWriteTimeout(nsec int64) *os.Error { return os.EINVAL }
-func (c *NoConn) SetLinger(sec int) *os.Error { return os.EINVAL }
-func (c *NoConn) SetReuseAddr(reuseaddr bool) *os.Error { return os.EINVAL }
-func (c *NoConn) SetDontRoute(dontroute bool) *os.Error { return os.EINVAL }
-func (c *NoConn) SetKeepAlive(keepalive bool) *os.Error { return os.EINVAL }
-func (c *NoConn) BindToDevice(dev string) *os.Error { return os.EINVAL }
-
-var noconn NoConn
// Dial's arguments are the network, local address, and remote address.
// Examples:
@@ -501,13 +455,13 @@
case "tcp", "tcp4", "tcp6":
c, err := DialTCP(net, laddr, raddr);
if err != nil {
- return &noconn, err
+ return nil, err
}
return c, nil;
-/*
case "udp", "udp4", "upd6":
c, err := DialUDP(net, laddr, raddr);
return c, err;
+/*
case "ether":
c, err := DialEther(net, laddr, raddr);
return c, err;
@@ -528,14 +482,6 @@
Close() *os.Error;
}
-type NoListener struct { unused int }
-func (l *NoListener) Accept() (c Conn, raddr string, err *os.Error) {
- return &noconn, "", os.EINVAL
-}
-func (l *NoListener) Close() *os.Error { return os.EINVAL }
-
-var nolistener NoListener
-
export type ListenerTCP struct {
fd *FD;
laddr string
@@ -576,7 +522,7 @@
func (l *ListenerTCP) Accept() (c Conn, raddr string, err *os.Error) {
c1, r1, e1 := l.AcceptTCP();
if e1 != nil {
- return &noconn, "", e1
+ return nil, "", e1
}
return c1, r1, nil
}
@@ -593,7 +539,7 @@
case "tcp", "tcp4", "tcp6":
l, err := ListenTCP(net, laddr);
if err != nil {
- return &nolistener, err
+ return nil, err
}
return l, nil
/*
diff --git a/src/lib/reflect/all_test.go b/src/lib/reflect/all_test.go
index a6ac1a7..bb851d4 100644
--- a/src/lib/reflect/all_test.go
+++ b/src/lib/reflect/all_test.go
@@ -294,3 +294,36 @@
v3 := reflect.NewValue(i2);
assert(v3.Type().String(), "float");
}
+
+export func TestCopyArray(t *testing.T) {
+ a := &[]int{ 1, 2, 3, 4, 10, 9, 8, 7 };
+ b := &[]int{ 11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44 };
+ c := &[]int{ 11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44 };
+ va := NewValue(a);
+ vb := NewValue(b);
+ for i := 0; i < len(b); i++ {
+ if b[i] != c[i] {
+ t.Fatalf("b != c before test");
+ }
+ }
+ for tocopy := 5; tocopy <= 6; tocopy++ {
+ CopyArray(vb.(PtrValue).Sub(), va.(PtrValue).Sub(), tocopy);
+ for i := 0; i < tocopy; i++ {
+ if a[i] != b[i] {
+ t.Errorf("tocopy=%d a[%d]=%d, b[%d]=%d",
+ tocopy, i, a[i], i, b[i]);
+ }
+ }
+ for i := tocopy; i < len(b); i++ {
+ if b[i] != c[i] {
+ if i < len(a) {
+ t.Errorf("tocopy=%d a[%d]=%d, b[%d]=%d, c[%d]=%d",
+ tocopy, i, a[i], i, b[i], i, c[i]);
+ } else {
+ t.Errorf("tocopy=%d b[%d]=%d, c[%d]=%d",
+ tocopy, i, b[i], i, c[i]);
+ }
+ }
+ }
+ }
+}
diff --git a/src/lib/reflect/value.go b/src/lib/reflect/value.go
index 0457080..1b6ec31 100644
--- a/src/lib/reflect/value.go
+++ b/src/lib/reflect/value.go
@@ -14,6 +14,10 @@
type Addr unsafe.pointer // TODO: where are ptrint/intptr etc?
+func EqualType(a, b Type) bool {
+ return a.String() == b.String()
+}
+
export type Value interface {
Kind() int;
Type() Type;
@@ -490,11 +494,12 @@
return NewValueAddr(v.typ.(PtrType).Sub(), v.Get());
}
-func (v *PtrValueStruct) SetSub(subv Value) {
- a := v.typ.(PtrType).Sub().String();
- b := subv.Type().String();
- if a != b {
- panicln("reflect: incompatible types in PtrValue.SetSub:", a, b);
+func (v *PtrValueStruct) SetSub(subv Value) {
+ a := v.typ.(PtrType).Sub();
+ b := subv.Type();
+ if !EqualType(a, b) {
+ panicln("reflect: incompatible types in PtrValue.SetSub:",
+ a.String(), b.String());
}
*v.addr.(*Addr) = subv.Addr();
}
@@ -806,6 +811,38 @@
return NewValueAddr(typ, Addr(array));
}
+export func CopyArray(dst ArrayValue, src ArrayValue, n int) {
+ if n == 0 {
+ return
+ }
+ dt := dst.Type().(ArrayType).Elem();
+ st := src.Type().(ArrayType).Elem();
+ if !EqualType(dt, st) {
+ panicln("reflect: incompatible types in CopyArray:",
+ dt.String(), st.String());
+ }
+ if n < 0 || n > dst.Len() || n > src.Len() {
+ panicln("reflect: CopyArray: invalid count", n);
+ }
+ dstp := uintptr(dst.Elem(0).Addr());
+ srcp := uintptr(src.Elem(0).Addr());
+ end := uintptr(n)*uintptr(dt.Size());
+ if dst.Type().Size() % 8 == 0 {
+ for i := uintptr(0); i < end; i += 8{
+ di := Addr(dstp + i);
+ si := Addr(srcp + i);
+ *di.(*uint64) = *si.(*uint64);
+ }
+ } else {
+ for i := uintptr(0); i < end; i++ {
+ di := Addr(dstp + i);
+ si := Addr(srcp + i);
+ *di.(*byte) = *si.(*byte);
+ }
+ }
+}
+
+
export func NewValue(e interface {}) Value {
value, typestring := sys.reflect(e);
p, ok := typecache[typestring];
diff --git a/src/lib/strconv/quote.go b/src/lib/strconv/quote.go
index 122af92..36fa195 100644
--- a/src/lib/strconv/quote.go
+++ b/src/lib/strconv/quote.go
@@ -36,6 +36,9 @@
case s[i] == '\v':
t += `\v`;
+ case s[i] < utf8.RuneSelf:
+ t += `\x` + string(ldigits[s[i]>>4]) + string(ldigits[s[i]&0xF]);
+
case utf8.FullRuneInString(s, i):
r, size := utf8.DecodeRuneInString(s, i);
if r == utf8.RuneError && size == 1 {
diff --git a/src/lib/strconv/quote_test.go b/src/lib/strconv/quote_test.go
index 2c0e98e..a5df94b 100644
--- a/src/lib/strconv/quote_test.go
+++ b/src/lib/strconv/quote_test.go
@@ -20,6 +20,7 @@
QuoteTest{ "abc\xffdef", `"abc\xffdef"` },
QuoteTest{ "\u263a", `"\u263a"` },
QuoteTest{ "\U0010ffff", `"\U0010ffff"` },
+ QuoteTest{ "\x04", `"\x04"` },
}
export func TestQuote(t *testing.T) {