mirror of
https://github.com/golang/go.git
synced 2025-05-22 16:09:37 +00:00
1) Change default gofmt default settings for
parsing and printing to new syntax. Use -oldparser to parse the old syntax, use -oldprinter to print the old syntax. 2) Change default gofmt formatting settings to use tabs for indentation only and to use spaces for alignment. This will make the code alignment insensitive to an editor's tabwidth. Use -spaces=false to use tabs for alignment. 3) Manually changed src/exp/parser/parser_test.go so that it doesn't try to parse the parser's source files using the old syntax (they have new syntax now). 4) gofmt -w src misc test/bench 4th set of files. R=rsc CC=golang-dev https://golang.org/cl/180049
This commit is contained in:
parent
a3d1045fb7
commit
d65a5cce89
@ -9,8 +9,8 @@ package once
|
|||||||
import "sync"
|
import "sync"
|
||||||
|
|
||||||
type job struct {
|
type job struct {
|
||||||
done bool;
|
done bool
|
||||||
sync.Mutex; // should probably be sync.Notification or some such
|
sync.Mutex // should probably be sync.Notification or some such
|
||||||
}
|
}
|
||||||
|
|
||||||
var jobs = make(map[func()]*job)
|
var jobs = make(map[func()]*job)
|
||||||
@ -37,23 +37,23 @@ var joblock sync.Mutex
|
|||||||
// because the func() expression in the first creates a new
|
// because the func() expression in the first creates a new
|
||||||
// func each time f runs, and each of those funcs is run once.
|
// func each time f runs, and each of those funcs is run once.
|
||||||
func Do(f func()) {
|
func Do(f func()) {
|
||||||
joblock.Lock();
|
joblock.Lock()
|
||||||
j, present := jobs[f];
|
j, present := jobs[f]
|
||||||
if !present {
|
if !present {
|
||||||
// run it
|
// run it
|
||||||
j = new(job);
|
j = new(job)
|
||||||
j.Lock();
|
j.Lock()
|
||||||
jobs[f] = j;
|
jobs[f] = j
|
||||||
joblock.Unlock();
|
joblock.Unlock()
|
||||||
f();
|
f()
|
||||||
j.done = true;
|
j.done = true
|
||||||
j.Unlock();
|
j.Unlock()
|
||||||
} else {
|
} else {
|
||||||
// wait for it
|
// wait for it
|
||||||
joblock.Unlock();
|
joblock.Unlock()
|
||||||
if j.done != true {
|
if j.done != true {
|
||||||
j.Lock();
|
j.Lock()
|
||||||
j.Unlock();
|
j.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
package once_test
|
package once_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"once";
|
"once"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ncall int
|
var ncall int
|
||||||
@ -14,16 +14,16 @@ var ncall int
|
|||||||
func call() { ncall++ }
|
func call() { ncall++ }
|
||||||
|
|
||||||
func TestDo(t *testing.T) {
|
func TestDo(t *testing.T) {
|
||||||
ncall = 0;
|
ncall = 0
|
||||||
once.Do(call);
|
once.Do(call)
|
||||||
if ncall != 1 {
|
if ncall != 1 {
|
||||||
t.Fatalf("once.Do(call) didn't call(): ncall=%d", ncall)
|
t.Fatalf("once.Do(call) didn't call(): ncall=%d", ncall)
|
||||||
}
|
}
|
||||||
once.Do(call);
|
once.Do(call)
|
||||||
if ncall != 1 {
|
if ncall != 1 {
|
||||||
t.Fatalf("second once.Do(call) did call(): ncall=%d", ncall)
|
t.Fatalf("second once.Do(call) did call(): ncall=%d", ncall)
|
||||||
}
|
}
|
||||||
once.Do(call);
|
once.Do(call)
|
||||||
if ncall != 1 {
|
if ncall != 1 {
|
||||||
t.Fatalf("third once.Do(call) did call(): ncall=%d", ncall)
|
t.Fatalf("third once.Do(call) did call(): ncall=%d", ncall)
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
package os
|
package os
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall";
|
"syscall"
|
||||||
"unsafe";
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
blockSize = 4096; // TODO(r): use statfs
|
blockSize = 4096 // TODO(r): use statfs
|
||||||
)
|
)
|
||||||
|
|
||||||
// Readdirnames reads the contents of the directory associated with file and
|
// Readdirnames reads the contents of the directory associated with file and
|
||||||
@ -21,27 +21,27 @@ const (
|
|||||||
func (file *File) Readdirnames(count int) (names []string, err Error) {
|
func (file *File) Readdirnames(count int) (names []string, err Error) {
|
||||||
// If this file has no dirinfo, create one.
|
// If this file has no dirinfo, create one.
|
||||||
if file.dirinfo == nil {
|
if file.dirinfo == nil {
|
||||||
file.dirinfo = new(dirInfo);
|
file.dirinfo = new(dirInfo)
|
||||||
// The buffer must be at least a block long.
|
// The buffer must be at least a block long.
|
||||||
// TODO(r): use fstatfs to find fs block size.
|
// TODO(r): use fstatfs to find fs block size.
|
||||||
file.dirinfo.buf = make([]byte, blockSize);
|
file.dirinfo.buf = make([]byte, blockSize)
|
||||||
}
|
}
|
||||||
d := file.dirinfo;
|
d := file.dirinfo
|
||||||
size := count;
|
size := count
|
||||||
if size < 0 {
|
if size < 0 {
|
||||||
size = 100
|
size = 100
|
||||||
}
|
}
|
||||||
names = make([]string, 0, size); // Empty with room to grow.
|
names = make([]string, 0, size) // Empty with room to grow.
|
||||||
for count != 0 {
|
for count != 0 {
|
||||||
// Refill the buffer if necessary
|
// Refill the buffer if necessary
|
||||||
if d.bufp >= d.nbuf {
|
if d.bufp >= d.nbuf {
|
||||||
var errno int;
|
var errno int
|
||||||
d.bufp = 0;
|
d.bufp = 0
|
||||||
// Final argument is (basep *uintptr) and the syscall doesn't take nil.
|
// Final argument is (basep *uintptr) and the syscall doesn't take nil.
|
||||||
d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, new(uintptr));
|
d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, new(uintptr))
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
d.nbuf = 0;
|
d.nbuf = 0
|
||||||
return names, NewSyscallError("getdirentries", errno);
|
return names, NewSyscallError("getdirentries", errno)
|
||||||
}
|
}
|
||||||
if d.nbuf <= 0 {
|
if d.nbuf <= 0 {
|
||||||
break // EOF
|
break // EOF
|
||||||
@ -49,31 +49,31 @@ func (file *File) Readdirnames(count int) (names []string, err Error) {
|
|||||||
}
|
}
|
||||||
// Drain the buffer
|
// Drain the buffer
|
||||||
for count != 0 && d.bufp < d.nbuf {
|
for count != 0 && d.bufp < d.nbuf {
|
||||||
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]));
|
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]))
|
||||||
if dirent.Reclen == 0 {
|
if dirent.Reclen == 0 {
|
||||||
d.bufp = d.nbuf;
|
d.bufp = d.nbuf
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
d.bufp += int(dirent.Reclen);
|
d.bufp += int(dirent.Reclen)
|
||||||
if dirent.Ino == 0 { // File absent in directory.
|
if dirent.Ino == 0 { // File absent in directory.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]));
|
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]))
|
||||||
var name = string(bytes[0:dirent.Namlen]);
|
var name = string(bytes[0:dirent.Namlen])
|
||||||
if name == "." || name == ".." { // Useless names
|
if name == "." || name == ".." { // Useless names
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
count--;
|
count--
|
||||||
if len(names) == cap(names) {
|
if len(names) == cap(names) {
|
||||||
nnames := make([]string, len(names), 2*len(names));
|
nnames := make([]string, len(names), 2*len(names))
|
||||||
for i := 0; i < len(names); i++ {
|
for i := 0; i < len(names); i++ {
|
||||||
nnames[i] = names[i]
|
nnames[i] = names[i]
|
||||||
}
|
}
|
||||||
names = nnames;
|
names = nnames
|
||||||
}
|
}
|
||||||
names = names[0 : len(names)+1];
|
names = names[0 : len(names)+1]
|
||||||
names[len(names)-1] = name;
|
names[len(names)-1] = name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return names, nil;
|
return names, nil
|
||||||
}
|
}
|
||||||
|
@ -5,38 +5,38 @@
|
|||||||
package os
|
package os
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall";
|
"syscall"
|
||||||
"unsafe";
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
blockSize = 4096; // TODO(r): use statfs
|
blockSize = 4096 // TODO(r): use statfs
|
||||||
)
|
)
|
||||||
|
|
||||||
func (file *File) Readdirnames(count int) (names []string, err Error) {
|
func (file *File) Readdirnames(count int) (names []string, err Error) {
|
||||||
// If this file has no dirinfo, create one.
|
// If this file has no dirinfo, create one.
|
||||||
if file.dirinfo == nil {
|
if file.dirinfo == nil {
|
||||||
file.dirinfo = new(dirInfo);
|
file.dirinfo = new(dirInfo)
|
||||||
// The buffer must be at least a block long.
|
// The buffer must be at least a block long.
|
||||||
// TODO(r): use fstatfs to find fs block size.
|
// TODO(r): use fstatfs to find fs block size.
|
||||||
file.dirinfo.buf = make([]byte, blockSize);
|
file.dirinfo.buf = make([]byte, blockSize)
|
||||||
}
|
}
|
||||||
d := file.dirinfo;
|
d := file.dirinfo
|
||||||
size := count;
|
size := count
|
||||||
if size < 0 {
|
if size < 0 {
|
||||||
size = 100
|
size = 100
|
||||||
}
|
}
|
||||||
names = make([]string, 0, size); // Empty with room to grow.
|
names = make([]string, 0, size) // Empty with room to grow.
|
||||||
for count != 0 {
|
for count != 0 {
|
||||||
// Refill the buffer if necessary
|
// Refill the buffer if necessary
|
||||||
if d.bufp >= d.nbuf {
|
if d.bufp >= d.nbuf {
|
||||||
var errno int;
|
var errno int
|
||||||
d.bufp = 0;
|
d.bufp = 0
|
||||||
// Final argument is (basep *uintptr) and the syscall doesn't take nil.
|
// Final argument is (basep *uintptr) and the syscall doesn't take nil.
|
||||||
d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, new(uintptr));
|
d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, new(uintptr))
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
d.nbuf = 0;
|
d.nbuf = 0
|
||||||
return names, NewSyscallError("getdirentries", errno);
|
return names, NewSyscallError("getdirentries", errno)
|
||||||
}
|
}
|
||||||
if d.nbuf <= 0 {
|
if d.nbuf <= 0 {
|
||||||
break // EOF
|
break // EOF
|
||||||
@ -44,31 +44,31 @@ func (file *File) Readdirnames(count int) (names []string, err Error) {
|
|||||||
}
|
}
|
||||||
// Drain the buffer
|
// Drain the buffer
|
||||||
for count != 0 && d.bufp < d.nbuf {
|
for count != 0 && d.bufp < d.nbuf {
|
||||||
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]));
|
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]))
|
||||||
if dirent.Reclen == 0 {
|
if dirent.Reclen == 0 {
|
||||||
d.bufp = d.nbuf;
|
d.bufp = d.nbuf
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
d.bufp += int(dirent.Reclen);
|
d.bufp += int(dirent.Reclen)
|
||||||
if dirent.Fileno == 0 { // File absent in directory.
|
if dirent.Fileno == 0 { // File absent in directory.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]));
|
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]))
|
||||||
var name = string(bytes[0:dirent.Namlen]);
|
var name = string(bytes[0:dirent.Namlen])
|
||||||
if name == "." || name == ".." { // Useless names
|
if name == "." || name == ".." { // Useless names
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
count--;
|
count--
|
||||||
if len(names) == cap(names) {
|
if len(names) == cap(names) {
|
||||||
nnames := make([]string, len(names), 2*len(names));
|
nnames := make([]string, len(names), 2*len(names))
|
||||||
for i := 0; i < len(names); i++ {
|
for i := 0; i < len(names); i++ {
|
||||||
nnames[i] = names[i]
|
nnames[i] = names[i]
|
||||||
}
|
}
|
||||||
names = nnames;
|
names = nnames
|
||||||
}
|
}
|
||||||
names = names[0 : len(names)+1];
|
names = names[0 : len(names)+1]
|
||||||
names[len(names)-1] = name;
|
names[len(names)-1] = name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return names, nil;
|
return names, nil
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
package os
|
package os
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall";
|
"syscall"
|
||||||
"unsafe";
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
blockSize = 4096; // TODO(r): use statfs
|
blockSize = 4096 // TODO(r): use statfs
|
||||||
)
|
)
|
||||||
|
|
||||||
func clen(n []byte) int {
|
func clen(n []byte) int {
|
||||||
@ -19,59 +19,59 @@ func clen(n []byte) int {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return len(n);
|
return len(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (file *File) Readdirnames(count int) (names []string, err Error) {
|
func (file *File) Readdirnames(count int) (names []string, err Error) {
|
||||||
// If this file has no dirinfo, create one.
|
// If this file has no dirinfo, create one.
|
||||||
if file.dirinfo == nil {
|
if file.dirinfo == nil {
|
||||||
file.dirinfo = new(dirInfo);
|
file.dirinfo = new(dirInfo)
|
||||||
// The buffer must be at least a block long.
|
// The buffer must be at least a block long.
|
||||||
// TODO(r): use fstatfs to find fs block size.
|
// TODO(r): use fstatfs to find fs block size.
|
||||||
file.dirinfo.buf = make([]byte, blockSize);
|
file.dirinfo.buf = make([]byte, blockSize)
|
||||||
}
|
}
|
||||||
d := file.dirinfo;
|
d := file.dirinfo
|
||||||
size := count;
|
size := count
|
||||||
if size < 0 {
|
if size < 0 {
|
||||||
size = 100
|
size = 100
|
||||||
}
|
}
|
||||||
names = make([]string, 0, size); // Empty with room to grow.
|
names = make([]string, 0, size) // Empty with room to grow.
|
||||||
for count != 0 {
|
for count != 0 {
|
||||||
// Refill the buffer if necessary
|
// Refill the buffer if necessary
|
||||||
if d.bufp >= d.nbuf {
|
if d.bufp >= d.nbuf {
|
||||||
var errno int;
|
var errno int
|
||||||
d.nbuf, errno = syscall.Getdents(file.fd, d.buf);
|
d.nbuf, errno = syscall.Getdents(file.fd, d.buf)
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return names, NewSyscallError("getdents", errno)
|
return names, NewSyscallError("getdents", errno)
|
||||||
}
|
}
|
||||||
if d.nbuf <= 0 {
|
if d.nbuf <= 0 {
|
||||||
break // EOF
|
break // EOF
|
||||||
}
|
}
|
||||||
d.bufp = 0;
|
d.bufp = 0
|
||||||
}
|
}
|
||||||
// Drain the buffer
|
// Drain the buffer
|
||||||
for count != 0 && d.bufp < d.nbuf {
|
for count != 0 && d.bufp < d.nbuf {
|
||||||
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]));
|
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]))
|
||||||
d.bufp += int(dirent.Reclen);
|
d.bufp += int(dirent.Reclen)
|
||||||
if dirent.Ino == 0 { // File absent in directory.
|
if dirent.Ino == 0 { // File absent in directory.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]));
|
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]))
|
||||||
var name = string(bytes[0:clen(bytes)]);
|
var name = string(bytes[0:clen(bytes)])
|
||||||
if name == "." || name == ".." { // Useless names
|
if name == "." || name == ".." { // Useless names
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
count--;
|
count--
|
||||||
if len(names) == cap(names) {
|
if len(names) == cap(names) {
|
||||||
nnames := make([]string, len(names), 2*len(names));
|
nnames := make([]string, len(names), 2*len(names))
|
||||||
for i := 0; i < len(names); i++ {
|
for i := 0; i < len(names); i++ {
|
||||||
nnames[i] = names[i]
|
nnames[i] = names[i]
|
||||||
}
|
}
|
||||||
names = nnames;
|
names = nnames
|
||||||
}
|
}
|
||||||
names = names[0 : len(names)+1];
|
names = names[0 : len(names)+1]
|
||||||
names[len(names)-1] = name;
|
names[len(names)-1] = name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return names, nil;
|
return names, nil
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
package os
|
package os
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall";
|
"syscall"
|
||||||
"unsafe";
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
blockSize = 4096; // TODO(r): use statfs
|
blockSize = 4096 // TODO(r): use statfs
|
||||||
)
|
)
|
||||||
|
|
||||||
func clen(n []byte) int {
|
func clen(n []byte) int {
|
||||||
@ -19,59 +19,59 @@ func clen(n []byte) int {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return len(n);
|
return len(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (file *File) Readdirnames(count int) (names []string, err Error) {
|
func (file *File) Readdirnames(count int) (names []string, err Error) {
|
||||||
// If this file has no dirinfo, create one.
|
// If this file has no dirinfo, create one.
|
||||||
if file.dirinfo == nil {
|
if file.dirinfo == nil {
|
||||||
file.dirinfo = new(dirInfo);
|
file.dirinfo = new(dirInfo)
|
||||||
// The buffer must be at least a block long.
|
// The buffer must be at least a block long.
|
||||||
// TODO(r): use fstatfs to find fs block size.
|
// TODO(r): use fstatfs to find fs block size.
|
||||||
file.dirinfo.buf = make([]byte, blockSize);
|
file.dirinfo.buf = make([]byte, blockSize)
|
||||||
}
|
}
|
||||||
d := file.dirinfo;
|
d := file.dirinfo
|
||||||
size := count;
|
size := count
|
||||||
if size < 0 {
|
if size < 0 {
|
||||||
size = 100
|
size = 100
|
||||||
}
|
}
|
||||||
names = make([]string, 0, size); // Empty with room to grow.
|
names = make([]string, 0, size) // Empty with room to grow.
|
||||||
for count != 0 {
|
for count != 0 {
|
||||||
// Refill the buffer if necessary
|
// Refill the buffer if necessary
|
||||||
if d.bufp >= d.nbuf {
|
if d.bufp >= d.nbuf {
|
||||||
var errno int;
|
var errno int
|
||||||
d.nbuf, errno = syscall.Getdents(file.fd, d.buf);
|
d.nbuf, errno = syscall.Getdents(file.fd, d.buf)
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return names, NewSyscallError("getdents", errno)
|
return names, NewSyscallError("getdents", errno)
|
||||||
}
|
}
|
||||||
if d.nbuf <= 0 {
|
if d.nbuf <= 0 {
|
||||||
break // EOF
|
break // EOF
|
||||||
}
|
}
|
||||||
d.bufp = 0;
|
d.bufp = 0
|
||||||
}
|
}
|
||||||
// Drain the buffer
|
// Drain the buffer
|
||||||
for count != 0 && d.bufp < d.nbuf {
|
for count != 0 && d.bufp < d.nbuf {
|
||||||
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]));
|
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]))
|
||||||
d.bufp += int(dirent.Reclen);
|
d.bufp += int(dirent.Reclen)
|
||||||
if dirent.Ino == 0 { // File absent in directory.
|
if dirent.Ino == 0 { // File absent in directory.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]));
|
bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0]))
|
||||||
var name = string(bytes[0:clen(bytes)]);
|
var name = string(bytes[0:clen(bytes)])
|
||||||
if name == "." || name == ".." { // Useless names
|
if name == "." || name == ".." { // Useless names
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
count--;
|
count--
|
||||||
if len(names) == cap(names) {
|
if len(names) == cap(names) {
|
||||||
nnames := make([]string, len(names), 2*len(names));
|
nnames := make([]string, len(names), 2*len(names))
|
||||||
for i := 0; i < len(names); i++ {
|
for i := 0; i < len(names); i++ {
|
||||||
nnames[i] = names[i]
|
nnames[i] = names[i]
|
||||||
}
|
}
|
||||||
names = nnames;
|
names = nnames
|
||||||
}
|
}
|
||||||
names = names[0 : len(names)+1];
|
names = names[0 : len(names)+1]
|
||||||
names[len(names)-1] = name;
|
names[len(names)-1] = name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return names, nil;
|
return names, nil
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
package os
|
package os
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"once";
|
"once"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ENOENV is the Error indicating that an environment variable does not exist.
|
// ENOENV is the Error indicating that an environment variable does not exist.
|
||||||
@ -17,12 +17,12 @@ var env map[string]string
|
|||||||
|
|
||||||
|
|
||||||
func copyenv() {
|
func copyenv() {
|
||||||
env = make(map[string]string);
|
env = make(map[string]string)
|
||||||
for _, s := range Envs {
|
for _, s := range Envs {
|
||||||
for j := 0; j < len(s); j++ {
|
for j := 0; j < len(s); j++ {
|
||||||
if s[j] == '=' {
|
if s[j] == '=' {
|
||||||
env[s[0:j]] = s[j+1:];
|
env[s[0:j]] = s[j+1:]
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -31,56 +31,56 @@ func copyenv() {
|
|||||||
// Getenverror retrieves the value of the environment variable named by the key.
|
// Getenverror retrieves the value of the environment variable named by the key.
|
||||||
// It returns the value and an error, if any.
|
// It returns the value and an error, if any.
|
||||||
func Getenverror(key string) (value string, err Error) {
|
func Getenverror(key string) (value string, err Error) {
|
||||||
once.Do(copyenv);
|
once.Do(copyenv)
|
||||||
|
|
||||||
if len(key) == 0 {
|
if len(key) == 0 {
|
||||||
return "", EINVAL
|
return "", EINVAL
|
||||||
}
|
}
|
||||||
v, ok := env[key];
|
v, ok := env[key]
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", ENOENV
|
return "", ENOENV
|
||||||
}
|
}
|
||||||
return v, nil;
|
return v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getenv retrieves the value of the environment variable named by the key.
|
// Getenv retrieves the value of the environment variable named by the key.
|
||||||
// It returns the value, which will be empty if the variable is not present.
|
// It returns the value, which will be empty if the variable is not present.
|
||||||
func Getenv(key string) string {
|
func Getenv(key string) string {
|
||||||
v, _ := Getenverror(key);
|
v, _ := Getenverror(key)
|
||||||
return v;
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setenv sets the value of the environment variable named by the key.
|
// Setenv sets the value of the environment variable named by the key.
|
||||||
// It returns an Error, if any.
|
// It returns an Error, if any.
|
||||||
func Setenv(key, value string) Error {
|
func Setenv(key, value string) Error {
|
||||||
once.Do(copyenv);
|
once.Do(copyenv)
|
||||||
|
|
||||||
if len(key) == 0 {
|
if len(key) == 0 {
|
||||||
return EINVAL
|
return EINVAL
|
||||||
}
|
}
|
||||||
env[key] = value;
|
env[key] = value
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clearenv deletes all environment variables.
|
// Clearenv deletes all environment variables.
|
||||||
func Clearenv() {
|
func Clearenv() {
|
||||||
once.Do(copyenv); // prevent copyenv in Getenv/Setenv
|
once.Do(copyenv) // prevent copyenv in Getenv/Setenv
|
||||||
env = make(map[string]string);
|
env = make(map[string]string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Environ returns an array of strings representing the environment,
|
// Environ returns an array of strings representing the environment,
|
||||||
// in the form "key=value".
|
// in the form "key=value".
|
||||||
func Environ() []string {
|
func Environ() []string {
|
||||||
once.Do(copyenv);
|
once.Do(copyenv)
|
||||||
a := make([]string, len(env));
|
a := make([]string, len(env))
|
||||||
i := 0;
|
i := 0
|
||||||
for k, v := range env {
|
for k, v := range env {
|
||||||
// check i < len(a) for safety,
|
// check i < len(a) for safety,
|
||||||
// in case env is changing underfoot.
|
// in case env is changing underfoot.
|
||||||
if i < len(a) {
|
if i < len(a) {
|
||||||
a[i] = k + "=" + v;
|
a[i] = k + "=" + v
|
||||||
i++;
|
i++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return a[0:i];
|
return a[0:i]
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import syscall "syscall"
|
|||||||
|
|
||||||
// An Error can represent any printable error condition.
|
// An Error can represent any printable error condition.
|
||||||
type Error interface {
|
type Error interface {
|
||||||
String() string;
|
String() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// A helper type that can be embedded or wrapped to simplify satisfying
|
// A helper type that can be embedded or wrapped to simplify satisfying
|
||||||
@ -32,58 +32,58 @@ func (e Errno) String() string { return syscall.Errstr(int(e)) }
|
|||||||
|
|
||||||
// Commonly known Unix errors.
|
// Commonly known Unix errors.
|
||||||
var (
|
var (
|
||||||
EPERM Error = Errno(syscall.EPERM);
|
EPERM Error = Errno(syscall.EPERM)
|
||||||
ENOENT Error = Errno(syscall.ENOENT);
|
ENOENT Error = Errno(syscall.ENOENT)
|
||||||
ESRCH Error = Errno(syscall.ESRCH);
|
ESRCH Error = Errno(syscall.ESRCH)
|
||||||
EINTR Error = Errno(syscall.EINTR);
|
EINTR Error = Errno(syscall.EINTR)
|
||||||
EIO Error = Errno(syscall.EIO);
|
EIO Error = Errno(syscall.EIO)
|
||||||
ENXIO Error = Errno(syscall.ENXIO);
|
ENXIO Error = Errno(syscall.ENXIO)
|
||||||
E2BIG Error = Errno(syscall.E2BIG);
|
E2BIG Error = Errno(syscall.E2BIG)
|
||||||
ENOEXEC Error = Errno(syscall.ENOEXEC);
|
ENOEXEC Error = Errno(syscall.ENOEXEC)
|
||||||
EBADF Error = Errno(syscall.EBADF);
|
EBADF Error = Errno(syscall.EBADF)
|
||||||
ECHILD Error = Errno(syscall.ECHILD);
|
ECHILD Error = Errno(syscall.ECHILD)
|
||||||
EDEADLK Error = Errno(syscall.EDEADLK);
|
EDEADLK Error = Errno(syscall.EDEADLK)
|
||||||
ENOMEM Error = Errno(syscall.ENOMEM);
|
ENOMEM Error = Errno(syscall.ENOMEM)
|
||||||
EACCES Error = Errno(syscall.EACCES);
|
EACCES Error = Errno(syscall.EACCES)
|
||||||
EFAULT Error = Errno(syscall.EFAULT);
|
EFAULT Error = Errno(syscall.EFAULT)
|
||||||
EBUSY Error = Errno(syscall.EBUSY);
|
EBUSY Error = Errno(syscall.EBUSY)
|
||||||
EEXIST Error = Errno(syscall.EEXIST);
|
EEXIST Error = Errno(syscall.EEXIST)
|
||||||
EXDEV Error = Errno(syscall.EXDEV);
|
EXDEV Error = Errno(syscall.EXDEV)
|
||||||
ENODEV Error = Errno(syscall.ENODEV);
|
ENODEV Error = Errno(syscall.ENODEV)
|
||||||
ENOTDIR Error = Errno(syscall.ENOTDIR);
|
ENOTDIR Error = Errno(syscall.ENOTDIR)
|
||||||
EISDIR Error = Errno(syscall.EISDIR);
|
EISDIR Error = Errno(syscall.EISDIR)
|
||||||
EINVAL Error = Errno(syscall.EINVAL);
|
EINVAL Error = Errno(syscall.EINVAL)
|
||||||
ENFILE Error = Errno(syscall.ENFILE);
|
ENFILE Error = Errno(syscall.ENFILE)
|
||||||
EMFILE Error = Errno(syscall.EMFILE);
|
EMFILE Error = Errno(syscall.EMFILE)
|
||||||
ENOTTY Error = Errno(syscall.ENOTTY);
|
ENOTTY Error = Errno(syscall.ENOTTY)
|
||||||
EFBIG Error = Errno(syscall.EFBIG);
|
EFBIG Error = Errno(syscall.EFBIG)
|
||||||
ENOSPC Error = Errno(syscall.ENOSPC);
|
ENOSPC Error = Errno(syscall.ENOSPC)
|
||||||
ESPIPE Error = Errno(syscall.ESPIPE);
|
ESPIPE Error = Errno(syscall.ESPIPE)
|
||||||
EROFS Error = Errno(syscall.EROFS);
|
EROFS Error = Errno(syscall.EROFS)
|
||||||
EMLINK Error = Errno(syscall.EMLINK);
|
EMLINK Error = Errno(syscall.EMLINK)
|
||||||
EPIPE Error = Errno(syscall.EPIPE);
|
EPIPE Error = Errno(syscall.EPIPE)
|
||||||
EAGAIN Error = Errno(syscall.EAGAIN);
|
EAGAIN Error = Errno(syscall.EAGAIN)
|
||||||
EDOM Error = Errno(syscall.EDOM);
|
EDOM Error = Errno(syscall.EDOM)
|
||||||
ERANGE Error = Errno(syscall.ERANGE);
|
ERANGE Error = Errno(syscall.ERANGE)
|
||||||
EADDRINUSE Error = Errno(syscall.EADDRINUSE);
|
EADDRINUSE Error = Errno(syscall.EADDRINUSE)
|
||||||
ECONNREFUSED Error = Errno(syscall.ECONNREFUSED);
|
ECONNREFUSED Error = Errno(syscall.ECONNREFUSED)
|
||||||
ENAMETOOLONG Error = Errno(syscall.ENAMETOOLONG);
|
ENAMETOOLONG Error = Errno(syscall.ENAMETOOLONG)
|
||||||
EAFNOSUPPORT Error = Errno(syscall.EAFNOSUPPORT);
|
EAFNOSUPPORT Error = Errno(syscall.EAFNOSUPPORT)
|
||||||
)
|
)
|
||||||
|
|
||||||
// PathError records an error and the operation and file path that caused it.
|
// PathError records an error and the operation and file path that caused it.
|
||||||
type PathError struct {
|
type PathError struct {
|
||||||
Op string;
|
Op string
|
||||||
Path string;
|
Path string
|
||||||
Error Error;
|
Error Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *PathError) String() string { return e.Op + " " + e.Path + ": " + e.Error.String() }
|
func (e *PathError) String() string { return e.Op + " " + e.Path + ": " + e.Error.String() }
|
||||||
|
|
||||||
// SyscallError records an error from a specific system call.
|
// SyscallError records an error from a specific system call.
|
||||||
type SyscallError struct {
|
type SyscallError struct {
|
||||||
Syscall string;
|
Syscall string
|
||||||
Errno Errno;
|
Errno Errno
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *SyscallError) String() string { return e.Syscall + ": " + e.Errno.String() }
|
func (e *SyscallError) String() string { return e.Syscall + ": " + e.Errno.String() }
|
||||||
@ -99,5 +99,5 @@ func NewSyscallError(syscall string, errno int) Error {
|
|||||||
if errno == 0 {
|
if errno == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &SyscallError{syscall, Errno(errno)};
|
return &SyscallError{syscall, Errno(errno)}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
package os
|
package os
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall";
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ForkExec forks the current process and invokes Exec with the file, arguments,
|
// ForkExec forks the current process and invokes Exec with the file, arguments,
|
||||||
@ -17,7 +17,7 @@ import (
|
|||||||
// If dir is not empty, the child chdirs into the directory before execing the program.
|
// If dir is not empty, the child chdirs into the directory before execing the program.
|
||||||
func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*File) (pid int, err Error) {
|
func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*File) (pid int, err Error) {
|
||||||
// Create array of integer (system) fds.
|
// Create array of integer (system) fds.
|
||||||
intfd := make([]int, len(fd));
|
intfd := make([]int, len(fd))
|
||||||
for i, f := range fd {
|
for i, f := range fd {
|
||||||
if f == nil {
|
if f == nil {
|
||||||
intfd[i] = -1
|
intfd[i] = -1
|
||||||
@ -26,11 +26,11 @@ func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*File
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p, e := syscall.ForkExec(argv0, argv, envv, dir, intfd);
|
p, e := syscall.ForkExec(argv0, argv, envv, dir, intfd)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return 0, &PathError{"fork/exec", argv0, Errno(e)}
|
return 0, &PathError{"fork/exec", argv0, Errno(e)}
|
||||||
}
|
}
|
||||||
return p, nil;
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec replaces the current process with an execution of the program
|
// Exec replaces the current process with an execution of the program
|
||||||
@ -41,11 +41,11 @@ func Exec(argv0 string, argv []string, envv []string) Error {
|
|||||||
if envv == nil {
|
if envv == nil {
|
||||||
envv = Environ()
|
envv = Environ()
|
||||||
}
|
}
|
||||||
e := syscall.Exec(argv0, argv, envv);
|
e := syscall.Exec(argv0, argv, envv)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return &PathError{"exec", argv0, Errno(e)}
|
return &PathError{"exec", argv0, Errno(e)}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(rsc): Should os implement its own syscall.WaitStatus
|
// TODO(rsc): Should os implement its own syscall.WaitStatus
|
||||||
@ -57,17 +57,17 @@ func Exec(argv0 string, argv []string, envv []string) Error {
|
|||||||
|
|
||||||
// Waitmsg stores the information about an exited process as reported by Wait.
|
// Waitmsg stores the information about an exited process as reported by Wait.
|
||||||
type Waitmsg struct {
|
type Waitmsg struct {
|
||||||
Pid int; // The process's id.
|
Pid int // The process's id.
|
||||||
syscall.WaitStatus; // System-dependent status info.
|
syscall.WaitStatus // System-dependent status info.
|
||||||
Rusage *syscall.Rusage; // System-dependent resource usage info.
|
Rusage *syscall.Rusage // System-dependent resource usage info.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Options for Wait.
|
// Options for Wait.
|
||||||
const (
|
const (
|
||||||
WNOHANG = syscall.WNOHANG; // Don't wait if no process has exited.
|
WNOHANG = syscall.WNOHANG // Don't wait if no process has exited.
|
||||||
WSTOPPED = syscall.WSTOPPED; // If set, status of stopped subprocesses is also reported.
|
WSTOPPED = syscall.WSTOPPED // If set, status of stopped subprocesses is also reported.
|
||||||
WUNTRACED = WSTOPPED;
|
WUNTRACED = WSTOPPED
|
||||||
WRUSAGE = 1 << 20; // Record resource usage.
|
WRUSAGE = 1 << 20 // Record resource usage.
|
||||||
)
|
)
|
||||||
|
|
||||||
// WRUSAGE must not be too high a bit, to avoid clashing with Linux's
|
// WRUSAGE must not be too high a bit, to avoid clashing with Linux's
|
||||||
@ -78,21 +78,21 @@ const (
|
|||||||
// Waitmsg describing its status and an Error, if any. The options
|
// Waitmsg describing its status and an Error, if any. The options
|
||||||
// (WNOHANG etc.) affect the behavior of the Wait call.
|
// (WNOHANG etc.) affect the behavior of the Wait call.
|
||||||
func Wait(pid int, options int) (w *Waitmsg, err Error) {
|
func Wait(pid int, options int) (w *Waitmsg, err Error) {
|
||||||
var status syscall.WaitStatus;
|
var status syscall.WaitStatus
|
||||||
var rusage *syscall.Rusage;
|
var rusage *syscall.Rusage
|
||||||
if options&WRUSAGE != 0 {
|
if options&WRUSAGE != 0 {
|
||||||
rusage = new(syscall.Rusage);
|
rusage = new(syscall.Rusage)
|
||||||
options ^= WRUSAGE;
|
options ^= WRUSAGE
|
||||||
}
|
}
|
||||||
pid1, e := syscall.Wait4(pid, &status, options, rusage);
|
pid1, e := syscall.Wait4(pid, &status, options, rusage)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return nil, NewSyscallError("wait", e)
|
return nil, NewSyscallError("wait", e)
|
||||||
}
|
}
|
||||||
w = new(Waitmsg);
|
w = new(Waitmsg)
|
||||||
w.Pid = pid1;
|
w.Pid = pid1
|
||||||
w.WaitStatus = status;
|
w.WaitStatus = status
|
||||||
w.Rusage = rusage;
|
w.Rusage = rusage
|
||||||
return w, nil;
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert i to decimal string.
|
// Convert i to decimal string.
|
||||||
@ -101,37 +101,37 @@ func itod(i int) string {
|
|||||||
return "0"
|
return "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
u := uint64(i);
|
u := uint64(i)
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
u = -u
|
u = -u
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assemble decimal in reverse order.
|
// Assemble decimal in reverse order.
|
||||||
var b [32]byte;
|
var b [32]byte
|
||||||
bp := len(b);
|
bp := len(b)
|
||||||
for ; u > 0; u /= 10 {
|
for ; u > 0; u /= 10 {
|
||||||
bp--;
|
bp--
|
||||||
b[bp] = byte(u%10) + '0';
|
b[bp] = byte(u%10) + '0'
|
||||||
}
|
}
|
||||||
|
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
bp--;
|
bp--
|
||||||
b[bp] = '-';
|
b[bp] = '-'
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(b[bp:]);
|
return string(b[bp:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w Waitmsg) String() string {
|
func (w Waitmsg) String() string {
|
||||||
// TODO(austin) Use signal names when possible?
|
// TODO(austin) Use signal names when possible?
|
||||||
res := "";
|
res := ""
|
||||||
switch {
|
switch {
|
||||||
case w.Exited():
|
case w.Exited():
|
||||||
res = "exit status " + itod(w.ExitStatus())
|
res = "exit status " + itod(w.ExitStatus())
|
||||||
case w.Signaled():
|
case w.Signaled():
|
||||||
res = "signal " + itod(w.Signal())
|
res = "signal " + itod(w.Signal())
|
||||||
case w.Stopped():
|
case w.Stopped():
|
||||||
res = "stop signal " + itod(w.StopSignal());
|
res = "stop signal " + itod(w.StopSignal())
|
||||||
if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 {
|
if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 {
|
||||||
res += " (trap " + itod(w.TrapCause()) + ")"
|
res += " (trap " + itod(w.TrapCause()) + ")"
|
||||||
}
|
}
|
||||||
@ -141,7 +141,7 @@ func (w Waitmsg) String() string {
|
|||||||
if w.CoreDump() {
|
if w.CoreDump() {
|
||||||
res += " (core dumped)"
|
res += " (core dumped)"
|
||||||
}
|
}
|
||||||
return res;
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getpid returns the process id of the caller.
|
// Getpid returns the process id of the caller.
|
||||||
|
@ -7,22 +7,22 @@
|
|||||||
package os
|
package os
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall";
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Auxiliary information if the File describes a directory
|
// Auxiliary information if the File describes a directory
|
||||||
type dirInfo struct {
|
type dirInfo struct {
|
||||||
buf []byte; // buffer for directory I/O
|
buf []byte // buffer for directory I/O
|
||||||
nbuf int; // length of buf; return value from Getdirentries
|
nbuf int // length of buf; return value from Getdirentries
|
||||||
bufp int; // location of next record in buf.
|
bufp int // location of next record in buf.
|
||||||
}
|
}
|
||||||
|
|
||||||
// File represents an open file descriptor.
|
// File represents an open file descriptor.
|
||||||
type File struct {
|
type File struct {
|
||||||
fd int;
|
fd int
|
||||||
name string;
|
name string
|
||||||
dirinfo *dirInfo; // nil unless directory being read
|
dirinfo *dirInfo // nil unless directory being read
|
||||||
nepipe int; // number of consecutive EPIPE in Write
|
nepipe int // number of consecutive EPIPE in Write
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fd returns the integer Unix file descriptor referencing the open file.
|
// Fd returns the integer Unix file descriptor referencing the open file.
|
||||||
@ -36,40 +36,40 @@ func NewFile(fd int, name string) *File {
|
|||||||
if fd < 0 {
|
if fd < 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &File{fd, name, nil, 0};
|
return &File{fd, name, nil, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stdin, Stdout, and Stderr are open Files pointing to the standard input,
|
// Stdin, Stdout, and Stderr are open Files pointing to the standard input,
|
||||||
// standard output, and standard error file descriptors.
|
// standard output, and standard error file descriptors.
|
||||||
var (
|
var (
|
||||||
Stdin = NewFile(0, "/dev/stdin");
|
Stdin = NewFile(0, "/dev/stdin")
|
||||||
Stdout = NewFile(1, "/dev/stdout");
|
Stdout = NewFile(1, "/dev/stdout")
|
||||||
Stderr = NewFile(2, "/dev/stderr");
|
Stderr = NewFile(2, "/dev/stderr")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Flags to Open wrapping those of the underlying system. Not all flags
|
// Flags to Open wrapping those of the underlying system. Not all flags
|
||||||
// may be implemented on a given system.
|
// may be implemented on a given system.
|
||||||
const (
|
const (
|
||||||
O_RDONLY = syscall.O_RDONLY; // open the file read-only.
|
O_RDONLY = syscall.O_RDONLY // open the file read-only.
|
||||||
O_WRONLY = syscall.O_WRONLY; // open the file write-only.
|
O_WRONLY = syscall.O_WRONLY // open the file write-only.
|
||||||
O_RDWR = syscall.O_RDWR; // open the file read-write.
|
O_RDWR = syscall.O_RDWR // open the file read-write.
|
||||||
O_APPEND = syscall.O_APPEND; // open the file append-only.
|
O_APPEND = syscall.O_APPEND // open the file append-only.
|
||||||
O_ASYNC = syscall.O_ASYNC; // generate a signal when I/O is available.
|
O_ASYNC = syscall.O_ASYNC // generate a signal when I/O is available.
|
||||||
O_CREAT = syscall.O_CREAT; // create a new file if none exists.
|
O_CREAT = syscall.O_CREAT // create a new file if none exists.
|
||||||
O_EXCL = syscall.O_EXCL; // used with O_CREAT, file must not exist
|
O_EXCL = syscall.O_EXCL // used with O_CREAT, file must not exist
|
||||||
O_NOCTTY = syscall.O_NOCTTY; // do not make file the controlling tty.
|
O_NOCTTY = syscall.O_NOCTTY // do not make file the controlling tty.
|
||||||
O_NONBLOCK = syscall.O_NONBLOCK; // open in non-blocking mode.
|
O_NONBLOCK = syscall.O_NONBLOCK // open in non-blocking mode.
|
||||||
O_NDELAY = O_NONBLOCK; // synonym for O_NONBLOCK
|
O_NDELAY = O_NONBLOCK // synonym for O_NONBLOCK
|
||||||
O_SYNC = syscall.O_SYNC; // open for synchronous I/O.
|
O_SYNC = syscall.O_SYNC // open for synchronous I/O.
|
||||||
O_TRUNC = syscall.O_TRUNC; // if possible, truncate file when opened.
|
O_TRUNC = syscall.O_TRUNC // if possible, truncate file when opened.
|
||||||
O_CREATE = O_CREAT; // create a new file if none exists.
|
O_CREATE = O_CREAT // create a new file if none exists.
|
||||||
)
|
)
|
||||||
|
|
||||||
// Open opens the named file with specified flag (O_RDONLY etc.) and perm, (0666 etc.)
|
// Open opens the named file with specified flag (O_RDONLY etc.) and perm, (0666 etc.)
|
||||||
// if applicable. If successful, methods on the returned File can be used for I/O.
|
// if applicable. If successful, methods on the returned File can be used for I/O.
|
||||||
// It returns the File and an Error, if any.
|
// It returns the File and an Error, if any.
|
||||||
func Open(name string, flag int, perm int) (file *File, err Error) {
|
func Open(name string, flag int, perm int) (file *File, err Error) {
|
||||||
r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, perm);
|
r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, perm)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return nil, &PathError{"open", name, Errno(e)}
|
return nil, &PathError{"open", name, Errno(e)}
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ func Open(name string, flag int, perm int) (file *File, err Error) {
|
|||||||
syscall.CloseOnExec(r)
|
syscall.CloseOnExec(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewFile(r, name), nil;
|
return NewFile(r, name), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the File, rendering it unusable for I/O.
|
// Close closes the File, rendering it unusable for I/O.
|
||||||
@ -89,12 +89,12 @@ func (file *File) Close() Error {
|
|||||||
if file == nil {
|
if file == nil {
|
||||||
return EINVAL
|
return EINVAL
|
||||||
}
|
}
|
||||||
var err Error;
|
var err Error
|
||||||
if e := syscall.Close(file.fd); e != 0 {
|
if e := syscall.Close(file.fd); e != 0 {
|
||||||
err = &PathError{"close", file.name, Errno(e)}
|
err = &PathError{"close", file.name, Errno(e)}
|
||||||
}
|
}
|
||||||
file.fd = -1; // so it can't be closed again
|
file.fd = -1 // so it can't be closed again
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
type eofError int
|
type eofError int
|
||||||
@ -115,7 +115,7 @@ func (file *File) Read(b []byte) (n int, err Error) {
|
|||||||
if file == nil {
|
if file == nil {
|
||||||
return 0, EINVAL
|
return 0, EINVAL
|
||||||
}
|
}
|
||||||
n, e := syscall.Read(file.fd, b);
|
n, e := syscall.Read(file.fd, b)
|
||||||
if n < 0 {
|
if n < 0 {
|
||||||
n = 0
|
n = 0
|
||||||
}
|
}
|
||||||
@ -125,7 +125,7 @@ func (file *File) Read(b []byte) (n int, err Error) {
|
|||||||
if e != 0 {
|
if e != 0 {
|
||||||
err = &PathError{"read", file.name, Errno(e)}
|
err = &PathError{"read", file.name, Errno(e)}
|
||||||
}
|
}
|
||||||
return n, err;
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadAt reads len(b) bytes from the File starting at byte offset off.
|
// ReadAt reads len(b) bytes from the File starting at byte offset off.
|
||||||
@ -137,19 +137,19 @@ func (file *File) ReadAt(b []byte, off int64) (n int, err Error) {
|
|||||||
return 0, EINVAL
|
return 0, EINVAL
|
||||||
}
|
}
|
||||||
for len(b) > 0 {
|
for len(b) > 0 {
|
||||||
m, e := syscall.Pread(file.fd, b, off);
|
m, e := syscall.Pread(file.fd, b, off)
|
||||||
if m == 0 && e == 0 {
|
if m == 0 && e == 0 {
|
||||||
return n, EOF
|
return n, EOF
|
||||||
}
|
}
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
err = &PathError{"read", file.name, Errno(e)};
|
err = &PathError{"read", file.name, Errno(e)}
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
n += m;
|
n += m
|
||||||
b = b[m:];
|
b = b[m:]
|
||||||
off += int64(m);
|
off += int64(m)
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write writes len(b) bytes to the File.
|
// Write writes len(b) bytes to the File.
|
||||||
@ -159,12 +159,12 @@ func (file *File) Write(b []byte) (n int, err Error) {
|
|||||||
if file == nil {
|
if file == nil {
|
||||||
return 0, EINVAL
|
return 0, EINVAL
|
||||||
}
|
}
|
||||||
n, e := syscall.Write(file.fd, b);
|
n, e := syscall.Write(file.fd, b)
|
||||||
if n < 0 {
|
if n < 0 {
|
||||||
n = 0
|
n = 0
|
||||||
}
|
}
|
||||||
if e == syscall.EPIPE {
|
if e == syscall.EPIPE {
|
||||||
file.nepipe++;
|
file.nepipe++
|
||||||
if file.nepipe >= 10 {
|
if file.nepipe >= 10 {
|
||||||
Exit(syscall.EPIPE)
|
Exit(syscall.EPIPE)
|
||||||
}
|
}
|
||||||
@ -174,7 +174,7 @@ func (file *File) Write(b []byte) (n int, err Error) {
|
|||||||
if e != 0 {
|
if e != 0 {
|
||||||
err = &PathError{"write", file.name, Errno(e)}
|
err = &PathError{"write", file.name, Errno(e)}
|
||||||
}
|
}
|
||||||
return n, err;
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteAt writes len(b) bytes to the File starting at byte offset off.
|
// WriteAt writes len(b) bytes to the File starting at byte offset off.
|
||||||
@ -185,16 +185,16 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
|
|||||||
return 0, EINVAL
|
return 0, EINVAL
|
||||||
}
|
}
|
||||||
for len(b) > 0 {
|
for len(b) > 0 {
|
||||||
m, e := syscall.Pwrite(file.fd, b, off);
|
m, e := syscall.Pwrite(file.fd, b, off)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
err = &PathError{"write", file.name, Errno(e)};
|
err = &PathError{"write", file.name, Errno(e)}
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
n += m;
|
n += m
|
||||||
b = b[m:];
|
b = b[m:]
|
||||||
off += int64(m);
|
off += int64(m)
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seek sets the offset for the next Read or Write on file to offset, interpreted
|
// Seek sets the offset for the next Read or Write on file to offset, interpreted
|
||||||
@ -202,14 +202,14 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
|
|||||||
// relative to the current offset, and 2 means relative to the end.
|
// relative to the current offset, and 2 means relative to the end.
|
||||||
// It returns the new offset and an Error, if any.
|
// It returns the new offset and an Error, if any.
|
||||||
func (file *File) Seek(offset int64, whence int) (ret int64, err Error) {
|
func (file *File) Seek(offset int64, whence int) (ret int64, err Error) {
|
||||||
r, e := syscall.Seek(file.fd, offset, whence);
|
r, e := syscall.Seek(file.fd, offset, whence)
|
||||||
if e == 0 && file.dirinfo != nil && r != 0 {
|
if e == 0 && file.dirinfo != nil && r != 0 {
|
||||||
e = syscall.EISDIR
|
e = syscall.EISDIR
|
||||||
}
|
}
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return 0, &PathError{"seek", file.name, Errno(e)}
|
return 0, &PathError{"seek", file.name, Errno(e)}
|
||||||
}
|
}
|
||||||
return r, nil;
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteString is like Write, but writes the contents of string s rather than
|
// WriteString is like Write, but writes the contents of string s rather than
|
||||||
@ -218,38 +218,38 @@ func (file *File) WriteString(s string) (ret int, err Error) {
|
|||||||
if file == nil {
|
if file == nil {
|
||||||
return 0, EINVAL
|
return 0, EINVAL
|
||||||
}
|
}
|
||||||
b := syscall.StringByteSlice(s);
|
b := syscall.StringByteSlice(s)
|
||||||
b = b[0 : len(b)-1];
|
b = b[0 : len(b)-1]
|
||||||
return file.Write(b);
|
return file.Write(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pipe returns a connected pair of Files; reads from r return bytes written to w.
|
// Pipe returns a connected pair of Files; reads from r return bytes written to w.
|
||||||
// It returns the files and an Error, if any.
|
// It returns the files and an Error, if any.
|
||||||
func Pipe() (r *File, w *File, err Error) {
|
func Pipe() (r *File, w *File, err Error) {
|
||||||
var p [2]int;
|
var p [2]int
|
||||||
|
|
||||||
// See ../syscall/exec.go for description of lock.
|
// See ../syscall/exec.go for description of lock.
|
||||||
syscall.ForkLock.RLock();
|
syscall.ForkLock.RLock()
|
||||||
e := syscall.Pipe(&p);
|
e := syscall.Pipe(&p)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
syscall.ForkLock.RUnlock();
|
syscall.ForkLock.RUnlock()
|
||||||
return nil, nil, NewSyscallError("pipe", e);
|
return nil, nil, NewSyscallError("pipe", e)
|
||||||
}
|
}
|
||||||
syscall.CloseOnExec(p[0]);
|
syscall.CloseOnExec(p[0])
|
||||||
syscall.CloseOnExec(p[1]);
|
syscall.CloseOnExec(p[1])
|
||||||
syscall.ForkLock.RUnlock();
|
syscall.ForkLock.RUnlock()
|
||||||
|
|
||||||
return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil;
|
return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mkdir creates a new directory with the specified name and permission bits.
|
// Mkdir creates a new directory with the specified name and permission bits.
|
||||||
// It returns an error, if any.
|
// It returns an error, if any.
|
||||||
func Mkdir(name string, perm int) Error {
|
func Mkdir(name string, perm int) Error {
|
||||||
e := syscall.Mkdir(name, perm);
|
e := syscall.Mkdir(name, perm)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return &PathError{"mkdir", name, Errno(e)}
|
return &PathError{"mkdir", name, Errno(e)}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat returns a Dir structure describing the named file and an error, if any.
|
// Stat returns a Dir structure describing the named file and an error, if any.
|
||||||
@ -258,42 +258,42 @@ func Mkdir(name string, perm int) Error {
|
|||||||
// If name names an invalid symbolic link, the returned Dir describes
|
// If name names an invalid symbolic link, the returned Dir describes
|
||||||
// the link itself and has dir.FollowedSymlink set to false.
|
// the link itself and has dir.FollowedSymlink set to false.
|
||||||
func Stat(name string) (dir *Dir, err Error) {
|
func Stat(name string) (dir *Dir, err Error) {
|
||||||
var lstat, stat syscall.Stat_t;
|
var lstat, stat syscall.Stat_t
|
||||||
e := syscall.Lstat(name, &lstat);
|
e := syscall.Lstat(name, &lstat)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return nil, &PathError{"stat", name, Errno(e)}
|
return nil, &PathError{"stat", name, Errno(e)}
|
||||||
}
|
}
|
||||||
statp := &lstat;
|
statp := &lstat
|
||||||
if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
|
if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
|
||||||
e := syscall.Stat(name, &stat);
|
e := syscall.Stat(name, &stat)
|
||||||
if e == 0 {
|
if e == 0 {
|
||||||
statp = &stat
|
statp = &stat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dirFromStat(name, new(Dir), &lstat, statp), nil;
|
return dirFromStat(name, new(Dir), &lstat, statp), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat returns the Dir structure describing file.
|
// Stat returns the Dir structure describing file.
|
||||||
// It returns the Dir and an error, if any.
|
// It returns the Dir and an error, if any.
|
||||||
func (file *File) Stat() (dir *Dir, err Error) {
|
func (file *File) Stat() (dir *Dir, err Error) {
|
||||||
var stat syscall.Stat_t;
|
var stat syscall.Stat_t
|
||||||
e := syscall.Fstat(file.fd, &stat);
|
e := syscall.Fstat(file.fd, &stat)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return nil, &PathError{"stat", file.name, Errno(e)}
|
return nil, &PathError{"stat", file.name, Errno(e)}
|
||||||
}
|
}
|
||||||
return dirFromStat(file.name, new(Dir), &stat, &stat), nil;
|
return dirFromStat(file.name, new(Dir), &stat, &stat), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lstat returns the Dir structure describing the named file and an error, if any.
|
// Lstat returns the Dir structure describing the named file and an error, if any.
|
||||||
// If the file is a symbolic link, the returned Dir describes the
|
// If the file is a symbolic link, the returned Dir describes the
|
||||||
// symbolic link. Lstat makes no attempt to follow the link.
|
// symbolic link. Lstat makes no attempt to follow the link.
|
||||||
func Lstat(name string) (dir *Dir, err Error) {
|
func Lstat(name string) (dir *Dir, err Error) {
|
||||||
var stat syscall.Stat_t;
|
var stat syscall.Stat_t
|
||||||
e := syscall.Lstat(name, &stat);
|
e := syscall.Lstat(name, &stat)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return nil, &PathError{"lstat", name, Errno(e)}
|
return nil, &PathError{"lstat", name, Errno(e)}
|
||||||
}
|
}
|
||||||
return dirFromStat(name, new(Dir), &stat, &stat), nil;
|
return dirFromStat(name, new(Dir), &stat, &stat), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Readdir reads the contents of the directory associated with file and
|
// Readdir reads the contents of the directory associated with file and
|
||||||
@ -302,25 +302,25 @@ func Lstat(name string) (dir *Dir, err Error) {
|
|||||||
// A negative count means to read until EOF.
|
// A negative count means to read until EOF.
|
||||||
// Readdir returns the array and an Error, if any.
|
// Readdir returns the array and an Error, if any.
|
||||||
func (file *File) Readdir(count int) (dirs []Dir, err Error) {
|
func (file *File) Readdir(count int) (dirs []Dir, err Error) {
|
||||||
dirname := file.name;
|
dirname := file.name
|
||||||
if dirname == "" {
|
if dirname == "" {
|
||||||
dirname = "."
|
dirname = "."
|
||||||
}
|
}
|
||||||
dirname += "/";
|
dirname += "/"
|
||||||
names, err1 := file.Readdirnames(count);
|
names, err1 := file.Readdirnames(count)
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
return nil, err1
|
return nil, err1
|
||||||
}
|
}
|
||||||
dirs = make([]Dir, len(names));
|
dirs = make([]Dir, len(names))
|
||||||
for i, filename := range names {
|
for i, filename := range names {
|
||||||
dirp, err := Lstat(dirname + filename);
|
dirp, err := Lstat(dirname + filename)
|
||||||
if dirp == nil || err != nil {
|
if dirp == nil || err != nil {
|
||||||
dirs[i].Name = filename // rest is already zeroed out
|
dirs[i].Name = filename // rest is already zeroed out
|
||||||
} else {
|
} else {
|
||||||
dirs[i] = *dirp
|
dirs[i] = *dirp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chdir changes the current working directory to the named directory.
|
// Chdir changes the current working directory to the named directory.
|
||||||
@ -328,7 +328,7 @@ func Chdir(dir string) Error {
|
|||||||
if e := syscall.Chdir(dir); e != 0 {
|
if e := syscall.Chdir(dir); e != 0 {
|
||||||
return &PathError{"chdir", dir, Errno(e)}
|
return &PathError{"chdir", dir, Errno(e)}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chdir changes the current working directory to the file,
|
// Chdir changes the current working directory to the file,
|
||||||
@ -337,7 +337,7 @@ func (f *File) Chdir() Error {
|
|||||||
if e := syscall.Fchdir(f.fd); e != 0 {
|
if e := syscall.Fchdir(f.fd); e != 0 {
|
||||||
return &PathError{"chdir", f.name, Errno(e)}
|
return &PathError{"chdir", f.name, Errno(e)}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes the named file or directory.
|
// Remove removes the named file or directory.
|
||||||
@ -346,11 +346,11 @@ func Remove(name string) Error {
|
|||||||
// whether name is a file or directory.
|
// whether name is a file or directory.
|
||||||
// Try both: it is cheaper on average than
|
// Try both: it is cheaper on average than
|
||||||
// doing a Stat plus the right one.
|
// doing a Stat plus the right one.
|
||||||
e := syscall.Unlink(name);
|
e := syscall.Unlink(name)
|
||||||
if e == 0 {
|
if e == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
e1 := syscall.Rmdir(name);
|
e1 := syscall.Rmdir(name)
|
||||||
if e1 == 0 {
|
if e1 == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -367,16 +367,16 @@ func Remove(name string) Error {
|
|||||||
if e1 != syscall.ENOTDIR {
|
if e1 != syscall.ENOTDIR {
|
||||||
e = e1
|
e = e1
|
||||||
}
|
}
|
||||||
return &PathError{"remove", name, Errno(e)};
|
return &PathError{"remove", name, Errno(e)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinkError records an error during a link or symlink or rename
|
// LinkError records an error during a link or symlink or rename
|
||||||
// system call and the paths that caused it.
|
// system call and the paths that caused it.
|
||||||
type LinkError struct {
|
type LinkError struct {
|
||||||
Op string;
|
Op string
|
||||||
Old string;
|
Old string
|
||||||
New string;
|
New string
|
||||||
Error Error;
|
Error Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *LinkError) String() string {
|
func (e *LinkError) String() string {
|
||||||
@ -385,28 +385,28 @@ func (e *LinkError) String() string {
|
|||||||
|
|
||||||
// Link creates a hard link.
|
// Link creates a hard link.
|
||||||
func Link(oldname, newname string) Error {
|
func Link(oldname, newname string) Error {
|
||||||
e := syscall.Link(oldname, newname);
|
e := syscall.Link(oldname, newname)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return &LinkError{"link", oldname, newname, Errno(e)}
|
return &LinkError{"link", oldname, newname, Errno(e)}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Symlink creates a symbolic link.
|
// Symlink creates a symbolic link.
|
||||||
func Symlink(oldname, newname string) Error {
|
func Symlink(oldname, newname string) Error {
|
||||||
e := syscall.Symlink(oldname, newname);
|
e := syscall.Symlink(oldname, newname)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return &LinkError{"symlink", oldname, newname, Errno(e)}
|
return &LinkError{"symlink", oldname, newname, Errno(e)}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Readlink reads the contents of a symbolic link: the destination of
|
// Readlink reads the contents of a symbolic link: the destination of
|
||||||
// the link. It returns the contents and an Error, if any.
|
// the link. It returns the contents and an Error, if any.
|
||||||
func Readlink(name string) (string, Error) {
|
func Readlink(name string) (string, Error) {
|
||||||
for len := 128; ; len *= 2 {
|
for len := 128; ; len *= 2 {
|
||||||
b := make([]byte, len);
|
b := make([]byte, len)
|
||||||
n, e := syscall.Readlink(name, b);
|
n, e := syscall.Readlink(name, b)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return "", &PathError{"readlink", name, Errno(e)}
|
return "", &PathError{"readlink", name, Errno(e)}
|
||||||
}
|
}
|
||||||
@ -415,16 +415,16 @@ func Readlink(name string) (string, Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Silence 6g.
|
// Silence 6g.
|
||||||
return "", nil;
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rename renames a file.
|
// Rename renames a file.
|
||||||
func Rename(oldname, newname string) Error {
|
func Rename(oldname, newname string) Error {
|
||||||
e := syscall.Rename(oldname, newname);
|
e := syscall.Rename(oldname, newname)
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
return &LinkError{"rename", oldname, newname, Errno(e)}
|
return &LinkError{"rename", oldname, newname, Errno(e)}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chmod changes the mode of the named file to mode.
|
// Chmod changes the mode of the named file to mode.
|
||||||
@ -433,7 +433,7 @@ func Chmod(name string, mode int) Error {
|
|||||||
if e := syscall.Chmod(name, mode); e != 0 {
|
if e := syscall.Chmod(name, mode); e != 0 {
|
||||||
return &PathError{"chmod", name, Errno(e)}
|
return &PathError{"chmod", name, Errno(e)}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chmod changes the mode of the file to mode.
|
// Chmod changes the mode of the file to mode.
|
||||||
@ -441,7 +441,7 @@ func (f *File) Chmod(mode int) Error {
|
|||||||
if e := syscall.Fchmod(f.fd, mode); e != 0 {
|
if e := syscall.Fchmod(f.fd, mode); e != 0 {
|
||||||
return &PathError{"chmod", f.name, Errno(e)}
|
return &PathError{"chmod", f.name, Errno(e)}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chown changes the numeric uid and gid of the named file.
|
// Chown changes the numeric uid and gid of the named file.
|
||||||
@ -450,7 +450,7 @@ func Chown(name string, uid, gid int) Error {
|
|||||||
if e := syscall.Chown(name, uid, gid); e != 0 {
|
if e := syscall.Chown(name, uid, gid); e != 0 {
|
||||||
return &PathError{"chown", name, Errno(e)}
|
return &PathError{"chown", name, Errno(e)}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lchown changes the numeric uid and gid of the named file.
|
// Lchown changes the numeric uid and gid of the named file.
|
||||||
@ -459,7 +459,7 @@ func Lchown(name string, uid, gid int) Error {
|
|||||||
if e := syscall.Lchown(name, uid, gid); e != 0 {
|
if e := syscall.Lchown(name, uid, gid); e != 0 {
|
||||||
return &PathError{"lchown", name, Errno(e)}
|
return &PathError{"lchown", name, Errno(e)}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chown changes the numeric uid and gid of the named file.
|
// Chown changes the numeric uid and gid of the named file.
|
||||||
@ -467,7 +467,7 @@ func (f *File) Chown(uid, gid int) Error {
|
|||||||
if e := syscall.Fchown(f.fd, uid, gid); e != 0 {
|
if e := syscall.Fchown(f.fd, uid, gid); e != 0 {
|
||||||
return &PathError{"chown", f.name, Errno(e)}
|
return &PathError{"chown", f.name, Errno(e)}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Truncate changes the size of the named file.
|
// Truncate changes the size of the named file.
|
||||||
@ -476,7 +476,7 @@ func Truncate(name string, size int64) Error {
|
|||||||
if e := syscall.Truncate(name, size); e != 0 {
|
if e := syscall.Truncate(name, size); e != 0 {
|
||||||
return &PathError{"truncate", name, Errno(e)}
|
return &PathError{"truncate", name, Errno(e)}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Truncate changes the size of the file.
|
// Truncate changes the size of the file.
|
||||||
@ -485,5 +485,5 @@ func (f *File) Truncate(size int64) Error {
|
|||||||
if e := syscall.Ftruncate(f.fd, size); e != 0 {
|
if e := syscall.Ftruncate(f.fd, size); e != 0 {
|
||||||
return &PathError{"truncate", f.name, Errno(e)}
|
return &PathError{"truncate", f.name, Errno(e)}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
package os
|
package os
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall";
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Getwd returns a rooted path name corresponding to the
|
// Getwd returns a rooted path name corresponding to the
|
||||||
@ -15,21 +15,21 @@ import (
|
|||||||
func Getwd() (string, Error) {
|
func Getwd() (string, Error) {
|
||||||
// If the operating system provides a Getwd call, use it.
|
// If the operating system provides a Getwd call, use it.
|
||||||
if syscall.ImplementsGetwd {
|
if syscall.ImplementsGetwd {
|
||||||
s, e := syscall.Getwd();
|
s, e := syscall.Getwd()
|
||||||
return s, NewSyscallError("getwd", e);
|
return s, NewSyscallError("getwd", e)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, we're trying to find our way back to ".".
|
// Otherwise, we're trying to find our way back to ".".
|
||||||
dot, err := Stat(".");
|
dot, err := Stat(".")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clumsy but widespread kludge:
|
// Clumsy but widespread kludge:
|
||||||
// if $PWD is set and matches ".", use it.
|
// if $PWD is set and matches ".", use it.
|
||||||
pwd := Getenv("PWD");
|
pwd := Getenv("PWD")
|
||||||
if len(pwd) > 0 && pwd[0] == '/' {
|
if len(pwd) > 0 && pwd[0] == '/' {
|
||||||
d, err := Stat(pwd);
|
d, err := Stat(pwd)
|
||||||
if err == nil && d.Dev == dot.Dev && d.Ino == dot.Ino {
|
if err == nil && d.Dev == dot.Dev && d.Ino == dot.Ino {
|
||||||
return pwd, nil
|
return pwd, nil
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ func Getwd() (string, Error) {
|
|||||||
|
|
||||||
// Root is a special case because it has no parent
|
// Root is a special case because it has no parent
|
||||||
// and ends in a slash.
|
// and ends in a slash.
|
||||||
root, err := Stat("/");
|
root, err := Stat("/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Can't stat root - no hope.
|
// Can't stat root - no hope.
|
||||||
return "", err
|
return "", err
|
||||||
@ -49,44 +49,44 @@ func Getwd() (string, Error) {
|
|||||||
// General algorithm: find name in parent
|
// General algorithm: find name in parent
|
||||||
// and then find name of parent. Each iteration
|
// and then find name of parent. Each iteration
|
||||||
// adds /name to the beginning of pwd.
|
// adds /name to the beginning of pwd.
|
||||||
pwd = "";
|
pwd = ""
|
||||||
for parent := ".."; ; parent = "../" + parent {
|
for parent := ".."; ; parent = "../" + parent {
|
||||||
if len(parent) >= 1024 { // Sanity check
|
if len(parent) >= 1024 { // Sanity check
|
||||||
return "", ENAMETOOLONG
|
return "", ENAMETOOLONG
|
||||||
}
|
}
|
||||||
fd, err := Open(parent, O_RDONLY, 0);
|
fd, err := Open(parent, O_RDONLY, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
names, err := fd.Readdirnames(100);
|
names, err := fd.Readdirnames(100)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fd.Close();
|
fd.Close()
|
||||||
return "", err;
|
return "", err
|
||||||
}
|
}
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
d, _ := Lstat(parent + "/" + name);
|
d, _ := Lstat(parent + "/" + name)
|
||||||
if d.Dev == dot.Dev && d.Ino == dot.Ino {
|
if d.Dev == dot.Dev && d.Ino == dot.Ino {
|
||||||
pwd = "/" + name + pwd;
|
pwd = "/" + name + pwd
|
||||||
goto Found;
|
goto Found
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fd.Close();
|
fd.Close()
|
||||||
return "", ENOENT;
|
return "", ENOENT
|
||||||
|
|
||||||
Found:
|
Found:
|
||||||
pd, err := fd.Stat();
|
pd, err := fd.Stat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
fd.Close();
|
fd.Close()
|
||||||
if pd.Dev == root.Dev && pd.Ino == root.Ino {
|
if pd.Dev == root.Dev && pd.Ino == root.Ino {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// Set up for next round.
|
// Set up for next round.
|
||||||
dot = pd;
|
dot = pd
|
||||||
}
|
}
|
||||||
return pwd, nil;
|
return pwd, nil
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,13 @@
|
|||||||
package os_test
|
package os_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes";
|
"bytes"
|
||||||
"fmt";
|
"fmt"
|
||||||
"io";
|
"io"
|
||||||
"io/ioutil";
|
"io/ioutil"
|
||||||
. "os";
|
. "os"
|
||||||
"strings";
|
"strings"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var dot = []string{
|
var dot = []string{
|
||||||
@ -34,16 +34,16 @@ var etc = []string{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func size(name string, t *testing.T) uint64 {
|
func size(name string, t *testing.T) uint64 {
|
||||||
file, err := Open(name, O_RDONLY, 0);
|
file, err := Open(name, O_RDONLY, 0)
|
||||||
defer file.Close();
|
defer file.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("open failed:", err)
|
t.Fatal("open failed:", err)
|
||||||
}
|
}
|
||||||
var buf [100]byte;
|
var buf [100]byte
|
||||||
len := 0;
|
len := 0
|
||||||
for {
|
for {
|
||||||
n, e := file.Read(&buf);
|
n, e := file.Read(&buf)
|
||||||
len += n;
|
len += n
|
||||||
if e == EOF {
|
if e == EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -51,68 +51,68 @@ func size(name string, t *testing.T) uint64 {
|
|||||||
t.Fatal("read failed:", err)
|
t.Fatal("read failed:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return uint64(len);
|
return uint64(len)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStat(t *testing.T) {
|
func TestStat(t *testing.T) {
|
||||||
dir, err := Stat("/etc/passwd");
|
dir, err := Stat("/etc/passwd")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("stat failed:", err)
|
t.Fatal("stat failed:", err)
|
||||||
}
|
}
|
||||||
if dir.Name != "passwd" {
|
if dir.Name != "passwd" {
|
||||||
t.Error("name should be passwd; is", dir.Name)
|
t.Error("name should be passwd; is", dir.Name)
|
||||||
}
|
}
|
||||||
filesize := size("/etc/passwd", t);
|
filesize := size("/etc/passwd", t)
|
||||||
if dir.Size != filesize {
|
if dir.Size != filesize {
|
||||||
t.Error("size should be", filesize, "; is", dir.Size)
|
t.Error("size should be", filesize, "; is", dir.Size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFstat(t *testing.T) {
|
func TestFstat(t *testing.T) {
|
||||||
file, err1 := Open("/etc/passwd", O_RDONLY, 0);
|
file, err1 := Open("/etc/passwd", O_RDONLY, 0)
|
||||||
defer file.Close();
|
defer file.Close()
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
t.Fatal("open failed:", err1)
|
t.Fatal("open failed:", err1)
|
||||||
}
|
}
|
||||||
dir, err2 := file.Stat();
|
dir, err2 := file.Stat()
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
t.Fatal("fstat failed:", err2)
|
t.Fatal("fstat failed:", err2)
|
||||||
}
|
}
|
||||||
if dir.Name != "passwd" {
|
if dir.Name != "passwd" {
|
||||||
t.Error("name should be passwd; is", dir.Name)
|
t.Error("name should be passwd; is", dir.Name)
|
||||||
}
|
}
|
||||||
filesize := size("/etc/passwd", t);
|
filesize := size("/etc/passwd", t)
|
||||||
if dir.Size != filesize {
|
if dir.Size != filesize {
|
||||||
t.Error("size should be", filesize, "; is", dir.Size)
|
t.Error("size should be", filesize, "; is", dir.Size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLstat(t *testing.T) {
|
func TestLstat(t *testing.T) {
|
||||||
dir, err := Lstat("/etc/passwd");
|
dir, err := Lstat("/etc/passwd")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("lstat failed:", err)
|
t.Fatal("lstat failed:", err)
|
||||||
}
|
}
|
||||||
if dir.Name != "passwd" {
|
if dir.Name != "passwd" {
|
||||||
t.Error("name should be passwd; is", dir.Name)
|
t.Error("name should be passwd; is", dir.Name)
|
||||||
}
|
}
|
||||||
filesize := size("/etc/passwd", t);
|
filesize := size("/etc/passwd", t)
|
||||||
if dir.Size != filesize {
|
if dir.Size != filesize {
|
||||||
t.Error("size should be", filesize, "; is", dir.Size)
|
t.Error("size should be", filesize, "; is", dir.Size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testReaddirnames(dir string, contents []string, t *testing.T) {
|
func testReaddirnames(dir string, contents []string, t *testing.T) {
|
||||||
file, err := Open(dir, O_RDONLY, 0);
|
file, err := Open(dir, O_RDONLY, 0)
|
||||||
defer file.Close();
|
defer file.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("open %q failed: %v", dir, err)
|
t.Fatalf("open %q failed: %v", dir, err)
|
||||||
}
|
}
|
||||||
s, err2 := file.Readdirnames(-1);
|
s, err2 := file.Readdirnames(-1)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
t.Fatalf("readdirnames %q failed: %v", err2)
|
t.Fatalf("readdirnames %q failed: %v", err2)
|
||||||
}
|
}
|
||||||
for _, m := range contents {
|
for _, m := range contents {
|
||||||
found := false;
|
found := false
|
||||||
for _, n := range s {
|
for _, n := range s {
|
||||||
if n == "." || n == ".." {
|
if n == "." || n == ".." {
|
||||||
t.Errorf("got %s in directory", n)
|
t.Errorf("got %s in directory", n)
|
||||||
@ -121,7 +121,7 @@ func testReaddirnames(dir string, contents []string, t *testing.T) {
|
|||||||
if found {
|
if found {
|
||||||
t.Error("present twice:", m)
|
t.Error("present twice:", m)
|
||||||
}
|
}
|
||||||
found = true;
|
found = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
@ -131,23 +131,23 @@ func testReaddirnames(dir string, contents []string, t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testReaddir(dir string, contents []string, t *testing.T) {
|
func testReaddir(dir string, contents []string, t *testing.T) {
|
||||||
file, err := Open(dir, O_RDONLY, 0);
|
file, err := Open(dir, O_RDONLY, 0)
|
||||||
defer file.Close();
|
defer file.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("open %q failed: %v", dir, err)
|
t.Fatalf("open %q failed: %v", dir, err)
|
||||||
}
|
}
|
||||||
s, err2 := file.Readdir(-1);
|
s, err2 := file.Readdir(-1)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
t.Fatalf("readdir %q failed: %v", dir, err2)
|
t.Fatalf("readdir %q failed: %v", dir, err2)
|
||||||
}
|
}
|
||||||
for _, m := range contents {
|
for _, m := range contents {
|
||||||
found := false;
|
found := false
|
||||||
for _, n := range s {
|
for _, n := range s {
|
||||||
if m == n.Name {
|
if m == n.Name {
|
||||||
if found {
|
if found {
|
||||||
t.Error("present twice:", m)
|
t.Error("present twice:", m)
|
||||||
}
|
}
|
||||||
found = true;
|
found = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
@ -157,51 +157,51 @@ func testReaddir(dir string, contents []string, t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestReaddirnames(t *testing.T) {
|
func TestReaddirnames(t *testing.T) {
|
||||||
testReaddirnames(".", dot, t);
|
testReaddirnames(".", dot, t)
|
||||||
testReaddirnames("/etc", etc, t);
|
testReaddirnames("/etc", etc, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReaddir(t *testing.T) {
|
func TestReaddir(t *testing.T) {
|
||||||
testReaddir(".", dot, t);
|
testReaddir(".", dot, t)
|
||||||
testReaddir("/etc", etc, t);
|
testReaddir("/etc", etc, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the directory one entry at a time.
|
// Read the directory one entry at a time.
|
||||||
func smallReaddirnames(file *File, length int, t *testing.T) []string {
|
func smallReaddirnames(file *File, length int, t *testing.T) []string {
|
||||||
names := make([]string, length);
|
names := make([]string, length)
|
||||||
count := 0;
|
count := 0
|
||||||
for {
|
for {
|
||||||
d, err := file.Readdirnames(1);
|
d, err := file.Readdirnames(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("readdir %q failed: %v", file.Name(), err)
|
t.Fatalf("readdir %q failed: %v", file.Name(), err)
|
||||||
}
|
}
|
||||||
if len(d) == 0 {
|
if len(d) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
names[count] = d[0];
|
names[count] = d[0]
|
||||||
count++;
|
count++
|
||||||
}
|
}
|
||||||
return names[0:count];
|
return names[0:count]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that reading a directory one entry at a time gives the same result
|
// Check that reading a directory one entry at a time gives the same result
|
||||||
// as reading it all at once.
|
// as reading it all at once.
|
||||||
func TestReaddirnamesOneAtATime(t *testing.T) {
|
func TestReaddirnamesOneAtATime(t *testing.T) {
|
||||||
dir := "/usr/bin"; // big directory that doesn't change often.
|
dir := "/usr/bin" // big directory that doesn't change often.
|
||||||
file, err := Open(dir, O_RDONLY, 0);
|
file, err := Open(dir, O_RDONLY, 0)
|
||||||
defer file.Close();
|
defer file.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("open %q failed: %v", dir, err)
|
t.Fatalf("open %q failed: %v", dir, err)
|
||||||
}
|
}
|
||||||
all, err1 := file.Readdirnames(-1);
|
all, err1 := file.Readdirnames(-1)
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
t.Fatalf("readdirnames %q failed: %v", dir, err1)
|
t.Fatalf("readdirnames %q failed: %v", dir, err1)
|
||||||
}
|
}
|
||||||
file1, err2 := Open(dir, O_RDONLY, 0);
|
file1, err2 := Open(dir, O_RDONLY, 0)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
t.Fatalf("open %q failed: %v", dir, err2)
|
t.Fatalf("open %q failed: %v", dir, err2)
|
||||||
}
|
}
|
||||||
small := smallReaddirnames(file1, len(all)+100, t); // +100 in case we screw up
|
small := smallReaddirnames(file1, len(all)+100, t) // +100 in case we screw up
|
||||||
for i, n := range all {
|
for i, n := range all {
|
||||||
if small[i] != n {
|
if small[i] != n {
|
||||||
t.Errorf("small read %q %q mismatch: %v", small[i], n)
|
t.Errorf("small read %q %q mismatch: %v", small[i], n)
|
||||||
@ -210,26 +210,26 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHardLink(t *testing.T) {
|
func TestHardLink(t *testing.T) {
|
||||||
from, to := "hardlinktestfrom", "hardlinktestto";
|
from, to := "hardlinktestfrom", "hardlinktestto"
|
||||||
Remove(from); // Just in case.
|
Remove(from) // Just in case.
|
||||||
file, err := Open(to, O_CREAT|O_WRONLY, 0666);
|
file, err := Open(to, O_CREAT|O_WRONLY, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("open %q failed: %v", to, err)
|
t.Fatalf("open %q failed: %v", to, err)
|
||||||
}
|
}
|
||||||
defer Remove(to);
|
defer Remove(to)
|
||||||
if err = file.Close(); err != nil {
|
if err = file.Close(); err != nil {
|
||||||
t.Errorf("close %q failed: %v", to, err)
|
t.Errorf("close %q failed: %v", to, err)
|
||||||
}
|
}
|
||||||
err = Link(to, from);
|
err = Link(to, from)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("link %q, %q failed: %v", to, from, err)
|
t.Fatalf("link %q, %q failed: %v", to, from, err)
|
||||||
}
|
}
|
||||||
defer Remove(from);
|
defer Remove(from)
|
||||||
tostat, err := Stat(to);
|
tostat, err := Stat(to)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("stat %q failed: %v", to, err)
|
t.Fatalf("stat %q failed: %v", to, err)
|
||||||
}
|
}
|
||||||
fromstat, err := Stat(from);
|
fromstat, err := Stat(from)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("stat %q failed: %v", from, err)
|
t.Fatalf("stat %q failed: %v", from, err)
|
||||||
}
|
}
|
||||||
@ -239,74 +239,74 @@ func TestHardLink(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSymLink(t *testing.T) {
|
func TestSymLink(t *testing.T) {
|
||||||
from, to := "symlinktestfrom", "symlinktestto";
|
from, to := "symlinktestfrom", "symlinktestto"
|
||||||
Remove(from); // Just in case.
|
Remove(from) // Just in case.
|
||||||
file, err := Open(to, O_CREAT|O_WRONLY, 0666);
|
file, err := Open(to, O_CREAT|O_WRONLY, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("open %q failed: %v", to, err)
|
t.Fatalf("open %q failed: %v", to, err)
|
||||||
}
|
}
|
||||||
defer Remove(to);
|
defer Remove(to)
|
||||||
if err = file.Close(); err != nil {
|
if err = file.Close(); err != nil {
|
||||||
t.Errorf("close %q failed: %v", to, err)
|
t.Errorf("close %q failed: %v", to, err)
|
||||||
}
|
}
|
||||||
err = Symlink(to, from);
|
err = Symlink(to, from)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("symlink %q, %q failed: %v", to, from, err)
|
t.Fatalf("symlink %q, %q failed: %v", to, from, err)
|
||||||
}
|
}
|
||||||
defer Remove(from);
|
defer Remove(from)
|
||||||
tostat, err := Stat(to);
|
tostat, err := Stat(to)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("stat %q failed: %v", to, err)
|
t.Fatalf("stat %q failed: %v", to, err)
|
||||||
}
|
}
|
||||||
if tostat.FollowedSymlink {
|
if tostat.FollowedSymlink {
|
||||||
t.Fatalf("stat %q claims to have followed a symlink", to)
|
t.Fatalf("stat %q claims to have followed a symlink", to)
|
||||||
}
|
}
|
||||||
fromstat, err := Stat(from);
|
fromstat, err := Stat(from)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("stat %q failed: %v", from, err)
|
t.Fatalf("stat %q failed: %v", from, err)
|
||||||
}
|
}
|
||||||
if tostat.Dev != fromstat.Dev || tostat.Ino != fromstat.Ino {
|
if tostat.Dev != fromstat.Dev || tostat.Ino != fromstat.Ino {
|
||||||
t.Errorf("symlink %q, %q did not create symlink", to, from)
|
t.Errorf("symlink %q, %q did not create symlink", to, from)
|
||||||
}
|
}
|
||||||
fromstat, err = Lstat(from);
|
fromstat, err = Lstat(from)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("lstat %q failed: %v", from, err)
|
t.Fatalf("lstat %q failed: %v", from, err)
|
||||||
}
|
}
|
||||||
if !fromstat.IsSymlink() {
|
if !fromstat.IsSymlink() {
|
||||||
t.Fatalf("symlink %q, %q did not create symlink", to, from)
|
t.Fatalf("symlink %q, %q did not create symlink", to, from)
|
||||||
}
|
}
|
||||||
fromstat, err = Stat(from);
|
fromstat, err = Stat(from)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("stat %q failed: %v", from, err)
|
t.Fatalf("stat %q failed: %v", from, err)
|
||||||
}
|
}
|
||||||
if !fromstat.FollowedSymlink {
|
if !fromstat.FollowedSymlink {
|
||||||
t.Fatalf("stat %q did not follow symlink")
|
t.Fatalf("stat %q did not follow symlink")
|
||||||
}
|
}
|
||||||
s, err := Readlink(from);
|
s, err := Readlink(from)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("readlink %q failed: %v", from, err)
|
t.Fatalf("readlink %q failed: %v", from, err)
|
||||||
}
|
}
|
||||||
if s != to {
|
if s != to {
|
||||||
t.Fatalf("after symlink %q != %q", s, to)
|
t.Fatalf("after symlink %q != %q", s, to)
|
||||||
}
|
}
|
||||||
file, err = Open(from, O_RDONLY, 0);
|
file, err = Open(from, O_RDONLY, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("open %q failed: %v", from, err)
|
t.Fatalf("open %q failed: %v", from, err)
|
||||||
}
|
}
|
||||||
file.Close();
|
file.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLongSymlink(t *testing.T) {
|
func TestLongSymlink(t *testing.T) {
|
||||||
s := "0123456789abcdef";
|
s := "0123456789abcdef"
|
||||||
// Long, but not too long: a common limit is 255.
|
// Long, but not too long: a common limit is 255.
|
||||||
s = s + s + s + s + s + s + s + s + s + s + s + s + s + s + s;
|
s = s + s + s + s + s + s + s + s + s + s + s + s + s + s + s
|
||||||
from := "longsymlinktestfrom";
|
from := "longsymlinktestfrom"
|
||||||
err := Symlink(s, from);
|
err := Symlink(s, from)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("symlink %q, %q failed: %v", s, from, err)
|
t.Fatalf("symlink %q, %q failed: %v", s, from, err)
|
||||||
}
|
}
|
||||||
defer Remove(from);
|
defer Remove(from)
|
||||||
r, err := Readlink(from);
|
r, err := Readlink(from)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("readlink %q failed: %v", from, err)
|
t.Fatalf("readlink %q failed: %v", from, err)
|
||||||
}
|
}
|
||||||
@ -316,49 +316,49 @@ func TestLongSymlink(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRename(t *testing.T) {
|
func TestRename(t *testing.T) {
|
||||||
from, to := "renamefrom", "renameto";
|
from, to := "renamefrom", "renameto"
|
||||||
Remove(to); // Just in case.
|
Remove(to) // Just in case.
|
||||||
file, err := Open(from, O_CREAT|O_WRONLY, 0666);
|
file, err := Open(from, O_CREAT|O_WRONLY, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("open %q failed: %v", to, err)
|
t.Fatalf("open %q failed: %v", to, err)
|
||||||
}
|
}
|
||||||
if err = file.Close(); err != nil {
|
if err = file.Close(); err != nil {
|
||||||
t.Errorf("close %q failed: %v", to, err)
|
t.Errorf("close %q failed: %v", to, err)
|
||||||
}
|
}
|
||||||
err = Rename(from, to);
|
err = Rename(from, to)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("rename %q, %q failed: %v", to, from, err)
|
t.Fatalf("rename %q, %q failed: %v", to, from, err)
|
||||||
}
|
}
|
||||||
defer Remove(to);
|
defer Remove(to)
|
||||||
_, err = Stat(to);
|
_, err = Stat(to)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("stat %q failed: %v", to, err)
|
t.Errorf("stat %q failed: %v", to, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestForkExec(t *testing.T) {
|
func TestForkExec(t *testing.T) {
|
||||||
r, w, err := Pipe();
|
r, w, err := Pipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Pipe: %v", err)
|
t.Fatalf("Pipe: %v", err)
|
||||||
}
|
}
|
||||||
pid, err := ForkExec("/bin/pwd", []string{"pwd"}, nil, "/", []*File{nil, w, Stderr});
|
pid, err := ForkExec("/bin/pwd", []string{"pwd"}, nil, "/", []*File{nil, w, Stderr})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("ForkExec: %v", err)
|
t.Fatalf("ForkExec: %v", err)
|
||||||
}
|
}
|
||||||
w.Close();
|
w.Close()
|
||||||
|
|
||||||
var b bytes.Buffer;
|
var b bytes.Buffer
|
||||||
io.Copy(&b, r);
|
io.Copy(&b, r)
|
||||||
output := b.String();
|
output := b.String()
|
||||||
expect := "/\n";
|
expect := "/\n"
|
||||||
if output != expect {
|
if output != expect {
|
||||||
t.Errorf("exec /bin/pwd returned %q wanted %q", output, expect)
|
t.Errorf("exec /bin/pwd returned %q wanted %q", output, expect)
|
||||||
}
|
}
|
||||||
Wait(pid, 0);
|
Wait(pid, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkMode(t *testing.T, path string, mode uint32) {
|
func checkMode(t *testing.T, path string, mode uint32) {
|
||||||
dir, err := Stat(path);
|
dir, err := Stat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
|
t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
|
||||||
}
|
}
|
||||||
@ -368,9 +368,9 @@ func checkMode(t *testing.T, path string, mode uint32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestChmod(t *testing.T) {
|
func TestChmod(t *testing.T) {
|
||||||
MkdirAll("_obj", 0777);
|
MkdirAll("_obj", 0777)
|
||||||
const Path = "_obj/_TestChmod_";
|
const Path = "_obj/_TestChmod_"
|
||||||
fd, err := Open(Path, O_WRONLY|O_CREAT, 0666);
|
fd, err := Open(Path, O_WRONLY|O_CREAT, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("create %s: %s", Path, err)
|
t.Fatalf("create %s: %s", Path, err)
|
||||||
}
|
}
|
||||||
@ -378,19 +378,19 @@ func TestChmod(t *testing.T) {
|
|||||||
if err = Chmod(Path, 0456); err != nil {
|
if err = Chmod(Path, 0456); err != nil {
|
||||||
t.Fatalf("chmod %s 0456: %s", Path, err)
|
t.Fatalf("chmod %s 0456: %s", Path, err)
|
||||||
}
|
}
|
||||||
checkMode(t, Path, 0456);
|
checkMode(t, Path, 0456)
|
||||||
|
|
||||||
if err = fd.Chmod(0123); err != nil {
|
if err = fd.Chmod(0123); err != nil {
|
||||||
t.Fatalf("fchmod %s 0123: %s", Path, err)
|
t.Fatalf("fchmod %s 0123: %s", Path, err)
|
||||||
}
|
}
|
||||||
checkMode(t, Path, 0123);
|
checkMode(t, Path, 0123)
|
||||||
|
|
||||||
fd.Close();
|
fd.Close()
|
||||||
Remove(Path);
|
Remove(Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkUidGid(t *testing.T, path string, uid, gid int) {
|
func checkUidGid(t *testing.T, path string, uid, gid int) {
|
||||||
dir, err := Stat(path);
|
dir, err := Stat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Stat %q (looking for uid/gid %d/%d): %s", path, uid, gid, err)
|
t.Fatalf("Stat %q (looking for uid/gid %d/%d): %s", path, uid, gid, err)
|
||||||
}
|
}
|
||||||
@ -408,49 +408,49 @@ func TestChown(t *testing.T) {
|
|||||||
// on the file. If _obj is on NFS, the Getgroups groups are
|
// on the file. If _obj is on NFS, the Getgroups groups are
|
||||||
// basically useless.
|
// basically useless.
|
||||||
|
|
||||||
const Path = "/tmp/_TestChown_";
|
const Path = "/tmp/_TestChown_"
|
||||||
fd, err := Open(Path, O_WRONLY|O_CREAT, 0666);
|
fd, err := Open(Path, O_WRONLY|O_CREAT, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("create %s: %s", Path, err)
|
t.Fatalf("create %s: %s", Path, err)
|
||||||
}
|
}
|
||||||
dir, err := fd.Stat();
|
dir, err := fd.Stat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("fstat %s: %s", Path, err)
|
t.Fatalf("fstat %s: %s", Path, err)
|
||||||
}
|
}
|
||||||
defer fd.Close();
|
defer fd.Close()
|
||||||
defer Remove(Path);
|
defer Remove(Path)
|
||||||
|
|
||||||
// Can't change uid unless root, but can try
|
// Can't change uid unless root, but can try
|
||||||
// changing the group id. First try our current group.
|
// changing the group id. First try our current group.
|
||||||
gid := Getgid();
|
gid := Getgid()
|
||||||
t.Log("gid:", gid);
|
t.Log("gid:", gid)
|
||||||
if err = Chown(Path, -1, gid); err != nil {
|
if err = Chown(Path, -1, gid); err != nil {
|
||||||
t.Fatalf("chown %s -1 %d: %s", Path, gid, err)
|
t.Fatalf("chown %s -1 %d: %s", Path, gid, err)
|
||||||
}
|
}
|
||||||
checkUidGid(t, Path, int(dir.Uid), gid);
|
checkUidGid(t, Path, int(dir.Uid), gid)
|
||||||
|
|
||||||
// Then try all the auxiliary groups.
|
// Then try all the auxiliary groups.
|
||||||
groups, err := Getgroups();
|
groups, err := Getgroups()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("getgroups: %s", err)
|
t.Fatalf("getgroups: %s", err)
|
||||||
}
|
}
|
||||||
t.Log("groups: ", groups);
|
t.Log("groups: ", groups)
|
||||||
for _, g := range groups {
|
for _, g := range groups {
|
||||||
if err = Chown(Path, -1, g); err != nil {
|
if err = Chown(Path, -1, g); err != nil {
|
||||||
t.Fatalf("chown %s -1 %d: %s", Path, g, err)
|
t.Fatalf("chown %s -1 %d: %s", Path, g, err)
|
||||||
}
|
}
|
||||||
checkUidGid(t, Path, int(dir.Uid), g);
|
checkUidGid(t, Path, int(dir.Uid), g)
|
||||||
|
|
||||||
// change back to gid to test fd.Chown
|
// change back to gid to test fd.Chown
|
||||||
if err = fd.Chown(-1, gid); err != nil {
|
if err = fd.Chown(-1, gid); err != nil {
|
||||||
t.Fatalf("fchown %s -1 %d: %s", Path, gid, err)
|
t.Fatalf("fchown %s -1 %d: %s", Path, gid, err)
|
||||||
}
|
}
|
||||||
checkUidGid(t, Path, int(dir.Uid), gid);
|
checkUidGid(t, Path, int(dir.Uid), gid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkSize(t *testing.T, path string, size uint64) {
|
func checkSize(t *testing.T, path string, size uint64) {
|
||||||
dir, err := Stat(path);
|
dir, err := Stat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Stat %q (looking for size %d): %s", path, size, err)
|
t.Fatalf("Stat %q (looking for size %d): %s", path, size, err)
|
||||||
}
|
}
|
||||||
@ -460,73 +460,73 @@ func checkSize(t *testing.T, path string, size uint64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestTruncate(t *testing.T) {
|
func TestTruncate(t *testing.T) {
|
||||||
MkdirAll("_obj", 0777);
|
MkdirAll("_obj", 0777)
|
||||||
const Path = "_obj/_TestTruncate_";
|
const Path = "_obj/_TestTruncate_"
|
||||||
fd, err := Open(Path, O_WRONLY|O_CREAT, 0666);
|
fd, err := Open(Path, O_WRONLY|O_CREAT, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("create %s: %s", Path, err)
|
t.Fatalf("create %s: %s", Path, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkSize(t, Path, 0);
|
checkSize(t, Path, 0)
|
||||||
fd.Write(strings.Bytes("hello, world\n"));
|
fd.Write(strings.Bytes("hello, world\n"))
|
||||||
checkSize(t, Path, 13);
|
checkSize(t, Path, 13)
|
||||||
fd.Truncate(10);
|
fd.Truncate(10)
|
||||||
checkSize(t, Path, 10);
|
checkSize(t, Path, 10)
|
||||||
fd.Truncate(1024);
|
fd.Truncate(1024)
|
||||||
checkSize(t, Path, 1024);
|
checkSize(t, Path, 1024)
|
||||||
fd.Truncate(0);
|
fd.Truncate(0)
|
||||||
checkSize(t, Path, 0);
|
checkSize(t, Path, 0)
|
||||||
fd.Write(strings.Bytes("surprise!"));
|
fd.Write(strings.Bytes("surprise!"))
|
||||||
checkSize(t, Path, 13+9); // wrote at offset past where hello, world was.
|
checkSize(t, Path, 13+9) // wrote at offset past where hello, world was.
|
||||||
fd.Close();
|
fd.Close()
|
||||||
Remove(Path);
|
Remove(Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestChdirAndGetwd(t *testing.T) {
|
func TestChdirAndGetwd(t *testing.T) {
|
||||||
fd, err := Open(".", O_RDONLY, 0);
|
fd, err := Open(".", O_RDONLY, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Open .: %s", err)
|
t.Fatalf("Open .: %s", err)
|
||||||
}
|
}
|
||||||
// These are chosen carefully not to be symlinks on a Mac
|
// These are chosen carefully not to be symlinks on a Mac
|
||||||
// (unlike, say, /var, /etc, and /tmp).
|
// (unlike, say, /var, /etc, and /tmp).
|
||||||
dirs := []string{"/bin", "/", "/usr/bin"};
|
dirs := []string{"/bin", "/", "/usr/bin"}
|
||||||
for mode := 0; mode < 2; mode++ {
|
for mode := 0; mode < 2; mode++ {
|
||||||
for _, d := range dirs {
|
for _, d := range dirs {
|
||||||
if mode == 0 {
|
if mode == 0 {
|
||||||
err = Chdir(d)
|
err = Chdir(d)
|
||||||
} else {
|
} else {
|
||||||
fd1, err := Open(d, O_RDONLY, 0);
|
fd1, err := Open(d, O_RDONLY, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Open %s: %s", d, err);
|
t.Errorf("Open %s: %s", d, err)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
err = fd1.Chdir();
|
err = fd1.Chdir()
|
||||||
fd1.Close();
|
fd1.Close()
|
||||||
}
|
}
|
||||||
pwd, err1 := Getwd();
|
pwd, err1 := Getwd()
|
||||||
err2 := fd.Chdir();
|
err2 := fd.Chdir()
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
// We changed the current directory and cannot go back.
|
// We changed the current directory and cannot go back.
|
||||||
// Don't let the tests continue; they'll scribble
|
// Don't let the tests continue; they'll scribble
|
||||||
// all over some other directory.
|
// all over some other directory.
|
||||||
fmt.Fprintf(Stderr, "fchdir back to dot failed: %s\n", err2);
|
fmt.Fprintf(Stderr, "fchdir back to dot failed: %s\n", err2)
|
||||||
Exit(1);
|
Exit(1)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fd.Close();
|
fd.Close()
|
||||||
t.Fatalf("Chdir %s: %s", d, err);
|
t.Fatalf("Chdir %s: %s", d, err)
|
||||||
}
|
}
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
fd.Close();
|
fd.Close()
|
||||||
t.Fatalf("Getwd in %s: %s", d, err1);
|
t.Fatalf("Getwd in %s: %s", d, err1)
|
||||||
}
|
}
|
||||||
if pwd != d {
|
if pwd != d {
|
||||||
fd.Close();
|
fd.Close()
|
||||||
t.Fatalf("Getwd returned %q want %q", pwd, d);
|
t.Fatalf("Getwd returned %q want %q", pwd, d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fd.Close();
|
fd.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTime(t *testing.T) {
|
func TestTime(t *testing.T) {
|
||||||
@ -536,25 +536,25 @@ func TestTime(t *testing.T) {
|
|||||||
// filling in the structure passed to the system call.
|
// filling in the structure passed to the system call.
|
||||||
// Too bad the compiler doesn't know that
|
// Too bad the compiler doesn't know that
|
||||||
// 365.24*86400 is an integer.
|
// 365.24*86400 is an integer.
|
||||||
sec, nsec, err := Time();
|
sec, nsec, err := Time()
|
||||||
if sec < (2009-1970)*36524*864 {
|
if sec < (2009-1970)*36524*864 {
|
||||||
t.Errorf("Time() = %d, %d, %s; not plausible", sec, nsec, err)
|
t.Errorf("Time() = %d, %d, %s; not plausible", sec, nsec, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSeek(t *testing.T) {
|
func TestSeek(t *testing.T) {
|
||||||
f, err := Open("_obj/seektest", O_CREAT|O_RDWR|O_TRUNC, 0666);
|
f, err := Open("_obj/seektest", O_CREAT|O_RDWR|O_TRUNC, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("open _obj/seektest: %s", err)
|
t.Fatalf("open _obj/seektest: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = "hello, world\n";
|
const data = "hello, world\n"
|
||||||
io.WriteString(f, data);
|
io.WriteString(f, data)
|
||||||
|
|
||||||
type test struct {
|
type test struct {
|
||||||
in int64;
|
in int64
|
||||||
whence int;
|
whence int
|
||||||
out int64;
|
out int64
|
||||||
}
|
}
|
||||||
var tests = []test{
|
var tests = []test{
|
||||||
test{0, 1, int64(len(data))},
|
test{0, 1, int64(len(data))},
|
||||||
@ -565,25 +565,25 @@ func TestSeek(t *testing.T) {
|
|||||||
test{-1, 2, int64(len(data)) - 1},
|
test{-1, 2, int64(len(data)) - 1},
|
||||||
test{1 << 33, 0, 1 << 33},
|
test{1 << 33, 0, 1 << 33},
|
||||||
test{1 << 33, 2, 1<<33 + int64(len(data))},
|
test{1 << 33, 2, 1<<33 + int64(len(data))},
|
||||||
};
|
}
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
off, err := f.Seek(tt.in, tt.whence);
|
off, err := f.Seek(tt.in, tt.whence)
|
||||||
if off != tt.out || err != nil {
|
if off != tt.out || err != nil {
|
||||||
if e, ok := err.(*PathError); ok && e.Error == EINVAL && tt.out > 1<<32 {
|
if e, ok := err.(*PathError); ok && e.Error == EINVAL && tt.out > 1<<32 {
|
||||||
// Reiserfs rejects the big seeks.
|
// Reiserfs rejects the big seeks.
|
||||||
// http://code.google.com/p/go/issues/detail?id=91
|
// http://code.google.com/p/go/issues/detail?id=91
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out);
|
t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.Close();
|
f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
type openErrorTest struct {
|
type openErrorTest struct {
|
||||||
path string;
|
path string
|
||||||
mode int;
|
mode int
|
||||||
error string;
|
error string
|
||||||
}
|
}
|
||||||
|
|
||||||
var openErrorTests = []openErrorTest{
|
var openErrorTests = []openErrorTest{
|
||||||
@ -606,11 +606,11 @@ var openErrorTests = []openErrorTest{
|
|||||||
|
|
||||||
func TestOpenError(t *testing.T) {
|
func TestOpenError(t *testing.T) {
|
||||||
for _, tt := range openErrorTests {
|
for _, tt := range openErrorTests {
|
||||||
f, err := Open(tt.path, tt.mode, 0);
|
f, err := Open(tt.path, tt.mode, 0)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Open(%q, %d) succeeded", tt.path, tt.mode);
|
t.Errorf("Open(%q, %d) succeeded", tt.path, tt.mode)
|
||||||
f.Close();
|
f.Close()
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if s := err.String(); s != tt.error {
|
if s := err.String(); s != tt.error {
|
||||||
t.Errorf("Open(%q, %d) = _, %q; want %q", tt.path, tt.mode, s, tt.error)
|
t.Errorf("Open(%q, %d) = _, %q; want %q", tt.path, tt.mode, s, tt.error)
|
||||||
@ -620,20 +620,20 @@ func TestOpenError(t *testing.T) {
|
|||||||
|
|
||||||
func run(t *testing.T, cmd []string) string {
|
func run(t *testing.T, cmd []string) string {
|
||||||
// Run /bin/hostname and collect output.
|
// Run /bin/hostname and collect output.
|
||||||
r, w, err := Pipe();
|
r, w, err := Pipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
pid, err := ForkExec("/bin/hostname", []string{"hostname"}, nil, "/", []*File{nil, w, Stderr});
|
pid, err := ForkExec("/bin/hostname", []string{"hostname"}, nil, "/", []*File{nil, w, Stderr})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
w.Close();
|
w.Close()
|
||||||
|
|
||||||
var b bytes.Buffer;
|
var b bytes.Buffer
|
||||||
io.Copy(&b, r);
|
io.Copy(&b, r)
|
||||||
Wait(pid, 0);
|
Wait(pid, 0)
|
||||||
output := b.String();
|
output := b.String()
|
||||||
if n := len(output); n > 0 && output[n-1] == '\n' {
|
if n := len(output); n > 0 && output[n-1] == '\n' {
|
||||||
output = output[0 : n-1]
|
output = output[0 : n-1]
|
||||||
}
|
}
|
||||||
@ -641,32 +641,32 @@ func run(t *testing.T, cmd []string) string {
|
|||||||
t.Fatalf("%v produced no output", cmd)
|
t.Fatalf("%v produced no output", cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func TestHostname(t *testing.T) {
|
func TestHostname(t *testing.T) {
|
||||||
// Check internal Hostname() against the output of /bin/hostname.
|
// Check internal Hostname() against the output of /bin/hostname.
|
||||||
hostname, err := Hostname();
|
hostname, err := Hostname()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%v", err)
|
t.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
want := run(t, []string{"/bin/hostname"});
|
want := run(t, []string{"/bin/hostname"})
|
||||||
if hostname != want {
|
if hostname != want {
|
||||||
t.Errorf("Hostname() = %q, want %q", hostname, want)
|
t.Errorf("Hostname() = %q, want %q", hostname, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadAt(t *testing.T) {
|
func TestReadAt(t *testing.T) {
|
||||||
f, err := Open("_obj/readtest", O_CREAT|O_RDWR|O_TRUNC, 0666);
|
f, err := Open("_obj/readtest", O_CREAT|O_RDWR|O_TRUNC, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("open _obj/readtest: %s", err)
|
t.Fatalf("open _obj/readtest: %s", err)
|
||||||
}
|
}
|
||||||
const data = "hello, world\n";
|
const data = "hello, world\n"
|
||||||
io.WriteString(f, data);
|
io.WriteString(f, data)
|
||||||
|
|
||||||
b := make([]byte, 5);
|
b := make([]byte, 5)
|
||||||
n, err := f.ReadAt(b, 7);
|
n, err := f.ReadAt(b, 7)
|
||||||
if err != nil || n != len(b) {
|
if err != nil || n != len(b) {
|
||||||
t.Fatalf("ReadAt 7: %d, %r", n, err)
|
t.Fatalf("ReadAt 7: %d, %r", n, err)
|
||||||
}
|
}
|
||||||
@ -676,19 +676,19 @@ func TestReadAt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestWriteAt(t *testing.T) {
|
func TestWriteAt(t *testing.T) {
|
||||||
f, err := Open("_obj/writetest", O_CREAT|O_RDWR|O_TRUNC, 0666);
|
f, err := Open("_obj/writetest", O_CREAT|O_RDWR|O_TRUNC, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("open _obj/writetest: %s", err)
|
t.Fatalf("open _obj/writetest: %s", err)
|
||||||
}
|
}
|
||||||
const data = "hello, world\n";
|
const data = "hello, world\n"
|
||||||
io.WriteString(f, data);
|
io.WriteString(f, data)
|
||||||
|
|
||||||
n, err := f.WriteAt(strings.Bytes("WORLD"), 7);
|
n, err := f.WriteAt(strings.Bytes("WORLD"), 7)
|
||||||
if err != nil || n != 5 {
|
if err != nil || n != 5 {
|
||||||
t.Fatalf("WriteAt 7: %d, %v", n, err)
|
t.Fatalf("WriteAt 7: %d, %v", n, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := ioutil.ReadFile("_obj/writetest");
|
b, err := ioutil.ReadFile("_obj/writetest")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("ReadFile _obj/writetest: %v", err)
|
t.Fatalf("ReadFile _obj/writetest: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -14,45 +14,45 @@ package os
|
|||||||
// and returns nil.
|
// and returns nil.
|
||||||
func MkdirAll(path string, perm int) Error {
|
func MkdirAll(path string, perm int) Error {
|
||||||
// If path exists, stop with success or error.
|
// If path exists, stop with success or error.
|
||||||
dir, err := Lstat(path);
|
dir, err := Lstat(path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if dir.IsDirectory() {
|
if dir.IsDirectory() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &PathError{"mkdir", path, ENOTDIR};
|
return &PathError{"mkdir", path, ENOTDIR}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Doesn't already exist; make sure parent does.
|
// Doesn't already exist; make sure parent does.
|
||||||
i := len(path);
|
i := len(path)
|
||||||
for i > 0 && path[i-1] == '/' { // Skip trailing slashes.
|
for i > 0 && path[i-1] == '/' { // Skip trailing slashes.
|
||||||
i--
|
i--
|
||||||
}
|
}
|
||||||
|
|
||||||
j := i;
|
j := i
|
||||||
for j > 0 && path[j-1] != '/' { // Scan backward over element.
|
for j > 0 && path[j-1] != '/' { // Scan backward over element.
|
||||||
j--
|
j--
|
||||||
}
|
}
|
||||||
|
|
||||||
if j > 0 {
|
if j > 0 {
|
||||||
// Create parent
|
// Create parent
|
||||||
err = MkdirAll(path[0:j-1], perm);
|
err = MkdirAll(path[0:j-1], perm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now parent exists, try to create.
|
// Now parent exists, try to create.
|
||||||
err = Mkdir(path, perm);
|
err = Mkdir(path, perm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Handle arguments like "foo/." by
|
// Handle arguments like "foo/." by
|
||||||
// double-checking that directory doesn't exist.
|
// double-checking that directory doesn't exist.
|
||||||
dir, err1 := Lstat(path);
|
dir, err1 := Lstat(path)
|
||||||
if err1 == nil && dir.IsDirectory() {
|
if err1 == nil && dir.IsDirectory() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveAll removes path and any children it contains.
|
// RemoveAll removes path and any children it contains.
|
||||||
@ -61,18 +61,18 @@ func MkdirAll(path string, perm int) Error {
|
|||||||
// returns nil (no error).
|
// returns nil (no error).
|
||||||
func RemoveAll(path string) Error {
|
func RemoveAll(path string) Error {
|
||||||
// Simple case: if Remove works, we're done.
|
// Simple case: if Remove works, we're done.
|
||||||
err := Remove(path);
|
err := Remove(path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, is this a directory we need to recurse into?
|
// Otherwise, is this a directory we need to recurse into?
|
||||||
dir, serr := Lstat(path);
|
dir, serr := Lstat(path)
|
||||||
if serr != nil {
|
if serr != nil {
|
||||||
if serr, ok := serr.(*PathError); ok && serr.Error == ENOENT {
|
if serr, ok := serr.(*PathError); ok && serr.Error == ENOENT {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return serr;
|
return serr
|
||||||
}
|
}
|
||||||
if !dir.IsDirectory() {
|
if !dir.IsDirectory() {
|
||||||
// Not a directory; return the error from Remove.
|
// Not a directory; return the error from Remove.
|
||||||
@ -80,18 +80,18 @@ func RemoveAll(path string) Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Directory.
|
// Directory.
|
||||||
fd, err := Open(path, O_RDONLY, 0);
|
fd, err := Open(path, O_RDONLY, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer fd.Close();
|
defer fd.Close()
|
||||||
|
|
||||||
// Remove contents & return first error.
|
// Remove contents & return first error.
|
||||||
err = nil;
|
err = nil
|
||||||
for {
|
for {
|
||||||
names, err1 := fd.Readdirnames(100);
|
names, err1 := fd.Readdirnames(100)
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
err1 := RemoveAll(path + "/" + name);
|
err1 := RemoveAll(path + "/" + name)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = err1
|
err = err1
|
||||||
}
|
}
|
||||||
@ -106,9 +106,9 @@ func RemoveAll(path string) Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove directory.
|
// Remove directory.
|
||||||
err1 := Remove(path);
|
err1 := Remove(path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = err1
|
err = err1
|
||||||
}
|
}
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
|
@ -5,38 +5,38 @@
|
|||||||
package os_test
|
package os_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "os";
|
. "os"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMkdirAll(t *testing.T) {
|
func TestMkdirAll(t *testing.T) {
|
||||||
// Create new dir, in _obj so it will get
|
// Create new dir, in _obj so it will get
|
||||||
// cleaned up by make if not by us.
|
// cleaned up by make if not by us.
|
||||||
path := "_obj/_TestMkdirAll_/dir/./dir2";
|
path := "_obj/_TestMkdirAll_/dir/./dir2"
|
||||||
err := MkdirAll(path, 0777);
|
err := MkdirAll(path, 0777)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("MkdirAll %q: %s", path, err)
|
t.Fatalf("MkdirAll %q: %s", path, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Already exists, should succeed.
|
// Already exists, should succeed.
|
||||||
err = MkdirAll(path, 0777);
|
err = MkdirAll(path, 0777)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("MkdirAll %q (second time): %s", path, err)
|
t.Fatalf("MkdirAll %q (second time): %s", path, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make file.
|
// Make file.
|
||||||
fpath := path + "/file";
|
fpath := path + "/file"
|
||||||
_, err = Open(fpath, O_WRONLY|O_CREAT, 0666);
|
_, err = Open(fpath, O_WRONLY|O_CREAT, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("create %q: %s", fpath, err)
|
t.Fatalf("create %q: %s", fpath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can't make directory named after file.
|
// Can't make directory named after file.
|
||||||
err = MkdirAll(fpath, 0777);
|
err = MkdirAll(fpath, 0777)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("MkdirAll %q: no error")
|
t.Fatalf("MkdirAll %q: no error")
|
||||||
}
|
}
|
||||||
perr, ok := err.(*PathError);
|
perr, ok := err.(*PathError)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("MkdirAll %q returned %T, not *PathError", fpath, err)
|
t.Fatalf("MkdirAll %q returned %T, not *PathError", fpath, err)
|
||||||
}
|
}
|
||||||
@ -45,12 +45,12 @@ func TestMkdirAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Can't make subdirectory of file.
|
// Can't make subdirectory of file.
|
||||||
ffpath := fpath + "/subdir";
|
ffpath := fpath + "/subdir"
|
||||||
err = MkdirAll(ffpath, 0777);
|
err = MkdirAll(ffpath, 0777)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("MkdirAll %q: no error")
|
t.Fatalf("MkdirAll %q: no error")
|
||||||
}
|
}
|
||||||
perr, ok = err.(*PathError);
|
perr, ok = err.(*PathError)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("MkdirAll %q returned %T, not *PathError", ffpath, err)
|
t.Fatalf("MkdirAll %q returned %T, not *PathError", ffpath, err)
|
||||||
}
|
}
|
||||||
@ -58,24 +58,24 @@ func TestMkdirAll(t *testing.T) {
|
|||||||
t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, perr.Path, fpath)
|
t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, perr.Path, fpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveAll("_obj/_TestMkdirAll_");
|
RemoveAll("_obj/_TestMkdirAll_")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveAll(t *testing.T) {
|
func TestRemoveAll(t *testing.T) {
|
||||||
// Work directory.
|
// Work directory.
|
||||||
path := "_obj/_TestRemoveAll_";
|
path := "_obj/_TestRemoveAll_"
|
||||||
fpath := path + "/file";
|
fpath := path + "/file"
|
||||||
dpath := path + "/dir";
|
dpath := path + "/dir"
|
||||||
|
|
||||||
// Make directory with 1 file and remove.
|
// Make directory with 1 file and remove.
|
||||||
if err := MkdirAll(path, 0777); err != nil {
|
if err := MkdirAll(path, 0777); err != nil {
|
||||||
t.Fatalf("MkdirAll %q: %s", path, err)
|
t.Fatalf("MkdirAll %q: %s", path, err)
|
||||||
}
|
}
|
||||||
fd, err := Open(fpath, O_WRONLY|O_CREAT, 0666);
|
fd, err := Open(fpath, O_WRONLY|O_CREAT, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("create %q: %s", fpath, err)
|
t.Fatalf("create %q: %s", fpath, err)
|
||||||
}
|
}
|
||||||
fd.Close();
|
fd.Close()
|
||||||
if err = RemoveAll(path); err != nil {
|
if err = RemoveAll(path); err != nil {
|
||||||
t.Fatalf("RemoveAll %q (first): %s", path, err)
|
t.Fatalf("RemoveAll %q (first): %s", path, err)
|
||||||
}
|
}
|
||||||
@ -87,16 +87,16 @@ func TestRemoveAll(t *testing.T) {
|
|||||||
if err = MkdirAll(dpath, 0777); err != nil {
|
if err = MkdirAll(dpath, 0777); err != nil {
|
||||||
t.Fatalf("MkdirAll %q: %s", dpath, err)
|
t.Fatalf("MkdirAll %q: %s", dpath, err)
|
||||||
}
|
}
|
||||||
fd, err = Open(fpath, O_WRONLY|O_CREAT, 0666);
|
fd, err = Open(fpath, O_WRONLY|O_CREAT, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("create %q: %s", fpath, err)
|
t.Fatalf("create %q: %s", fpath, err)
|
||||||
}
|
}
|
||||||
fd.Close();
|
fd.Close()
|
||||||
fd, err = Open(dpath+"/file", O_WRONLY|O_CREAT, 0666);
|
fd, err = Open(dpath+"/file", O_WRONLY|O_CREAT, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("create %q: %s", fpath, err)
|
t.Fatalf("create %q: %s", fpath, err)
|
||||||
}
|
}
|
||||||
fd.Close();
|
fd.Close()
|
||||||
if err = RemoveAll(path); err != nil {
|
if err = RemoveAll(path); err != nil {
|
||||||
t.Fatalf("RemoveAll %q (second): %s", path, err)
|
t.Fatalf("RemoveAll %q (second): %s", path, err)
|
||||||
}
|
}
|
||||||
@ -111,23 +111,23 @@ func TestRemoveAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range []string{fpath, dpath + "/file1", path + "/zzz"} {
|
for _, s := range []string{fpath, dpath + "/file1", path + "/zzz"} {
|
||||||
fd, err = Open(s, O_WRONLY|O_CREAT, 0666);
|
fd, err = Open(s, O_WRONLY|O_CREAT, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("create %q: %s", s, err)
|
t.Fatalf("create %q: %s", s, err)
|
||||||
}
|
}
|
||||||
fd.Close();
|
fd.Close()
|
||||||
}
|
}
|
||||||
if err = Chmod(dpath, 0); err != nil {
|
if err = Chmod(dpath, 0); err != nil {
|
||||||
t.Fatalf("Chmod %q 0: %s", dpath, err)
|
t.Fatalf("Chmod %q 0: %s", dpath, err)
|
||||||
}
|
}
|
||||||
if err = RemoveAll(path); err == nil {
|
if err = RemoveAll(path); err == nil {
|
||||||
_, err := Lstat(path);
|
_, err := Lstat(path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Can lstat %q after supposed RemoveAll", path)
|
t.Errorf("Can lstat %q after supposed RemoveAll", path)
|
||||||
}
|
}
|
||||||
t.Fatalf("RemoveAll %q succeeded with chmod 0 subdirectory", path, err);
|
t.Fatalf("RemoveAll %q succeeded with chmod 0 subdirectory", path, err)
|
||||||
}
|
}
|
||||||
perr, ok := err.(*PathError);
|
perr, ok := err.(*PathError)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("RemoveAll %q returned %T not *PathError", path, err)
|
t.Fatalf("RemoveAll %q returned %T not *PathError", path, err)
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,8 @@ func Getegid() int { return syscall.Getegid() }
|
|||||||
|
|
||||||
// Getgroups returns a list of the numeric ids of groups that the caller belongs to.
|
// Getgroups returns a list of the numeric ids of groups that the caller belongs to.
|
||||||
func Getgroups() ([]int, Error) {
|
func Getgroups() ([]int, Error) {
|
||||||
gids, errno := syscall.Getgroups();
|
gids, errno := syscall.Getgroups()
|
||||||
return gids, NewSyscallError("getgroups", errno);
|
return gids, NewSyscallError("getgroups", errno)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exit causes the current program to exit with the given status code.
|
// Exit causes the current program to exit with the given status code.
|
||||||
|
@ -11,28 +11,28 @@ func isSymlink(stat *syscall.Stat_t) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
|
func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
|
||||||
dir.Dev = uint64(stat.Dev);
|
dir.Dev = uint64(stat.Dev)
|
||||||
dir.Ino = stat.Ino;
|
dir.Ino = stat.Ino
|
||||||
dir.Nlink = uint64(stat.Nlink);
|
dir.Nlink = uint64(stat.Nlink)
|
||||||
dir.Mode = uint32(stat.Mode);
|
dir.Mode = uint32(stat.Mode)
|
||||||
dir.Uid = stat.Uid;
|
dir.Uid = stat.Uid
|
||||||
dir.Gid = stat.Gid;
|
dir.Gid = stat.Gid
|
||||||
dir.Rdev = uint64(stat.Rdev);
|
dir.Rdev = uint64(stat.Rdev)
|
||||||
dir.Size = uint64(stat.Size);
|
dir.Size = uint64(stat.Size)
|
||||||
dir.Blksize = uint64(stat.Blksize);
|
dir.Blksize = uint64(stat.Blksize)
|
||||||
dir.Blocks = uint64(stat.Blocks);
|
dir.Blocks = uint64(stat.Blocks)
|
||||||
dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atimespec));
|
dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atimespec))
|
||||||
dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtimespec));
|
dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtimespec))
|
||||||
dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctimespec));
|
dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctimespec))
|
||||||
for i := len(name) - 1; i >= 0; i-- {
|
for i := len(name) - 1; i >= 0; i-- {
|
||||||
if name[i] == '/' {
|
if name[i] == '/' {
|
||||||
name = name[i+1:];
|
name = name[i+1:]
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dir.Name = name;
|
dir.Name = name
|
||||||
if isSymlink(lstat) && !isSymlink(stat) {
|
if isSymlink(lstat) && !isSymlink(stat) {
|
||||||
dir.FollowedSymlink = true
|
dir.FollowedSymlink = true
|
||||||
}
|
}
|
||||||
return dir;
|
return dir
|
||||||
}
|
}
|
||||||
|
@ -11,28 +11,28 @@ func isSymlink(stat *syscall.Stat_t) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
|
func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
|
||||||
dir.Dev = uint64(stat.Dev);
|
dir.Dev = uint64(stat.Dev)
|
||||||
dir.Ino = uint64(stat.Ino);
|
dir.Ino = uint64(stat.Ino)
|
||||||
dir.Nlink = uint64(stat.Nlink);
|
dir.Nlink = uint64(stat.Nlink)
|
||||||
dir.Mode = uint32(stat.Mode);
|
dir.Mode = uint32(stat.Mode)
|
||||||
dir.Uid = stat.Uid;
|
dir.Uid = stat.Uid
|
||||||
dir.Gid = stat.Gid;
|
dir.Gid = stat.Gid
|
||||||
dir.Rdev = uint64(stat.Rdev);
|
dir.Rdev = uint64(stat.Rdev)
|
||||||
dir.Size = uint64(stat.Size);
|
dir.Size = uint64(stat.Size)
|
||||||
dir.Blksize = uint64(stat.Blksize);
|
dir.Blksize = uint64(stat.Blksize)
|
||||||
dir.Blocks = uint64(stat.Blocks);
|
dir.Blocks = uint64(stat.Blocks)
|
||||||
dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atimespec));
|
dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atimespec))
|
||||||
dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtimespec));
|
dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtimespec))
|
||||||
dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctimespec));
|
dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctimespec))
|
||||||
for i := len(name) - 1; i >= 0; i-- {
|
for i := len(name) - 1; i >= 0; i-- {
|
||||||
if name[i] == '/' {
|
if name[i] == '/' {
|
||||||
name = name[i+1:];
|
name = name[i+1:]
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dir.Name = name;
|
dir.Name = name
|
||||||
if isSymlink(lstat) && !isSymlink(stat) {
|
if isSymlink(lstat) && !isSymlink(stat) {
|
||||||
dir.FollowedSymlink = true
|
dir.FollowedSymlink = true
|
||||||
}
|
}
|
||||||
return dir;
|
return dir
|
||||||
}
|
}
|
||||||
|
@ -11,28 +11,28 @@ func isSymlink(stat *syscall.Stat_t) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
|
func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
|
||||||
dir.Dev = stat.Dev;
|
dir.Dev = stat.Dev
|
||||||
dir.Ino = uint64(stat.Ino);
|
dir.Ino = uint64(stat.Ino)
|
||||||
dir.Nlink = uint64(stat.Nlink);
|
dir.Nlink = uint64(stat.Nlink)
|
||||||
dir.Mode = stat.Mode;
|
dir.Mode = stat.Mode
|
||||||
dir.Uid = stat.Uid;
|
dir.Uid = stat.Uid
|
||||||
dir.Gid = stat.Gid;
|
dir.Gid = stat.Gid
|
||||||
dir.Rdev = stat.Rdev;
|
dir.Rdev = stat.Rdev
|
||||||
dir.Size = uint64(stat.Size);
|
dir.Size = uint64(stat.Size)
|
||||||
dir.Blksize = uint64(stat.Blksize);
|
dir.Blksize = uint64(stat.Blksize)
|
||||||
dir.Blocks = uint64(stat.Blocks);
|
dir.Blocks = uint64(stat.Blocks)
|
||||||
dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atim));
|
dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atim))
|
||||||
dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtim));
|
dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtim))
|
||||||
dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctim));
|
dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctim))
|
||||||
for i := len(name) - 1; i >= 0; i-- {
|
for i := len(name) - 1; i >= 0; i-- {
|
||||||
if name[i] == '/' {
|
if name[i] == '/' {
|
||||||
name = name[i+1:];
|
name = name[i+1:]
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dir.Name = name;
|
dir.Name = name
|
||||||
if isSymlink(lstat) && !isSymlink(stat) {
|
if isSymlink(lstat) && !isSymlink(stat) {
|
||||||
dir.FollowedSymlink = true
|
dir.FollowedSymlink = true
|
||||||
}
|
}
|
||||||
return dir;
|
return dir
|
||||||
}
|
}
|
||||||
|
@ -11,28 +11,28 @@ func isSymlink(stat *syscall.Stat_t) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
|
func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir {
|
||||||
dir.Dev = uint64(stat.Dev);
|
dir.Dev = uint64(stat.Dev)
|
||||||
dir.Ino = uint64(stat.Ino);
|
dir.Ino = uint64(stat.Ino)
|
||||||
dir.Nlink = uint64(stat.Nlink);
|
dir.Nlink = uint64(stat.Nlink)
|
||||||
dir.Mode = stat.Mode;
|
dir.Mode = stat.Mode
|
||||||
dir.Uid = stat.Uid;
|
dir.Uid = stat.Uid
|
||||||
dir.Gid = stat.Gid;
|
dir.Gid = stat.Gid
|
||||||
dir.Rdev = uint64(stat.Rdev);
|
dir.Rdev = uint64(stat.Rdev)
|
||||||
dir.Size = uint64(stat.Size);
|
dir.Size = uint64(stat.Size)
|
||||||
dir.Blksize = uint64(stat.Blksize);
|
dir.Blksize = uint64(stat.Blksize)
|
||||||
dir.Blocks = uint64(stat.Blocks);
|
dir.Blocks = uint64(stat.Blocks)
|
||||||
dir.Atime_ns = uint64(stat.Atime) * 1e9;
|
dir.Atime_ns = uint64(stat.Atime) * 1e9
|
||||||
dir.Mtime_ns = uint64(stat.Mtime) * 1e9;
|
dir.Mtime_ns = uint64(stat.Mtime) * 1e9
|
||||||
dir.Ctime_ns = uint64(stat.Ctime) * 1e9;
|
dir.Ctime_ns = uint64(stat.Ctime) * 1e9
|
||||||
for i := len(name) - 1; i >= 0; i-- {
|
for i := len(name) - 1; i >= 0; i-- {
|
||||||
if name[i] == '/' {
|
if name[i] == '/' {
|
||||||
name = name[i+1:];
|
name = name[i+1:]
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dir.Name = name;
|
dir.Name = name
|
||||||
if isSymlink(lstat) && !isSymlink(stat) {
|
if isSymlink(lstat) && !isSymlink(stat) {
|
||||||
dir.FollowedSymlink = true
|
dir.FollowedSymlink = true
|
||||||
}
|
}
|
||||||
return dir;
|
return dir
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,10 @@ package os
|
|||||||
import "syscall"
|
import "syscall"
|
||||||
|
|
||||||
func Hostname() (name string, err Error) {
|
func Hostname() (name string, err Error) {
|
||||||
var errno int;
|
var errno int
|
||||||
name, errno = syscall.Sysctl("kern.hostname");
|
name, errno = syscall.Sysctl("kern.hostname")
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return "", NewSyscallError("sysctl kern.hostname", errno)
|
return "", NewSyscallError("sysctl kern.hostname", errno)
|
||||||
}
|
}
|
||||||
return name, nil;
|
return name, nil
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,10 @@ package os
|
|||||||
import "syscall"
|
import "syscall"
|
||||||
|
|
||||||
func Hostname() (name string, err Error) {
|
func Hostname() (name string, err Error) {
|
||||||
var errno int;
|
var errno int
|
||||||
name, errno = syscall.Sysctl("kern.hostname");
|
name, errno = syscall.Sysctl("kern.hostname")
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return "", NewSyscallError("sysctl kern.hostname", errno)
|
return "", NewSyscallError("sysctl kern.hostname", errno)
|
||||||
}
|
}
|
||||||
return name, nil;
|
return name, nil
|
||||||
}
|
}
|
||||||
|
@ -9,14 +9,14 @@ package os
|
|||||||
|
|
||||||
// Hostname returns the host name reported by the kernel.
|
// Hostname returns the host name reported by the kernel.
|
||||||
func Hostname() (name string, err Error) {
|
func Hostname() (name string, err Error) {
|
||||||
f, err := Open("/proc/sys/kernel/hostname", O_RDONLY, 0);
|
f, err := Open("/proc/sys/kernel/hostname", O_RDONLY, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer f.Close();
|
defer f.Close()
|
||||||
|
|
||||||
var buf [512]byte; // Enough for a DNS name.
|
var buf [512]byte // Enough for a DNS name.
|
||||||
n, err := f.Read(&buf);
|
n, err := f.Read(&buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -24,5 +24,5 @@ func Hostname() (name string, err Error) {
|
|||||||
if n > 0 && buf[n-1] == '\n' {
|
if n > 0 && buf[n-1] == '\n' {
|
||||||
n--
|
n--
|
||||||
}
|
}
|
||||||
return string(buf[0:n]), nil;
|
return string(buf[0:n]), nil
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,9 @@ import "syscall"
|
|||||||
// time is thus 1e9*sec+nsec, in nanoseconds. The zero of
|
// time is thus 1e9*sec+nsec, in nanoseconds. The zero of
|
||||||
// time is the Unix epoch.
|
// time is the Unix epoch.
|
||||||
func Time() (sec int64, nsec int64, err Error) {
|
func Time() (sec int64, nsec int64, err Error) {
|
||||||
var tv syscall.Timeval;
|
var tv syscall.Timeval
|
||||||
if errno := syscall.Gettimeofday(&tv); errno != 0 {
|
if errno := syscall.Gettimeofday(&tv); errno != 0 {
|
||||||
return 0, 0, NewSyscallError("gettimeofday", errno)
|
return 0, 0, NewSyscallError("gettimeofday", errno)
|
||||||
}
|
}
|
||||||
return int64(tv.Sec), int64(tv.Usec) * 1000, err;
|
return int64(tv.Sec), int64(tv.Usec) * 1000, err
|
||||||
}
|
}
|
||||||
|
@ -14,21 +14,21 @@ func Getpagesize() int { return syscall.Getpagesize() }
|
|||||||
|
|
||||||
// A Dir describes a file and is returned by Stat, Fstat, and Lstat
|
// A Dir describes a file and is returned by Stat, Fstat, and Lstat
|
||||||
type Dir struct {
|
type Dir struct {
|
||||||
Dev uint64; // device number of file system holding file.
|
Dev uint64 // device number of file system holding file.
|
||||||
Ino uint64; // inode number.
|
Ino uint64 // inode number.
|
||||||
Nlink uint64; // number of hard links.
|
Nlink uint64 // number of hard links.
|
||||||
Mode uint32; // permission and mode bits.
|
Mode uint32 // permission and mode bits.
|
||||||
Uid uint32; // user id of owner.
|
Uid uint32 // user id of owner.
|
||||||
Gid uint32; // group id of owner.
|
Gid uint32 // group id of owner.
|
||||||
Rdev uint64; // device type for special file.
|
Rdev uint64 // device type for special file.
|
||||||
Size uint64; // length in bytes.
|
Size uint64 // length in bytes.
|
||||||
Blksize uint64; // size of blocks, in bytes.
|
Blksize uint64 // size of blocks, in bytes.
|
||||||
Blocks uint64; // number of blocks allocated for file.
|
Blocks uint64 // number of blocks allocated for file.
|
||||||
Atime_ns uint64; // access time; nanoseconds since epoch.
|
Atime_ns uint64 // access time; nanoseconds since epoch.
|
||||||
Mtime_ns uint64; // modified time; nanoseconds since epoch.
|
Mtime_ns uint64 // modified time; nanoseconds since epoch.
|
||||||
Ctime_ns uint64; // status change time; nanoseconds since epoch.
|
Ctime_ns uint64 // status change time; nanoseconds since epoch.
|
||||||
Name string; // name of file as presented to Open.
|
Name string // name of file as presented to Open.
|
||||||
FollowedSymlink bool; // followed a symlink to get this information
|
FollowedSymlink bool // followed a symlink to get this information
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsFifo reports whether the Dir describes a FIFO file.
|
// IsFifo reports whether the Dir describes a FIFO file.
|
||||||
|
@ -8,11 +8,11 @@ import "os"
|
|||||||
|
|
||||||
// An Op is a single operation to execute to apply a patch.
|
// An Op is a single operation to execute to apply a patch.
|
||||||
type Op struct {
|
type Op struct {
|
||||||
Verb Verb; // action
|
Verb Verb // action
|
||||||
Src string; // source file
|
Src string // source file
|
||||||
Dst string; // destination file
|
Dst string // destination file
|
||||||
Mode int; // mode for destination (if non-zero)
|
Mode int // mode for destination (if non-zero)
|
||||||
Data []byte; // data for destination (if non-nil)
|
Data []byte // data for destination (if non-nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply applies the patch set to the files named in the patch set,
|
// Apply applies the patch set to the files named in the patch set,
|
||||||
@ -24,31 +24,31 @@ type Op struct {
|
|||||||
// Typically this function will be io.ReadFile.
|
// Typically this function will be io.ReadFile.
|
||||||
//
|
//
|
||||||
func (set *Set) Apply(readFile func(string) ([]byte, os.Error)) ([]Op, os.Error) {
|
func (set *Set) Apply(readFile func(string) ([]byte, os.Error)) ([]Op, os.Error) {
|
||||||
op := make([]Op, len(set.File));
|
op := make([]Op, len(set.File))
|
||||||
|
|
||||||
for i, f := range set.File {
|
for i, f := range set.File {
|
||||||
o := &op[i];
|
o := &op[i]
|
||||||
o.Verb = f.Verb;
|
o.Verb = f.Verb
|
||||||
o.Src = f.Src;
|
o.Src = f.Src
|
||||||
o.Dst = f.Dst;
|
o.Dst = f.Dst
|
||||||
o.Mode = f.NewMode;
|
o.Mode = f.NewMode
|
||||||
if f.Diff != NoDiff || o.Verb != Edit {
|
if f.Diff != NoDiff || o.Verb != Edit {
|
||||||
// Clients assume o.Data == nil means no data diff.
|
// Clients assume o.Data == nil means no data diff.
|
||||||
// Start with a non-nil data.
|
// Start with a non-nil data.
|
||||||
var old []byte = make([]byte, 0); // not nil
|
var old []byte = make([]byte, 0) // not nil
|
||||||
var err os.Error;
|
var err os.Error
|
||||||
if f.Src != "" {
|
if f.Src != "" {
|
||||||
old, err = readFile(f.Src);
|
old, err = readFile(f.Src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &os.PathError{string(f.Verb), f.Src, err}
|
return nil, &os.PathError{string(f.Verb), f.Src, err}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
o.Data, err = f.Diff.Apply(old);
|
o.Data, err = f.Diff.Apply(old)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &os.PathError{string(f.Verb), f.Src, err}
|
return nil, &os.PathError{string(f.Verb), f.Src, err}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return op, nil;
|
return op, nil
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,13 @@
|
|||||||
package patch
|
package patch
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes";
|
"bytes"
|
||||||
"compress/zlib";
|
"compress/zlib"
|
||||||
"crypto/sha1";
|
"crypto/sha1"
|
||||||
"encoding/git85";
|
"encoding/git85"
|
||||||
"fmt";
|
"fmt"
|
||||||
"io";
|
"io"
|
||||||
"os";
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
func gitSHA1(data []byte) []byte {
|
func gitSHA1(data []byte) []byte {
|
||||||
@ -19,18 +19,18 @@ func gitSHA1(data []byte) []byte {
|
|||||||
// special case: 0 length is all zeros sum
|
// special case: 0 length is all zeros sum
|
||||||
return make([]byte, 20)
|
return make([]byte, 20)
|
||||||
}
|
}
|
||||||
h := sha1.New();
|
h := sha1.New()
|
||||||
fmt.Fprintf(h, "blob %d\x00", len(data));
|
fmt.Fprintf(h, "blob %d\x00", len(data))
|
||||||
h.Write(data);
|
h.Write(data)
|
||||||
return h.Sum();
|
return h.Sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
// BUG(rsc): The Git binary delta format is not implemented, only Git binary literals.
|
// BUG(rsc): The Git binary delta format is not implemented, only Git binary literals.
|
||||||
|
|
||||||
// GitBinaryLiteral represents a Git binary literal diff.
|
// GitBinaryLiteral represents a Git binary literal diff.
|
||||||
type GitBinaryLiteral struct {
|
type GitBinaryLiteral struct {
|
||||||
OldSHA1 []byte; // if non-empty, the SHA1 hash of the original
|
OldSHA1 []byte // if non-empty, the SHA1 hash of the original
|
||||||
New []byte; // the new contents
|
New []byte // the new contents
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply implements the Diff interface's Apply method.
|
// Apply implements the Diff interface's Apply method.
|
||||||
@ -38,7 +38,7 @@ func (d *GitBinaryLiteral) Apply(old []byte) ([]byte, os.Error) {
|
|||||||
if sum := gitSHA1(old); !bytes.HasPrefix(sum, d.OldSHA1) {
|
if sum := gitSHA1(old); !bytes.HasPrefix(sum, d.OldSHA1) {
|
||||||
return nil, ErrPatchFailure
|
return nil, ErrPatchFailure
|
||||||
}
|
}
|
||||||
return d.New, nil;
|
return d.New, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func unhex(c byte) uint8 {
|
func unhex(c byte) uint8 {
|
||||||
@ -50,60 +50,60 @@ func unhex(c byte) uint8 {
|
|||||||
case 'A' <= c && c <= 'F':
|
case 'A' <= c && c <= 'F':
|
||||||
return c - 'A' + 10
|
return c - 'A' + 10
|
||||||
}
|
}
|
||||||
return 255;
|
return 255
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHex(s []byte) (data []byte, rest []byte) {
|
func getHex(s []byte) (data []byte, rest []byte) {
|
||||||
n := 0;
|
n := 0
|
||||||
for n < len(s) && unhex(s[n]) != 255 {
|
for n < len(s) && unhex(s[n]) != 255 {
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
n &^= 1; // Only take an even number of hex digits.
|
n &^= 1 // Only take an even number of hex digits.
|
||||||
data = make([]byte, n/2);
|
data = make([]byte, n/2)
|
||||||
for i := range data {
|
for i := range data {
|
||||||
data[i] = unhex(s[2*i])<<4 | unhex(s[2*i+1])
|
data[i] = unhex(s[2*i])<<4 | unhex(s[2*i+1])
|
||||||
}
|
}
|
||||||
rest = s[n:];
|
rest = s[n:]
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseGitBinary parses raw as a Git binary patch.
|
// ParseGitBinary parses raw as a Git binary patch.
|
||||||
func ParseGitBinary(raw []byte) (Diff, os.Error) {
|
func ParseGitBinary(raw []byte) (Diff, os.Error) {
|
||||||
var oldSHA1, newSHA1 []byte;
|
var oldSHA1, newSHA1 []byte
|
||||||
var sawBinary bool;
|
var sawBinary bool
|
||||||
|
|
||||||
for {
|
for {
|
||||||
var first []byte;
|
var first []byte
|
||||||
first, raw, _ = getLine(raw, 1);
|
first, raw, _ = getLine(raw, 1)
|
||||||
first = bytes.TrimSpace(first);
|
first = bytes.TrimSpace(first)
|
||||||
if s, ok := skip(first, "index "); ok {
|
if s, ok := skip(first, "index "); ok {
|
||||||
oldSHA1, s = getHex(s);
|
oldSHA1, s = getHex(s)
|
||||||
if s, ok = skip(s, ".."); !ok {
|
if s, ok = skip(s, ".."); !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
newSHA1, s = getHex(s);
|
newSHA1, s = getHex(s)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if _, ok := skip(first, "GIT binary patch"); ok {
|
if _, ok := skip(first, "GIT binary patch"); ok {
|
||||||
sawBinary = true;
|
sawBinary = true
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if n, _, ok := atoi(first, "literal ", 10); ok && sawBinary {
|
if n, _, ok := atoi(first, "literal ", 10); ok && sawBinary {
|
||||||
data := make([]byte, n);
|
data := make([]byte, n)
|
||||||
d := git85.NewDecoder(bytes.NewBuffer(raw));
|
d := git85.NewDecoder(bytes.NewBuffer(raw))
|
||||||
z, err := zlib.NewInflater(d);
|
z, err := zlib.NewInflater(d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer z.Close();
|
defer z.Close()
|
||||||
if _, err = io.ReadFull(z, data); err != nil {
|
if _, err = io.ReadFull(z, data); err != nil {
|
||||||
if err == os.EOF {
|
if err == os.EOF {
|
||||||
err = io.ErrUnexpectedEOF
|
err = io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
return nil, err;
|
return nil, err
|
||||||
}
|
}
|
||||||
var buf [1]byte;
|
var buf [1]byte
|
||||||
m, err := z.Read(&buf);
|
m, err := z.Read(&buf)
|
||||||
if m != 0 || err != os.EOF {
|
if m != 0 || err != os.EOF {
|
||||||
return nil, os.NewError("Git binary literal longer than expected")
|
return nil, os.NewError("Git binary literal longer than expected")
|
||||||
}
|
}
|
||||||
@ -111,11 +111,11 @@ func ParseGitBinary(raw []byte) (Diff, os.Error) {
|
|||||||
if sum := gitSHA1(data); !bytes.HasPrefix(sum, newSHA1) {
|
if sum := gitSHA1(data); !bytes.HasPrefix(sum, newSHA1) {
|
||||||
return nil, os.NewError("Git binary literal SHA1 mismatch")
|
return nil, os.NewError("Git binary literal SHA1 mismatch")
|
||||||
}
|
}
|
||||||
return &GitBinaryLiteral{oldSHA1, data}, nil;
|
return &GitBinaryLiteral{oldSHA1, data}, nil
|
||||||
}
|
}
|
||||||
if !sawBinary {
|
if !sawBinary {
|
||||||
return nil, os.NewError("unexpected Git patch header: " + string(first))
|
return nil, os.NewError("unexpected Git patch header: " + string(first))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic("unreachable");
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
|
@ -8,37 +8,37 @@
|
|||||||
package patch
|
package patch
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes";
|
"bytes"
|
||||||
"os";
|
"os"
|
||||||
"path";
|
"path"
|
||||||
"strings";
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Set represents a set of patches to be applied as a single atomic unit.
|
// A Set represents a set of patches to be applied as a single atomic unit.
|
||||||
// Patch sets are often preceded by a descriptive header.
|
// Patch sets are often preceded by a descriptive header.
|
||||||
type Set struct {
|
type Set struct {
|
||||||
Header string; // free-form text
|
Header string // free-form text
|
||||||
File []*File;
|
File []*File
|
||||||
}
|
}
|
||||||
|
|
||||||
// A File represents a collection of changes to be made to a single file.
|
// A File represents a collection of changes to be made to a single file.
|
||||||
type File struct {
|
type File struct {
|
||||||
Verb Verb;
|
Verb Verb
|
||||||
Src string; // source for Verb == Copy, Verb == Rename
|
Src string // source for Verb == Copy, Verb == Rename
|
||||||
Dst string;
|
Dst string
|
||||||
OldMode, NewMode int; // 0 indicates not used
|
OldMode, NewMode int // 0 indicates not used
|
||||||
Diff; // changes to data; == NoDiff if operation does not edit file
|
Diff // changes to data; == NoDiff if operation does not edit file
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Verb is an action performed on a file.
|
// A Verb is an action performed on a file.
|
||||||
type Verb string
|
type Verb string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Add Verb = "add";
|
Add Verb = "add"
|
||||||
Copy Verb = "copy";
|
Copy Verb = "copy"
|
||||||
Delete Verb = "delete";
|
Delete Verb = "delete"
|
||||||
Edit Verb = "edit";
|
Edit Verb = "edit"
|
||||||
Rename Verb = "rename";
|
Rename Verb = "rename"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Diff is any object that describes changes to transform
|
// A Diff is any object that describes changes to transform
|
||||||
@ -47,7 +47,7 @@ type Diff interface {
|
|||||||
// Apply applies the changes listed in the diff
|
// Apply applies the changes listed in the diff
|
||||||
// to the string s, returning the new version of the string.
|
// to the string s, returning the new version of the string.
|
||||||
// Note that the string s need not be a text string.
|
// Note that the string s need not be a text string.
|
||||||
Apply(old []byte) (new []byte, err os.Error);
|
Apply(old []byte) (new []byte, err os.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoDiff is a no-op Diff implementation: it passes the
|
// NoDiff is a no-op Diff implementation: it passes the
|
||||||
@ -82,37 +82,37 @@ func Parse(text []byte) (*Set, os.Error) {
|
|||||||
// diff [--git] a/file/path b/file/path.
|
// diff [--git] a/file/path b/file/path.
|
||||||
//
|
//
|
||||||
// First look for Index: lines. If none, fall back on diff lines.
|
// First look for Index: lines. If none, fall back on diff lines.
|
||||||
text, files := sections(text, "Index: ");
|
text, files := sections(text, "Index: ")
|
||||||
if len(files) == 0 {
|
if len(files) == 0 {
|
||||||
text, files = sections(text, "diff ")
|
text, files = sections(text, "diff ")
|
||||||
}
|
}
|
||||||
|
|
||||||
set := &Set{string(text), make([]*File, len(files))};
|
set := &Set{string(text), make([]*File, len(files))}
|
||||||
|
|
||||||
// Parse file header and then
|
// Parse file header and then
|
||||||
// parse files into patch chunks.
|
// parse files into patch chunks.
|
||||||
// Each chunk begins with @@.
|
// Each chunk begins with @@.
|
||||||
for i, raw := range files {
|
for i, raw := range files {
|
||||||
p := new(File);
|
p := new(File)
|
||||||
set.File[i] = p;
|
set.File[i] = p
|
||||||
|
|
||||||
// First line of hdr is the Index: that
|
// First line of hdr is the Index: that
|
||||||
// begins the section. After that is the file name.
|
// begins the section. After that is the file name.
|
||||||
s, raw, _ := getLine(raw, 1);
|
s, raw, _ := getLine(raw, 1)
|
||||||
if hasPrefix(s, "Index: ") {
|
if hasPrefix(s, "Index: ") {
|
||||||
p.Dst = string(bytes.TrimSpace(s[7:]));
|
p.Dst = string(bytes.TrimSpace(s[7:]))
|
||||||
goto HaveName;
|
goto HaveName
|
||||||
} else if hasPrefix(s, "diff ") {
|
} else if hasPrefix(s, "diff ") {
|
||||||
str := string(bytes.TrimSpace(s));
|
str := string(bytes.TrimSpace(s))
|
||||||
i := strings.LastIndex(str, " b/");
|
i := strings.LastIndex(str, " b/")
|
||||||
if i >= 0 {
|
if i >= 0 {
|
||||||
p.Dst = str[i+3:];
|
p.Dst = str[i+3:]
|
||||||
goto HaveName;
|
goto HaveName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, SyntaxError("unexpected patch header line: " + string(s));
|
return nil, SyntaxError("unexpected patch header line: " + string(s))
|
||||||
HaveName:
|
HaveName:
|
||||||
p.Dst = path.Clean(p.Dst);
|
p.Dst = path.Clean(p.Dst)
|
||||||
if strings.HasPrefix(p.Dst, "../") || strings.HasPrefix(p.Dst, "/") {
|
if strings.HasPrefix(p.Dst, "../") || strings.HasPrefix(p.Dst, "/") {
|
||||||
return nil, SyntaxError("invalid path: " + p.Dst)
|
return nil, SyntaxError("invalid path: " + p.Dst)
|
||||||
}
|
}
|
||||||
@ -126,55 +126,55 @@ func Parse(text []byte) (*Set, os.Error) {
|
|||||||
// rename to %s
|
// rename to %s
|
||||||
// copy from %s - file copied from other file
|
// copy from %s - file copied from other file
|
||||||
// copy to %s
|
// copy to %s
|
||||||
p.Verb = Edit;
|
p.Verb = Edit
|
||||||
for len(raw) > 0 {
|
for len(raw) > 0 {
|
||||||
oldraw := raw;
|
oldraw := raw
|
||||||
var l []byte;
|
var l []byte
|
||||||
l, raw, _ = getLine(raw, 1);
|
l, raw, _ = getLine(raw, 1)
|
||||||
l = bytes.TrimSpace(l);
|
l = bytes.TrimSpace(l)
|
||||||
if m, s, ok := atoi(l, "new file mode ", 8); ok && len(s) == 0 {
|
if m, s, ok := atoi(l, "new file mode ", 8); ok && len(s) == 0 {
|
||||||
p.NewMode = m;
|
p.NewMode = m
|
||||||
p.Verb = Add;
|
p.Verb = Add
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if m, s, ok := atoi(l, "deleted file mode ", 8); ok && len(s) == 0 {
|
if m, s, ok := atoi(l, "deleted file mode ", 8); ok && len(s) == 0 {
|
||||||
p.OldMode = m;
|
p.OldMode = m
|
||||||
p.Verb = Delete;
|
p.Verb = Delete
|
||||||
p.Src = p.Dst;
|
p.Src = p.Dst
|
||||||
p.Dst = "";
|
p.Dst = ""
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if m, s, ok := atoi(l, "old file mode ", 8); ok && len(s) == 0 {
|
if m, s, ok := atoi(l, "old file mode ", 8); ok && len(s) == 0 {
|
||||||
// usually implies p.Verb = "rename" or "copy"
|
// usually implies p.Verb = "rename" or "copy"
|
||||||
// but we'll get that from the rename or copy line.
|
// but we'll get that from the rename or copy line.
|
||||||
p.OldMode = m;
|
p.OldMode = m
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if m, s, ok := atoi(l, "old mode ", 8); ok && len(s) == 0 {
|
if m, s, ok := atoi(l, "old mode ", 8); ok && len(s) == 0 {
|
||||||
p.OldMode = m;
|
p.OldMode = m
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if m, s, ok := atoi(l, "new mode ", 8); ok && len(s) == 0 {
|
if m, s, ok := atoi(l, "new mode ", 8); ok && len(s) == 0 {
|
||||||
p.NewMode = m;
|
p.NewMode = m
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if s, ok := skip(l, "rename from "); ok && len(s) > 0 {
|
if s, ok := skip(l, "rename from "); ok && len(s) > 0 {
|
||||||
p.Src = string(s);
|
p.Src = string(s)
|
||||||
p.Verb = Rename;
|
p.Verb = Rename
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if s, ok := skip(l, "rename to "); ok && len(s) > 0 {
|
if s, ok := skip(l, "rename to "); ok && len(s) > 0 {
|
||||||
p.Verb = Rename;
|
p.Verb = Rename
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if s, ok := skip(l, "copy from "); ok && len(s) > 0 {
|
if s, ok := skip(l, "copy from "); ok && len(s) > 0 {
|
||||||
p.Src = string(s);
|
p.Src = string(s)
|
||||||
p.Verb = Copy;
|
p.Verb = Copy
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if s, ok := skip(l, "copy to "); ok && len(s) > 0 {
|
if s, ok := skip(l, "copy to "); ok && len(s) > 0 {
|
||||||
p.Verb = Copy;
|
p.Verb = Copy
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if s, ok := skip(l, "Binary file "); ok && len(s) > 0 {
|
if s, ok := skip(l, "Binary file "); ok && len(s) > 0 {
|
||||||
// Hg prints
|
// Hg prints
|
||||||
@ -200,22 +200,22 @@ func Parse(text []byte) (*Set, os.Error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if hasPrefix(l, "@@ -") {
|
if hasPrefix(l, "@@ -") {
|
||||||
diff, err := ParseTextDiff(oldraw);
|
diff, err := ParseTextDiff(oldraw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
p.Diff = diff;
|
p.Diff = diff
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
if hasPrefix(l, "index ") || hasPrefix(l, "GIT binary patch") {
|
if hasPrefix(l, "index ") || hasPrefix(l, "GIT binary patch") {
|
||||||
diff, err := ParseGitBinary(oldraw);
|
diff, err := ParseGitBinary(oldraw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
p.Diff = diff;
|
p.Diff = diff
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
return nil, SyntaxError("unexpected patch header line: " + string(l));
|
return nil, SyntaxError("unexpected patch header line: " + string(l))
|
||||||
}
|
}
|
||||||
if p.Diff == nil {
|
if p.Diff == nil {
|
||||||
p.Diff = NoDiff
|
p.Diff = NoDiff
|
||||||
@ -225,25 +225,25 @@ func Parse(text []byte) (*Set, os.Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return set, nil;
|
return set, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getLine returns the first n lines of data and the remainder.
|
// getLine returns the first n lines of data and the remainder.
|
||||||
// If data has no newline, getLine returns data, nil, false
|
// If data has no newline, getLine returns data, nil, false
|
||||||
func getLine(data []byte, n int) (first []byte, rest []byte, ok bool) {
|
func getLine(data []byte, n int) (first []byte, rest []byte, ok bool) {
|
||||||
rest = data;
|
rest = data
|
||||||
ok = true;
|
ok = true
|
||||||
for ; n > 0; n-- {
|
for ; n > 0; n-- {
|
||||||
nl := bytes.Index(rest, newline);
|
nl := bytes.Index(rest, newline)
|
||||||
if nl < 0 {
|
if nl < 0 {
|
||||||
rest = nil;
|
rest = nil
|
||||||
ok = false;
|
ok = false
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
rest = rest[nl+1:];
|
rest = rest[nl+1:]
|
||||||
}
|
}
|
||||||
first = data[0 : len(data)-len(rest)];
|
first = data[0 : len(data)-len(rest)]
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// sections returns a collection of file sections,
|
// sections returns a collection of file sections,
|
||||||
@ -251,34 +251,34 @@ func getLine(data []byte, n int) (first []byte, rest []byte, ok bool) {
|
|||||||
// text before the first instance of such a line is
|
// text before the first instance of such a line is
|
||||||
// returned separately.
|
// returned separately.
|
||||||
func sections(text []byte, prefix string) ([]byte, [][]byte) {
|
func sections(text []byte, prefix string) ([]byte, [][]byte) {
|
||||||
n := 0;
|
n := 0
|
||||||
for b := text; ; {
|
for b := text; ; {
|
||||||
if hasPrefix(b, prefix) {
|
if hasPrefix(b, prefix) {
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
nl := bytes.Index(b, newline);
|
nl := bytes.Index(b, newline)
|
||||||
if nl < 0 {
|
if nl < 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b = b[nl+1:];
|
b = b[nl+1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
sect := make([][]byte, n+1);
|
sect := make([][]byte, n+1)
|
||||||
n = 0;
|
n = 0
|
||||||
for b := text; ; {
|
for b := text; ; {
|
||||||
if hasPrefix(b, prefix) {
|
if hasPrefix(b, prefix) {
|
||||||
sect[n] = text[0 : len(text)-len(b)];
|
sect[n] = text[0 : len(text)-len(b)]
|
||||||
n++;
|
n++
|
||||||
text = b;
|
text = b
|
||||||
}
|
}
|
||||||
nl := bytes.Index(b, newline);
|
nl := bytes.Index(b, newline)
|
||||||
if nl < 0 {
|
if nl < 0 {
|
||||||
sect[n] = text;
|
sect[n] = text
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
b = b[nl+1:];
|
b = b[nl+1:]
|
||||||
}
|
}
|
||||||
return sect[0], sect[1:];
|
return sect[0], sect[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// if s begins with the prefix t, skip returns
|
// if s begins with the prefix t, skip returns
|
||||||
@ -287,7 +287,7 @@ func skip(s []byte, t string) (ss []byte, ok bool) {
|
|||||||
if len(s) < len(t) || string(s[0:len(t)]) != t {
|
if len(s) < len(t) || string(s[0:len(t)]) != t {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
return s[len(t):], true;
|
return s[len(t):], true
|
||||||
}
|
}
|
||||||
|
|
||||||
// if s begins with the prefix t and then is a sequence
|
// if s begins with the prefix t and then is a sequence
|
||||||
@ -298,20 +298,20 @@ func atoi(s []byte, t string, base int) (n int, ss []byte, ok bool) {
|
|||||||
if s, ok = skip(s, t); !ok {
|
if s, ok = skip(s, t); !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var i int;
|
var i int
|
||||||
for i = 0; i < len(s) && '0' <= s[i] && s[i] <= byte('0'+base-1); i++ {
|
for i = 0; i < len(s) && '0' <= s[i] && s[i] <= byte('0'+base-1); i++ {
|
||||||
n = n*base + int(s[i]-'0')
|
n = n*base + int(s[i]-'0')
|
||||||
}
|
}
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return n, s[i:], true;
|
return n, s[i:], true
|
||||||
}
|
}
|
||||||
|
|
||||||
// hasPrefix returns true if s begins with t.
|
// hasPrefix returns true if s begins with t.
|
||||||
func hasPrefix(s []byte, t string) bool {
|
func hasPrefix(s []byte, t string) bool {
|
||||||
_, ok := skip(s, t);
|
_, ok := skip(s, t)
|
||||||
return ok;
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// splitLines returns the result of splitting s into lines.
|
// splitLines returns the result of splitting s into lines.
|
||||||
|
@ -7,31 +7,31 @@ package patch
|
|||||||
// TODO(rsc): test Apply
|
// TODO(rsc): test Apply
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings";
|
"strings"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Test struct {
|
type Test struct {
|
||||||
in string;
|
in string
|
||||||
out string;
|
out string
|
||||||
diff string;
|
diff string
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileApply(t *testing.T) {
|
func TestFileApply(t *testing.T) {
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
set, err := Parse(strings.Bytes(test.diff));
|
set, err := Parse(strings.Bytes(test.diff))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("#%d: Parse: %s", i, err);
|
t.Errorf("#%d: Parse: %s", i, err)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if len(set.File) != 1 {
|
if len(set.File) != 1 {
|
||||||
t.Errorf("#%d: Parse returned %d patches, want 1", i, len(set.File));
|
t.Errorf("#%d: Parse returned %d patches, want 1", i, len(set.File))
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
new, err := set.File[0].Apply(strings.Bytes(test.in));
|
new, err := set.File[0].Apply(strings.Bytes(test.in))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("#%d: Apply: %s", i, err);
|
t.Errorf("#%d: Apply: %s", i, err)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if s := string(new); s != test.out {
|
if s := string(new); s != test.out {
|
||||||
t.Errorf("#%d:\n--- have\n%s--- want\n%s", i, s, test.out)
|
t.Errorf("#%d:\n--- have\n%s--- want\n%s", i, s, test.out)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package patch
|
package patch
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes";
|
"bytes"
|
||||||
"os";
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TextDiff []TextChunk
|
type TextDiff []TextChunk
|
||||||
@ -11,25 +11,25 @@ type TextDiff []TextChunk
|
|||||||
// the text beginning at Line, which should be exactly Old,
|
// the text beginning at Line, which should be exactly Old,
|
||||||
// is to be replaced with New.
|
// is to be replaced with New.
|
||||||
type TextChunk struct {
|
type TextChunk struct {
|
||||||
Line int;
|
Line int
|
||||||
Old []byte;
|
Old []byte
|
||||||
New []byte;
|
New []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
|
func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
|
||||||
// Copy raw so it is safe to keep references to slices.
|
// Copy raw so it is safe to keep references to slices.
|
||||||
_, chunks := sections(raw, "@@ -");
|
_, chunks := sections(raw, "@@ -")
|
||||||
delta := 0;
|
delta := 0
|
||||||
diff := make(TextDiff, len(chunks));
|
diff := make(TextDiff, len(chunks))
|
||||||
for i, raw := range chunks {
|
for i, raw := range chunks {
|
||||||
c := &diff[i];
|
c := &diff[i]
|
||||||
|
|
||||||
// Parse start line: @@ -oldLine,oldCount +newLine,newCount @@ junk
|
// Parse start line: @@ -oldLine,oldCount +newLine,newCount @@ junk
|
||||||
chunk := splitLines(raw);
|
chunk := splitLines(raw)
|
||||||
chunkHeader := chunk[0];
|
chunkHeader := chunk[0]
|
||||||
var ok bool;
|
var ok bool
|
||||||
var oldLine, oldCount, newLine, newCount int;
|
var oldLine, oldCount, newLine, newCount int
|
||||||
s := chunkHeader;
|
s := chunkHeader
|
||||||
if oldLine, s, ok = atoi(s, "@@ -", 10); !ok {
|
if oldLine, s, ok = atoi(s, "@@ -", 10); !ok {
|
||||||
ErrChunkHdr:
|
ErrChunkHdr:
|
||||||
return nil, SyntaxError("unexpected chunk header line: " + string(chunkHeader))
|
return nil, SyntaxError("unexpected chunk header line: " + string(chunkHeader))
|
||||||
@ -61,16 +61,16 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Count lines in text
|
// Count lines in text
|
||||||
var dropOldNL, dropNewNL bool;
|
var dropOldNL, dropNewNL bool
|
||||||
var nold, nnew int;
|
var nold, nnew int
|
||||||
var lastch byte;
|
var lastch byte
|
||||||
chunk = chunk[1:];
|
chunk = chunk[1:]
|
||||||
for _, l := range chunk {
|
for _, l := range chunk {
|
||||||
if nold == oldCount && nnew == newCount && (len(l) == 0 || l[0] != '\\') {
|
if nold == oldCount && nnew == newCount && (len(l) == 0 || l[0] != '\\') {
|
||||||
if len(bytes.TrimSpace(l)) != 0 {
|
if len(bytes.TrimSpace(l)) != 0 {
|
||||||
return nil, SyntaxError("too many chunk lines")
|
return nil, SyntaxError("too many chunk lines")
|
||||||
}
|
}
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if len(l) == 0 {
|
if len(l) == 0 {
|
||||||
return nil, SyntaxError("empty chunk line")
|
return nil, SyntaxError("empty chunk line")
|
||||||
@ -81,8 +81,8 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
|
|||||||
case '-':
|
case '-':
|
||||||
nold++
|
nold++
|
||||||
case ' ':
|
case ' ':
|
||||||
nnew++;
|
nnew++
|
||||||
nold++;
|
nold++
|
||||||
case '\\':
|
case '\\':
|
||||||
if _, ok := skip(l, "\\ No newline at end of file"); ok {
|
if _, ok := skip(l, "\\ No newline at end of file"); ok {
|
||||||
switch lastch {
|
switch lastch {
|
||||||
@ -91,18 +91,18 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
|
|||||||
case '+':
|
case '+':
|
||||||
dropNewNL = true
|
dropNewNL = true
|
||||||
case ' ':
|
case ' ':
|
||||||
dropOldNL = true;
|
dropOldNL = true
|
||||||
dropNewNL = true;
|
dropNewNL = true
|
||||||
default:
|
default:
|
||||||
return nil, SyntaxError("message `\\ No newline at end of file' out of context")
|
return nil, SyntaxError("message `\\ No newline at end of file' out of context")
|
||||||
}
|
}
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
fallthrough;
|
fallthrough
|
||||||
default:
|
default:
|
||||||
return nil, SyntaxError("unexpected chunk line: " + string(l))
|
return nil, SyntaxError("unexpected chunk line: " + string(l))
|
||||||
}
|
}
|
||||||
lastch = l[0];
|
lastch = l[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does it match the header?
|
// Does it match the header?
|
||||||
@ -112,31 +112,31 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
|
|||||||
if oldLine+delta != newLine {
|
if oldLine+delta != newLine {
|
||||||
return nil, SyntaxError("chunk delta is out of sync with previous chunks")
|
return nil, SyntaxError("chunk delta is out of sync with previous chunks")
|
||||||
}
|
}
|
||||||
delta += nnew - nold;
|
delta += nnew - nold
|
||||||
c.Line = oldLine;
|
c.Line = oldLine
|
||||||
|
|
||||||
var old, new bytes.Buffer;
|
var old, new bytes.Buffer
|
||||||
nold = 0;
|
nold = 0
|
||||||
nnew = 0;
|
nnew = 0
|
||||||
for _, l := range chunk {
|
for _, l := range chunk {
|
||||||
if nold == oldCount && nnew == newCount {
|
if nold == oldCount && nnew == newCount {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
ch, l := l[0], l[1:];
|
ch, l := l[0], l[1:]
|
||||||
if ch == '\\' {
|
if ch == '\\' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ch != '+' {
|
if ch != '+' {
|
||||||
old.Write(l);
|
old.Write(l)
|
||||||
nold++;
|
nold++
|
||||||
}
|
}
|
||||||
if ch != '-' {
|
if ch != '-' {
|
||||||
new.Write(l);
|
new.Write(l)
|
||||||
nnew++;
|
nnew++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.Old = old.Bytes();
|
c.Old = old.Bytes()
|
||||||
c.New = new.Bytes();
|
c.New = new.Bytes()
|
||||||
if dropOldNL {
|
if dropOldNL {
|
||||||
c.Old = c.Old[0 : len(c.Old)-1]
|
c.Old = c.Old[0 : len(c.Old)-1]
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
|
|||||||
c.New = c.New[0 : len(c.New)-1]
|
c.New = c.New[0 : len(c.New)-1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return diff, nil;
|
return diff, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrPatchFailure = os.NewError("patch did not apply cleanly")
|
var ErrPatchFailure = os.NewError("patch did not apply cleanly")
|
||||||
@ -152,20 +152,20 @@ var ErrPatchFailure = os.NewError("patch did not apply cleanly")
|
|||||||
// Apply applies the changes listed in the diff
|
// Apply applies the changes listed in the diff
|
||||||
// to the data, returning the new version.
|
// to the data, returning the new version.
|
||||||
func (d TextDiff) Apply(data []byte) ([]byte, os.Error) {
|
func (d TextDiff) Apply(data []byte) ([]byte, os.Error) {
|
||||||
var buf bytes.Buffer;
|
var buf bytes.Buffer
|
||||||
line := 1;
|
line := 1
|
||||||
for _, c := range d {
|
for _, c := range d {
|
||||||
var ok bool;
|
var ok bool
|
||||||
var prefix []byte;
|
var prefix []byte
|
||||||
prefix, data, ok = getLine(data, c.Line-line);
|
prefix, data, ok = getLine(data, c.Line-line)
|
||||||
if !ok || !bytes.HasPrefix(data, c.Old) {
|
if !ok || !bytes.HasPrefix(data, c.Old) {
|
||||||
return nil, ErrPatchFailure
|
return nil, ErrPatchFailure
|
||||||
}
|
}
|
||||||
buf.Write(prefix);
|
buf.Write(prefix)
|
||||||
data = data[len(c.Old):];
|
data = data[len(c.Old):]
|
||||||
buf.Write(c.New);
|
buf.Write(c.New)
|
||||||
line = c.Line + bytes.Count(c.Old, newline);
|
line = c.Line + bytes.Count(c.Old, newline)
|
||||||
}
|
}
|
||||||
buf.Write(data);
|
buf.Write(data)
|
||||||
return buf.Bytes(), nil;
|
return buf.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
package path
|
package path
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil";
|
"io/ioutil"
|
||||||
"os";
|
"os"
|
||||||
"strings";
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Clean returns the shortest path name equivalent to path
|
// Clean returns the shortest path name equivalent to path
|
||||||
@ -34,16 +34,16 @@ func Clean(path string) string {
|
|||||||
return "."
|
return "."
|
||||||
}
|
}
|
||||||
|
|
||||||
rooted := path[0] == '/';
|
rooted := path[0] == '/'
|
||||||
n := len(path);
|
n := len(path)
|
||||||
|
|
||||||
// Invariants:
|
// Invariants:
|
||||||
// reading from path; r is index of next byte to process.
|
// reading from path; r is index of next byte to process.
|
||||||
// writing to buf; w is index of next byte to write.
|
// writing to buf; w is index of next byte to write.
|
||||||
// dotdot is index in buf where .. must stop, either because
|
// dotdot is index in buf where .. must stop, either because
|
||||||
// it is the leading slash or it is a leading ../../.. prefix.
|
// it is the leading slash or it is a leading ../../.. prefix.
|
||||||
buf := strings.Bytes(path);
|
buf := strings.Bytes(path)
|
||||||
r, w, dotdot := 0, 0, 0;
|
r, w, dotdot := 0, 0, 0
|
||||||
if rooted {
|
if rooted {
|
||||||
r, w, dotdot = 1, 1, 1
|
r, w, dotdot = 1, 1, 1
|
||||||
}
|
}
|
||||||
@ -58,48 +58,48 @@ func Clean(path string) string {
|
|||||||
r++
|
r++
|
||||||
case path[r] == '.' && path[r+1] == '.' && (r+2 == n || path[r+2] == '/'):
|
case path[r] == '.' && path[r+1] == '.' && (r+2 == n || path[r+2] == '/'):
|
||||||
// .. element: remove to last /
|
// .. element: remove to last /
|
||||||
r += 2;
|
r += 2
|
||||||
switch {
|
switch {
|
||||||
case w > dotdot:
|
case w > dotdot:
|
||||||
// can backtrack
|
// can backtrack
|
||||||
w--;
|
w--
|
||||||
for w > dotdot && buf[w] != '/' {
|
for w > dotdot && buf[w] != '/' {
|
||||||
w--
|
w--
|
||||||
}
|
}
|
||||||
case !rooted:
|
case !rooted:
|
||||||
// cannot backtrack, but not rooted, so append .. element.
|
// cannot backtrack, but not rooted, so append .. element.
|
||||||
if w > 0 {
|
if w > 0 {
|
||||||
buf[w] = '/';
|
buf[w] = '/'
|
||||||
w++;
|
w++
|
||||||
}
|
}
|
||||||
buf[w] = '.';
|
buf[w] = '.'
|
||||||
w++;
|
w++
|
||||||
buf[w] = '.';
|
buf[w] = '.'
|
||||||
w++;
|
w++
|
||||||
dotdot = w;
|
dotdot = w
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
// real path element.
|
// real path element.
|
||||||
// add slash if needed
|
// add slash if needed
|
||||||
if rooted && w != 1 || !rooted && w != 0 {
|
if rooted && w != 1 || !rooted && w != 0 {
|
||||||
buf[w] = '/';
|
buf[w] = '/'
|
||||||
w++;
|
w++
|
||||||
}
|
}
|
||||||
// copy element
|
// copy element
|
||||||
for ; r < n && path[r] != '/'; r++ {
|
for ; r < n && path[r] != '/'; r++ {
|
||||||
buf[w] = path[r];
|
buf[w] = path[r]
|
||||||
w++;
|
w++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn empty string into "."
|
// Turn empty string into "."
|
||||||
if w == 0 {
|
if w == 0 {
|
||||||
buf[w] = '.';
|
buf[w] = '.'
|
||||||
w++;
|
w++
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(buf[0:w]);
|
return string(buf[0:w])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split splits path immediately following the final slash,
|
// Split splits path immediately following the final slash,
|
||||||
@ -112,7 +112,7 @@ func Split(path string) (dir, file string) {
|
|||||||
return path[0 : i+1], path[i+1:]
|
return path[0 : i+1], path[i+1:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", path;
|
return "", path
|
||||||
}
|
}
|
||||||
|
|
||||||
// Join joins dir and file into a single path, adding a separating
|
// Join joins dir and file into a single path, adding a separating
|
||||||
@ -121,7 +121,7 @@ func Join(dir, file string) string {
|
|||||||
if dir == "" {
|
if dir == "" {
|
||||||
return file
|
return file
|
||||||
}
|
}
|
||||||
return Clean(dir + "/" + file);
|
return Clean(dir + "/" + file)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ext returns the file name extension used by path.
|
// Ext returns the file name extension used by path.
|
||||||
@ -134,28 +134,28 @@ func Ext(path string) string {
|
|||||||
return path[i:]
|
return path[i:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visitor methods are invoked for corresponding file tree entries
|
// Visitor methods are invoked for corresponding file tree entries
|
||||||
// visited by Walk. The parameter path is the full path of d relative
|
// visited by Walk. The parameter path is the full path of d relative
|
||||||
// to root.
|
// to root.
|
||||||
type Visitor interface {
|
type Visitor interface {
|
||||||
VisitDir(path string, d *os.Dir) bool;
|
VisitDir(path string, d *os.Dir) bool
|
||||||
VisitFile(path string, d *os.Dir);
|
VisitFile(path string, d *os.Dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
func walk(path string, d *os.Dir, v Visitor, errors chan<- os.Error) {
|
func walk(path string, d *os.Dir, v Visitor, errors chan<- os.Error) {
|
||||||
if !d.IsDirectory() {
|
if !d.IsDirectory() {
|
||||||
v.VisitFile(path, d);
|
v.VisitFile(path, d)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !v.VisitDir(path, d) {
|
if !v.VisitDir(path, d) {
|
||||||
return // skip directory entries
|
return // skip directory entries
|
||||||
}
|
}
|
||||||
|
|
||||||
list, err := ioutil.ReadDir(path);
|
list, err := ioutil.ReadDir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors != nil {
|
if errors != nil {
|
||||||
errors <- err
|
errors <- err
|
||||||
@ -175,12 +175,12 @@ func walk(path string, d *os.Dir, v Visitor, errors chan<- os.Error) {
|
|||||||
// If errors != nil, Walk sends each directory read error
|
// If errors != nil, Walk sends each directory read error
|
||||||
// to the channel. Otherwise Walk discards the error.
|
// to the channel. Otherwise Walk discards the error.
|
||||||
func Walk(root string, v Visitor, errors chan<- os.Error) {
|
func Walk(root string, v Visitor, errors chan<- os.Error) {
|
||||||
d, err := os.Lstat(root);
|
d, err := os.Lstat(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors != nil {
|
if errors != nil {
|
||||||
errors <- err
|
errors <- err
|
||||||
}
|
}
|
||||||
return; // can't progress
|
return // can't progress
|
||||||
}
|
}
|
||||||
walk(root, d, v, errors);
|
walk(root, d, v, errors)
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
package path
|
package path
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os";
|
"os"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CleanTest struct {
|
type CleanTest struct {
|
||||||
path, clean string;
|
path, clean string
|
||||||
}
|
}
|
||||||
|
|
||||||
var cleantests = []CleanTest{
|
var cleantests = []CleanTest{
|
||||||
@ -72,7 +72,7 @@ func TestClean(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SplitTest struct {
|
type SplitTest struct {
|
||||||
path, dir, file string;
|
path, dir, file string
|
||||||
}
|
}
|
||||||
|
|
||||||
var splittests = []SplitTest{
|
var splittests = []SplitTest{
|
||||||
@ -92,7 +92,7 @@ func TestSplit(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type JoinTest struct {
|
type JoinTest struct {
|
||||||
dir, file, path string;
|
dir, file, path string
|
||||||
}
|
}
|
||||||
|
|
||||||
var jointests = []JoinTest{
|
var jointests = []JoinTest{
|
||||||
@ -114,7 +114,7 @@ func TestJoin(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ExtTest struct {
|
type ExtTest struct {
|
||||||
path, ext string;
|
path, ext string
|
||||||
}
|
}
|
||||||
|
|
||||||
var exttests = []ExtTest{
|
var exttests = []ExtTest{
|
||||||
@ -134,9 +134,9 @@ func TestExt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Node struct {
|
type Node struct {
|
||||||
name string;
|
name string
|
||||||
entries []*Node; // nil if the entry is a file
|
entries []*Node // nil if the entry is a file
|
||||||
mark int;
|
mark int
|
||||||
}
|
}
|
||||||
|
|
||||||
var tree = &Node{
|
var tree = &Node{
|
||||||
@ -166,7 +166,7 @@ var tree = &Node{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func walkTree(n *Node, path string, f func(path string, n *Node)) {
|
func walkTree(n *Node, path string, f func(path string, n *Node)) {
|
||||||
f(path, n);
|
f(path, n)
|
||||||
for _, e := range n.entries {
|
for _, e := range n.entries {
|
||||||
walkTree(e, Join(path, e.name), f)
|
walkTree(e, Join(path, e.name), f)
|
||||||
}
|
}
|
||||||
@ -175,11 +175,11 @@ func walkTree(n *Node, path string, f func(path string, n *Node)) {
|
|||||||
func makeTree(t *testing.T) {
|
func makeTree(t *testing.T) {
|
||||||
walkTree(tree, tree.name, func(path string, n *Node) {
|
walkTree(tree, tree.name, func(path string, n *Node) {
|
||||||
if n.entries == nil {
|
if n.entries == nil {
|
||||||
fd, err := os.Open(path, os.O_CREAT, 0660);
|
fd, err := os.Open(path, os.O_CREAT, 0660)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("makeTree: %v", err)
|
t.Errorf("makeTree: %v", err)
|
||||||
}
|
}
|
||||||
fd.Close();
|
fd.Close()
|
||||||
} else {
|
} else {
|
||||||
os.Mkdir(path, 0770)
|
os.Mkdir(path, 0770)
|
||||||
}
|
}
|
||||||
@ -193,7 +193,7 @@ func checkMarks(t *testing.T) {
|
|||||||
if n.mark != 1 {
|
if n.mark != 1 {
|
||||||
t.Errorf("node %s mark = %d; expected 1", path, n.mark)
|
t.Errorf("node %s mark = %d; expected 1", path, n.mark)
|
||||||
}
|
}
|
||||||
n.mark = 0;
|
n.mark = 0
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,8 +209,8 @@ func mark(name string) {
|
|||||||
type TestVisitor struct{}
|
type TestVisitor struct{}
|
||||||
|
|
||||||
func (v *TestVisitor) VisitDir(path string, d *os.Dir) bool {
|
func (v *TestVisitor) VisitDir(path string, d *os.Dir) bool {
|
||||||
mark(d.Name);
|
mark(d.Name)
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *TestVisitor) VisitFile(path string, d *os.Dir) {
|
func (v *TestVisitor) VisitFile(path string, d *os.Dir) {
|
||||||
@ -218,52 +218,52 @@ func (v *TestVisitor) VisitFile(path string, d *os.Dir) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestWalk(t *testing.T) {
|
func TestWalk(t *testing.T) {
|
||||||
makeTree(t);
|
makeTree(t)
|
||||||
|
|
||||||
// 1) ignore error handling, expect none
|
// 1) ignore error handling, expect none
|
||||||
v := &TestVisitor{};
|
v := &TestVisitor{}
|
||||||
Walk(tree.name, v, nil);
|
Walk(tree.name, v, nil)
|
||||||
checkMarks(t);
|
checkMarks(t)
|
||||||
|
|
||||||
// 2) handle errors, expect none
|
// 2) handle errors, expect none
|
||||||
errors := make(chan os.Error, 64);
|
errors := make(chan os.Error, 64)
|
||||||
Walk(tree.name, v, errors);
|
Walk(tree.name, v, errors)
|
||||||
if err, ok := <-errors; ok {
|
if err, ok := <-errors; ok {
|
||||||
t.Errorf("no error expected, found: s", err)
|
t.Errorf("no error expected, found: s", err)
|
||||||
}
|
}
|
||||||
checkMarks(t);
|
checkMarks(t)
|
||||||
|
|
||||||
if os.Getuid() != 0 {
|
if os.Getuid() != 0 {
|
||||||
// introduce 2 errors: chmod top-level directories to 0
|
// introduce 2 errors: chmod top-level directories to 0
|
||||||
os.Chmod(Join(tree.name, tree.entries[1].name), 0);
|
os.Chmod(Join(tree.name, tree.entries[1].name), 0)
|
||||||
os.Chmod(Join(tree.name, tree.entries[3].name), 0);
|
os.Chmod(Join(tree.name, tree.entries[3].name), 0)
|
||||||
// mark respective subtrees manually
|
// mark respective subtrees manually
|
||||||
markTree(tree.entries[1]);
|
markTree(tree.entries[1])
|
||||||
markTree(tree.entries[3]);
|
markTree(tree.entries[3])
|
||||||
// correct double-marking of directory itself
|
// correct double-marking of directory itself
|
||||||
tree.entries[1].mark--;
|
tree.entries[1].mark--
|
||||||
tree.entries[3].mark--;
|
tree.entries[3].mark--
|
||||||
|
|
||||||
// 3) handle errors, expect two
|
// 3) handle errors, expect two
|
||||||
errors = make(chan os.Error, 64);
|
errors = make(chan os.Error, 64)
|
||||||
os.Chmod(Join(tree.name, tree.entries[1].name), 0);
|
os.Chmod(Join(tree.name, tree.entries[1].name), 0)
|
||||||
Walk(tree.name, v, errors);
|
Walk(tree.name, v, errors)
|
||||||
for i := 1; i <= 2; i++ {
|
for i := 1; i <= 2; i++ {
|
||||||
if _, ok := <-errors; !ok {
|
if _, ok := <-errors; !ok {
|
||||||
t.Errorf("%d. error expected, none found", i);
|
t.Errorf("%d. error expected, none found", i)
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err, ok := <-errors; ok {
|
if err, ok := <-errors; ok {
|
||||||
t.Errorf("only two errors expected, found 3rd: %v", err)
|
t.Errorf("only two errors expected, found 3rd: %v", err)
|
||||||
}
|
}
|
||||||
// the inaccessible subtrees were marked manually
|
// the inaccessible subtrees were marked manually
|
||||||
checkMarks(t);
|
checkMarks(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
os.Chmod(Join(tree.name, tree.entries[1].name), 0770);
|
os.Chmod(Join(tree.name, tree.entries[1].name), 0770)
|
||||||
os.Chmod(Join(tree.name, tree.entries[3].name), 0770);
|
os.Chmod(Join(tree.name, tree.entries[3].name), 0770)
|
||||||
if err := os.RemoveAll(tree.name); err != nil {
|
if err := os.RemoveAll(tree.name); err != nil {
|
||||||
t.Errorf("removeTree: %v", err)
|
t.Errorf("removeTree: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
package rand
|
package rand
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math";
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -17,7 +17,7 @@ import (
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const (
|
const (
|
||||||
re = 7.69711747013104972;
|
re = 7.69711747013104972
|
||||||
)
|
)
|
||||||
|
|
||||||
// ExpFloat64 returns an exponentially distributed float64 in the range
|
// ExpFloat64 returns an exponentially distributed float64 in the range
|
||||||
@ -30,9 +30,9 @@ const (
|
|||||||
//
|
//
|
||||||
func (r *Rand) ExpFloat64() float64 {
|
func (r *Rand) ExpFloat64() float64 {
|
||||||
for {
|
for {
|
||||||
j := r.Uint32();
|
j := r.Uint32()
|
||||||
i := j & 0xFF;
|
i := j & 0xFF
|
||||||
x := float64(j) * float64(we[i]);
|
x := float64(j) * float64(we[i])
|
||||||
if j < ke[i] {
|
if j < ke[i] {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
@ -43,7 +43,7 @@ func (r *Rand) ExpFloat64() float64 {
|
|||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic("unreachable");
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
|
|
||||||
var ke = [256]uint32{
|
var ke = [256]uint32{
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
package rand
|
package rand
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math";
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -17,14 +17,14 @@ import (
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const (
|
const (
|
||||||
rn = 3.442619855899;
|
rn = 3.442619855899
|
||||||
)
|
)
|
||||||
|
|
||||||
func absInt32(i int32) uint32 {
|
func absInt32(i int32) uint32 {
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
return uint32(-i)
|
return uint32(-i)
|
||||||
}
|
}
|
||||||
return uint32(i);
|
return uint32(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NormFloat64 returns a normally distributed float64 in the range
|
// NormFloat64 returns a normally distributed float64 in the range
|
||||||
@ -37,9 +37,9 @@ func absInt32(i int32) uint32 {
|
|||||||
//
|
//
|
||||||
func (r *Rand) NormFloat64() float64 {
|
func (r *Rand) NormFloat64() float64 {
|
||||||
for {
|
for {
|
||||||
j := int32(r.Uint32()); // Possibly negative
|
j := int32(r.Uint32()) // Possibly negative
|
||||||
i := j & 0x7F;
|
i := j & 0x7F
|
||||||
x := float64(j) * float64(wn[i]);
|
x := float64(j) * float64(wn[i])
|
||||||
if absInt32(j) < kn[i] {
|
if absInt32(j) < kn[i] {
|
||||||
// This case should be hit better than 99% of the time.
|
// This case should be hit better than 99% of the time.
|
||||||
return x
|
return x
|
||||||
@ -48,8 +48,8 @@ func (r *Rand) NormFloat64() float64 {
|
|||||||
if i == 0 {
|
if i == 0 {
|
||||||
// This extra work is only required for the base strip.
|
// This extra work is only required for the base strip.
|
||||||
for {
|
for {
|
||||||
x = -math.Log(r.Float64()) * (1.0 / rn);
|
x = -math.Log(r.Float64()) * (1.0 / rn)
|
||||||
y := -math.Log(r.Float64());
|
y := -math.Log(r.Float64())
|
||||||
if y+y >= x*x {
|
if y+y >= x*x {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -57,13 +57,13 @@ func (r *Rand) NormFloat64() float64 {
|
|||||||
if j > 0 {
|
if j > 0 {
|
||||||
return rn + x
|
return rn + x
|
||||||
}
|
}
|
||||||
return -rn - x;
|
return -rn - x
|
||||||
}
|
}
|
||||||
if fn[i]+float32(r.Float64())*(fn[i-1]-fn[i]) < float32(math.Exp(-.5*x*x)) {
|
if fn[i]+float32(r.Float64())*(fn[i-1]-fn[i]) < float32(math.Exp(-.5*x*x)) {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic("unreachable");
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
|
|
||||||
var kn = [128]uint32{
|
var kn = [128]uint32{
|
||||||
|
@ -10,20 +10,20 @@ import "sync"
|
|||||||
// A Source represents a source of uniformly-distributed
|
// A Source represents a source of uniformly-distributed
|
||||||
// pseudo-random int64 values in the range [0, 1<<63).
|
// pseudo-random int64 values in the range [0, 1<<63).
|
||||||
type Source interface {
|
type Source interface {
|
||||||
Int63() int64;
|
Int63() int64
|
||||||
Seed(seed int64);
|
Seed(seed int64)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSource returns a new pseudo-random Source seeded with the given value.
|
// NewSource returns a new pseudo-random Source seeded with the given value.
|
||||||
func NewSource(seed int64) Source {
|
func NewSource(seed int64) Source {
|
||||||
var rng rngSource;
|
var rng rngSource
|
||||||
rng.Seed(seed);
|
rng.Seed(seed)
|
||||||
return &rng;
|
return &rng
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Rand is a source of random numbers.
|
// A Rand is a source of random numbers.
|
||||||
type Rand struct {
|
type Rand struct {
|
||||||
src Source;
|
src Source
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new Rand that uses random values from src
|
// New returns a new Rand that uses random values from src
|
||||||
@ -44,8 +44,8 @@ func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) }
|
|||||||
|
|
||||||
// Int returns a non-negative pseudo-random int.
|
// Int returns a non-negative pseudo-random int.
|
||||||
func (r *Rand) Int() int {
|
func (r *Rand) Int() int {
|
||||||
u := uint(r.Int63());
|
u := uint(r.Int63())
|
||||||
return int(u << 1 >> 1); // clear sign bit if int == int32
|
return int(u << 1 >> 1) // clear sign bit if int == int32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
|
// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
|
||||||
@ -53,12 +53,12 @@ func (r *Rand) Int63n(n int64) int64 {
|
|||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
max := int64((1 << 63) - 1 - (1<<63)%uint64(n));
|
max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
|
||||||
v := r.Int63();
|
v := r.Int63()
|
||||||
for v > max {
|
for v > max {
|
||||||
v = r.Int63()
|
v = r.Int63()
|
||||||
}
|
}
|
||||||
return v % n;
|
return v % n
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
|
// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
|
||||||
@ -78,15 +78,15 @@ func (r *Rand) Float() float { return float(r.Float64()) }
|
|||||||
|
|
||||||
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
|
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
|
||||||
func (r *Rand) Perm(n int) []int {
|
func (r *Rand) Perm(n int) []int {
|
||||||
m := make([]int, n);
|
m := make([]int, n)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
m[i] = i
|
m[i] = i
|
||||||
}
|
}
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
j := r.Intn(i + 1);
|
j := r.Intn(i + 1)
|
||||||
m[i], m[j] = m[j], m[i];
|
m[i], m[j] = m[j], m[i]
|
||||||
}
|
}
|
||||||
return m;
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -152,19 +152,19 @@ func NormFloat64() float64 { return globalRand.NormFloat64() }
|
|||||||
func ExpFloat64() float64 { return globalRand.ExpFloat64() }
|
func ExpFloat64() float64 { return globalRand.ExpFloat64() }
|
||||||
|
|
||||||
type lockedSource struct {
|
type lockedSource struct {
|
||||||
lk sync.Mutex;
|
lk sync.Mutex
|
||||||
src Source;
|
src Source
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *lockedSource) Int63() (n int64) {
|
func (r *lockedSource) Int63() (n int64) {
|
||||||
r.lk.Lock();
|
r.lk.Lock()
|
||||||
n = r.src.Int63();
|
n = r.src.Int63()
|
||||||
r.lk.Unlock();
|
r.lk.Unlock()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *lockedSource) Seed(seed int64) {
|
func (r *lockedSource) Seed(seed int64) {
|
||||||
r.lk.Lock();
|
r.lk.Lock()
|
||||||
r.src.Seed(seed);
|
r.src.Seed(seed)
|
||||||
r.lk.Unlock();
|
r.lk.Unlock()
|
||||||
}
|
}
|
||||||
|
@ -5,36 +5,36 @@
|
|||||||
package rand
|
package rand
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math";
|
"math"
|
||||||
"fmt";
|
"fmt"
|
||||||
"os";
|
"os"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
numTestSamples = 10000;
|
numTestSamples = 10000
|
||||||
)
|
)
|
||||||
|
|
||||||
type statsResults struct {
|
type statsResults struct {
|
||||||
mean float64;
|
mean float64
|
||||||
stddev float64;
|
stddev float64
|
||||||
closeEnough float64;
|
closeEnough float64
|
||||||
maxError float64;
|
maxError float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func max(a, b float64) float64 {
|
func max(a, b float64) float64 {
|
||||||
if a > b {
|
if a > b {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
return b;
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func nearEqual(a, b, closeEnough, maxError float64) bool {
|
func nearEqual(a, b, closeEnough, maxError float64) bool {
|
||||||
absDiff := math.Fabs(a - b);
|
absDiff := math.Fabs(a - b)
|
||||||
if absDiff < closeEnough { // Necessary when one value is zero and one value is close to zero.
|
if absDiff < closeEnough { // Necessary when one value is zero and one value is close to zero.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return absDiff/max(math.Fabs(a), math.Fabs(b)) < maxError;
|
return absDiff/max(math.Fabs(a), math.Fabs(b)) < maxError
|
||||||
}
|
}
|
||||||
|
|
||||||
var testSeeds = []int64{1, 1754801282, 1698661970, 1550503961}
|
var testSeeds = []int64{1, 1754801282, 1698661970, 1550503961}
|
||||||
@ -43,52 +43,52 @@ var testSeeds = []int64{1, 1754801282, 1698661970, 1550503961}
|
|||||||
// two statsResults are similar.
|
// two statsResults are similar.
|
||||||
func (this *statsResults) checkSimilarDistribution(expected *statsResults) os.Error {
|
func (this *statsResults) checkSimilarDistribution(expected *statsResults) os.Error {
|
||||||
if !nearEqual(this.mean, expected.mean, expected.closeEnough, expected.maxError) {
|
if !nearEqual(this.mean, expected.mean, expected.closeEnough, expected.maxError) {
|
||||||
s := fmt.Sprintf("mean %v != %v (allowed error %v, %v)", this.mean, expected.mean, expected.closeEnough, expected.maxError);
|
s := fmt.Sprintf("mean %v != %v (allowed error %v, %v)", this.mean, expected.mean, expected.closeEnough, expected.maxError)
|
||||||
fmt.Println(s);
|
fmt.Println(s)
|
||||||
return os.ErrorString(s);
|
return os.ErrorString(s)
|
||||||
}
|
}
|
||||||
if !nearEqual(this.stddev, expected.stddev, 0, expected.maxError) {
|
if !nearEqual(this.stddev, expected.stddev, 0, expected.maxError) {
|
||||||
s := fmt.Sprintf("stddev %v != %v (allowed error %v, %v)", this.stddev, expected.stddev, expected.closeEnough, expected.maxError);
|
s := fmt.Sprintf("stddev %v != %v (allowed error %v, %v)", this.stddev, expected.stddev, expected.closeEnough, expected.maxError)
|
||||||
fmt.Println(s);
|
fmt.Println(s)
|
||||||
return os.ErrorString(s);
|
return os.ErrorString(s)
|
||||||
}
|
}
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStatsResults(samples []float64) *statsResults {
|
func getStatsResults(samples []float64) *statsResults {
|
||||||
res := new(statsResults);
|
res := new(statsResults)
|
||||||
var sum float64;
|
var sum float64
|
||||||
for i := range samples {
|
for i := range samples {
|
||||||
sum += samples[i]
|
sum += samples[i]
|
||||||
}
|
}
|
||||||
res.mean = sum / float64(len(samples));
|
res.mean = sum / float64(len(samples))
|
||||||
var devsum float64;
|
var devsum float64
|
||||||
for i := range samples {
|
for i := range samples {
|
||||||
devsum += math.Pow(samples[i]-res.mean, 2)
|
devsum += math.Pow(samples[i]-res.mean, 2)
|
||||||
}
|
}
|
||||||
res.stddev = math.Sqrt(devsum / float64(len(samples)));
|
res.stddev = math.Sqrt(devsum / float64(len(samples)))
|
||||||
return res;
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkSampleDistribution(t *testing.T, samples []float64, expected *statsResults) {
|
func checkSampleDistribution(t *testing.T, samples []float64, expected *statsResults) {
|
||||||
actual := getStatsResults(samples);
|
actual := getStatsResults(samples)
|
||||||
err := actual.checkSimilarDistribution(expected);
|
err := actual.checkSimilarDistribution(expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.String())
|
t.Errorf(err.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkSampleSliceDistributions(t *testing.T, samples []float64, nslices int, expected *statsResults) {
|
func checkSampleSliceDistributions(t *testing.T, samples []float64, nslices int, expected *statsResults) {
|
||||||
chunk := len(samples) / nslices;
|
chunk := len(samples) / nslices
|
||||||
for i := 0; i < nslices; i++ {
|
for i := 0; i < nslices; i++ {
|
||||||
low := i * chunk;
|
low := i * chunk
|
||||||
var high int;
|
var high int
|
||||||
if i == nslices-1 {
|
if i == nslices-1 {
|
||||||
high = len(samples) - 1
|
high = len(samples) - 1
|
||||||
} else {
|
} else {
|
||||||
high = (i + 1) * chunk
|
high = (i + 1) * chunk
|
||||||
}
|
}
|
||||||
checkSampleDistribution(t, samples[low:high], expected);
|
checkSampleDistribution(t, samples[low:high], expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,29 +97,29 @@ func checkSampleSliceDistributions(t *testing.T, samples []float64, nslices int,
|
|||||||
//
|
//
|
||||||
|
|
||||||
func generateNormalSamples(nsamples int, mean, stddev float64, seed int64) []float64 {
|
func generateNormalSamples(nsamples int, mean, stddev float64, seed int64) []float64 {
|
||||||
r := New(NewSource(seed));
|
r := New(NewSource(seed))
|
||||||
samples := make([]float64, nsamples);
|
samples := make([]float64, nsamples)
|
||||||
for i := range samples {
|
for i := range samples {
|
||||||
samples[i] = r.NormFloat64()*stddev + mean
|
samples[i] = r.NormFloat64()*stddev + mean
|
||||||
}
|
}
|
||||||
return samples;
|
return samples
|
||||||
}
|
}
|
||||||
|
|
||||||
func testNormalDistribution(t *testing.T, nsamples int, mean, stddev float64, seed int64) {
|
func testNormalDistribution(t *testing.T, nsamples int, mean, stddev float64, seed int64) {
|
||||||
//fmt.Printf("testing nsamples=%v mean=%v stddev=%v seed=%v\n", nsamples, mean, stddev, seed);
|
//fmt.Printf("testing nsamples=%v mean=%v stddev=%v seed=%v\n", nsamples, mean, stddev, seed);
|
||||||
|
|
||||||
samples := generateNormalSamples(nsamples, mean, stddev, seed);
|
samples := generateNormalSamples(nsamples, mean, stddev, seed)
|
||||||
errorScale := max(1.0, stddev); // Error scales with stddev
|
errorScale := max(1.0, stddev) // Error scales with stddev
|
||||||
expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.08 * errorScale};
|
expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.08 * errorScale}
|
||||||
|
|
||||||
// Make sure that the entire set matches the expected distribution.
|
// Make sure that the entire set matches the expected distribution.
|
||||||
checkSampleDistribution(t, samples, expected);
|
checkSampleDistribution(t, samples, expected)
|
||||||
|
|
||||||
// Make sure that each half of the set matches the expected distribution.
|
// Make sure that each half of the set matches the expected distribution.
|
||||||
checkSampleSliceDistributions(t, samples, 2, expected);
|
checkSampleSliceDistributions(t, samples, 2, expected)
|
||||||
|
|
||||||
// Make sure that each 7th of the set matches the expected distribution.
|
// Make sure that each 7th of the set matches the expected distribution.
|
||||||
checkSampleSliceDistributions(t, samples, 7, expected);
|
checkSampleSliceDistributions(t, samples, 7, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actual tests
|
// Actual tests
|
||||||
@ -145,32 +145,32 @@ func TestNonStandardNormalValues(t *testing.T) {
|
|||||||
//
|
//
|
||||||
|
|
||||||
func generateExponentialSamples(nsamples int, rate float64, seed int64) []float64 {
|
func generateExponentialSamples(nsamples int, rate float64, seed int64) []float64 {
|
||||||
r := New(NewSource(seed));
|
r := New(NewSource(seed))
|
||||||
samples := make([]float64, nsamples);
|
samples := make([]float64, nsamples)
|
||||||
for i := range samples {
|
for i := range samples {
|
||||||
samples[i] = r.ExpFloat64() / rate
|
samples[i] = r.ExpFloat64() / rate
|
||||||
}
|
}
|
||||||
return samples;
|
return samples
|
||||||
}
|
}
|
||||||
|
|
||||||
func testExponentialDistribution(t *testing.T, nsamples int, rate float64, seed int64) {
|
func testExponentialDistribution(t *testing.T, nsamples int, rate float64, seed int64) {
|
||||||
//fmt.Printf("testing nsamples=%v rate=%v seed=%v\n", nsamples, rate, seed);
|
//fmt.Printf("testing nsamples=%v rate=%v seed=%v\n", nsamples, rate, seed);
|
||||||
|
|
||||||
mean := 1 / rate;
|
mean := 1 / rate
|
||||||
stddev := mean;
|
stddev := mean
|
||||||
|
|
||||||
samples := generateExponentialSamples(nsamples, rate, seed);
|
samples := generateExponentialSamples(nsamples, rate, seed)
|
||||||
errorScale := max(1.0, 1/rate); // Error scales with the inverse of the rate
|
errorScale := max(1.0, 1/rate) // Error scales with the inverse of the rate
|
||||||
expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.20 * errorScale};
|
expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.20 * errorScale}
|
||||||
|
|
||||||
// Make sure that the entire set matches the expected distribution.
|
// Make sure that the entire set matches the expected distribution.
|
||||||
checkSampleDistribution(t, samples, expected);
|
checkSampleDistribution(t, samples, expected)
|
||||||
|
|
||||||
// Make sure that each half of the set matches the expected distribution.
|
// Make sure that each half of the set matches the expected distribution.
|
||||||
checkSampleSliceDistributions(t, samples, 2, expected);
|
checkSampleSliceDistributions(t, samples, 2, expected)
|
||||||
|
|
||||||
// Make sure that each 7th of the set matches the expected distribution.
|
// Make sure that each 7th of the set matches the expected distribution.
|
||||||
checkSampleSliceDistributions(t, samples, 7, expected);
|
checkSampleSliceDistributions(t, samples, 7, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actual tests
|
// Actual tests
|
||||||
@ -194,61 +194,61 @@ func TestNonStandardExponentialValues(t *testing.T) {
|
|||||||
//
|
//
|
||||||
|
|
||||||
func initNorm() (testKn []uint32, testWn, testFn []float32) {
|
func initNorm() (testKn []uint32, testWn, testFn []float32) {
|
||||||
const m1 = 1 << 31;
|
const m1 = 1 << 31
|
||||||
var (
|
var (
|
||||||
dn float64 = rn;
|
dn float64 = rn
|
||||||
tn = dn;
|
tn = dn
|
||||||
vn float64 = 9.91256303526217e-3;
|
vn float64 = 9.91256303526217e-3
|
||||||
)
|
)
|
||||||
|
|
||||||
testKn = make([]uint32, 128);
|
testKn = make([]uint32, 128)
|
||||||
testWn = make([]float32, 128);
|
testWn = make([]float32, 128)
|
||||||
testFn = make([]float32, 128);
|
testFn = make([]float32, 128)
|
||||||
|
|
||||||
q := vn / math.Exp(-0.5*dn*dn);
|
q := vn / math.Exp(-0.5*dn*dn)
|
||||||
testKn[0] = uint32((dn / q) * m1);
|
testKn[0] = uint32((dn / q) * m1)
|
||||||
testKn[1] = 0;
|
testKn[1] = 0
|
||||||
testWn[0] = float32(q / m1);
|
testWn[0] = float32(q / m1)
|
||||||
testWn[127] = float32(dn / m1);
|
testWn[127] = float32(dn / m1)
|
||||||
testFn[0] = 1.0;
|
testFn[0] = 1.0
|
||||||
testFn[127] = float32(math.Exp(-0.5 * dn * dn));
|
testFn[127] = float32(math.Exp(-0.5 * dn * dn))
|
||||||
for i := 126; i >= 1; i-- {
|
for i := 126; i >= 1; i-- {
|
||||||
dn = math.Sqrt(-2.0 * math.Log(vn/dn+math.Exp(-0.5*dn*dn)));
|
dn = math.Sqrt(-2.0 * math.Log(vn/dn+math.Exp(-0.5*dn*dn)))
|
||||||
testKn[i+1] = uint32((dn / tn) * m1);
|
testKn[i+1] = uint32((dn / tn) * m1)
|
||||||
tn = dn;
|
tn = dn
|
||||||
testFn[i] = float32(math.Exp(-0.5 * dn * dn));
|
testFn[i] = float32(math.Exp(-0.5 * dn * dn))
|
||||||
testWn[i] = float32(dn / m1);
|
testWn[i] = float32(dn / m1)
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func initExp() (testKe []uint32, testWe, testFe []float32) {
|
func initExp() (testKe []uint32, testWe, testFe []float32) {
|
||||||
const m2 = 1 << 32;
|
const m2 = 1 << 32
|
||||||
var (
|
var (
|
||||||
de float64 = re;
|
de float64 = re
|
||||||
te = de;
|
te = de
|
||||||
ve float64 = 3.9496598225815571993e-3;
|
ve float64 = 3.9496598225815571993e-3
|
||||||
)
|
)
|
||||||
|
|
||||||
testKe = make([]uint32, 256);
|
testKe = make([]uint32, 256)
|
||||||
testWe = make([]float32, 256);
|
testWe = make([]float32, 256)
|
||||||
testFe = make([]float32, 256);
|
testFe = make([]float32, 256)
|
||||||
|
|
||||||
q := ve / math.Exp(-de);
|
q := ve / math.Exp(-de)
|
||||||
testKe[0] = uint32((de / q) * m2);
|
testKe[0] = uint32((de / q) * m2)
|
||||||
testKe[1] = 0;
|
testKe[1] = 0
|
||||||
testWe[0] = float32(q / m2);
|
testWe[0] = float32(q / m2)
|
||||||
testWe[255] = float32(de / m2);
|
testWe[255] = float32(de / m2)
|
||||||
testFe[0] = 1.0;
|
testFe[0] = 1.0
|
||||||
testFe[255] = float32(math.Exp(-de));
|
testFe[255] = float32(math.Exp(-de))
|
||||||
for i := 254; i >= 1; i-- {
|
for i := 254; i >= 1; i-- {
|
||||||
de = -math.Log(ve/de + math.Exp(-de));
|
de = -math.Log(ve/de + math.Exp(-de))
|
||||||
testKe[i+1] = uint32((de / te) * m2);
|
testKe[i+1] = uint32((de / te) * m2)
|
||||||
te = de;
|
te = de
|
||||||
testFe[i] = float32(math.Exp(-de));
|
testFe[i] = float32(math.Exp(-de))
|
||||||
testWe[i] = float32(de / m2);
|
testWe[i] = float32(de / m2)
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// compareUint32Slices returns the first index where the two slices
|
// compareUint32Slices returns the first index where the two slices
|
||||||
@ -259,14 +259,14 @@ func compareUint32Slices(s1, s2 []uint32) int {
|
|||||||
if len(s1) > len(s2) {
|
if len(s1) > len(s2) {
|
||||||
return len(s2) + 1
|
return len(s2) + 1
|
||||||
}
|
}
|
||||||
return len(s1) + 1;
|
return len(s1) + 1
|
||||||
}
|
}
|
||||||
for i := range s1 {
|
for i := range s1 {
|
||||||
if s1[i] != s2[i] {
|
if s1[i] != s2[i] {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// compareFloat32Slices returns the first index where the two slices
|
// compareFloat32Slices returns the first index where the two slices
|
||||||
@ -277,18 +277,18 @@ func compareFloat32Slices(s1, s2 []float32) int {
|
|||||||
if len(s1) > len(s2) {
|
if len(s1) > len(s2) {
|
||||||
return len(s2) + 1
|
return len(s2) + 1
|
||||||
}
|
}
|
||||||
return len(s1) + 1;
|
return len(s1) + 1
|
||||||
}
|
}
|
||||||
for i := range s1 {
|
for i := range s1 {
|
||||||
if !nearEqual(float64(s1[i]), float64(s2[i]), 0, 1e-7) {
|
if !nearEqual(float64(s1[i]), float64(s2[i]), 0, 1e-7) {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNormTables(t *testing.T) {
|
func TestNormTables(t *testing.T) {
|
||||||
testKn, testWn, testFn := initNorm();
|
testKn, testWn, testFn := initNorm()
|
||||||
if i := compareUint32Slices(kn[0:], testKn); i >= 0 {
|
if i := compareUint32Slices(kn[0:], testKn); i >= 0 {
|
||||||
t.Errorf("kn disagrees at index %v; %v != %v\n", i, kn[i], testKn[i])
|
t.Errorf("kn disagrees at index %v; %v != %v\n", i, kn[i], testKn[i])
|
||||||
}
|
}
|
||||||
@ -301,7 +301,7 @@ func TestNormTables(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestExpTables(t *testing.T) {
|
func TestExpTables(t *testing.T) {
|
||||||
testKe, testWe, testFe := initExp();
|
testKe, testWe, testFe := initExp()
|
||||||
if i := compareUint32Slices(ke[0:], testKe); i >= 0 {
|
if i := compareUint32Slices(ke[0:], testKe); i >= 0 {
|
||||||
t.Errorf("ke disagrees at index %v; %v != %v\n", i, ke[i], testKe[i])
|
t.Errorf("ke disagrees at index %v; %v != %v\n", i, ke[i], testKe[i])
|
||||||
}
|
}
|
||||||
@ -322,7 +322,7 @@ func BenchmarkInt63Threadsafe(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkInt63Unthreadsafe(b *testing.B) {
|
func BenchmarkInt63Unthreadsafe(b *testing.B) {
|
||||||
r := New(NewSource(1));
|
r := New(NewSource(1))
|
||||||
for n := b.N; n > 0; n-- {
|
for n := b.N; n > 0; n-- {
|
||||||
r.Int63()
|
r.Int63()
|
||||||
}
|
}
|
||||||
|
@ -12,14 +12,14 @@ package rand
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const (
|
const (
|
||||||
_LEN = 607;
|
_LEN = 607
|
||||||
_TAP = 273;
|
_TAP = 273
|
||||||
_MAX = 1 << 63;
|
_MAX = 1 << 63
|
||||||
_MASK = _MAX - 1;
|
_MASK = _MAX - 1
|
||||||
_A = 48271;
|
_A = 48271
|
||||||
_M = (1 << 31) - 1;
|
_M = (1 << 31) - 1
|
||||||
_Q = 44488;
|
_Q = 44488
|
||||||
_R = 3399;
|
_R = 3399
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -179,32 +179,32 @@ var (
|
|||||||
4922828954023452664, 2879211533496425641, 5896236396443472108, 8465043815351752425,
|
4922828954023452664, 2879211533496425641, 5896236396443472108, 8465043815351752425,
|
||||||
7329020396871624740, 8915471717014488588, 2944902635677463047, 7052079073493465134,
|
7329020396871624740, 8915471717014488588, 2944902635677463047, 7052079073493465134,
|
||||||
8382142935188824023, 9103922860780351547, 4152330101494654406,
|
8382142935188824023, 9103922860780351547, 4152330101494654406,
|
||||||
};
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
type rngSource struct {
|
type rngSource struct {
|
||||||
tap int; // index into vec
|
tap int // index into vec
|
||||||
feed int; // index into vec
|
feed int // index into vec
|
||||||
vec [_LEN]int64; // current feedback register
|
vec [_LEN]int64 // current feedback register
|
||||||
}
|
}
|
||||||
|
|
||||||
// seed rng x[n+1] = 48271 * x[n] mod (2**31 - 1)
|
// seed rng x[n+1] = 48271 * x[n] mod (2**31 - 1)
|
||||||
func seedrand(x int32) int32 {
|
func seedrand(x int32) int32 {
|
||||||
hi := x / _Q;
|
hi := x / _Q
|
||||||
lo := x % _Q;
|
lo := x % _Q
|
||||||
x = _A*lo - _R*hi;
|
x = _A*lo - _R*hi
|
||||||
if x < 0 {
|
if x < 0 {
|
||||||
x += _M
|
x += _M
|
||||||
}
|
}
|
||||||
return x;
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seed uses the provided seed value to initialize the generator to a deterministic state.
|
// Seed uses the provided seed value to initialize the generator to a deterministic state.
|
||||||
func (rng *rngSource) Seed(seed int64) {
|
func (rng *rngSource) Seed(seed int64) {
|
||||||
rng.tap = 0;
|
rng.tap = 0
|
||||||
rng.feed = _LEN - _TAP;
|
rng.feed = _LEN - _TAP
|
||||||
|
|
||||||
seed = seed % _M;
|
seed = seed % _M
|
||||||
if seed < 0 {
|
if seed < 0 {
|
||||||
seed += _M
|
seed += _M
|
||||||
}
|
}
|
||||||
@ -212,35 +212,35 @@ func (rng *rngSource) Seed(seed int64) {
|
|||||||
seed = 89482311
|
seed = 89482311
|
||||||
}
|
}
|
||||||
|
|
||||||
x := int32(seed);
|
x := int32(seed)
|
||||||
for i := -20; i < _LEN; i++ {
|
for i := -20; i < _LEN; i++ {
|
||||||
x = seedrand(x);
|
x = seedrand(x)
|
||||||
if i >= 0 {
|
if i >= 0 {
|
||||||
var u int64;
|
var u int64
|
||||||
u = int64(x) << 40;
|
u = int64(x) << 40
|
||||||
x = seedrand(x);
|
x = seedrand(x)
|
||||||
u ^= int64(x) << 20;
|
u ^= int64(x) << 20
|
||||||
x = seedrand(x);
|
x = seedrand(x)
|
||||||
u ^= int64(x);
|
u ^= int64(x)
|
||||||
u ^= rng_cooked[i];
|
u ^= rng_cooked[i]
|
||||||
rng.vec[i] = u & _MASK;
|
rng.vec[i] = u & _MASK
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
|
// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
|
||||||
func (rng *rngSource) Int63() int64 {
|
func (rng *rngSource) Int63() int64 {
|
||||||
rng.tap--;
|
rng.tap--
|
||||||
if rng.tap < 0 {
|
if rng.tap < 0 {
|
||||||
rng.tap += _LEN
|
rng.tap += _LEN
|
||||||
}
|
}
|
||||||
|
|
||||||
rng.feed--;
|
rng.feed--
|
||||||
if rng.feed < 0 {
|
if rng.feed < 0 {
|
||||||
rng.feed += _LEN
|
rng.feed += _LEN
|
||||||
}
|
}
|
||||||
|
|
||||||
x := (rng.vec[rng.feed] + rng.vec[rng.tap]) & _MASK;
|
x := (rng.vec[rng.feed] + rng.vec[rng.tap]) & _MASK
|
||||||
rng.vec[rng.feed] = x;
|
rng.vec[rng.feed] = x
|
||||||
return x;
|
return x
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -12,10 +12,10 @@ package reflect
|
|||||||
// checks in progress are true when it reencounters them.
|
// checks in progress are true when it reencounters them.
|
||||||
// Visited are stored in a map indexed by 17 * a1 + a2;
|
// Visited are stored in a map indexed by 17 * a1 + a2;
|
||||||
type visit struct {
|
type visit struct {
|
||||||
a1 uintptr;
|
a1 uintptr
|
||||||
a2 uintptr;
|
a2 uintptr
|
||||||
typ Type;
|
typ Type
|
||||||
next *visit;
|
next *visit
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests for deep equality using reflected types. The map argument tracks
|
// Tests for deep equality using reflected types. The map argument tracks
|
||||||
@ -31,8 +31,8 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
|
|||||||
|
|
||||||
// if depth > 10 { panic("deepValueEqual") } // for debugging
|
// if depth > 10 { panic("deepValueEqual") } // for debugging
|
||||||
|
|
||||||
addr1 := v1.Addr();
|
addr1 := v1.Addr()
|
||||||
addr2 := v2.Addr();
|
addr2 := v2.Addr()
|
||||||
if addr1 > addr2 {
|
if addr1 > addr2 {
|
||||||
// Canonicalize order to reduce number of entries in visited.
|
// Canonicalize order to reduce number of entries in visited.
|
||||||
addr1, addr2 = addr2, addr1
|
addr1, addr2 = addr2, addr1
|
||||||
@ -44,9 +44,9 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ... or already seen
|
// ... or already seen
|
||||||
h := 17*addr1 + addr2;
|
h := 17*addr1 + addr2
|
||||||
seen, _ := visited[h];
|
seen, _ := visited[h]
|
||||||
typ := v1.Type();
|
typ := v1.Type()
|
||||||
for p := seen; p != nil; p = p.next {
|
for p := seen; p != nil; p = p.next {
|
||||||
if p.a1 == addr1 && p.a2 == addr2 && p.typ == typ {
|
if p.a1 == addr1 && p.a2 == addr2 && p.typ == typ {
|
||||||
return true
|
return true
|
||||||
@ -54,12 +54,12 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remember for later.
|
// Remember for later.
|
||||||
visited[h] = &visit{addr1, addr2, typ, seen};
|
visited[h] = &visit{addr1, addr2, typ, seen}
|
||||||
|
|
||||||
switch v := v1.(type) {
|
switch v := v1.(type) {
|
||||||
case *ArrayValue:
|
case *ArrayValue:
|
||||||
arr1 := v;
|
arr1 := v
|
||||||
arr2 := v2.(*ArrayValue);
|
arr2 := v2.(*ArrayValue)
|
||||||
if arr1.Len() != arr2.Len() {
|
if arr1.Len() != arr2.Len() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -68,10 +68,10 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
case *SliceValue:
|
case *SliceValue:
|
||||||
arr1 := v;
|
arr1 := v
|
||||||
arr2 := v2.(*SliceValue);
|
arr2 := v2.(*SliceValue)
|
||||||
if arr1.Len() != arr2.Len() {
|
if arr1.Len() != arr2.Len() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -80,28 +80,28 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
case *InterfaceValue:
|
case *InterfaceValue:
|
||||||
i1 := v.Interface();
|
i1 := v.Interface()
|
||||||
i2 := v2.Interface();
|
i2 := v2.Interface()
|
||||||
if i1 == nil || i2 == nil {
|
if i1 == nil || i2 == nil {
|
||||||
return i1 == i2
|
return i1 == i2
|
||||||
}
|
}
|
||||||
return deepValueEqual(NewValue(i1), NewValue(i2), visited, depth+1);
|
return deepValueEqual(NewValue(i1), NewValue(i2), visited, depth+1)
|
||||||
case *PtrValue:
|
case *PtrValue:
|
||||||
return deepValueEqual(v.Elem(), v2.(*PtrValue).Elem(), visited, depth+1)
|
return deepValueEqual(v.Elem(), v2.(*PtrValue).Elem(), visited, depth+1)
|
||||||
case *StructValue:
|
case *StructValue:
|
||||||
struct1 := v;
|
struct1 := v
|
||||||
struct2 := v2.(*StructValue);
|
struct2 := v2.(*StructValue)
|
||||||
for i, n := 0, v.NumField(); i < n; i++ {
|
for i, n := 0, v.NumField(); i < n; i++ {
|
||||||
if !deepValueEqual(struct1.Field(i), struct2.Field(i), visited, depth+1) {
|
if !deepValueEqual(struct1.Field(i), struct2.Field(i), visited, depth+1) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
case *MapValue:
|
case *MapValue:
|
||||||
map1 := v;
|
map1 := v
|
||||||
map2 := v2.(*MapValue);
|
map2 := v2.(*MapValue)
|
||||||
if map1.Len() != map2.Len() {
|
if map1.Len() != map2.Len() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -110,13 +110,13 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
default:
|
default:
|
||||||
// Normal equality suffices
|
// Normal equality suffices
|
||||||
return v1.Interface() == v2.Interface()
|
return v1.Interface() == v2.Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
panic("Not reached");
|
panic("Not reached")
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepEqual tests for deep equality. It uses normal == equality where possible
|
// DeepEqual tests for deep equality. It uses normal == equality where possible
|
||||||
@ -126,10 +126,10 @@ func DeepEqual(a1, a2 interface{}) bool {
|
|||||||
if a1 == nil || a2 == nil {
|
if a1 == nil || a2 == nil {
|
||||||
return a1 == a2
|
return a1 == a2
|
||||||
}
|
}
|
||||||
v1 := NewValue(a1);
|
v1 := NewValue(a1)
|
||||||
v2 := NewValue(a2);
|
v2 := NewValue(a2)
|
||||||
if v1.Type() != v2.Type() {
|
if v1.Type() != v2.Type() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return deepValueEqual(v1, v2, make(map[uintptr]*visit), 0);
|
return deepValueEqual(v1, v2, make(map[uintptr]*visit), 0)
|
||||||
}
|
}
|
||||||
|
@ -9,18 +9,18 @@
|
|||||||
package reflect_test
|
package reflect_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "reflect";
|
. "reflect"
|
||||||
"strconv";
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// valueToString returns a textual representation of the reflection value val.
|
// valueToString returns a textual representation of the reflection value val.
|
||||||
// For debugging only.
|
// For debugging only.
|
||||||
func valueToString(val Value) string {
|
func valueToString(val Value) string {
|
||||||
var str string;
|
var str string
|
||||||
if val == nil {
|
if val == nil {
|
||||||
return "<nil>"
|
return "<nil>"
|
||||||
}
|
}
|
||||||
typ := val.Type();
|
typ := val.Type()
|
||||||
switch val := val.(type) {
|
switch val := val.(type) {
|
||||||
case *IntValue:
|
case *IntValue:
|
||||||
return strconv.Uitoa64(uint64(val.Get()))
|
return strconv.Uitoa64(uint64(val.Get()))
|
||||||
@ -61,57 +61,57 @@ func valueToString(val Value) string {
|
|||||||
return "false"
|
return "false"
|
||||||
}
|
}
|
||||||
case *PtrValue:
|
case *PtrValue:
|
||||||
v := val;
|
v := val
|
||||||
str = typ.String() + "(";
|
str = typ.String() + "("
|
||||||
if v.IsNil() {
|
if v.IsNil() {
|
||||||
str += "0"
|
str += "0"
|
||||||
} else {
|
} else {
|
||||||
str += "&" + valueToString(v.Elem())
|
str += "&" + valueToString(v.Elem())
|
||||||
}
|
}
|
||||||
str += ")";
|
str += ")"
|
||||||
return str;
|
return str
|
||||||
case ArrayOrSliceValue:
|
case ArrayOrSliceValue:
|
||||||
v := val;
|
v := val
|
||||||
str += typ.String();
|
str += typ.String()
|
||||||
str += "{";
|
str += "{"
|
||||||
for i := 0; i < v.Len(); i++ {
|
for i := 0; i < v.Len(); i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
str += ", "
|
str += ", "
|
||||||
}
|
}
|
||||||
str += valueToString(v.Elem(i));
|
str += valueToString(v.Elem(i))
|
||||||
}
|
}
|
||||||
str += "}";
|
str += "}"
|
||||||
return str;
|
return str
|
||||||
case *MapValue:
|
case *MapValue:
|
||||||
t := typ.(*MapType);
|
t := typ.(*MapType)
|
||||||
str = t.String();
|
str = t.String()
|
||||||
str += "{";
|
str += "{"
|
||||||
str += "<can't iterate on maps>";
|
str += "<can't iterate on maps>"
|
||||||
str += "}";
|
str += "}"
|
||||||
return str;
|
return str
|
||||||
case *ChanValue:
|
case *ChanValue:
|
||||||
str = typ.String();
|
str = typ.String()
|
||||||
return str;
|
return str
|
||||||
case *StructValue:
|
case *StructValue:
|
||||||
t := typ.(*StructType);
|
t := typ.(*StructType)
|
||||||
v := val;
|
v := val
|
||||||
str += t.String();
|
str += t.String()
|
||||||
str += "{";
|
str += "{"
|
||||||
for i, n := 0, v.NumField(); i < n; i++ {
|
for i, n := 0, v.NumField(); i < n; i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
str += ", "
|
str += ", "
|
||||||
}
|
}
|
||||||
str += valueToString(v.Field(i));
|
str += valueToString(v.Field(i))
|
||||||
}
|
}
|
||||||
str += "}";
|
str += "}"
|
||||||
return str;
|
return str
|
||||||
case *InterfaceValue:
|
case *InterfaceValue:
|
||||||
return typ.String() + "(" + valueToString(val.Elem()) + ")"
|
return typ.String() + "(" + valueToString(val.Elem()) + ")"
|
||||||
case *FuncValue:
|
case *FuncValue:
|
||||||
v := val;
|
v := val
|
||||||
return typ.String() + "(" + strconv.Itoa64(int64(v.Get())) + ")";
|
return typ.String() + "(" + strconv.Itoa64(int64(v.Get())) + ")"
|
||||||
default:
|
default:
|
||||||
panicln("valueToString: can't print type ", typ.String())
|
panicln("valueToString: can't print type ", typ.String())
|
||||||
}
|
}
|
||||||
return "valueToString: can't happen";
|
return "valueToString: can't happen"
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,9 @@
|
|||||||
package reflect
|
package reflect
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime";
|
"runtime"
|
||||||
"strconv";
|
"strconv"
|
||||||
"unsafe";
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -35,198 +35,198 @@ import (
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
type commonType struct {
|
type commonType struct {
|
||||||
size uintptr;
|
size uintptr
|
||||||
hash uint32;
|
hash uint32
|
||||||
alg uint8;
|
alg uint8
|
||||||
align uint8;
|
align uint8
|
||||||
fieldAlign uint8;
|
fieldAlign uint8
|
||||||
string *string;
|
string *string
|
||||||
*uncommonType;
|
*uncommonType
|
||||||
}
|
}
|
||||||
|
|
||||||
type method struct {
|
type method struct {
|
||||||
hash uint32;
|
hash uint32
|
||||||
name *string;
|
name *string
|
||||||
pkgPath *string;
|
pkgPath *string
|
||||||
typ *runtime.Type;
|
typ *runtime.Type
|
||||||
ifn unsafe.Pointer;
|
ifn unsafe.Pointer
|
||||||
tfn unsafe.Pointer;
|
tfn unsafe.Pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
type uncommonType struct {
|
type uncommonType struct {
|
||||||
name *string;
|
name *string
|
||||||
pkgPath *string;
|
pkgPath *string
|
||||||
methods []method;
|
methods []method
|
||||||
}
|
}
|
||||||
|
|
||||||
// BoolType represents a boolean type.
|
// BoolType represents a boolean type.
|
||||||
type BoolType struct {
|
type BoolType struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Float32Type represents a float32 type.
|
// Float32Type represents a float32 type.
|
||||||
type Float32Type struct {
|
type Float32Type struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Float64Type represents a float64 type.
|
// Float64Type represents a float64 type.
|
||||||
type Float64Type struct {
|
type Float64Type struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// FloatType represents a float type.
|
// FloatType represents a float type.
|
||||||
type FloatType struct {
|
type FloatType struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int16Type represents an int16 type.
|
// Int16Type represents an int16 type.
|
||||||
type Int16Type struct {
|
type Int16Type struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int32Type represents an int32 type.
|
// Int32Type represents an int32 type.
|
||||||
type Int32Type struct {
|
type Int32Type struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int64Type represents an int64 type.
|
// Int64Type represents an int64 type.
|
||||||
type Int64Type struct {
|
type Int64Type struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int8Type represents an int8 type.
|
// Int8Type represents an int8 type.
|
||||||
type Int8Type struct {
|
type Int8Type struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// IntType represents an int type.
|
// IntType represents an int type.
|
||||||
type IntType struct {
|
type IntType struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint16Type represents a uint16 type.
|
// Uint16Type represents a uint16 type.
|
||||||
type Uint16Type struct {
|
type Uint16Type struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint32Type represents a uint32 type.
|
// Uint32Type represents a uint32 type.
|
||||||
type Uint32Type struct {
|
type Uint32Type struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint64Type represents a uint64 type.
|
// Uint64Type represents a uint64 type.
|
||||||
type Uint64Type struct {
|
type Uint64Type struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint8Type represents a uint8 type.
|
// Uint8Type represents a uint8 type.
|
||||||
type Uint8Type struct {
|
type Uint8Type struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// UintType represents a uint type.
|
// UintType represents a uint type.
|
||||||
type UintType struct {
|
type UintType struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringType represents a string type.
|
// StringType represents a string type.
|
||||||
type StringType struct {
|
type StringType struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// UintptrType represents a uintptr type.
|
// UintptrType represents a uintptr type.
|
||||||
type UintptrType struct {
|
type UintptrType struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// DotDotDotType represents the ... that can
|
// DotDotDotType represents the ... that can
|
||||||
// be used as the type of the final function parameter.
|
// be used as the type of the final function parameter.
|
||||||
type DotDotDotType struct {
|
type DotDotDotType struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnsafePointerType represents an unsafe.Pointer type.
|
// UnsafePointerType represents an unsafe.Pointer type.
|
||||||
type UnsafePointerType struct {
|
type UnsafePointerType struct {
|
||||||
commonType;
|
commonType
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArrayType represents a fixed array type.
|
// ArrayType represents a fixed array type.
|
||||||
type ArrayType struct {
|
type ArrayType struct {
|
||||||
commonType;
|
commonType
|
||||||
elem *runtime.Type;
|
elem *runtime.Type
|
||||||
len uintptr;
|
len uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChanDir represents a channel type's direction.
|
// ChanDir represents a channel type's direction.
|
||||||
type ChanDir int
|
type ChanDir int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RecvDir ChanDir = 1 << iota;
|
RecvDir ChanDir = 1 << iota
|
||||||
SendDir;
|
SendDir
|
||||||
BothDir = RecvDir | SendDir;
|
BothDir = RecvDir | SendDir
|
||||||
)
|
)
|
||||||
|
|
||||||
// ChanType represents a channel type.
|
// ChanType represents a channel type.
|
||||||
type ChanType struct {
|
type ChanType struct {
|
||||||
commonType;
|
commonType
|
||||||
elem *runtime.Type;
|
elem *runtime.Type
|
||||||
dir uintptr;
|
dir uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
// FuncType represents a function type.
|
// FuncType represents a function type.
|
||||||
type FuncType struct {
|
type FuncType struct {
|
||||||
commonType;
|
commonType
|
||||||
in []*runtime.Type;
|
in []*runtime.Type
|
||||||
out []*runtime.Type;
|
out []*runtime.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method on interface type
|
// Method on interface type
|
||||||
type imethod struct {
|
type imethod struct {
|
||||||
hash uint32;
|
hash uint32
|
||||||
perm uint32;
|
perm uint32
|
||||||
name *string;
|
name *string
|
||||||
pkgPath *string;
|
pkgPath *string
|
||||||
typ *runtime.Type;
|
typ *runtime.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// InterfaceType represents an interface type.
|
// InterfaceType represents an interface type.
|
||||||
type InterfaceType struct {
|
type InterfaceType struct {
|
||||||
commonType;
|
commonType
|
||||||
methods []imethod;
|
methods []imethod
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapType represents a map type.
|
// MapType represents a map type.
|
||||||
type MapType struct {
|
type MapType struct {
|
||||||
commonType;
|
commonType
|
||||||
key *runtime.Type;
|
key *runtime.Type
|
||||||
elem *runtime.Type;
|
elem *runtime.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// PtrType represents a pointer type.
|
// PtrType represents a pointer type.
|
||||||
type PtrType struct {
|
type PtrType struct {
|
||||||
commonType;
|
commonType
|
||||||
elem *runtime.Type;
|
elem *runtime.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// SliceType represents a slice type.
|
// SliceType represents a slice type.
|
||||||
type SliceType struct {
|
type SliceType struct {
|
||||||
commonType;
|
commonType
|
||||||
elem *runtime.Type;
|
elem *runtime.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// Struct field
|
// Struct field
|
||||||
type structField struct {
|
type structField struct {
|
||||||
name *string;
|
name *string
|
||||||
pkgPath *string;
|
pkgPath *string
|
||||||
typ *runtime.Type;
|
typ *runtime.Type
|
||||||
tag *string;
|
tag *string
|
||||||
offset uintptr;
|
offset uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
// StructType represents a struct type.
|
// StructType represents a struct type.
|
||||||
type StructType struct {
|
type StructType struct {
|
||||||
commonType;
|
commonType
|
||||||
fields []structField;
|
fields []structField
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -237,10 +237,10 @@ type StructType struct {
|
|||||||
|
|
||||||
// Method represents a single method.
|
// Method represents a single method.
|
||||||
type Method struct {
|
type Method struct {
|
||||||
PkgPath string; // empty for uppercase Name
|
PkgPath string // empty for uppercase Name
|
||||||
Name string;
|
Name string
|
||||||
Type *FuncType;
|
Type *FuncType
|
||||||
Func *FuncValue;
|
Func *FuncValue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type is the runtime representation of a Go type.
|
// Type is the runtime representation of a Go type.
|
||||||
@ -253,37 +253,37 @@ type Type interface {
|
|||||||
// PkgPath returns the type's package path.
|
// PkgPath returns the type's package path.
|
||||||
// The package path is a full package import path like "container/vector".
|
// The package path is a full package import path like "container/vector".
|
||||||
// PkgPath returns an empty string for unnamed types.
|
// PkgPath returns an empty string for unnamed types.
|
||||||
PkgPath() string;
|
PkgPath() string
|
||||||
|
|
||||||
// Name returns the type's name within its package.
|
// Name returns the type's name within its package.
|
||||||
// Name returns an empty string for unnamed types.
|
// Name returns an empty string for unnamed types.
|
||||||
Name() string;
|
Name() string
|
||||||
|
|
||||||
// String returns a string representation of the type.
|
// String returns a string representation of the type.
|
||||||
// The string representation may use shortened package names
|
// The string representation may use shortened package names
|
||||||
// (e.g., vector instead of "container/vector") and is not
|
// (e.g., vector instead of "container/vector") and is not
|
||||||
// guaranteed to be unique among types. To test for equality,
|
// guaranteed to be unique among types. To test for equality,
|
||||||
// compare the Types directly.
|
// compare the Types directly.
|
||||||
String() string;
|
String() string
|
||||||
|
|
||||||
// Size returns the number of bytes needed to store
|
// Size returns the number of bytes needed to store
|
||||||
// a value of the given type; it is analogous to unsafe.Sizeof.
|
// a value of the given type; it is analogous to unsafe.Sizeof.
|
||||||
Size() uintptr;
|
Size() uintptr
|
||||||
|
|
||||||
// Align returns the alignment of a value of this type
|
// Align returns the alignment of a value of this type
|
||||||
// when allocated in memory.
|
// when allocated in memory.
|
||||||
Align() int;
|
Align() int
|
||||||
|
|
||||||
// FieldAlign returns the alignment of a value of this type
|
// FieldAlign returns the alignment of a value of this type
|
||||||
// when used as a field in a struct.
|
// when used as a field in a struct.
|
||||||
FieldAlign() int;
|
FieldAlign() int
|
||||||
|
|
||||||
// For non-interface types, Method returns the i'th method with receiver T.
|
// For non-interface types, Method returns the i'th method with receiver T.
|
||||||
// For interface types, Method returns the i'th method in the interface.
|
// For interface types, Method returns the i'th method in the interface.
|
||||||
// NumMethod returns the number of such methods.
|
// NumMethod returns the number of such methods.
|
||||||
Method(int) Method;
|
Method(int) Method
|
||||||
NumMethod() int;
|
NumMethod() int
|
||||||
uncommon() *uncommonType;
|
uncommon() *uncommonType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *uncommonType) uncommon() *uncommonType {
|
func (t *uncommonType) uncommon() *uncommonType {
|
||||||
@ -294,14 +294,14 @@ func (t *uncommonType) PkgPath() string {
|
|||||||
if t == nil || t.pkgPath == nil {
|
if t == nil || t.pkgPath == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return *t.pkgPath;
|
return *t.pkgPath
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *uncommonType) Name() string {
|
func (t *uncommonType) Name() string {
|
||||||
if t == nil || t.name == nil {
|
if t == nil || t.name == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return *t.name;
|
return *t.name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *commonType) String() string { return *t.string }
|
func (t *commonType) String() string { return *t.string }
|
||||||
@ -316,24 +316,24 @@ func (t *uncommonType) Method(i int) (m Method) {
|
|||||||
if t == nil || i < 0 || i >= len(t.methods) {
|
if t == nil || i < 0 || i >= len(t.methods) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p := &t.methods[i];
|
p := &t.methods[i]
|
||||||
if p.name != nil {
|
if p.name != nil {
|
||||||
m.Name = *p.name
|
m.Name = *p.name
|
||||||
}
|
}
|
||||||
if p.pkgPath != nil {
|
if p.pkgPath != nil {
|
||||||
m.PkgPath = *p.pkgPath
|
m.PkgPath = *p.pkgPath
|
||||||
}
|
}
|
||||||
m.Type = toType(*p.typ).(*FuncType);
|
m.Type = toType(*p.typ).(*FuncType)
|
||||||
fn := p.tfn;
|
fn := p.tfn
|
||||||
m.Func = newFuncValue(m.Type, addr(&fn), true);
|
m.Func = newFuncValue(m.Type, addr(&fn), true)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *uncommonType) NumMethod() int {
|
func (t *uncommonType) NumMethod() int {
|
||||||
if t == nil {
|
if t == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return len(t.methods);
|
return len(t.methods)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(rsc): 6g supplies these, but they are not
|
// TODO(rsc): 6g supplies these, but they are not
|
||||||
@ -368,7 +368,7 @@ func (d ChanDir) String() string {
|
|||||||
case BothDir:
|
case BothDir:
|
||||||
return "chan"
|
return "chan"
|
||||||
}
|
}
|
||||||
return "ChanDir" + strconv.Itoa(int(d));
|
return "ChanDir" + strconv.Itoa(int(d))
|
||||||
}
|
}
|
||||||
|
|
||||||
// In returns the type of the i'th function input parameter.
|
// In returns the type of the i'th function input parameter.
|
||||||
@ -376,7 +376,7 @@ func (t *FuncType) In(i int) Type {
|
|||||||
if i < 0 || i >= len(t.in) {
|
if i < 0 || i >= len(t.in) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return toType(*t.in[i]);
|
return toType(*t.in[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
// NumIn returns the number of input parameters.
|
// NumIn returns the number of input parameters.
|
||||||
@ -387,7 +387,7 @@ func (t *FuncType) Out(i int) Type {
|
|||||||
if i < 0 || i >= len(t.out) {
|
if i < 0 || i >= len(t.out) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return toType(*t.out[i]);
|
return toType(*t.out[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
// NumOut returns the number of function output parameters.
|
// NumOut returns the number of function output parameters.
|
||||||
@ -398,13 +398,13 @@ func (t *InterfaceType) Method(i int) (m Method) {
|
|||||||
if i < 0 || i >= len(t.methods) {
|
if i < 0 || i >= len(t.methods) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p := &t.methods[i];
|
p := &t.methods[i]
|
||||||
m.Name = *p.name;
|
m.Name = *p.name
|
||||||
if p.pkgPath != nil {
|
if p.pkgPath != nil {
|
||||||
m.PkgPath = *p.pkgPath
|
m.PkgPath = *p.pkgPath
|
||||||
}
|
}
|
||||||
m.Type = toType(*p.typ).(*FuncType);
|
m.Type = toType(*p.typ).(*FuncType)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// NumMethod returns the number of interface methods.
|
// NumMethod returns the number of interface methods.
|
||||||
@ -423,13 +423,13 @@ func (t *PtrType) Elem() Type { return toType(*t.elem) }
|
|||||||
func (t *SliceType) Elem() Type { return toType(*t.elem) }
|
func (t *SliceType) Elem() Type { return toType(*t.elem) }
|
||||||
|
|
||||||
type StructField struct {
|
type StructField struct {
|
||||||
PkgPath string; // empty for uppercase Name
|
PkgPath string // empty for uppercase Name
|
||||||
Name string;
|
Name string
|
||||||
Type Type;
|
Type Type
|
||||||
Tag string;
|
Tag string
|
||||||
Offset uintptr;
|
Offset uintptr
|
||||||
Index []int;
|
Index []int
|
||||||
Anonymous bool;
|
Anonymous bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Field returns the i'th struct field.
|
// Field returns the i'th struct field.
|
||||||
@ -437,17 +437,17 @@ func (t *StructType) Field(i int) (f StructField) {
|
|||||||
if i < 0 || i >= len(t.fields) {
|
if i < 0 || i >= len(t.fields) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p := t.fields[i];
|
p := t.fields[i]
|
||||||
f.Type = toType(*p.typ);
|
f.Type = toType(*p.typ)
|
||||||
if p.name != nil {
|
if p.name != nil {
|
||||||
f.Name = *p.name
|
f.Name = *p.name
|
||||||
} else {
|
} else {
|
||||||
t := f.Type;
|
t := f.Type
|
||||||
if pt, ok := t.(*PtrType); ok {
|
if pt, ok := t.(*PtrType); ok {
|
||||||
t = pt.Elem()
|
t = pt.Elem()
|
||||||
}
|
}
|
||||||
f.Name = t.Name();
|
f.Name = t.Name()
|
||||||
f.Anonymous = true;
|
f.Anonymous = true
|
||||||
}
|
}
|
||||||
if p.pkgPath != nil {
|
if p.pkgPath != nil {
|
||||||
f.PkgPath = *p.pkgPath
|
f.PkgPath = *p.pkgPath
|
||||||
@ -455,9 +455,9 @@ func (t *StructType) Field(i int) (f StructField) {
|
|||||||
if p.tag != nil {
|
if p.tag != nil {
|
||||||
f.Tag = *p.tag
|
f.Tag = *p.tag
|
||||||
}
|
}
|
||||||
f.Offset = p.offset;
|
f.Offset = p.offset
|
||||||
f.Index = []int{i};
|
f.Index = []int{i}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(gri): Should there be an error/bool indicator if the index
|
// TODO(gri): Should there be an error/bool indicator if the index
|
||||||
@ -467,45 +467,45 @@ func (t *StructType) Field(i int) (f StructField) {
|
|||||||
func (t *StructType) FieldByIndex(index []int) (f StructField) {
|
func (t *StructType) FieldByIndex(index []int) (f StructField) {
|
||||||
for i, x := range index {
|
for i, x := range index {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
ft := f.Type;
|
ft := f.Type
|
||||||
if pt, ok := ft.(*PtrType); ok {
|
if pt, ok := ft.(*PtrType); ok {
|
||||||
ft = pt.Elem()
|
ft = pt.Elem()
|
||||||
}
|
}
|
||||||
if st, ok := ft.(*StructType); ok {
|
if st, ok := ft.(*StructType); ok {
|
||||||
t = st
|
t = st
|
||||||
} else {
|
} else {
|
||||||
var f0 StructField;
|
var f0 StructField
|
||||||
f = f0;
|
f = f0
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f = t.Field(x);
|
f = t.Field(x)
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const inf = 1 << 30 // infinity - no struct has that many nesting levels
|
const inf = 1 << 30 // infinity - no struct has that many nesting levels
|
||||||
|
|
||||||
func (t *StructType) fieldByName(name string, mark map[*StructType]bool, depth int) (ff StructField, fd int) {
|
func (t *StructType) fieldByName(name string, mark map[*StructType]bool, depth int) (ff StructField, fd int) {
|
||||||
fd = inf; // field depth
|
fd = inf // field depth
|
||||||
|
|
||||||
if _, marked := mark[t]; marked {
|
if _, marked := mark[t]; marked {
|
||||||
// Struct already seen.
|
// Struct already seen.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mark[t] = true;
|
mark[t] = true
|
||||||
|
|
||||||
var fi int; // field index
|
var fi int // field index
|
||||||
n := 0; // number of matching fields at depth fd
|
n := 0 // number of matching fields at depth fd
|
||||||
L: for i, _ := range t.fields {
|
L: for i, _ := range t.fields {
|
||||||
f := t.Field(i);
|
f := t.Field(i)
|
||||||
d := inf;
|
d := inf
|
||||||
switch {
|
switch {
|
||||||
case f.Name == name:
|
case f.Name == name:
|
||||||
// Matching top-level field.
|
// Matching top-level field.
|
||||||
d = depth
|
d = depth
|
||||||
case f.Anonymous:
|
case f.Anonymous:
|
||||||
ft := f.Type;
|
ft := f.Type
|
||||||
if pt, ok := ft.(*PtrType); ok {
|
if pt, ok := ft.(*PtrType); ok {
|
||||||
ft = pt.Elem()
|
ft = pt.Elem()
|
||||||
}
|
}
|
||||||
@ -524,12 +524,12 @@ L: for i, _ := range t.fields {
|
|||||||
switch {
|
switch {
|
||||||
case d < fd:
|
case d < fd:
|
||||||
// Found field at shallower depth.
|
// Found field at shallower depth.
|
||||||
ff, fi, fd = f, i, d;
|
ff, fi, fd = f, i, d
|
||||||
n = 1;
|
n = 1
|
||||||
case d == fd:
|
case d == fd:
|
||||||
// More than one matching field at the same depth (or d, fd == inf).
|
// More than one matching field at the same depth (or d, fd == inf).
|
||||||
// Same as no field found at this depth.
|
// Same as no field found at this depth.
|
||||||
n++;
|
n++
|
||||||
if d == depth {
|
if d == depth {
|
||||||
// Impossible to find a field at lower depth.
|
// Impossible to find a field at lower depth.
|
||||||
break L
|
break L
|
||||||
@ -542,24 +542,24 @@ L: for i, _ := range t.fields {
|
|||||||
if len(ff.Index) <= depth {
|
if len(ff.Index) <= depth {
|
||||||
ff.Index = make([]int, depth+1)
|
ff.Index = make([]int, depth+1)
|
||||||
}
|
}
|
||||||
ff.Index[depth] = fi;
|
ff.Index[depth] = fi
|
||||||
} else {
|
} else {
|
||||||
// None or more than one matching field found.
|
// None or more than one matching field found.
|
||||||
fd = inf
|
fd = inf
|
||||||
}
|
}
|
||||||
|
|
||||||
mark[t] = false, false;
|
mark[t] = false, false
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// FieldByName returns the struct field with the given name
|
// FieldByName returns the struct field with the given name
|
||||||
// and a boolean to indicate if the field was found.
|
// and a boolean to indicate if the field was found.
|
||||||
func (t *StructType) FieldByName(name string) (f StructField, present bool) {
|
func (t *StructType) FieldByName(name string) (f StructField, present bool) {
|
||||||
if ff, fd := t.fieldByName(name, make(map[*StructType]bool), 0); fd < inf {
|
if ff, fd := t.fieldByName(name, make(map[*StructType]bool), 0); fd < inf {
|
||||||
ff.Index = ff.Index[0 : fd+1];
|
ff.Index = ff.Index[0 : fd+1]
|
||||||
f, present = ff, true;
|
f, present = ff, true
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// NumField returns the number of struct fields.
|
// NumField returns the number of struct fields.
|
||||||
@ -624,14 +624,14 @@ func toType(i interface{}) Type {
|
|||||||
case *runtime.StructType:
|
case *runtime.StructType:
|
||||||
return (*StructType)(unsafe.Pointer(v))
|
return (*StructType)(unsafe.Pointer(v))
|
||||||
}
|
}
|
||||||
panicln("toType", i);
|
panicln("toType", i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArrayOrSliceType is the common interface implemented
|
// ArrayOrSliceType is the common interface implemented
|
||||||
// by both ArrayType and SliceType.
|
// by both ArrayType and SliceType.
|
||||||
type ArrayOrSliceType interface {
|
type ArrayOrSliceType interface {
|
||||||
Type;
|
Type
|
||||||
Elem() Type;
|
Elem() Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// Typeof returns the reflection Type of the value in the interface{}.
|
// Typeof returns the reflection Type of the value in the interface{}.
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -5,9 +5,9 @@
|
|||||||
package regexp
|
package regexp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os";
|
"os"
|
||||||
"strings";
|
"strings"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var good_re = []string{
|
var good_re = []string{
|
||||||
@ -32,8 +32,8 @@ var good_re = []string{
|
|||||||
|
|
||||||
// TODO: nice to do this with a map
|
// TODO: nice to do this with a map
|
||||||
type stringError struct {
|
type stringError struct {
|
||||||
re string;
|
re string
|
||||||
err os.Error;
|
err os.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
var bad_re = []stringError{
|
var bad_re = []stringError{
|
||||||
@ -54,9 +54,9 @@ var bad_re = []stringError{
|
|||||||
type vec []int
|
type vec []int
|
||||||
|
|
||||||
type tester struct {
|
type tester struct {
|
||||||
re string;
|
re string
|
||||||
text string;
|
text string
|
||||||
match vec;
|
match vec
|
||||||
}
|
}
|
||||||
|
|
||||||
var matches = []tester{
|
var matches = []tester{
|
||||||
@ -100,27 +100,27 @@ var matches = []tester{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func compileTest(t *testing.T, expr string, error os.Error) *Regexp {
|
func compileTest(t *testing.T, expr string, error os.Error) *Regexp {
|
||||||
re, err := Compile(expr);
|
re, err := Compile(expr)
|
||||||
if err != error {
|
if err != error {
|
||||||
t.Error("compiling `", expr, "`; unexpected error: ", err.String())
|
t.Error("compiling `", expr, "`; unexpected error: ", err.String())
|
||||||
}
|
}
|
||||||
return re;
|
return re
|
||||||
}
|
}
|
||||||
|
|
||||||
func printVec(t *testing.T, m []int) {
|
func printVec(t *testing.T, m []int) {
|
||||||
l := len(m);
|
l := len(m)
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
t.Log("\t<no match>")
|
t.Log("\t<no match>")
|
||||||
} else {
|
} else {
|
||||||
if m[len(m)-1] == -1 {
|
if m[len(m)-1] == -1 {
|
||||||
m = m[0 : len(m)-2]
|
m = m[0 : len(m)-2]
|
||||||
}
|
}
|
||||||
t.Log("\t", m);
|
t.Log("\t", m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func equal(m1, m2 []int) bool {
|
func equal(m1, m2 []int) bool {
|
||||||
l := len(m1);
|
l := len(m1)
|
||||||
if l != len(m2) {
|
if l != len(m2) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -129,11 +129,11 @@ func equal(m1, m2 []int) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func equalStrings(m1, m2 []string) bool {
|
func equalStrings(m1, m2 []string) bool {
|
||||||
l := len(m1);
|
l := len(m1)
|
||||||
if l != len(m2) {
|
if l != len(m2) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -142,28 +142,28 @@ func equalStrings(m1, m2 []string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeTest(t *testing.T, expr string, str string, match []int) {
|
func executeTest(t *testing.T, expr string, str string, match []int) {
|
||||||
re := compileTest(t, expr, nil);
|
re := compileTest(t, expr, nil)
|
||||||
if re == nil {
|
if re == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m := re.ExecuteString(str);
|
m := re.ExecuteString(str)
|
||||||
if !equal(m, match) {
|
if !equal(m, match) {
|
||||||
t.Errorf("ExecuteString failure on %#q matching %q:", expr, str);
|
t.Errorf("ExecuteString failure on %#q matching %q:", expr, str)
|
||||||
printVec(t, m);
|
printVec(t, m)
|
||||||
t.Log("should be:");
|
t.Log("should be:")
|
||||||
printVec(t, match);
|
printVec(t, match)
|
||||||
}
|
}
|
||||||
// now try bytes
|
// now try bytes
|
||||||
m = re.Execute(strings.Bytes(str));
|
m = re.Execute(strings.Bytes(str))
|
||||||
if !equal(m, match) {
|
if !equal(m, match) {
|
||||||
t.Errorf("Execute failure on %#q matching %q:", expr, str);
|
t.Errorf("Execute failure on %#q matching %q:", expr, str)
|
||||||
printVec(t, m);
|
printVec(t, m)
|
||||||
t.Log("should be:");
|
t.Log("should be:")
|
||||||
printVec(t, match);
|
printVec(t, match)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,22 +181,22 @@ func TestBadCompile(t *testing.T) {
|
|||||||
|
|
||||||
func TestExecute(t *testing.T) {
|
func TestExecute(t *testing.T) {
|
||||||
for i := 0; i < len(matches); i++ {
|
for i := 0; i < len(matches); i++ {
|
||||||
test := &matches[i];
|
test := &matches[i]
|
||||||
executeTest(t, test.re, test.text, test.match);
|
executeTest(t, test.re, test.text, test.match)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func matchTest(t *testing.T, expr string, str string, match []int) {
|
func matchTest(t *testing.T, expr string, str string, match []int) {
|
||||||
re := compileTest(t, expr, nil);
|
re := compileTest(t, expr, nil)
|
||||||
if re == nil {
|
if re == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m := re.MatchString(str);
|
m := re.MatchString(str)
|
||||||
if m != (len(match) > 0) {
|
if m != (len(match) > 0) {
|
||||||
t.Errorf("MatchString failure on %#q matching %q: %t should be %t", expr, str, m, len(match) > 0)
|
t.Errorf("MatchString failure on %#q matching %q: %t should be %t", expr, str, m, len(match) > 0)
|
||||||
}
|
}
|
||||||
// now try bytes
|
// now try bytes
|
||||||
m = re.Match(strings.Bytes(str));
|
m = re.Match(strings.Bytes(str))
|
||||||
if m != (len(match) > 0) {
|
if m != (len(match) > 0) {
|
||||||
t.Errorf("Match failure on %#q matching %q: %t should be %t", expr, str, m, len(match) > 0)
|
t.Errorf("Match failure on %#q matching %q: %t should be %t", expr, str, m, len(match) > 0)
|
||||||
}
|
}
|
||||||
@ -204,20 +204,20 @@ func matchTest(t *testing.T, expr string, str string, match []int) {
|
|||||||
|
|
||||||
func TestMatch(t *testing.T) {
|
func TestMatch(t *testing.T) {
|
||||||
for i := 0; i < len(matches); i++ {
|
for i := 0; i < len(matches); i++ {
|
||||||
test := &matches[i];
|
test := &matches[i]
|
||||||
matchTest(t, test.re, test.text, test.match);
|
matchTest(t, test.re, test.text, test.match)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMatchStrings(t *testing.T) {
|
func TestMatchStrings(t *testing.T) {
|
||||||
for i := 0; i < len(matches); i++ {
|
for i := 0; i < len(matches); i++ {
|
||||||
test := &matches[i];
|
test := &matches[i]
|
||||||
matchTest(t, test.re, test.text, test.match);
|
matchTest(t, test.re, test.text, test.match)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func matchFunctionTest(t *testing.T, expr string, str string, match []int) {
|
func matchFunctionTest(t *testing.T, expr string, str string, match []int) {
|
||||||
m, err := MatchString(expr, str);
|
m, err := MatchString(expr, str)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -228,13 +228,13 @@ func matchFunctionTest(t *testing.T, expr string, str string, match []int) {
|
|||||||
|
|
||||||
func TestMatchFunction(t *testing.T) {
|
func TestMatchFunction(t *testing.T) {
|
||||||
for i := 0; i < len(matches); i++ {
|
for i := 0; i < len(matches); i++ {
|
||||||
test := &matches[i];
|
test := &matches[i]
|
||||||
matchFunctionTest(t, test.re, test.text, test.match);
|
matchFunctionTest(t, test.re, test.text, test.match)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReplaceTest struct {
|
type ReplaceTest struct {
|
||||||
pattern, replacement, input, output string;
|
pattern, replacement, input, output string
|
||||||
}
|
}
|
||||||
|
|
||||||
var replaceTests = []ReplaceTest{
|
var replaceTests = []ReplaceTest{
|
||||||
@ -301,18 +301,18 @@ var replaceTests = []ReplaceTest{
|
|||||||
|
|
||||||
func TestReplaceAll(t *testing.T) {
|
func TestReplaceAll(t *testing.T) {
|
||||||
for _, tc := range replaceTests {
|
for _, tc := range replaceTests {
|
||||||
re, err := Compile(tc.pattern);
|
re, err := Compile(tc.pattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err);
|
t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
actual := re.ReplaceAllString(tc.input, tc.replacement);
|
actual := re.ReplaceAllString(tc.input, tc.replacement)
|
||||||
if actual != tc.output {
|
if actual != tc.output {
|
||||||
t.Errorf("%q.Replace(%q,%q) = %q; want %q",
|
t.Errorf("%q.Replace(%q,%q) = %q; want %q",
|
||||||
tc.pattern, tc.input, tc.replacement, actual, tc.output)
|
tc.pattern, tc.input, tc.replacement, actual, tc.output)
|
||||||
}
|
}
|
||||||
// now try bytes
|
// now try bytes
|
||||||
actual = string(re.ReplaceAll(strings.Bytes(tc.input), strings.Bytes(tc.replacement)));
|
actual = string(re.ReplaceAll(strings.Bytes(tc.input), strings.Bytes(tc.replacement)))
|
||||||
if actual != tc.output {
|
if actual != tc.output {
|
||||||
t.Errorf("%q.Replace(%q,%q) = %q; want %q",
|
t.Errorf("%q.Replace(%q,%q) = %q; want %q",
|
||||||
tc.pattern, tc.input, tc.replacement, actual, tc.output)
|
tc.pattern, tc.input, tc.replacement, actual, tc.output)
|
||||||
@ -321,7 +321,7 @@ func TestReplaceAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type QuoteMetaTest struct {
|
type QuoteMetaTest struct {
|
||||||
pattern, output string;
|
pattern, output string
|
||||||
}
|
}
|
||||||
|
|
||||||
var quoteMetaTests = []QuoteMetaTest{
|
var quoteMetaTests = []QuoteMetaTest{
|
||||||
@ -333,25 +333,25 @@ var quoteMetaTests = []QuoteMetaTest{
|
|||||||
func TestQuoteMeta(t *testing.T) {
|
func TestQuoteMeta(t *testing.T) {
|
||||||
for _, tc := range quoteMetaTests {
|
for _, tc := range quoteMetaTests {
|
||||||
// Verify that QuoteMeta returns the expected string.
|
// Verify that QuoteMeta returns the expected string.
|
||||||
quoted := QuoteMeta(tc.pattern);
|
quoted := QuoteMeta(tc.pattern)
|
||||||
if quoted != tc.output {
|
if quoted != tc.output {
|
||||||
t.Errorf("QuoteMeta(`%s`) = `%s`; want `%s`",
|
t.Errorf("QuoteMeta(`%s`) = `%s`; want `%s`",
|
||||||
tc.pattern, quoted, tc.output);
|
tc.pattern, quoted, tc.output)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the quoted string is in fact treated as expected
|
// Verify that the quoted string is in fact treated as expected
|
||||||
// by Compile -- i.e. that it matches the original, unquoted string.
|
// by Compile -- i.e. that it matches the original, unquoted string.
|
||||||
if tc.pattern != "" {
|
if tc.pattern != "" {
|
||||||
re, err := Compile(quoted);
|
re, err := Compile(quoted)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected error compiling QuoteMeta(`%s`): %v", tc.pattern, err);
|
t.Errorf("Unexpected error compiling QuoteMeta(`%s`): %v", tc.pattern, err)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
src := "abc" + tc.pattern + "def";
|
src := "abc" + tc.pattern + "def"
|
||||||
repl := "xyz";
|
repl := "xyz"
|
||||||
replaced := re.ReplaceAllString(src, repl);
|
replaced := re.ReplaceAllString(src, repl)
|
||||||
expected := "abcxyzdef";
|
expected := "abcxyzdef"
|
||||||
if replaced != expected {
|
if replaced != expected {
|
||||||
t.Errorf("QuoteMeta(`%s`).Replace(`%s`,`%s`) = `%s`; want `%s`",
|
t.Errorf("QuoteMeta(`%s`).Replace(`%s`,`%s`) = `%s`; want `%s`",
|
||||||
tc.pattern, src, repl, replaced, expected)
|
tc.pattern, src, repl, replaced, expected)
|
||||||
@ -361,11 +361,11 @@ func TestQuoteMeta(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type matchCase struct {
|
type matchCase struct {
|
||||||
matchfunc string;
|
matchfunc string
|
||||||
input string;
|
input string
|
||||||
n int;
|
n int
|
||||||
regexp string;
|
regexp string
|
||||||
expected []string;
|
expected []string
|
||||||
}
|
}
|
||||||
|
|
||||||
var matchCases = []matchCase{
|
var matchCases = []matchCase{
|
||||||
@ -392,90 +392,90 @@ func printStringSlice(t *testing.T, s []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAllMatches(t *testing.T) {
|
func TestAllMatches(t *testing.T) {
|
||||||
ch := make(chan matchCase);
|
ch := make(chan matchCase)
|
||||||
go func() {
|
go func() {
|
||||||
for _, c := range matchCases {
|
for _, c := range matchCases {
|
||||||
ch <- c;
|
ch <- c
|
||||||
stringCase := matchCase{
|
stringCase := matchCase{
|
||||||
"string" + c.matchfunc,
|
"string" + c.matchfunc,
|
||||||
c.input,
|
c.input,
|
||||||
c.n,
|
c.n,
|
||||||
c.regexp,
|
c.regexp,
|
||||||
c.expected,
|
c.expected,
|
||||||
};
|
|
||||||
ch <- stringCase;
|
|
||||||
}
|
}
|
||||||
close(ch);
|
ch <- stringCase
|
||||||
}();
|
}
|
||||||
|
close(ch)
|
||||||
|
}()
|
||||||
|
|
||||||
for c := range ch {
|
for c := range ch {
|
||||||
var result []string;
|
var result []string
|
||||||
re, _ := Compile(c.regexp);
|
re, _ := Compile(c.regexp)
|
||||||
|
|
||||||
switch c.matchfunc {
|
switch c.matchfunc {
|
||||||
case "matchit":
|
case "matchit":
|
||||||
result = make([]string, len(c.input)+1);
|
result = make([]string, len(c.input)+1)
|
||||||
i := 0;
|
i := 0
|
||||||
b := strings.Bytes(c.input);
|
b := strings.Bytes(c.input)
|
||||||
for match := range re.AllMatchesIter(b, c.n) {
|
for match := range re.AllMatchesIter(b, c.n) {
|
||||||
result[i] = string(match);
|
result[i] = string(match)
|
||||||
i++;
|
i++
|
||||||
}
|
}
|
||||||
result = result[0:i];
|
result = result[0:i]
|
||||||
case "stringmatchit":
|
case "stringmatchit":
|
||||||
result = make([]string, len(c.input)+1);
|
result = make([]string, len(c.input)+1)
|
||||||
i := 0;
|
i := 0
|
||||||
for match := range re.AllMatchesStringIter(c.input, c.n) {
|
for match := range re.AllMatchesStringIter(c.input, c.n) {
|
||||||
result[i] = match;
|
result[i] = match
|
||||||
i++;
|
i++
|
||||||
}
|
}
|
||||||
result = result[0:i];
|
result = result[0:i]
|
||||||
case "match":
|
case "match":
|
||||||
result = make([]string, len(c.input)+1);
|
result = make([]string, len(c.input)+1)
|
||||||
b := strings.Bytes(c.input);
|
b := strings.Bytes(c.input)
|
||||||
i := 0;
|
i := 0
|
||||||
for _, match := range re.AllMatches(b, c.n) {
|
for _, match := range re.AllMatches(b, c.n) {
|
||||||
result[i] = string(match);
|
result[i] = string(match)
|
||||||
i++;
|
i++
|
||||||
}
|
}
|
||||||
result = result[0:i];
|
result = result[0:i]
|
||||||
case "stringmatch":
|
case "stringmatch":
|
||||||
result = re.AllMatchesString(c.input, c.n)
|
result = re.AllMatchesString(c.input, c.n)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !equalStrings(result, c.expected) {
|
if !equalStrings(result, c.expected) {
|
||||||
t.Errorf("testing '%s'.%s('%s', %d), expected: ",
|
t.Errorf("testing '%s'.%s('%s', %d), expected: ",
|
||||||
c.regexp, c.matchfunc, c.input, c.n);
|
c.regexp, c.matchfunc, c.input, c.n)
|
||||||
printStringSlice(t, c.expected);
|
printStringSlice(t, c.expected)
|
||||||
t.Log("got: ");
|
t.Log("got: ")
|
||||||
printStringSlice(t, result);
|
printStringSlice(t, result)
|
||||||
t.Log("\n");
|
t.Log("\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkLiteral(b *testing.B) {
|
func BenchmarkLiteral(b *testing.B) {
|
||||||
x := strings.Repeat("x", 50);
|
x := strings.Repeat("x", 50)
|
||||||
b.StopTimer();
|
b.StopTimer()
|
||||||
re, _ := Compile(x);
|
re, _ := Compile(x)
|
||||||
b.StartTimer();
|
b.StartTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
if !re.MatchString(x) {
|
if !re.MatchString(x) {
|
||||||
println("no match!");
|
println("no match!")
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkNotLiteral(b *testing.B) {
|
func BenchmarkNotLiteral(b *testing.B) {
|
||||||
x := strings.Repeat("x", 49);
|
x := strings.Repeat("x", 49)
|
||||||
b.StopTimer();
|
b.StopTimer()
|
||||||
re, _ := Compile("^" + x);
|
re, _ := Compile("^" + x)
|
||||||
b.StartTimer();
|
b.StartTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
if !re.MatchString(x) {
|
if !re.MatchString(x) {
|
||||||
println("no match!");
|
println("no match!")
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -5,84 +5,84 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio";
|
"bufio"
|
||||||
"gob";
|
"gob"
|
||||||
"http";
|
"http"
|
||||||
"io";
|
"io"
|
||||||
"log";
|
"log"
|
||||||
"net";
|
"net"
|
||||||
"os";
|
"os"
|
||||||
"sync";
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Call represents an active RPC.
|
// Call represents an active RPC.
|
||||||
type Call struct {
|
type Call struct {
|
||||||
ServiceMethod string; // The name of the service and method to call.
|
ServiceMethod string // The name of the service and method to call.
|
||||||
Args interface{}; // The argument to the function (*struct).
|
Args interface{} // The argument to the function (*struct).
|
||||||
Reply interface{}; // The reply from the function (*struct).
|
Reply interface{} // The reply from the function (*struct).
|
||||||
Error os.Error; // After completion, the error status.
|
Error os.Error // After completion, the error status.
|
||||||
Done chan *Call; // Strobes when call is complete; value is the error status.
|
Done chan *Call // Strobes when call is complete; value is the error status.
|
||||||
seq uint64;
|
seq uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client represents an RPC Client.
|
// Client represents an RPC Client.
|
||||||
// There may be multiple outstanding Calls associated
|
// There may be multiple outstanding Calls associated
|
||||||
// with a single Client.
|
// with a single Client.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
mutex sync.Mutex; // protects pending, seq
|
mutex sync.Mutex // protects pending, seq
|
||||||
shutdown os.Error; // non-nil if the client is shut down
|
shutdown os.Error // non-nil if the client is shut down
|
||||||
sending sync.Mutex;
|
sending sync.Mutex
|
||||||
seq uint64;
|
seq uint64
|
||||||
conn io.ReadWriteCloser;
|
conn io.ReadWriteCloser
|
||||||
enc *gob.Encoder;
|
enc *gob.Encoder
|
||||||
dec *gob.Decoder;
|
dec *gob.Decoder
|
||||||
pending map[uint64]*Call;
|
pending map[uint64]*Call
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) send(c *Call) {
|
func (client *Client) send(c *Call) {
|
||||||
// Register this call.
|
// Register this call.
|
||||||
client.mutex.Lock();
|
client.mutex.Lock()
|
||||||
if client.shutdown != nil {
|
if client.shutdown != nil {
|
||||||
c.Error = client.shutdown;
|
c.Error = client.shutdown
|
||||||
client.mutex.Unlock();
|
client.mutex.Unlock()
|
||||||
_ = c.Done <- c; // do not block
|
_ = c.Done <- c // do not block
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
c.seq = client.seq;
|
c.seq = client.seq
|
||||||
client.seq++;
|
client.seq++
|
||||||
client.pending[c.seq] = c;
|
client.pending[c.seq] = c
|
||||||
client.mutex.Unlock();
|
client.mutex.Unlock()
|
||||||
|
|
||||||
// Encode and send the request.
|
// Encode and send the request.
|
||||||
request := new(Request);
|
request := new(Request)
|
||||||
client.sending.Lock();
|
client.sending.Lock()
|
||||||
request.Seq = c.seq;
|
request.Seq = c.seq
|
||||||
request.ServiceMethod = c.ServiceMethod;
|
request.ServiceMethod = c.ServiceMethod
|
||||||
client.enc.Encode(request);
|
client.enc.Encode(request)
|
||||||
err := client.enc.Encode(c.Args);
|
err := client.enc.Encode(c.Args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panicln("rpc: client encode error:", err.String())
|
panicln("rpc: client encode error:", err.String())
|
||||||
}
|
}
|
||||||
client.sending.Unlock();
|
client.sending.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) input() {
|
func (client *Client) input() {
|
||||||
var err os.Error;
|
var err os.Error
|
||||||
for err == nil {
|
for err == nil {
|
||||||
response := new(Response);
|
response := new(Response)
|
||||||
err = client.dec.Decode(response);
|
err = client.dec.Decode(response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == os.EOF {
|
if err == os.EOF {
|
||||||
err = io.ErrUnexpectedEOF
|
err = io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
seq := response.Seq;
|
seq := response.Seq
|
||||||
client.mutex.Lock();
|
client.mutex.Lock()
|
||||||
c := client.pending[seq];
|
c := client.pending[seq]
|
||||||
client.pending[seq] = c, false;
|
client.pending[seq] = c, false
|
||||||
client.mutex.Unlock();
|
client.mutex.Unlock()
|
||||||
err = client.dec.Decode(c.Reply);
|
err = client.dec.Decode(c.Reply)
|
||||||
// Empty strings should turn into nil os.Errors
|
// Empty strings should turn into nil os.Errors
|
||||||
if response.Error != "" {
|
if response.Error != "" {
|
||||||
c.Error = os.ErrorString(response.Error)
|
c.Error = os.ErrorString(response.Error)
|
||||||
@ -91,59 +91,59 @@ func (client *Client) input() {
|
|||||||
}
|
}
|
||||||
// We don't want to block here. It is the caller's responsibility to make
|
// We don't want to block here. It is the caller's responsibility to make
|
||||||
// sure the channel has enough buffer space. See comment in Go().
|
// sure the channel has enough buffer space. See comment in Go().
|
||||||
_ = c.Done <- c; // do not block
|
_ = c.Done <- c // do not block
|
||||||
}
|
}
|
||||||
// Terminate pending calls.
|
// Terminate pending calls.
|
||||||
client.mutex.Lock();
|
client.mutex.Lock()
|
||||||
client.shutdown = err;
|
client.shutdown = err
|
||||||
for _, call := range client.pending {
|
for _, call := range client.pending {
|
||||||
call.Error = err;
|
call.Error = err
|
||||||
_ = call.Done <- call; // do not block
|
_ = call.Done <- call // do not block
|
||||||
}
|
}
|
||||||
client.mutex.Unlock();
|
client.mutex.Unlock()
|
||||||
log.Stderr("rpc: client protocol error:", err);
|
log.Stderr("rpc: client protocol error:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient returns a new Client to handle requests to the
|
// NewClient returns a new Client to handle requests to the
|
||||||
// set of services at the other end of the connection.
|
// set of services at the other end of the connection.
|
||||||
func NewClient(conn io.ReadWriteCloser) *Client {
|
func NewClient(conn io.ReadWriteCloser) *Client {
|
||||||
client := new(Client);
|
client := new(Client)
|
||||||
client.conn = conn;
|
client.conn = conn
|
||||||
client.enc = gob.NewEncoder(conn);
|
client.enc = gob.NewEncoder(conn)
|
||||||
client.dec = gob.NewDecoder(conn);
|
client.dec = gob.NewDecoder(conn)
|
||||||
client.pending = make(map[uint64]*Call);
|
client.pending = make(map[uint64]*Call)
|
||||||
go client.input();
|
go client.input()
|
||||||
return client;
|
return client
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialHTTP connects to an HTTP RPC server at the specified network address.
|
// DialHTTP connects to an HTTP RPC server at the specified network address.
|
||||||
func DialHTTP(network, address string) (*Client, os.Error) {
|
func DialHTTP(network, address string) (*Client, os.Error) {
|
||||||
conn, err := net.Dial(network, "", address);
|
conn, err := net.Dial(network, "", address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
io.WriteString(conn, "CONNECT "+rpcPath+" HTTP/1.0\n\n");
|
io.WriteString(conn, "CONNECT "+rpcPath+" HTTP/1.0\n\n")
|
||||||
|
|
||||||
// Require successful HTTP response
|
// Require successful HTTP response
|
||||||
// before switching to RPC protocol.
|
// before switching to RPC protocol.
|
||||||
resp, err := http.ReadResponse(bufio.NewReader(conn));
|
resp, err := http.ReadResponse(bufio.NewReader(conn))
|
||||||
if err == nil && resp.Status == connected {
|
if err == nil && resp.Status == connected {
|
||||||
return NewClient(conn), nil
|
return NewClient(conn), nil
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = os.ErrorString("unexpected HTTP response: " + resp.Status)
|
err = os.ErrorString("unexpected HTTP response: " + resp.Status)
|
||||||
}
|
}
|
||||||
conn.Close();
|
conn.Close()
|
||||||
return nil, &net.OpError{"dial-http", network + " " + address, nil, err};
|
return nil, &net.OpError{"dial-http", network + " " + address, nil, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dial connects to an RPC server at the specified network address.
|
// Dial connects to an RPC server at the specified network address.
|
||||||
func Dial(network, address string) (*Client, os.Error) {
|
func Dial(network, address string) (*Client, os.Error) {
|
||||||
conn, err := net.Dial(network, "", address);
|
conn, err := net.Dial(network, "", address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return NewClient(conn), nil;
|
return NewClient(conn), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go invokes the function asynchronously. It returns the Call structure representing
|
// Go invokes the function asynchronously. It returns the Call structure representing
|
||||||
@ -151,10 +151,10 @@ func Dial(network, address string) (*Client, os.Error) {
|
|||||||
// the same Call object. If done is nil, Go will allocate a new channel.
|
// the same Call object. If done is nil, Go will allocate a new channel.
|
||||||
// If non-nil, done must be buffered or Go will deliberately crash.
|
// If non-nil, done must be buffered or Go will deliberately crash.
|
||||||
func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call {
|
func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call {
|
||||||
c := new(Call);
|
c := new(Call)
|
||||||
c.ServiceMethod = serviceMethod;
|
c.ServiceMethod = serviceMethod
|
||||||
c.Args = args;
|
c.Args = args
|
||||||
c.Reply = reply;
|
c.Reply = reply
|
||||||
if done == nil {
|
if done == nil {
|
||||||
done = make(chan *Call, 10) // buffered.
|
done = make(chan *Call, 10) // buffered.
|
||||||
} else {
|
} else {
|
||||||
@ -166,14 +166,14 @@ func (client *Client) Go(serviceMethod string, args interface{}, reply interface
|
|||||||
log.Crash("rpc: done channel is unbuffered")
|
log.Crash("rpc: done channel is unbuffered")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.Done = done;
|
c.Done = done
|
||||||
if client.shutdown != nil {
|
if client.shutdown != nil {
|
||||||
c.Error = client.shutdown;
|
c.Error = client.shutdown
|
||||||
_ = c.Done <- c; // do not block
|
_ = c.Done <- c // do not block
|
||||||
return c;
|
return c
|
||||||
}
|
}
|
||||||
client.send(c);
|
client.send(c)
|
||||||
return c;
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call invokes the named function, waits for it to complete, and returns its error status.
|
// Call invokes the named function, waits for it to complete, and returns its error status.
|
||||||
@ -181,6 +181,6 @@ func (client *Client) Call(serviceMethod string, args interface{}, reply interfa
|
|||||||
if client.shutdown != nil {
|
if client.shutdown != nil {
|
||||||
return client.shutdown
|
return client.shutdown
|
||||||
}
|
}
|
||||||
call := <-client.Go(serviceMethod, args, reply, nil).Done;
|
call := <-client.Go(serviceMethod, args, reply, nil).Done
|
||||||
return call.Error;
|
return call.Error
|
||||||
}
|
}
|
||||||
|
@ -10,10 +10,10 @@ package rpc
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt";
|
"fmt"
|
||||||
"http";
|
"http"
|
||||||
"sort";
|
"sort"
|
||||||
"template";
|
"template"
|
||||||
)
|
)
|
||||||
|
|
||||||
const debugText = `<html>
|
const debugText = `<html>
|
||||||
@ -39,16 +39,16 @@ const debugText = `<html>
|
|||||||
var debug = template.MustParse(debugText, nil)
|
var debug = template.MustParse(debugText, nil)
|
||||||
|
|
||||||
type debugMethod struct {
|
type debugMethod struct {
|
||||||
m *methodType;
|
m *methodType
|
||||||
name string;
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
type methodArray []debugMethod
|
type methodArray []debugMethod
|
||||||
|
|
||||||
type debugService struct {
|
type debugService struct {
|
||||||
s *service;
|
s *service
|
||||||
name string;
|
name string
|
||||||
meth methodArray;
|
meth methodArray
|
||||||
}
|
}
|
||||||
|
|
||||||
type serviceArray []debugService
|
type serviceArray []debugService
|
||||||
@ -64,22 +64,22 @@ func (m methodArray) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
|
|||||||
// Runs at /debug/rpc
|
// Runs at /debug/rpc
|
||||||
func debugHTTP(c *http.Conn, req *http.Request) {
|
func debugHTTP(c *http.Conn, req *http.Request) {
|
||||||
// Build a sorted version of the data.
|
// Build a sorted version of the data.
|
||||||
var services = make(serviceArray, len(server.serviceMap));
|
var services = make(serviceArray, len(server.serviceMap))
|
||||||
i := 0;
|
i := 0
|
||||||
server.Lock();
|
server.Lock()
|
||||||
for sname, service := range server.serviceMap {
|
for sname, service := range server.serviceMap {
|
||||||
services[i] = debugService{service, sname, make(methodArray, len(service.method))};
|
services[i] = debugService{service, sname, make(methodArray, len(service.method))}
|
||||||
j := 0;
|
j := 0
|
||||||
for mname, method := range service.method {
|
for mname, method := range service.method {
|
||||||
services[i].meth[j] = debugMethod{method, mname};
|
services[i].meth[j] = debugMethod{method, mname}
|
||||||
j++;
|
j++
|
||||||
}
|
}
|
||||||
sort.Sort(services[i].meth);
|
sort.Sort(services[i].meth)
|
||||||
i++;
|
i++
|
||||||
}
|
}
|
||||||
server.Unlock();
|
server.Unlock()
|
||||||
sort.Sort(services);
|
sort.Sort(services)
|
||||||
err := debug.Execute(services, c);
|
err := debug.Execute(services, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(c, "rpc: error executing template:", err.String())
|
fmt.Fprintln(c, "rpc: error executing template:", err.String())
|
||||||
}
|
}
|
||||||
|
@ -108,17 +108,17 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"gob";
|
"gob"
|
||||||
"http";
|
"http"
|
||||||
"log";
|
"log"
|
||||||
"io";
|
"io"
|
||||||
"net";
|
"net"
|
||||||
"os";
|
"os"
|
||||||
"reflect";
|
"reflect"
|
||||||
"strings";
|
"strings"
|
||||||
"sync";
|
"sync"
|
||||||
"unicode";
|
"unicode"
|
||||||
"utf8";
|
"utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Precompute the reflect type for os.Error. Can't use os.Error directly
|
// Precompute the reflect type for os.Error. Can't use os.Error directly
|
||||||
@ -127,40 +127,40 @@ var unusedError *os.Error
|
|||||||
var typeOfOsError = reflect.Typeof(unusedError).(*reflect.PtrType).Elem()
|
var typeOfOsError = reflect.Typeof(unusedError).(*reflect.PtrType).Elem()
|
||||||
|
|
||||||
type methodType struct {
|
type methodType struct {
|
||||||
sync.Mutex; // protects counters
|
sync.Mutex // protects counters
|
||||||
method reflect.Method;
|
method reflect.Method
|
||||||
argType *reflect.PtrType;
|
argType *reflect.PtrType
|
||||||
replyType *reflect.PtrType;
|
replyType *reflect.PtrType
|
||||||
numCalls uint;
|
numCalls uint
|
||||||
}
|
}
|
||||||
|
|
||||||
type service struct {
|
type service struct {
|
||||||
name string; // name of service
|
name string // name of service
|
||||||
rcvr reflect.Value; // receiver of methods for the service
|
rcvr reflect.Value // receiver of methods for the service
|
||||||
typ reflect.Type; // type of the receiver
|
typ reflect.Type // type of the receiver
|
||||||
method map[string]*methodType; // registered methods
|
method map[string]*methodType // registered methods
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request is a header written before every RPC call. It is used internally
|
// Request is a header written before every RPC call. It is used internally
|
||||||
// but documented here as an aid to debugging, such as when analyzing
|
// but documented here as an aid to debugging, such as when analyzing
|
||||||
// network traffic.
|
// network traffic.
|
||||||
type Request struct {
|
type Request struct {
|
||||||
ServiceMethod string; // format: "Service.Method"
|
ServiceMethod string // format: "Service.Method"
|
||||||
Seq uint64; // sequence number chosen by client
|
Seq uint64 // sequence number chosen by client
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response is a header written before every RPC return. It is used internally
|
// Response is a header written before every RPC return. It is used internally
|
||||||
// but documented here as an aid to debugging, such as when analyzing
|
// but documented here as an aid to debugging, such as when analyzing
|
||||||
// network traffic.
|
// network traffic.
|
||||||
type Response struct {
|
type Response struct {
|
||||||
ServiceMethod string; // echoes that of the Request
|
ServiceMethod string // echoes that of the Request
|
||||||
Seq uint64; // echoes that of the request
|
Seq uint64 // echoes that of the request
|
||||||
Error string; // error, if any.
|
Error string // error, if any.
|
||||||
}
|
}
|
||||||
|
|
||||||
type serverType struct {
|
type serverType struct {
|
||||||
sync.Mutex; // protects the serviceMap
|
sync.Mutex // protects the serviceMap
|
||||||
serviceMap map[string]*service;
|
serviceMap map[string]*service
|
||||||
}
|
}
|
||||||
|
|
||||||
// This variable is a global whose "public" methods are really private methods
|
// This variable is a global whose "public" methods are really private methods
|
||||||
@ -170,198 +170,198 @@ var server = &serverType{serviceMap: make(map[string]*service)}
|
|||||||
|
|
||||||
// Is this a publicly visible - upper case - name?
|
// Is this a publicly visible - upper case - name?
|
||||||
func isPublic(name string) bool {
|
func isPublic(name string) bool {
|
||||||
rune, _ := utf8.DecodeRuneInString(name);
|
rune, _ := utf8.DecodeRuneInString(name)
|
||||||
return unicode.IsUpper(rune);
|
return unicode.IsUpper(rune)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *serverType) register(rcvr interface{}) os.Error {
|
func (server *serverType) register(rcvr interface{}) os.Error {
|
||||||
server.Lock();
|
server.Lock()
|
||||||
defer server.Unlock();
|
defer server.Unlock()
|
||||||
if server.serviceMap == nil {
|
if server.serviceMap == nil {
|
||||||
server.serviceMap = make(map[string]*service)
|
server.serviceMap = make(map[string]*service)
|
||||||
}
|
}
|
||||||
s := new(service);
|
s := new(service)
|
||||||
s.typ = reflect.Typeof(rcvr);
|
s.typ = reflect.Typeof(rcvr)
|
||||||
s.rcvr = reflect.NewValue(rcvr);
|
s.rcvr = reflect.NewValue(rcvr)
|
||||||
sname := reflect.Indirect(s.rcvr).Type().Name();
|
sname := reflect.Indirect(s.rcvr).Type().Name()
|
||||||
if sname == "" {
|
if sname == "" {
|
||||||
log.Exit("rpc: no service name for type", s.typ.String())
|
log.Exit("rpc: no service name for type", s.typ.String())
|
||||||
}
|
}
|
||||||
if !isPublic(sname) {
|
if !isPublic(sname) {
|
||||||
s := "rpc Register: type " + sname + " is not public";
|
s := "rpc Register: type " + sname + " is not public"
|
||||||
log.Stderr(s);
|
log.Stderr(s)
|
||||||
return os.ErrorString(s);
|
return os.ErrorString(s)
|
||||||
}
|
}
|
||||||
if _, present := server.serviceMap[sname]; present {
|
if _, present := server.serviceMap[sname]; present {
|
||||||
return os.ErrorString("rpc: service already defined: " + sname)
|
return os.ErrorString("rpc: service already defined: " + sname)
|
||||||
}
|
}
|
||||||
s.name = sname;
|
s.name = sname
|
||||||
s.method = make(map[string]*methodType);
|
s.method = make(map[string]*methodType)
|
||||||
|
|
||||||
// Install the methods
|
// Install the methods
|
||||||
for m := 0; m < s.typ.NumMethod(); m++ {
|
for m := 0; m < s.typ.NumMethod(); m++ {
|
||||||
method := s.typ.Method(m);
|
method := s.typ.Method(m)
|
||||||
mtype := method.Type;
|
mtype := method.Type
|
||||||
mname := method.Name;
|
mname := method.Name
|
||||||
if !isPublic(mname) {
|
if !isPublic(mname) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Method needs three ins: receiver, *args, *reply.
|
// Method needs three ins: receiver, *args, *reply.
|
||||||
// The args and reply must be structs until gobs are more general.
|
// The args and reply must be structs until gobs are more general.
|
||||||
if mtype.NumIn() != 3 {
|
if mtype.NumIn() != 3 {
|
||||||
log.Stderr("method", mname, "has wrong number of ins:", mtype.NumIn());
|
log.Stderr("method", mname, "has wrong number of ins:", mtype.NumIn())
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
argType, ok := mtype.In(1).(*reflect.PtrType);
|
argType, ok := mtype.In(1).(*reflect.PtrType)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Stderr(mname, "arg type not a pointer:", mtype.In(1));
|
log.Stderr(mname, "arg type not a pointer:", mtype.In(1))
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if _, ok := argType.Elem().(*reflect.StructType); !ok {
|
if _, ok := argType.Elem().(*reflect.StructType); !ok {
|
||||||
log.Stderr(mname, "arg type not a pointer to a struct:", argType);
|
log.Stderr(mname, "arg type not a pointer to a struct:", argType)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
replyType, ok := mtype.In(2).(*reflect.PtrType);
|
replyType, ok := mtype.In(2).(*reflect.PtrType)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Stderr(mname, "reply type not a pointer:", mtype.In(2));
|
log.Stderr(mname, "reply type not a pointer:", mtype.In(2))
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if _, ok := replyType.Elem().(*reflect.StructType); !ok {
|
if _, ok := replyType.Elem().(*reflect.StructType); !ok {
|
||||||
log.Stderr(mname, "reply type not a pointer to a struct:", replyType);
|
log.Stderr(mname, "reply type not a pointer to a struct:", replyType)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if !isPublic(argType.Elem().Name()) {
|
if !isPublic(argType.Elem().Name()) {
|
||||||
log.Stderr(mname, "argument type not public:", argType);
|
log.Stderr(mname, "argument type not public:", argType)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if !isPublic(replyType.Elem().Name()) {
|
if !isPublic(replyType.Elem().Name()) {
|
||||||
log.Stderr(mname, "reply type not public:", replyType);
|
log.Stderr(mname, "reply type not public:", replyType)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
// Method needs one out: os.Error.
|
// Method needs one out: os.Error.
|
||||||
if mtype.NumOut() != 1 {
|
if mtype.NumOut() != 1 {
|
||||||
log.Stderr("method", mname, "has wrong number of outs:", mtype.NumOut());
|
log.Stderr("method", mname, "has wrong number of outs:", mtype.NumOut())
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if returnType := mtype.Out(0); returnType != typeOfOsError {
|
if returnType := mtype.Out(0); returnType != typeOfOsError {
|
||||||
log.Stderr("method", mname, "returns", returnType.String(), "not os.Error");
|
log.Stderr("method", mname, "returns", returnType.String(), "not os.Error")
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
s.method[mname] = &methodType{method: method, argType: argType, replyType: replyType};
|
s.method[mname] = &methodType{method: method, argType: argType, replyType: replyType}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s.method) == 0 {
|
if len(s.method) == 0 {
|
||||||
s := "rpc Register: type " + sname + " has no public methods of suitable type";
|
s := "rpc Register: type " + sname + " has no public methods of suitable type"
|
||||||
log.Stderr(s);
|
log.Stderr(s)
|
||||||
return os.ErrorString(s);
|
return os.ErrorString(s)
|
||||||
}
|
}
|
||||||
server.serviceMap[s.name] = s;
|
server.serviceMap[s.name] = s
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// A value sent as a placeholder for the response when the server receives an invalid request.
|
// A value sent as a placeholder for the response when the server receives an invalid request.
|
||||||
type InvalidRequest struct {
|
type InvalidRequest struct {
|
||||||
marker int;
|
marker int
|
||||||
}
|
}
|
||||||
|
|
||||||
var invalidRequest = InvalidRequest{1}
|
var invalidRequest = InvalidRequest{1}
|
||||||
|
|
||||||
func _new(t *reflect.PtrType) *reflect.PtrValue {
|
func _new(t *reflect.PtrType) *reflect.PtrValue {
|
||||||
v := reflect.MakeZero(t).(*reflect.PtrValue);
|
v := reflect.MakeZero(t).(*reflect.PtrValue)
|
||||||
v.PointTo(reflect.MakeZero(t.Elem()));
|
v.PointTo(reflect.MakeZero(t.Elem()))
|
||||||
return v;
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendResponse(sending *sync.Mutex, req *Request, reply interface{}, enc *gob.Encoder, errmsg string) {
|
func sendResponse(sending *sync.Mutex, req *Request, reply interface{}, enc *gob.Encoder, errmsg string) {
|
||||||
resp := new(Response);
|
resp := new(Response)
|
||||||
// Encode the response header
|
// Encode the response header
|
||||||
resp.ServiceMethod = req.ServiceMethod;
|
resp.ServiceMethod = req.ServiceMethod
|
||||||
if errmsg != "" {
|
if errmsg != "" {
|
||||||
resp.Error = errmsg
|
resp.Error = errmsg
|
||||||
}
|
}
|
||||||
resp.Seq = req.Seq;
|
resp.Seq = req.Seq
|
||||||
sending.Lock();
|
sending.Lock()
|
||||||
enc.Encode(resp);
|
enc.Encode(resp)
|
||||||
// Encode the reply value.
|
// Encode the reply value.
|
||||||
enc.Encode(reply);
|
enc.Encode(reply)
|
||||||
sending.Unlock();
|
sending.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) call(sending *sync.Mutex, mtype *methodType, req *Request, argv, replyv reflect.Value, enc *gob.Encoder) {
|
func (s *service) call(sending *sync.Mutex, mtype *methodType, req *Request, argv, replyv reflect.Value, enc *gob.Encoder) {
|
||||||
mtype.Lock();
|
mtype.Lock()
|
||||||
mtype.numCalls++;
|
mtype.numCalls++
|
||||||
mtype.Unlock();
|
mtype.Unlock()
|
||||||
function := mtype.method.Func;
|
function := mtype.method.Func
|
||||||
// Invoke the method, providing a new value for the reply.
|
// Invoke the method, providing a new value for the reply.
|
||||||
returnValues := function.Call([]reflect.Value{s.rcvr, argv, replyv});
|
returnValues := function.Call([]reflect.Value{s.rcvr, argv, replyv})
|
||||||
// The return value for the method is an os.Error.
|
// The return value for the method is an os.Error.
|
||||||
errInter := returnValues[0].Interface();
|
errInter := returnValues[0].Interface()
|
||||||
errmsg := "";
|
errmsg := ""
|
||||||
if errInter != nil {
|
if errInter != nil {
|
||||||
errmsg = errInter.(os.Error).String()
|
errmsg = errInter.(os.Error).String()
|
||||||
}
|
}
|
||||||
sendResponse(sending, req, replyv.Interface(), enc, errmsg);
|
sendResponse(sending, req, replyv.Interface(), enc, errmsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *serverType) input(conn io.ReadWriteCloser) {
|
func (server *serverType) input(conn io.ReadWriteCloser) {
|
||||||
dec := gob.NewDecoder(conn);
|
dec := gob.NewDecoder(conn)
|
||||||
enc := gob.NewEncoder(conn);
|
enc := gob.NewEncoder(conn)
|
||||||
sending := new(sync.Mutex);
|
sending := new(sync.Mutex)
|
||||||
for {
|
for {
|
||||||
// Grab the request header.
|
// Grab the request header.
|
||||||
req := new(Request);
|
req := new(Request)
|
||||||
err := dec.Decode(req);
|
err := dec.Decode(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == os.EOF || err == io.ErrUnexpectedEOF {
|
if err == os.EOF || err == io.ErrUnexpectedEOF {
|
||||||
log.Stderr("rpc: ", err);
|
log.Stderr("rpc: ", err)
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
s := "rpc: server cannot decode request: " + err.String();
|
s := "rpc: server cannot decode request: " + err.String()
|
||||||
sendResponse(sending, req, invalidRequest, enc, s);
|
sendResponse(sending, req, invalidRequest, enc, s)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
serviceMethod := strings.Split(req.ServiceMethod, ".", 0);
|
serviceMethod := strings.Split(req.ServiceMethod, ".", 0)
|
||||||
if len(serviceMethod) != 2 {
|
if len(serviceMethod) != 2 {
|
||||||
s := "rpc: service/method request ill:formed: " + req.ServiceMethod;
|
s := "rpc: service/method request ill:formed: " + req.ServiceMethod
|
||||||
sendResponse(sending, req, invalidRequest, enc, s);
|
sendResponse(sending, req, invalidRequest, enc, s)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
// Look up the request.
|
// Look up the request.
|
||||||
server.Lock();
|
server.Lock()
|
||||||
service, ok := server.serviceMap[serviceMethod[0]];
|
service, ok := server.serviceMap[serviceMethod[0]]
|
||||||
server.Unlock();
|
server.Unlock()
|
||||||
if !ok {
|
if !ok {
|
||||||
s := "rpc: can't find service " + req.ServiceMethod;
|
s := "rpc: can't find service " + req.ServiceMethod
|
||||||
sendResponse(sending, req, invalidRequest, enc, s);
|
sendResponse(sending, req, invalidRequest, enc, s)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
mtype, ok := service.method[serviceMethod[1]];
|
mtype, ok := service.method[serviceMethod[1]]
|
||||||
if !ok {
|
if !ok {
|
||||||
s := "rpc: can't find method " + req.ServiceMethod;
|
s := "rpc: can't find method " + req.ServiceMethod
|
||||||
sendResponse(sending, req, invalidRequest, enc, s);
|
sendResponse(sending, req, invalidRequest, enc, s)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
// Decode the argument value.
|
// Decode the argument value.
|
||||||
argv := _new(mtype.argType);
|
argv := _new(mtype.argType)
|
||||||
replyv := _new(mtype.replyType);
|
replyv := _new(mtype.replyType)
|
||||||
err = dec.Decode(argv.Interface());
|
err = dec.Decode(argv.Interface())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Stderr("rpc: tearing down", serviceMethod[0], "connection:", err);
|
log.Stderr("rpc: tearing down", serviceMethod[0], "connection:", err)
|
||||||
sendResponse(sending, req, replyv.Interface(), enc, err.String());
|
sendResponse(sending, req, replyv.Interface(), enc, err.String())
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
go service.call(sending, mtype, req, argv, replyv, enc);
|
go service.call(sending, mtype, req, argv, replyv, enc)
|
||||||
}
|
}
|
||||||
conn.Close();
|
conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *serverType) accept(lis net.Listener) {
|
func (server *serverType) accept(lis net.Listener) {
|
||||||
for {
|
for {
|
||||||
conn, err := lis.Accept();
|
conn, err := lis.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Exit("rpc.Serve: accept:", err.String()) // TODO(r): exit?
|
log.Exit("rpc.Serve: accept:", err.String()) // TODO(r): exit?
|
||||||
}
|
}
|
||||||
go server.input(conn);
|
go server.input(conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,23 +391,23 @@ var connected = "200 Connected to Go RPC"
|
|||||||
|
|
||||||
func serveHTTP(c *http.Conn, req *http.Request) {
|
func serveHTTP(c *http.Conn, req *http.Request) {
|
||||||
if req.Method != "CONNECT" {
|
if req.Method != "CONNECT" {
|
||||||
c.SetHeader("Content-Type", "text/plain; charset=utf-8");
|
c.SetHeader("Content-Type", "text/plain; charset=utf-8")
|
||||||
c.WriteHeader(http.StatusMethodNotAllowed);
|
c.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
io.WriteString(c, "405 must CONNECT to "+rpcPath+"\n");
|
io.WriteString(c, "405 must CONNECT to "+rpcPath+"\n")
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
conn, _, err := c.Hijack();
|
conn, _, err := c.Hijack()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Stderr("rpc hijacking ", c.RemoteAddr, ": ", err.String());
|
log.Stderr("rpc hijacking ", c.RemoteAddr, ": ", err.String())
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n");
|
io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n")
|
||||||
server.input(conn);
|
server.input(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleHTTP registers an HTTP handler for RPC messages.
|
// HandleHTTP registers an HTTP handler for RPC messages.
|
||||||
// It is still necessary to invoke http.Serve(), typically in a go statement.
|
// It is still necessary to invoke http.Serve(), typically in a go statement.
|
||||||
func HandleHTTP() {
|
func HandleHTTP() {
|
||||||
http.Handle(rpcPath, http.HandlerFunc(serveHTTP));
|
http.Handle(rpcPath, http.HandlerFunc(serveHTTP))
|
||||||
http.Handle(debugPath, http.HandlerFunc(debugHTTP));
|
http.Handle(debugPath, http.HandlerFunc(debugHTTP))
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,13 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"http";
|
"http"
|
||||||
"log";
|
"log"
|
||||||
"net";
|
"net"
|
||||||
"once";
|
"once"
|
||||||
"os";
|
"os"
|
||||||
"strings";
|
"strings"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var serverAddr string
|
var serverAddr string
|
||||||
@ -21,31 +21,31 @@ const second = 1e9
|
|||||||
|
|
||||||
|
|
||||||
type Args struct {
|
type Args struct {
|
||||||
A, B int;
|
A, B int
|
||||||
}
|
}
|
||||||
|
|
||||||
type Reply struct {
|
type Reply struct {
|
||||||
C int;
|
C int
|
||||||
}
|
}
|
||||||
|
|
||||||
type Arith int
|
type Arith int
|
||||||
|
|
||||||
func (t *Arith) Add(args *Args, reply *Reply) os.Error {
|
func (t *Arith) Add(args *Args, reply *Reply) os.Error {
|
||||||
reply.C = args.A + args.B;
|
reply.C = args.A + args.B
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Arith) Mul(args *Args, reply *Reply) os.Error {
|
func (t *Arith) Mul(args *Args, reply *Reply) os.Error {
|
||||||
reply.C = args.A * args.B;
|
reply.C = args.A * args.B
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Arith) Div(args *Args, reply *Reply) os.Error {
|
func (t *Arith) Div(args *Args, reply *Reply) os.Error {
|
||||||
if args.B == 0 {
|
if args.B == 0 {
|
||||||
return os.ErrorString("divide by zero")
|
return os.ErrorString("divide by zero")
|
||||||
}
|
}
|
||||||
reply.C = args.A / args.B;
|
reply.C = args.A / args.B
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Arith) Error(args *Args, reply *Reply) os.Error {
|
func (t *Arith) Error(args *Args, reply *Reply) os.Error {
|
||||||
@ -53,39 +53,39 @@ func (t *Arith) Error(args *Args, reply *Reply) os.Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func startServer() {
|
func startServer() {
|
||||||
Register(new(Arith));
|
Register(new(Arith))
|
||||||
|
|
||||||
l, e := net.Listen("tcp", ":0"); // any available address
|
l, e := net.Listen("tcp", ":0") // any available address
|
||||||
if e != nil {
|
if e != nil {
|
||||||
log.Exitf("net.Listen tcp :0: %v", e)
|
log.Exitf("net.Listen tcp :0: %v", e)
|
||||||
}
|
}
|
||||||
serverAddr = l.Addr().String();
|
serverAddr = l.Addr().String()
|
||||||
log.Stderr("Test RPC server listening on ", serverAddr);
|
log.Stderr("Test RPC server listening on ", serverAddr)
|
||||||
go Accept(l);
|
go Accept(l)
|
||||||
|
|
||||||
HandleHTTP();
|
HandleHTTP()
|
||||||
l, e = net.Listen("tcp", ":0"); // any available address
|
l, e = net.Listen("tcp", ":0") // any available address
|
||||||
if e != nil {
|
if e != nil {
|
||||||
log.Stderrf("net.Listen tcp :0: %v", e);
|
log.Stderrf("net.Listen tcp :0: %v", e)
|
||||||
os.Exit(1);
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
httpServerAddr = l.Addr().String();
|
httpServerAddr = l.Addr().String()
|
||||||
log.Stderr("Test HTTP RPC server listening on ", httpServerAddr);
|
log.Stderr("Test HTTP RPC server listening on ", httpServerAddr)
|
||||||
go http.Serve(l, nil);
|
go http.Serve(l, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRPC(t *testing.T) {
|
func TestRPC(t *testing.T) {
|
||||||
once.Do(startServer);
|
once.Do(startServer)
|
||||||
|
|
||||||
client, err := Dial("tcp", serverAddr);
|
client, err := Dial("tcp", serverAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("dialing", err)
|
t.Fatal("dialing", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synchronous calls
|
// Synchronous calls
|
||||||
args := &Args{7, 8};
|
args := &Args{7, 8}
|
||||||
reply := new(Reply);
|
reply := new(Reply)
|
||||||
err = client.Call("Arith.Add", args, reply);
|
err = client.Call("Arith.Add", args, reply)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Add: expected no error but got string %q", err.String())
|
t.Errorf("Add: expected no error but got string %q", err.String())
|
||||||
}
|
}
|
||||||
@ -93,9 +93,9 @@ func TestRPC(t *testing.T) {
|
|||||||
t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
|
t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
|
||||||
}
|
}
|
||||||
|
|
||||||
args = &Args{7, 8};
|
args = &Args{7, 8}
|
||||||
reply = new(Reply);
|
reply = new(Reply)
|
||||||
err = client.Call("Arith.Mul", args, reply);
|
err = client.Call("Arith.Mul", args, reply)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Mul: expected no error but got string %q", err.String())
|
t.Errorf("Mul: expected no error but got string %q", err.String())
|
||||||
}
|
}
|
||||||
@ -104,13 +104,13 @@ func TestRPC(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Out of order.
|
// Out of order.
|
||||||
args = &Args{7, 8};
|
args = &Args{7, 8}
|
||||||
mulReply := new(Reply);
|
mulReply := new(Reply)
|
||||||
mulCall := client.Go("Arith.Mul", args, mulReply, nil);
|
mulCall := client.Go("Arith.Mul", args, mulReply, nil)
|
||||||
addReply := new(Reply);
|
addReply := new(Reply)
|
||||||
addCall := client.Go("Arith.Add", args, addReply, nil);
|
addCall := client.Go("Arith.Add", args, addReply, nil)
|
||||||
|
|
||||||
addCall = <-addCall.Done;
|
addCall = <-addCall.Done
|
||||||
if addCall.Error != nil {
|
if addCall.Error != nil {
|
||||||
t.Errorf("Add: expected no error but got string %q", addCall.Error.String())
|
t.Errorf("Add: expected no error but got string %q", addCall.Error.String())
|
||||||
}
|
}
|
||||||
@ -118,7 +118,7 @@ func TestRPC(t *testing.T) {
|
|||||||
t.Errorf("Add: expected %d got %d", addReply.C, args.A+args.B)
|
t.Errorf("Add: expected %d got %d", addReply.C, args.A+args.B)
|
||||||
}
|
}
|
||||||
|
|
||||||
mulCall = <-mulCall.Done;
|
mulCall = <-mulCall.Done
|
||||||
if mulCall.Error != nil {
|
if mulCall.Error != nil {
|
||||||
t.Errorf("Mul: expected no error but got string %q", mulCall.Error.String())
|
t.Errorf("Mul: expected no error but got string %q", mulCall.Error.String())
|
||||||
}
|
}
|
||||||
@ -127,9 +127,9 @@ func TestRPC(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Error test
|
// Error test
|
||||||
args = &Args{7, 0};
|
args = &Args{7, 0}
|
||||||
reply = new(Reply);
|
reply = new(Reply)
|
||||||
err = client.Call("Arith.Div", args, reply);
|
err = client.Call("Arith.Div", args, reply)
|
||||||
// expect an error: zero divide
|
// expect an error: zero divide
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("Div: expected error")
|
t.Error("Div: expected error")
|
||||||
@ -139,17 +139,17 @@ func TestRPC(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHTTPRPC(t *testing.T) {
|
func TestHTTPRPC(t *testing.T) {
|
||||||
once.Do(startServer);
|
once.Do(startServer)
|
||||||
|
|
||||||
client, err := DialHTTP("tcp", httpServerAddr);
|
client, err := DialHTTP("tcp", httpServerAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("dialing", err)
|
t.Fatal("dialing", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synchronous calls
|
// Synchronous calls
|
||||||
args := &Args{7, 8};
|
args := &Args{7, 8}
|
||||||
reply := new(Reply);
|
reply := new(Reply)
|
||||||
err = client.Call("Arith.Add", args, reply);
|
err = client.Call("Arith.Add", args, reply)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Add: expected no error but got string %q", err.String())
|
t.Errorf("Add: expected no error but got string %q", err.String())
|
||||||
}
|
}
|
||||||
@ -159,18 +159,18 @@ func TestHTTPRPC(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckUnknownService(t *testing.T) {
|
func TestCheckUnknownService(t *testing.T) {
|
||||||
once.Do(startServer);
|
once.Do(startServer)
|
||||||
|
|
||||||
conn, err := net.Dial("tcp", "", serverAddr);
|
conn, err := net.Dial("tcp", "", serverAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("dialing:", err)
|
t.Fatal("dialing:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client := NewClient(conn);
|
client := NewClient(conn)
|
||||||
|
|
||||||
args := &Args{7, 8};
|
args := &Args{7, 8}
|
||||||
reply := new(Reply);
|
reply := new(Reply)
|
||||||
err = client.Call("Unknown.Add", args, reply);
|
err = client.Call("Unknown.Add", args, reply)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("expected error calling unknown service")
|
t.Error("expected error calling unknown service")
|
||||||
} else if strings.Index(err.String(), "service") < 0 {
|
} else if strings.Index(err.String(), "service") < 0 {
|
||||||
@ -179,18 +179,18 @@ func TestCheckUnknownService(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckUnknownMethod(t *testing.T) {
|
func TestCheckUnknownMethod(t *testing.T) {
|
||||||
once.Do(startServer);
|
once.Do(startServer)
|
||||||
|
|
||||||
conn, err := net.Dial("tcp", "", serverAddr);
|
conn, err := net.Dial("tcp", "", serverAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("dialing:", err)
|
t.Fatal("dialing:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client := NewClient(conn);
|
client := NewClient(conn)
|
||||||
|
|
||||||
args := &Args{7, 8};
|
args := &Args{7, 8}
|
||||||
reply := new(Reply);
|
reply := new(Reply)
|
||||||
err = client.Call("Arith.Unknown", args, reply);
|
err = client.Call("Arith.Unknown", args, reply)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("expected error calling unknown service")
|
t.Error("expected error calling unknown service")
|
||||||
} else if strings.Index(err.String(), "method") < 0 {
|
} else if strings.Index(err.String(), "method") < 0 {
|
||||||
@ -199,17 +199,17 @@ func TestCheckUnknownMethod(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckBadType(t *testing.T) {
|
func TestCheckBadType(t *testing.T) {
|
||||||
once.Do(startServer);
|
once.Do(startServer)
|
||||||
|
|
||||||
conn, err := net.Dial("tcp", "", serverAddr);
|
conn, err := net.Dial("tcp", "", serverAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("dialing:", err)
|
t.Fatal("dialing:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client := NewClient(conn);
|
client := NewClient(conn)
|
||||||
|
|
||||||
reply := new(Reply);
|
reply := new(Reply)
|
||||||
err = client.Call("Arith.Add", reply, reply); // args, reply would be the correct thing to use
|
err = client.Call("Arith.Add", reply, reply) // args, reply would be the correct thing to use
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("expected error calling Arith.Add with wrong arg type")
|
t.Error("expected error calling Arith.Add with wrong arg type")
|
||||||
} else if strings.Index(err.String(), "type") < 0 {
|
} else if strings.Index(err.String(), "type") < 0 {
|
||||||
@ -246,7 +246,7 @@ func (t *Bad) ReplyNotPublic(args *Args, reply *local) os.Error {
|
|||||||
|
|
||||||
// Check that registration handles lots of bad methods and a type with no suitable methods.
|
// Check that registration handles lots of bad methods and a type with no suitable methods.
|
||||||
func TestRegistrationError(t *testing.T) {
|
func TestRegistrationError(t *testing.T) {
|
||||||
err := Register(new(Bad));
|
err := Register(new(Bad))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("expected error registering bad type")
|
t.Errorf("expected error registering bad type")
|
||||||
}
|
}
|
||||||
|
@ -26,56 +26,56 @@ type Type interface{}
|
|||||||
// All types begin with a few common fields needed for
|
// All types begin with a few common fields needed for
|
||||||
// the interface runtime.
|
// the interface runtime.
|
||||||
type commonType struct {
|
type commonType struct {
|
||||||
size uintptr; // size in bytes
|
size uintptr // size in bytes
|
||||||
hash uint32; // hash of type; avoids computation in hash tables
|
hash uint32 // hash of type; avoids computation in hash tables
|
||||||
alg uint8; // algorithm for copy+hash+cmp (../runtime/runtime.h:/AMEM)
|
alg uint8 // algorithm for copy+hash+cmp (../runtime/runtime.h:/AMEM)
|
||||||
align uint8; // alignment of variable with this type
|
align uint8 // alignment of variable with this type
|
||||||
fieldAlign uint8; // alignment of struct field with this type
|
fieldAlign uint8 // alignment of struct field with this type
|
||||||
kind uint8; // enumeration for C
|
kind uint8 // enumeration for C
|
||||||
string *string; // string form; unnecessary but undeniably useful
|
string *string // string form; unnecessary but undeniably useful
|
||||||
*uncommonType; // (relatively) uncommon fields
|
*uncommonType // (relatively) uncommon fields
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values for commonType.kind.
|
// Values for commonType.kind.
|
||||||
const (
|
const (
|
||||||
kindBool = 1 + iota;
|
kindBool = 1 + iota
|
||||||
kindInt;
|
kindInt
|
||||||
kindInt8;
|
kindInt8
|
||||||
kindInt16;
|
kindInt16
|
||||||
kindInt32;
|
kindInt32
|
||||||
kindInt64;
|
kindInt64
|
||||||
kindUint;
|
kindUint
|
||||||
kindUint8;
|
kindUint8
|
||||||
kindUint16;
|
kindUint16
|
||||||
kindUint32;
|
kindUint32
|
||||||
kindUint64;
|
kindUint64
|
||||||
kindUintptr;
|
kindUintptr
|
||||||
kindFloat;
|
kindFloat
|
||||||
kindFloat32;
|
kindFloat32
|
||||||
kindFloat64;
|
kindFloat64
|
||||||
kindArray;
|
kindArray
|
||||||
kindChan;
|
kindChan
|
||||||
kindDotDotDot;
|
kindDotDotDot
|
||||||
kindFunc;
|
kindFunc
|
||||||
kindInterface;
|
kindInterface
|
||||||
kindMap;
|
kindMap
|
||||||
kindPtr;
|
kindPtr
|
||||||
kindSlice;
|
kindSlice
|
||||||
kindString;
|
kindString
|
||||||
kindStruct;
|
kindStruct
|
||||||
kindUnsafePointer;
|
kindUnsafePointer
|
||||||
|
|
||||||
kindNoPointers = 1 << 7; // OR'ed into kind
|
kindNoPointers = 1 << 7 // OR'ed into kind
|
||||||
)
|
)
|
||||||
|
|
||||||
// Method on non-interface type
|
// Method on non-interface type
|
||||||
type method struct {
|
type method struct {
|
||||||
hash uint32; // hash of name + pkg + typ
|
hash uint32 // hash of name + pkg + typ
|
||||||
name *string; // name of method
|
name *string // name of method
|
||||||
pkgPath *string; // nil for exported Names; otherwise import path
|
pkgPath *string // nil for exported Names; otherwise import path
|
||||||
typ *Type; // .(*FuncType) underneath
|
typ *Type // .(*FuncType) underneath
|
||||||
ifn unsafe.Pointer; // fn used in interface call (one-word receiver)
|
ifn unsafe.Pointer // fn used in interface call (one-word receiver)
|
||||||
tfn unsafe.Pointer; // fn used for normal method call
|
tfn unsafe.Pointer // fn used for normal method call
|
||||||
}
|
}
|
||||||
|
|
||||||
// uncommonType is present only for types with names or methods
|
// uncommonType is present only for types with names or methods
|
||||||
@ -83,9 +83,9 @@ type method struct {
|
|||||||
// Using a pointer to this struct reduces the overall size required
|
// Using a pointer to this struct reduces the overall size required
|
||||||
// to describe an unnamed type with no methods.
|
// to describe an unnamed type with no methods.
|
||||||
type uncommonType struct {
|
type uncommonType struct {
|
||||||
name *string; // name of type
|
name *string // name of type
|
||||||
pkgPath *string; // import path; nil for built-in types like int, string
|
pkgPath *string // import path; nil for built-in types like int, string
|
||||||
methods []method; // methods associated with type
|
methods []method // methods associated with type
|
||||||
}
|
}
|
||||||
|
|
||||||
// BoolType represents a boolean type.
|
// BoolType represents a boolean type.
|
||||||
@ -145,91 +145,91 @@ type UnsafePointerType commonType
|
|||||||
|
|
||||||
// ArrayType represents a fixed array type.
|
// ArrayType represents a fixed array type.
|
||||||
type ArrayType struct {
|
type ArrayType struct {
|
||||||
commonType;
|
commonType
|
||||||
elem *Type; // array element type
|
elem *Type // array element type
|
||||||
len uintptr;
|
len uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
// SliceType represents a slice type.
|
// SliceType represents a slice type.
|
||||||
type SliceType struct {
|
type SliceType struct {
|
||||||
commonType;
|
commonType
|
||||||
elem *Type; // slice element type
|
elem *Type // slice element type
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChanDir represents a channel type's direction.
|
// ChanDir represents a channel type's direction.
|
||||||
type ChanDir int
|
type ChanDir int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RecvDir ChanDir = 1 << iota; // <-chan
|
RecvDir ChanDir = 1 << iota // <-chan
|
||||||
SendDir; // chan<-
|
SendDir // chan<-
|
||||||
BothDir = RecvDir | SendDir; // chan
|
BothDir = RecvDir | SendDir // chan
|
||||||
)
|
)
|
||||||
|
|
||||||
// ChanType represents a channel type.
|
// ChanType represents a channel type.
|
||||||
type ChanType struct {
|
type ChanType struct {
|
||||||
commonType;
|
commonType
|
||||||
elem *Type; // channel element type
|
elem *Type // channel element type
|
||||||
dir uintptr; // channel direction (ChanDir)
|
dir uintptr // channel direction (ChanDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FuncType represents a function type.
|
// FuncType represents a function type.
|
||||||
type FuncType struct {
|
type FuncType struct {
|
||||||
commonType;
|
commonType
|
||||||
in []*Type; // input parameter types
|
in []*Type // input parameter types
|
||||||
out []*Type; // output parameter types
|
out []*Type // output parameter types
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method on interface type
|
// Method on interface type
|
||||||
type imethod struct {
|
type imethod struct {
|
||||||
hash uint32; // hash of name + pkg + typ; same hash as method
|
hash uint32 // hash of name + pkg + typ; same hash as method
|
||||||
perm uint32; // index of function pointer in interface map
|
perm uint32 // index of function pointer in interface map
|
||||||
name *string; // name of method
|
name *string // name of method
|
||||||
pkgPath *string; // nil for exported Names; otherwise import path
|
pkgPath *string // nil for exported Names; otherwise import path
|
||||||
typ *Type; // .(*FuncType) underneath
|
typ *Type // .(*FuncType) underneath
|
||||||
}
|
}
|
||||||
|
|
||||||
// InterfaceType represents an interface type.
|
// InterfaceType represents an interface type.
|
||||||
type InterfaceType struct {
|
type InterfaceType struct {
|
||||||
commonType;
|
commonType
|
||||||
methods []imethod; // sorted by hash
|
methods []imethod // sorted by hash
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapType represents a map type.
|
// MapType represents a map type.
|
||||||
type MapType struct {
|
type MapType struct {
|
||||||
commonType;
|
commonType
|
||||||
key *Type; // map key type
|
key *Type // map key type
|
||||||
elem *Type; // map element (value) type
|
elem *Type // map element (value) type
|
||||||
}
|
}
|
||||||
|
|
||||||
// PtrType represents a pointer type.
|
// PtrType represents a pointer type.
|
||||||
type PtrType struct {
|
type PtrType struct {
|
||||||
commonType;
|
commonType
|
||||||
elem *Type; // pointer element (pointed at) type
|
elem *Type // pointer element (pointed at) type
|
||||||
}
|
}
|
||||||
|
|
||||||
// Struct field
|
// Struct field
|
||||||
type structField struct {
|
type structField struct {
|
||||||
name *string; // nil for embedded fields
|
name *string // nil for embedded fields
|
||||||
pkgPath *string; // nil for exported Names; otherwise import path
|
pkgPath *string // nil for exported Names; otherwise import path
|
||||||
typ *Type; // type of field
|
typ *Type // type of field
|
||||||
tag *string; // nil if no tag
|
tag *string // nil if no tag
|
||||||
offset uintptr; // byte offset of field within struct
|
offset uintptr // byte offset of field within struct
|
||||||
}
|
}
|
||||||
|
|
||||||
// StructType represents a struct type.
|
// StructType represents a struct type.
|
||||||
type StructType struct {
|
type StructType struct {
|
||||||
commonType;
|
commonType
|
||||||
fields []structField; // sorted by offset
|
fields []structField // sorted by offset
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Must match iface.c:/Itab and compilers.
|
* Must match iface.c:/Itab and compilers.
|
||||||
*/
|
*/
|
||||||
type Itable struct {
|
type Itable struct {
|
||||||
Itype *Type; // (*tab.inter).(*InterfaceType) is the interface type
|
Itype *Type // (*tab.inter).(*InterfaceType) is the interface type
|
||||||
Type *Type;
|
Type *Type
|
||||||
link *Itable;
|
link *Itable
|
||||||
bad int32;
|
bad int32
|
||||||
unused int32;
|
unused int32
|
||||||
Fn [100000]uintptr; // bigger than we'll ever see
|
Fn [100000]uintptr // bigger than we'll ever see
|
||||||
}
|
}
|
||||||
|
@ -11,19 +11,19 @@ package sort
|
|||||||
// elements of the collection be enumerated by an integer index.
|
// elements of the collection be enumerated by an integer index.
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
// Len is the number of elements in the collection.
|
// Len is the number of elements in the collection.
|
||||||
Len() int;
|
Len() int
|
||||||
// Less returns whether the element with index i is should sort
|
// Less returns whether the element with index i is should sort
|
||||||
// before the element with index j.
|
// before the element with index j.
|
||||||
Less(i, j int) bool;
|
Less(i, j int) bool
|
||||||
// Swap swaps the elements with indexes i and j.
|
// Swap swaps the elements with indexes i and j.
|
||||||
Swap(i, j int);
|
Swap(i, j int)
|
||||||
}
|
}
|
||||||
|
|
||||||
func min(a, b int) int {
|
func min(a, b int) int {
|
||||||
if a < b {
|
if a < b {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
return b;
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insertion sort
|
// Insertion sort
|
||||||
@ -40,9 +40,9 @@ func insertionSort(data Interface, a, b int) {
|
|||||||
|
|
||||||
// Move the median of the three values data[a], data[b], data[c] into data[a].
|
// Move the median of the three values data[a], data[b], data[c] into data[a].
|
||||||
func medianOfThree(data Interface, a, b, c int) {
|
func medianOfThree(data Interface, a, b, c int) {
|
||||||
m0 := b;
|
m0 := b
|
||||||
m1 := a;
|
m1 := a
|
||||||
m2 := c;
|
m2 := c
|
||||||
// bubble sort on 3 elements
|
// bubble sort on 3 elements
|
||||||
if data.Less(m1, m0) {
|
if data.Less(m1, m0) {
|
||||||
data.Swap(m1, m0)
|
data.Swap(m1, m0)
|
||||||
@ -63,15 +63,15 @@ func swapRange(data Interface, a, b, n int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
|
func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
|
||||||
m := (lo + hi) / 2;
|
m := (lo + hi) / 2
|
||||||
if hi-lo > 40 {
|
if hi-lo > 40 {
|
||||||
// Tukey's ``Ninther,'' median of three medians of three.
|
// Tukey's ``Ninther,'' median of three medians of three.
|
||||||
s := (hi - lo) / 8;
|
s := (hi - lo) / 8
|
||||||
medianOfThree(data, lo, lo+s, lo+2*s);
|
medianOfThree(data, lo, lo+s, lo+2*s)
|
||||||
medianOfThree(data, m, m-s, m+s);
|
medianOfThree(data, m, m-s, m+s)
|
||||||
medianOfThree(data, hi-1, hi-1-s, hi-1-2*s);
|
medianOfThree(data, hi-1, hi-1-s, hi-1-2*s)
|
||||||
}
|
}
|
||||||
medianOfThree(data, lo, m, hi-1);
|
medianOfThree(data, lo, m, hi-1)
|
||||||
|
|
||||||
// Invariants are:
|
// Invariants are:
|
||||||
// data[lo] = pivot (set up by ChoosePivot)
|
// data[lo] = pivot (set up by ChoosePivot)
|
||||||
@ -83,49 +83,49 @@ func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
|
|||||||
//
|
//
|
||||||
// Once b meets c, can swap the "= pivot" sections
|
// Once b meets c, can swap the "= pivot" sections
|
||||||
// into the middle of the array.
|
// into the middle of the array.
|
||||||
pivot := lo;
|
pivot := lo
|
||||||
a, b, c, d := lo+1, lo+1, hi, hi;
|
a, b, c, d := lo+1, lo+1, hi, hi
|
||||||
for b < c {
|
for b < c {
|
||||||
if data.Less(b, pivot) { // data[b] < pivot
|
if data.Less(b, pivot) { // data[b] < pivot
|
||||||
b++;
|
b++
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if !data.Less(pivot, b) { // data[b] = pivot
|
if !data.Less(pivot, b) { // data[b] = pivot
|
||||||
data.Swap(a, b);
|
data.Swap(a, b)
|
||||||
a++;
|
a++
|
||||||
b++;
|
b++
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if data.Less(pivot, c-1) { // data[c-1] > pivot
|
if data.Less(pivot, c-1) { // data[c-1] > pivot
|
||||||
c--;
|
c--
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if !data.Less(c-1, pivot) { // data[c-1] = pivot
|
if !data.Less(c-1, pivot) { // data[c-1] = pivot
|
||||||
data.Swap(c-1, d-1);
|
data.Swap(c-1, d-1)
|
||||||
c--;
|
c--
|
||||||
d--;
|
d--
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
// data[b] > pivot; data[c-1] < pivot
|
// data[b] > pivot; data[c-1] < pivot
|
||||||
data.Swap(b, c-1);
|
data.Swap(b, c-1)
|
||||||
b++;
|
b++
|
||||||
c--;
|
c--
|
||||||
}
|
}
|
||||||
|
|
||||||
n := min(b-a, a-lo);
|
n := min(b-a, a-lo)
|
||||||
swapRange(data, lo, b-n, n);
|
swapRange(data, lo, b-n, n)
|
||||||
|
|
||||||
n = min(hi-d, d-c);
|
n = min(hi-d, d-c)
|
||||||
swapRange(data, c, hi-n, n);
|
swapRange(data, c, hi-n, n)
|
||||||
|
|
||||||
return lo + b - a, hi - (d - c);
|
return lo + b - a, hi - (d - c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func quickSort(data Interface, a, b int) {
|
func quickSort(data Interface, a, b int) {
|
||||||
if b-a > 7 {
|
if b-a > 7 {
|
||||||
mlo, mhi := doPivot(data, a, b);
|
mlo, mhi := doPivot(data, a, b)
|
||||||
quickSort(data, a, mlo);
|
quickSort(data, a, mlo)
|
||||||
quickSort(data, mhi, b);
|
quickSort(data, mhi, b)
|
||||||
} else if b-a > 1 {
|
} else if b-a > 1 {
|
||||||
insertionSort(data, a, b)
|
insertionSort(data, a, b)
|
||||||
}
|
}
|
||||||
@ -135,13 +135,13 @@ func Sort(data Interface) { quickSort(data, 0, data.Len()) }
|
|||||||
|
|
||||||
|
|
||||||
func IsSorted(data Interface) bool {
|
func IsSorted(data Interface) bool {
|
||||||
n := data.Len();
|
n := data.Len()
|
||||||
for i := n - 1; i > 0; i-- {
|
for i := n - 1; i > 0; i-- {
|
||||||
if data.Less(i, i-1) {
|
if data.Less(i, i-1) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
package sort
|
package sort
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt";
|
"fmt"
|
||||||
"rand";
|
"rand"
|
||||||
"strconv";
|
"strconv"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -17,173 +17,173 @@ var floats = [...]float{74.3, 59.0, 238.2, -784.0, 2.3, 9845.768, -959.7485, 905
|
|||||||
var strings = [...]string{"", "Hello", "foo", "bar", "foo", "f00", "%*&^*&^&", "***"}
|
var strings = [...]string{"", "Hello", "foo", "bar", "foo", "f00", "%*&^*&^&", "***"}
|
||||||
|
|
||||||
func TestSortIntArray(t *testing.T) {
|
func TestSortIntArray(t *testing.T) {
|
||||||
data := ints;
|
data := ints
|
||||||
a := IntArray(&data);
|
a := IntArray(&data)
|
||||||
Sort(a);
|
Sort(a)
|
||||||
if !IsSorted(a) {
|
if !IsSorted(a) {
|
||||||
t.Errorf("sorted %v", ints);
|
t.Errorf("sorted %v", ints)
|
||||||
t.Errorf(" got %v", data);
|
t.Errorf(" got %v", data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSortFloatArray(t *testing.T) {
|
func TestSortFloatArray(t *testing.T) {
|
||||||
data := floats;
|
data := floats
|
||||||
a := FloatArray(&data);
|
a := FloatArray(&data)
|
||||||
Sort(a);
|
Sort(a)
|
||||||
if !IsSorted(a) {
|
if !IsSorted(a) {
|
||||||
t.Errorf("sorted %v", floats);
|
t.Errorf("sorted %v", floats)
|
||||||
t.Errorf(" got %v", data);
|
t.Errorf(" got %v", data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSortStringArray(t *testing.T) {
|
func TestSortStringArray(t *testing.T) {
|
||||||
data := strings;
|
data := strings
|
||||||
a := StringArray(&data);
|
a := StringArray(&data)
|
||||||
Sort(a);
|
Sort(a)
|
||||||
if !IsSorted(a) {
|
if !IsSorted(a) {
|
||||||
t.Errorf("sorted %v", strings);
|
t.Errorf("sorted %v", strings)
|
||||||
t.Errorf(" got %v", data);
|
t.Errorf(" got %v", data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSortInts(t *testing.T) {
|
func TestSortInts(t *testing.T) {
|
||||||
data := ints;
|
data := ints
|
||||||
SortInts(&data);
|
SortInts(&data)
|
||||||
if !IntsAreSorted(&data) {
|
if !IntsAreSorted(&data) {
|
||||||
t.Errorf("sorted %v", ints);
|
t.Errorf("sorted %v", ints)
|
||||||
t.Errorf(" got %v", data);
|
t.Errorf(" got %v", data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSortFloats(t *testing.T) {
|
func TestSortFloats(t *testing.T) {
|
||||||
data := floats;
|
data := floats
|
||||||
SortFloats(&data);
|
SortFloats(&data)
|
||||||
if !FloatsAreSorted(&data) {
|
if !FloatsAreSorted(&data) {
|
||||||
t.Errorf("sorted %v", floats);
|
t.Errorf("sorted %v", floats)
|
||||||
t.Errorf(" got %v", data);
|
t.Errorf(" got %v", data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSortStrings(t *testing.T) {
|
func TestSortStrings(t *testing.T) {
|
||||||
data := strings;
|
data := strings
|
||||||
SortStrings(&data);
|
SortStrings(&data)
|
||||||
if !StringsAreSorted(&data) {
|
if !StringsAreSorted(&data) {
|
||||||
t.Errorf("sorted %v", strings);
|
t.Errorf("sorted %v", strings)
|
||||||
t.Errorf(" got %v", data);
|
t.Errorf(" got %v", data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSortLarge_Random(t *testing.T) {
|
func TestSortLarge_Random(t *testing.T) {
|
||||||
data := make([]int, 1000000);
|
data := make([]int, 1000000)
|
||||||
for i := 0; i < len(data); i++ {
|
for i := 0; i < len(data); i++ {
|
||||||
data[i] = rand.Intn(100)
|
data[i] = rand.Intn(100)
|
||||||
}
|
}
|
||||||
if IntsAreSorted(data) {
|
if IntsAreSorted(data) {
|
||||||
t.Fatalf("terrible rand.rand")
|
t.Fatalf("terrible rand.rand")
|
||||||
}
|
}
|
||||||
SortInts(data);
|
SortInts(data)
|
||||||
if !IntsAreSorted(data) {
|
if !IntsAreSorted(data) {
|
||||||
t.Errorf("sort didn't sort - 1M ints")
|
t.Errorf("sort didn't sort - 1M ints")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkSortString1K(b *testing.B) {
|
func BenchmarkSortString1K(b *testing.B) {
|
||||||
b.StopTimer();
|
b.StopTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
data := make([]string, 1<<10);
|
data := make([]string, 1<<10)
|
||||||
for i := 0; i < len(data); i++ {
|
for i := 0; i < len(data); i++ {
|
||||||
data[i] = strconv.Itoa(i ^ 0x2cc)
|
data[i] = strconv.Itoa(i ^ 0x2cc)
|
||||||
}
|
}
|
||||||
b.StartTimer();
|
b.StartTimer()
|
||||||
SortStrings(data);
|
SortStrings(data)
|
||||||
b.StopTimer();
|
b.StopTimer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkSortInt1K(b *testing.B) {
|
func BenchmarkSortInt1K(b *testing.B) {
|
||||||
b.StopTimer();
|
b.StopTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
data := make([]int, 1<<10);
|
data := make([]int, 1<<10)
|
||||||
for i := 0; i < len(data); i++ {
|
for i := 0; i < len(data); i++ {
|
||||||
data[i] = i ^ 0x2cc
|
data[i] = i ^ 0x2cc
|
||||||
}
|
}
|
||||||
b.StartTimer();
|
b.StartTimer()
|
||||||
SortInts(data);
|
SortInts(data)
|
||||||
b.StopTimer();
|
b.StopTimer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkSortInt64K(b *testing.B) {
|
func BenchmarkSortInt64K(b *testing.B) {
|
||||||
b.StopTimer();
|
b.StopTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
data := make([]int, 1<<16);
|
data := make([]int, 1<<16)
|
||||||
for i := 0; i < len(data); i++ {
|
for i := 0; i < len(data); i++ {
|
||||||
data[i] = i ^ 0xcccc
|
data[i] = i ^ 0xcccc
|
||||||
}
|
}
|
||||||
b.StartTimer();
|
b.StartTimer()
|
||||||
SortInts(data);
|
SortInts(data)
|
||||||
b.StopTimer();
|
b.StopTimer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
_Sawtooth = iota;
|
_Sawtooth = iota
|
||||||
_Rand;
|
_Rand
|
||||||
_Stagger;
|
_Stagger
|
||||||
_Plateau;
|
_Plateau
|
||||||
_Shuffle;
|
_Shuffle
|
||||||
_NDist;
|
_NDist
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
_Copy = iota;
|
_Copy = iota
|
||||||
_Reverse;
|
_Reverse
|
||||||
_ReverseFirstHalf;
|
_ReverseFirstHalf
|
||||||
_ReverseSecondHalf;
|
_ReverseSecondHalf
|
||||||
_Sorted;
|
_Sorted
|
||||||
_Dither;
|
_Dither
|
||||||
_NMode;
|
_NMode
|
||||||
)
|
)
|
||||||
|
|
||||||
type testingData struct {
|
type testingData struct {
|
||||||
desc string;
|
desc string
|
||||||
t *testing.T;
|
t *testing.T
|
||||||
data []int;
|
data []int
|
||||||
maxswap int; // number of swaps allowed
|
maxswap int // number of swaps allowed
|
||||||
nswap int;
|
nswap int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *testingData) Len() int { return len(d.data) }
|
func (d *testingData) Len() int { return len(d.data) }
|
||||||
func (d *testingData) Less(i, j int) bool { return d.data[i] < d.data[j] }
|
func (d *testingData) Less(i, j int) bool { return d.data[i] < d.data[j] }
|
||||||
func (d *testingData) Swap(i, j int) {
|
func (d *testingData) Swap(i, j int) {
|
||||||
if d.nswap >= d.maxswap {
|
if d.nswap >= d.maxswap {
|
||||||
d.t.Errorf("%s: used %d swaps sorting array of %d", d.desc, d.nswap, len(d.data));
|
d.t.Errorf("%s: used %d swaps sorting array of %d", d.desc, d.nswap, len(d.data))
|
||||||
d.t.FailNow();
|
d.t.FailNow()
|
||||||
}
|
}
|
||||||
d.nswap++;
|
d.nswap++
|
||||||
d.data[i], d.data[j] = d.data[j], d.data[i];
|
d.data[i], d.data[j] = d.data[j], d.data[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
func lg(n int) int {
|
func lg(n int) int {
|
||||||
i := 0;
|
i := 0
|
||||||
for 1<<uint(i) < n {
|
for 1<<uint(i) < n {
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
return i;
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBentleyMcIlroy(t *testing.T) {
|
func TestBentleyMcIlroy(t *testing.T) {
|
||||||
sizes := []int{100, 1023, 1024, 1025};
|
sizes := []int{100, 1023, 1024, 1025}
|
||||||
dists := []string{"sawtooth", "rand", "stagger", "plateau", "shuffle"};
|
dists := []string{"sawtooth", "rand", "stagger", "plateau", "shuffle"}
|
||||||
modes := []string{"copy", "reverse", "reverse1", "reverse2", "sort", "dither"};
|
modes := []string{"copy", "reverse", "reverse1", "reverse2", "sort", "dither"}
|
||||||
var tmp1, tmp2 [1025]int;
|
var tmp1, tmp2 [1025]int
|
||||||
for ni := 0; ni < len(sizes); ni++ {
|
for ni := 0; ni < len(sizes); ni++ {
|
||||||
n := sizes[ni];
|
n := sizes[ni]
|
||||||
for m := 1; m < 2*n; m *= 2 {
|
for m := 1; m < 2*n; m *= 2 {
|
||||||
for dist := 0; dist < _NDist; dist++ {
|
for dist := 0; dist < _NDist; dist++ {
|
||||||
j := 0;
|
j := 0
|
||||||
k := 1;
|
k := 1
|
||||||
data := tmp1[0:n];
|
data := tmp1[0:n]
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
switch dist {
|
switch dist {
|
||||||
case _Sawtooth:
|
case _Sawtooth:
|
||||||
@ -196,16 +196,16 @@ func TestBentleyMcIlroy(t *testing.T) {
|
|||||||
data[i] = min(i, m)
|
data[i] = min(i, m)
|
||||||
case _Shuffle:
|
case _Shuffle:
|
||||||
if rand.Intn(m) != 0 {
|
if rand.Intn(m) != 0 {
|
||||||
j += 2;
|
j += 2
|
||||||
data[i] = j;
|
data[i] = j
|
||||||
} else {
|
} else {
|
||||||
k += 2;
|
k += 2
|
||||||
data[i] = k;
|
data[i] = k
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mdata := tmp2[0:n];
|
mdata := tmp2[0:n]
|
||||||
for mode := 0; mode < _NMode; mode++ {
|
for mode := 0; mode < _NMode; mode++ {
|
||||||
switch mode {
|
switch mode {
|
||||||
case _Copy:
|
case _Copy:
|
||||||
@ -236,16 +236,16 @@ func TestBentleyMcIlroy(t *testing.T) {
|
|||||||
}
|
}
|
||||||
// SortInts is known to be correct
|
// SortInts is known to be correct
|
||||||
// because mode Sort runs after mode _Copy.
|
// because mode Sort runs after mode _Copy.
|
||||||
SortInts(mdata);
|
SortInts(mdata)
|
||||||
case _Dither:
|
case _Dither:
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
mdata[i] = data[i] + i%5
|
mdata[i] = data[i] + i%5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
desc := fmt.Sprintf("n=%d m=%d dist=%s mode=%s", n, m, dists[dist], modes[mode]);
|
desc := fmt.Sprintf("n=%d m=%d dist=%s mode=%s", n, m, dists[dist], modes[mode])
|
||||||
d := &testingData{desc, t, mdata[0:n], n * lg(n) * 12 / 10, 0};
|
d := &testingData{desc, t, mdata[0:n], n * lg(n) * 12 / 10, 0}
|
||||||
Sort(d);
|
Sort(d)
|
||||||
|
|
||||||
// If we were testing C qsort, we'd have to make a copy
|
// If we were testing C qsort, we'd have to make a copy
|
||||||
// of the array and sort it ourselves and then compare
|
// of the array and sort it ourselves and then compare
|
||||||
@ -256,9 +256,9 @@ func TestBentleyMcIlroy(t *testing.T) {
|
|||||||
// mutating method Sort can call is TestingData.swap,
|
// mutating method Sort can call is TestingData.swap,
|
||||||
// it suffices here just to check that the final array is sorted.
|
// it suffices here just to check that the final array is sorted.
|
||||||
if !IntsAreSorted(mdata) {
|
if !IntsAreSorted(mdata) {
|
||||||
t.Errorf("%s: ints not sorted", desc);
|
t.Errorf("%s: ints not sorted", desc)
|
||||||
t.Errorf("\t%v", mdata);
|
t.Errorf("\t%v", mdata)
|
||||||
t.FailNow();
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,15 +13,15 @@
|
|||||||
package strconv
|
package strconv
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math";
|
"math"
|
||||||
"os";
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
var optimize = true // can change for testing
|
var optimize = true // can change for testing
|
||||||
|
|
||||||
// TODO(rsc): Better truncation handling.
|
// TODO(rsc): Better truncation handling.
|
||||||
func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) {
|
func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) {
|
||||||
i := 0;
|
i := 0
|
||||||
|
|
||||||
// optional sign
|
// optional sign
|
||||||
if i >= len(s) {
|
if i >= len(s) {
|
||||||
@ -31,35 +31,35 @@ func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) {
|
|||||||
case s[i] == '+':
|
case s[i] == '+':
|
||||||
i++
|
i++
|
||||||
case s[i] == '-':
|
case s[i] == '-':
|
||||||
neg = true;
|
neg = true
|
||||||
i++;
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
// digits
|
// digits
|
||||||
b := new(decimal);
|
b := new(decimal)
|
||||||
sawdot := false;
|
sawdot := false
|
||||||
sawdigits := false;
|
sawdigits := false
|
||||||
for ; i < len(s); i++ {
|
for ; i < len(s); i++ {
|
||||||
switch {
|
switch {
|
||||||
case s[i] == '.':
|
case s[i] == '.':
|
||||||
if sawdot {
|
if sawdot {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sawdot = true;
|
sawdot = true
|
||||||
b.dp = b.nd;
|
b.dp = b.nd
|
||||||
continue;
|
continue
|
||||||
|
|
||||||
case '0' <= s[i] && s[i] <= '9':
|
case '0' <= s[i] && s[i] <= '9':
|
||||||
sawdigits = true;
|
sawdigits = true
|
||||||
if s[i] == '0' && b.nd == 0 { // ignore leading zeros
|
if s[i] == '0' && b.nd == 0 { // ignore leading zeros
|
||||||
b.dp--;
|
b.dp--
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
b.d[b.nd] = s[i];
|
b.d[b.nd] = s[i]
|
||||||
b.nd++;
|
b.nd++
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
if !sawdigits {
|
if !sawdigits {
|
||||||
return
|
return
|
||||||
@ -74,50 +74,50 @@ func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) {
|
|||||||
// a lot (say, 100000). it doesn't matter if it's
|
// a lot (say, 100000). it doesn't matter if it's
|
||||||
// not the exact number.
|
// not the exact number.
|
||||||
if i < len(s) && s[i] == 'e' {
|
if i < len(s) && s[i] == 'e' {
|
||||||
i++;
|
i++
|
||||||
if i >= len(s) {
|
if i >= len(s) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
esign := 1;
|
esign := 1
|
||||||
if s[i] == '+' {
|
if s[i] == '+' {
|
||||||
i++
|
i++
|
||||||
} else if s[i] == '-' {
|
} else if s[i] == '-' {
|
||||||
i++;
|
i++
|
||||||
esign = -1;
|
esign = -1
|
||||||
}
|
}
|
||||||
if i >= len(s) || s[i] < '0' || s[i] > '9' {
|
if i >= len(s) || s[i] < '0' || s[i] > '9' {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
e := 0;
|
e := 0
|
||||||
for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
|
for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
|
||||||
if e < 10000 {
|
if e < 10000 {
|
||||||
e = e*10 + int(s[i]) - '0'
|
e = e*10 + int(s[i]) - '0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.dp += e * esign;
|
b.dp += e * esign
|
||||||
}
|
}
|
||||||
|
|
||||||
if i != len(s) {
|
if i != len(s) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
d = b;
|
d = b
|
||||||
ok = true;
|
ok = true
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// decimal power of ten to binary power of two.
|
// decimal power of ten to binary power of two.
|
||||||
var powtab = []int{1, 3, 6, 9, 13, 16, 19, 23, 26}
|
var powtab = []int{1, 3, 6, 9, 13, 16, 19, 23, 26}
|
||||||
|
|
||||||
func decimalToFloatBits(neg bool, d *decimal, trunc bool, flt *floatInfo) (b uint64, overflow bool) {
|
func decimalToFloatBits(neg bool, d *decimal, trunc bool, flt *floatInfo) (b uint64, overflow bool) {
|
||||||
var exp int;
|
var exp int
|
||||||
var mant uint64;
|
var mant uint64
|
||||||
|
|
||||||
// Zero is always a special case.
|
// Zero is always a special case.
|
||||||
if d.nd == 0 {
|
if d.nd == 0 {
|
||||||
mant = 0;
|
mant = 0
|
||||||
exp = flt.bias;
|
exp = flt.bias
|
||||||
goto out;
|
goto out
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obvious overflow/underflow.
|
// Obvious overflow/underflow.
|
||||||
@ -128,44 +128,44 @@ func decimalToFloatBits(neg bool, d *decimal, trunc bool, flt *floatInfo) (b uin
|
|||||||
}
|
}
|
||||||
if d.dp < -330 {
|
if d.dp < -330 {
|
||||||
// zero
|
// zero
|
||||||
mant = 0;
|
mant = 0
|
||||||
exp = flt.bias;
|
exp = flt.bias
|
||||||
goto out;
|
goto out
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scale by powers of two until in range [0.5, 1.0)
|
// Scale by powers of two until in range [0.5, 1.0)
|
||||||
exp = 0;
|
exp = 0
|
||||||
for d.dp > 0 {
|
for d.dp > 0 {
|
||||||
var n int;
|
var n int
|
||||||
if d.dp >= len(powtab) {
|
if d.dp >= len(powtab) {
|
||||||
n = 27
|
n = 27
|
||||||
} else {
|
} else {
|
||||||
n = powtab[d.dp]
|
n = powtab[d.dp]
|
||||||
}
|
}
|
||||||
d.Shift(-n);
|
d.Shift(-n)
|
||||||
exp += n;
|
exp += n
|
||||||
}
|
}
|
||||||
for d.dp < 0 || d.dp == 0 && d.d[0] < '5' {
|
for d.dp < 0 || d.dp == 0 && d.d[0] < '5' {
|
||||||
var n int;
|
var n int
|
||||||
if -d.dp >= len(powtab) {
|
if -d.dp >= len(powtab) {
|
||||||
n = 27
|
n = 27
|
||||||
} else {
|
} else {
|
||||||
n = powtab[-d.dp]
|
n = powtab[-d.dp]
|
||||||
}
|
}
|
||||||
d.Shift(n);
|
d.Shift(n)
|
||||||
exp -= n;
|
exp -= n
|
||||||
}
|
}
|
||||||
|
|
||||||
// Our range is [0.5,1) but floating point range is [1,2).
|
// Our range is [0.5,1) but floating point range is [1,2).
|
||||||
exp--;
|
exp--
|
||||||
|
|
||||||
// Minimum representable exponent is flt.bias+1.
|
// Minimum representable exponent is flt.bias+1.
|
||||||
// If the exponent is smaller, move it up and
|
// If the exponent is smaller, move it up and
|
||||||
// adjust d accordingly.
|
// adjust d accordingly.
|
||||||
if exp < flt.bias+1 {
|
if exp < flt.bias+1 {
|
||||||
n := flt.bias + 1 - exp;
|
n := flt.bias + 1 - exp
|
||||||
d.Shift(-n);
|
d.Shift(-n)
|
||||||
exp += n;
|
exp += n
|
||||||
}
|
}
|
||||||
|
|
||||||
if exp-flt.bias >= 1<<flt.expbits-1 {
|
if exp-flt.bias >= 1<<flt.expbits-1 {
|
||||||
@ -173,12 +173,12 @@ func decimalToFloatBits(neg bool, d *decimal, trunc bool, flt *floatInfo) (b uin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extract 1+flt.mantbits bits.
|
// Extract 1+flt.mantbits bits.
|
||||||
mant = d.Shift(int(1 + flt.mantbits)).RoundedInteger();
|
mant = d.Shift(int(1 + flt.mantbits)).RoundedInteger()
|
||||||
|
|
||||||
// Rounding might have added a bit; shift down.
|
// Rounding might have added a bit; shift down.
|
||||||
if mant == 2<<flt.mantbits {
|
if mant == 2<<flt.mantbits {
|
||||||
mant >>= 1;
|
mant >>= 1
|
||||||
exp++;
|
exp++
|
||||||
if exp-flt.bias >= 1<<flt.expbits-1 {
|
if exp-flt.bias >= 1<<flt.expbits-1 {
|
||||||
goto overflow
|
goto overflow
|
||||||
}
|
}
|
||||||
@ -188,46 +188,46 @@ func decimalToFloatBits(neg bool, d *decimal, trunc bool, flt *floatInfo) (b uin
|
|||||||
if mant&(1<<flt.mantbits) == 0 {
|
if mant&(1<<flt.mantbits) == 0 {
|
||||||
exp = flt.bias
|
exp = flt.bias
|
||||||
}
|
}
|
||||||
goto out;
|
goto out
|
||||||
|
|
||||||
overflow:
|
overflow:
|
||||||
// ±Inf
|
// ±Inf
|
||||||
mant = 0;
|
mant = 0
|
||||||
exp = 1<<flt.expbits - 1 + flt.bias;
|
exp = 1<<flt.expbits - 1 + flt.bias
|
||||||
overflow = true;
|
overflow = true
|
||||||
|
|
||||||
out:
|
out:
|
||||||
// Assemble bits.
|
// Assemble bits.
|
||||||
bits := mant & (uint64(1)<<flt.mantbits - 1);
|
bits := mant & (uint64(1)<<flt.mantbits - 1)
|
||||||
bits |= uint64((exp-flt.bias)&(1<<flt.expbits-1)) << flt.mantbits;
|
bits |= uint64((exp-flt.bias)&(1<<flt.expbits-1)) << flt.mantbits
|
||||||
if neg {
|
if neg {
|
||||||
bits |= 1 << flt.mantbits << flt.expbits
|
bits |= 1 << flt.mantbits << flt.expbits
|
||||||
}
|
}
|
||||||
return bits, overflow;
|
return bits, overflow
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute exact floating-point integer from d's digits.
|
// Compute exact floating-point integer from d's digits.
|
||||||
// Caller is responsible for avoiding overflow.
|
// Caller is responsible for avoiding overflow.
|
||||||
func decimalAtof64Int(neg bool, d *decimal) float64 {
|
func decimalAtof64Int(neg bool, d *decimal) float64 {
|
||||||
f := float64(0);
|
f := float64(0)
|
||||||
for i := 0; i < d.nd; i++ {
|
for i := 0; i < d.nd; i++ {
|
||||||
f = f*10 + float64(d.d[i]-'0')
|
f = f*10 + float64(d.d[i]-'0')
|
||||||
}
|
}
|
||||||
if neg {
|
if neg {
|
||||||
f *= -1 // BUG work around 6g f = -f.
|
f *= -1 // BUG work around 6g f = -f.
|
||||||
}
|
}
|
||||||
return f;
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
func decimalAtof32Int(neg bool, d *decimal) float32 {
|
func decimalAtof32Int(neg bool, d *decimal) float32 {
|
||||||
f := float32(0);
|
f := float32(0)
|
||||||
for i := 0; i < d.nd; i++ {
|
for i := 0; i < d.nd; i++ {
|
||||||
f = f*10 + float32(d.d[i]-'0')
|
f = f*10 + float32(d.d[i]-'0')
|
||||||
}
|
}
|
||||||
if neg {
|
if neg {
|
||||||
f *= -1 // BUG work around 6g f = -f.
|
f *= -1 // BUG work around 6g f = -f.
|
||||||
}
|
}
|
||||||
return f;
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exact powers of 10.
|
// Exact powers of 10.
|
||||||
@ -253,25 +253,25 @@ func decimalAtof64(neg bool, d *decimal, trunc bool) (f float64, ok bool) {
|
|||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case d.dp == d.nd: // int
|
case d.dp == d.nd: // int
|
||||||
f := decimalAtof64Int(neg, d);
|
f := decimalAtof64Int(neg, d)
|
||||||
return f, true;
|
return f, true
|
||||||
|
|
||||||
case d.dp > d.nd && d.dp <= 15+22: // int * 10^k
|
case d.dp > d.nd && d.dp <= 15+22: // int * 10^k
|
||||||
f := decimalAtof64Int(neg, d);
|
f := decimalAtof64Int(neg, d)
|
||||||
k := d.dp - d.nd;
|
k := d.dp - d.nd
|
||||||
// If exponent is big but number of digits is not,
|
// If exponent is big but number of digits is not,
|
||||||
// can move a few zeros into the integer part.
|
// can move a few zeros into the integer part.
|
||||||
if k > 22 {
|
if k > 22 {
|
||||||
f *= float64pow10[k-22];
|
f *= float64pow10[k-22]
|
||||||
k = 22;
|
k = 22
|
||||||
}
|
}
|
||||||
return f * float64pow10[k], true;
|
return f * float64pow10[k], true
|
||||||
|
|
||||||
case d.dp < d.nd && d.nd-d.dp <= 22: // int / 10^k
|
case d.dp < d.nd && d.nd-d.dp <= 22: // int / 10^k
|
||||||
f := decimalAtof64Int(neg, d);
|
f := decimalAtof64Int(neg, d)
|
||||||
return f / float64pow10[d.nd-d.dp], true;
|
return f / float64pow10[d.nd-d.dp], true
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If possible to convert decimal d to 32-bit float f exactly,
|
// If possible to convert decimal d to 32-bit float f exactly,
|
||||||
@ -284,25 +284,25 @@ func decimalAtof32(neg bool, d *decimal, trunc bool) (f float32, ok bool) {
|
|||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case d.dp == d.nd: // int
|
case d.dp == d.nd: // int
|
||||||
f := decimalAtof32Int(neg, d);
|
f := decimalAtof32Int(neg, d)
|
||||||
return f, true;
|
return f, true
|
||||||
|
|
||||||
case d.dp > d.nd && d.dp <= 7+10: // int * 10^k
|
case d.dp > d.nd && d.dp <= 7+10: // int * 10^k
|
||||||
f := decimalAtof32Int(neg, d);
|
f := decimalAtof32Int(neg, d)
|
||||||
k := d.dp - d.nd;
|
k := d.dp - d.nd
|
||||||
// If exponent is big but number of digits is not,
|
// If exponent is big but number of digits is not,
|
||||||
// can move a few zeros into the integer part.
|
// can move a few zeros into the integer part.
|
||||||
if k > 10 {
|
if k > 10 {
|
||||||
f *= float32pow10[k-10];
|
f *= float32pow10[k-10]
|
||||||
k = 10;
|
k = 10
|
||||||
}
|
}
|
||||||
return f * float32pow10[k], true;
|
return f * float32pow10[k], true
|
||||||
|
|
||||||
case d.dp < d.nd && d.nd-d.dp <= 10: // int / 10^k
|
case d.dp < d.nd && d.nd-d.dp <= 10: // int / 10^k
|
||||||
f := decimalAtof32Int(neg, d);
|
f := decimalAtof32Int(neg, d)
|
||||||
return f / float32pow10[d.nd-d.dp], true;
|
return f / float32pow10[d.nd-d.dp], true
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Atof32 converts the string s to a 32-bit floating-point number.
|
// Atof32 converts the string s to a 32-bit floating-point number.
|
||||||
@ -320,7 +320,7 @@ func decimalAtof32(neg bool, d *decimal, trunc bool) (f float32, ok bool) {
|
|||||||
// away from the largest floating point number of the given size,
|
// away from the largest floating point number of the given size,
|
||||||
// Atof32 returns f = ±Inf, err.Error = os.ERANGE.
|
// Atof32 returns f = ±Inf, err.Error = os.ERANGE.
|
||||||
func Atof32(s string) (f float32, err os.Error) {
|
func Atof32(s string) (f float32, err os.Error) {
|
||||||
neg, d, trunc, ok := stringToDecimal(s);
|
neg, d, trunc, ok := stringToDecimal(s)
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, &NumError{s, os.EINVAL}
|
return 0, &NumError{s, os.EINVAL}
|
||||||
}
|
}
|
||||||
@ -329,19 +329,19 @@ func Atof32(s string) (f float32, err os.Error) {
|
|||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b, ovf := decimalToFloatBits(neg, d, trunc, &float32info);
|
b, ovf := decimalToFloatBits(neg, d, trunc, &float32info)
|
||||||
f = math.Float32frombits(uint32(b));
|
f = math.Float32frombits(uint32(b))
|
||||||
if ovf {
|
if ovf {
|
||||||
err = &NumError{s, os.ERANGE}
|
err = &NumError{s, os.ERANGE}
|
||||||
}
|
}
|
||||||
return f, err;
|
return f, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Atof64 converts the string s to a 64-bit floating-point number.
|
// Atof64 converts the string s to a 64-bit floating-point number.
|
||||||
// Except for the type of its result, its definition is the same as that
|
// Except for the type of its result, its definition is the same as that
|
||||||
// of Atof32.
|
// of Atof32.
|
||||||
func Atof64(s string) (f float64, err os.Error) {
|
func Atof64(s string) (f float64, err os.Error) {
|
||||||
neg, d, trunc, ok := stringToDecimal(s);
|
neg, d, trunc, ok := stringToDecimal(s)
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, &NumError{s, os.EINVAL}
|
return 0, &NumError{s, os.EINVAL}
|
||||||
}
|
}
|
||||||
@ -350,20 +350,20 @@ func Atof64(s string) (f float64, err os.Error) {
|
|||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b, ovf := decimalToFloatBits(neg, d, trunc, &float64info);
|
b, ovf := decimalToFloatBits(neg, d, trunc, &float64info)
|
||||||
f = math.Float64frombits(b);
|
f = math.Float64frombits(b)
|
||||||
if ovf {
|
if ovf {
|
||||||
err = &NumError{s, os.ERANGE}
|
err = &NumError{s, os.ERANGE}
|
||||||
}
|
}
|
||||||
return f, err;
|
return f, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Atof is like Atof32 or Atof64, depending on the size of float.
|
// Atof is like Atof32 or Atof64, depending on the size of float.
|
||||||
func Atof(s string) (f float, err os.Error) {
|
func Atof(s string) (f float, err os.Error) {
|
||||||
if FloatSize == 32 {
|
if FloatSize == 32 {
|
||||||
f1, err1 := Atof32(s);
|
f1, err1 := Atof32(s)
|
||||||
return float(f1), err1;
|
return float(f1), err1
|
||||||
}
|
}
|
||||||
f1, err1 := Atof64(s);
|
f1, err1 := Atof64(s)
|
||||||
return float(f1), err1;
|
return float(f1), err1
|
||||||
}
|
}
|
||||||
|
@ -5,16 +5,16 @@
|
|||||||
package strconv_test
|
package strconv_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os";
|
"os"
|
||||||
"reflect";
|
"reflect"
|
||||||
. "strconv";
|
. "strconv"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type atofTest struct {
|
type atofTest struct {
|
||||||
in string;
|
in string
|
||||||
out string;
|
out string
|
||||||
err os.Error;
|
err os.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
var atoftests = []atofTest{
|
var atoftests = []atofTest{
|
||||||
@ -96,7 +96,7 @@ func init() {
|
|||||||
// The atof routines return NumErrors wrapping
|
// The atof routines return NumErrors wrapping
|
||||||
// the error and the string. Convert the table above.
|
// the error and the string. Convert the table above.
|
||||||
for i := range atoftests {
|
for i := range atoftests {
|
||||||
test := &atoftests[i];
|
test := &atoftests[i]
|
||||||
if test.err != nil {
|
if test.err != nil {
|
||||||
test.err = &NumError{test.in, test.err}
|
test.err = &NumError{test.in, test.err}
|
||||||
}
|
}
|
||||||
@ -104,19 +104,19 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testAtof(t *testing.T, opt bool) {
|
func testAtof(t *testing.T, opt bool) {
|
||||||
oldopt := SetOptimize(opt);
|
oldopt := SetOptimize(opt)
|
||||||
for i := 0; i < len(atoftests); i++ {
|
for i := 0; i < len(atoftests); i++ {
|
||||||
test := &atoftests[i];
|
test := &atoftests[i]
|
||||||
out, err := Atof64(test.in);
|
out, err := Atof64(test.in)
|
||||||
outs := Ftoa64(out, 'g', -1);
|
outs := Ftoa64(out, 'g', -1)
|
||||||
if outs != test.out || !reflect.DeepEqual(err, test.err) {
|
if outs != test.out || !reflect.DeepEqual(err, test.err) {
|
||||||
t.Errorf("Atof64(%v) = %v, %v want %v, %v\n",
|
t.Errorf("Atof64(%v) = %v, %v want %v, %v\n",
|
||||||
test.in, out, err, test.out, test.err)
|
test.in, out, err, test.out, test.err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if float64(float32(out)) == out {
|
if float64(float32(out)) == out {
|
||||||
out32, err := Atof32(test.in);
|
out32, err := Atof32(test.in)
|
||||||
outs := Ftoa32(out32, 'g', -1);
|
outs := Ftoa32(out32, 'g', -1)
|
||||||
if outs != test.out || !reflect.DeepEqual(err, test.err) {
|
if outs != test.out || !reflect.DeepEqual(err, test.err) {
|
||||||
t.Errorf("Atof32(%v) = %v, %v want %v, %v # %v\n",
|
t.Errorf("Atof32(%v) = %v, %v want %v, %v # %v\n",
|
||||||
test.in, out32, err, test.out, test.err, out)
|
test.in, out32, err, test.out, test.err, out)
|
||||||
@ -124,15 +124,15 @@ func testAtof(t *testing.T, opt bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if FloatSize == 64 || float64(float32(out)) == out {
|
if FloatSize == 64 || float64(float32(out)) == out {
|
||||||
outf, err := Atof(test.in);
|
outf, err := Atof(test.in)
|
||||||
outs := Ftoa(outf, 'g', -1);
|
outs := Ftoa(outf, 'g', -1)
|
||||||
if outs != test.out || !reflect.DeepEqual(err, test.err) {
|
if outs != test.out || !reflect.DeepEqual(err, test.err) {
|
||||||
t.Errorf("Ftoa(%v) = %v, %v want %v, %v # %v\n",
|
t.Errorf("Ftoa(%v) = %v, %v want %v, %v # %v\n",
|
||||||
test.in, outf, err, test.out, test.err, out)
|
test.in, outf, err, test.out, test.err, out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SetOptimize(oldopt);
|
SetOptimize(oldopt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAtof(t *testing.T) { testAtof(t, true) }
|
func TestAtof(t *testing.T) { testAtof(t, true) }
|
||||||
|
@ -7,19 +7,19 @@ package strconv
|
|||||||
import "os"
|
import "os"
|
||||||
|
|
||||||
type NumError struct {
|
type NumError struct {
|
||||||
Num string;
|
Num string
|
||||||
Error os.Error;
|
Error os.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *NumError) String() string { return "parsing " + e.Num + ": " + e.Error.String() }
|
func (e *NumError) String() string { return "parsing " + e.Num + ": " + e.Error.String() }
|
||||||
|
|
||||||
|
|
||||||
func computeIntsize() uint {
|
func computeIntsize() uint {
|
||||||
siz := uint(8);
|
siz := uint(8)
|
||||||
for 1<<siz != 0 {
|
for 1<<siz != 0 {
|
||||||
siz *= 2
|
siz *= 2
|
||||||
}
|
}
|
||||||
return siz;
|
return siz
|
||||||
}
|
}
|
||||||
|
|
||||||
var IntSize = computeIntsize()
|
var IntSize = computeIntsize()
|
||||||
@ -29,7 +29,7 @@ func cutoff64(base int) uint64 {
|
|||||||
if base < 2 {
|
if base < 2 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return (1<<64-1)/uint64(base) + 1;
|
return (1<<64-1)/uint64(base) + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Btoui64 interprets a string s in an arbitrary base b (2 to 36)
|
// Btoui64 interprets a string s in an arbitrary base b (2 to 36)
|
||||||
@ -42,11 +42,11 @@ func cutoff64(base int) uint64 {
|
|||||||
// digits, err.Error = os.EINVAL; if the value corresponding
|
// digits, err.Error = os.EINVAL; if the value corresponding
|
||||||
// to s cannot be represented by a uint64, err.Error = os.ERANGE.
|
// to s cannot be represented by a uint64, err.Error = os.ERANGE.
|
||||||
func Btoui64(s string, b int) (n uint64, err os.Error) {
|
func Btoui64(s string, b int) (n uint64, err os.Error) {
|
||||||
s0 := s;
|
s0 := s
|
||||||
switch {
|
switch {
|
||||||
case len(s) < 1:
|
case len(s) < 1:
|
||||||
err = os.EINVAL;
|
err = os.EINVAL
|
||||||
goto Error;
|
goto Error
|
||||||
|
|
||||||
case 2 <= b && b <= 36:
|
case 2 <= b && b <= 36:
|
||||||
// valid base; nothing to do
|
// valid base; nothing to do
|
||||||
@ -55,11 +55,11 @@ func Btoui64(s string, b int) (n uint64, err os.Error) {
|
|||||||
// Look for octal, hex prefix.
|
// Look for octal, hex prefix.
|
||||||
switch {
|
switch {
|
||||||
case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
|
case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
|
||||||
b = 16;
|
b = 16
|
||||||
s = s[2:];
|
s = s[2:]
|
||||||
if len(s) < 1 {
|
if len(s) < 1 {
|
||||||
err = os.EINVAL;
|
err = os.EINVAL
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
case s[0] == '0':
|
case s[0] == '0':
|
||||||
b = 8
|
b = 8
|
||||||
@ -68,15 +68,15 @@ func Btoui64(s string, b int) (n uint64, err os.Error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err = os.ErrorString("invalid base " + Itoa(b));
|
err = os.ErrorString("invalid base " + Itoa(b))
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
|
|
||||||
n = 0;
|
n = 0
|
||||||
cutoff := cutoff64(b);
|
cutoff := cutoff64(b)
|
||||||
|
|
||||||
for i := 0; i < len(s); i++ {
|
for i := 0; i < len(s); i++ {
|
||||||
var v byte;
|
var v byte
|
||||||
switch {
|
switch {
|
||||||
case '0' <= s[i] && s[i] <= '9':
|
case '0' <= s[i] && s[i] <= '9':
|
||||||
v = s[i] - '0'
|
v = s[i] - '0'
|
||||||
@ -85,38 +85,38 @@ func Btoui64(s string, b int) (n uint64, err os.Error) {
|
|||||||
case 'A' <= s[i] && s[i] <= 'Z':
|
case 'A' <= s[i] && s[i] <= 'Z':
|
||||||
v = s[i] - 'A' + 10
|
v = s[i] - 'A' + 10
|
||||||
default:
|
default:
|
||||||
n = 0;
|
n = 0
|
||||||
err = os.EINVAL;
|
err = os.EINVAL
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
if int(v) >= b {
|
if int(v) >= b {
|
||||||
n = 0;
|
n = 0
|
||||||
err = os.EINVAL;
|
err = os.EINVAL
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
|
|
||||||
if n >= cutoff {
|
if n >= cutoff {
|
||||||
// n*b overflows
|
// n*b overflows
|
||||||
n = 1<<64 - 1;
|
n = 1<<64 - 1
|
||||||
err = os.ERANGE;
|
err = os.ERANGE
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
n *= uint64(b);
|
n *= uint64(b)
|
||||||
|
|
||||||
n1 := n + uint64(v);
|
n1 := n + uint64(v)
|
||||||
if n1 < n {
|
if n1 < n {
|
||||||
// n+v overflows
|
// n+v overflows
|
||||||
n = 1<<64 - 1;
|
n = 1<<64 - 1
|
||||||
err = os.ERANGE;
|
err = os.ERANGE
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
n = n1;
|
n = n1
|
||||||
}
|
}
|
||||||
|
|
||||||
return n, nil;
|
return n, nil
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
return n, &NumError{s0, err};
|
return n, &NumError{s0, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Atoui64 interprets a string s as a decimal number and
|
// Atoui64 interprets a string s as a decimal number and
|
||||||
@ -137,21 +137,21 @@ func Btoi64(s string, base int) (i int64, err os.Error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pick off leading sign.
|
// Pick off leading sign.
|
||||||
s0 := s;
|
s0 := s
|
||||||
neg := false;
|
neg := false
|
||||||
if s[0] == '+' {
|
if s[0] == '+' {
|
||||||
s = s[1:]
|
s = s[1:]
|
||||||
} else if s[0] == '-' {
|
} else if s[0] == '-' {
|
||||||
neg = true;
|
neg = true
|
||||||
s = s[1:];
|
s = s[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert unsigned and check range.
|
// Convert unsigned and check range.
|
||||||
var un uint64;
|
var un uint64
|
||||||
un, err = Btoui64(s, base);
|
un, err = Btoui64(s, base)
|
||||||
if err != nil && err.(*NumError).Error != os.ERANGE {
|
if err != nil && err.(*NumError).Error != os.ERANGE {
|
||||||
err.(*NumError).Num = s0;
|
err.(*NumError).Num = s0
|
||||||
return 0, err;
|
return 0, err
|
||||||
}
|
}
|
||||||
if !neg && un >= 1<<63 {
|
if !neg && un >= 1<<63 {
|
||||||
return 1<<63 - 1, &NumError{s0, os.ERANGE}
|
return 1<<63 - 1, &NumError{s0, os.ERANGE}
|
||||||
@ -159,11 +159,11 @@ func Btoi64(s string, base int) (i int64, err os.Error) {
|
|||||||
if neg && un > 1<<63 {
|
if neg && un > 1<<63 {
|
||||||
return -1 << 63, &NumError{s0, os.ERANGE}
|
return -1 << 63, &NumError{s0, os.ERANGE}
|
||||||
}
|
}
|
||||||
n := int64(un);
|
n := int64(un)
|
||||||
if neg {
|
if neg {
|
||||||
n = -n
|
n = -n
|
||||||
}
|
}
|
||||||
return n, nil;
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Atoi64 is like Atoui64 but allows signed numbers and
|
// Atoi64 is like Atoui64 but allows signed numbers and
|
||||||
@ -173,29 +173,29 @@ func Atoi64(s string) (i int64, err os.Error) { return Btoi64(s, 10) }
|
|||||||
|
|
||||||
// Atoui is like Atoui64 but returns its result as a uint.
|
// Atoui is like Atoui64 but returns its result as a uint.
|
||||||
func Atoui(s string) (i uint, err os.Error) {
|
func Atoui(s string) (i uint, err os.Error) {
|
||||||
i1, e1 := Atoui64(s);
|
i1, e1 := Atoui64(s)
|
||||||
if e1 != nil && e1.(*NumError).Error != os.ERANGE {
|
if e1 != nil && e1.(*NumError).Error != os.ERANGE {
|
||||||
return 0, e1
|
return 0, e1
|
||||||
}
|
}
|
||||||
i = uint(i1);
|
i = uint(i1)
|
||||||
if uint64(i) != i1 {
|
if uint64(i) != i1 {
|
||||||
return ^uint(0), &NumError{s, os.ERANGE}
|
return ^uint(0), &NumError{s, os.ERANGE}
|
||||||
}
|
}
|
||||||
return i, nil;
|
return i, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Atoi is like Atoi64 but returns its result as an int.
|
// Atoi is like Atoi64 but returns its result as an int.
|
||||||
func Atoi(s string) (i int, err os.Error) {
|
func Atoi(s string) (i int, err os.Error) {
|
||||||
i1, e1 := Atoi64(s);
|
i1, e1 := Atoi64(s)
|
||||||
if e1 != nil && e1.(*NumError).Error != os.ERANGE {
|
if e1 != nil && e1.(*NumError).Error != os.ERANGE {
|
||||||
return 0, e1
|
return 0, e1
|
||||||
}
|
}
|
||||||
i = int(i1);
|
i = int(i1)
|
||||||
if int64(i) != i1 {
|
if int64(i) != i1 {
|
||||||
if i1 < 0 {
|
if i1 < 0 {
|
||||||
return -1 << (IntSize - 1), &NumError{s, os.ERANGE}
|
return -1 << (IntSize - 1), &NumError{s, os.ERANGE}
|
||||||
}
|
}
|
||||||
return 1<<(IntSize-1) - 1, &NumError{s, os.ERANGE};
|
return 1<<(IntSize-1) - 1, &NumError{s, os.ERANGE}
|
||||||
}
|
}
|
||||||
return i, nil;
|
return i, nil
|
||||||
}
|
}
|
||||||
|
@ -5,16 +5,16 @@
|
|||||||
package strconv_test
|
package strconv_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os";
|
"os"
|
||||||
"reflect";
|
"reflect"
|
||||||
. "strconv";
|
. "strconv"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type atoui64Test struct {
|
type atoui64Test struct {
|
||||||
in string;
|
in string
|
||||||
out uint64;
|
out uint64
|
||||||
err os.Error;
|
err os.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
var atoui64tests = []atoui64Test{
|
var atoui64tests = []atoui64Test{
|
||||||
@ -52,9 +52,9 @@ var btoui64tests = []atoui64Test{
|
|||||||
}
|
}
|
||||||
|
|
||||||
type atoi64Test struct {
|
type atoi64Test struct {
|
||||||
in string;
|
in string
|
||||||
out int64;
|
out int64
|
||||||
err os.Error;
|
err os.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
var atoi64tests = []atoi64Test{
|
var atoi64tests = []atoi64Test{
|
||||||
@ -102,9 +102,9 @@ var btoi64tests = []atoi64Test{
|
|||||||
}
|
}
|
||||||
|
|
||||||
type atoui32Test struct {
|
type atoui32Test struct {
|
||||||
in string;
|
in string
|
||||||
out uint32;
|
out uint32
|
||||||
err os.Error;
|
err os.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
var atoui32tests = []atoui32Test{
|
var atoui32tests = []atoui32Test{
|
||||||
@ -120,9 +120,9 @@ var atoui32tests = []atoui32Test{
|
|||||||
}
|
}
|
||||||
|
|
||||||
type atoi32Test struct {
|
type atoi32Test struct {
|
||||||
in string;
|
in string
|
||||||
out int32;
|
out int32
|
||||||
err os.Error;
|
err os.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
var atoi32tests = []atoi32Test{
|
var atoi32tests = []atoi32Test{
|
||||||
@ -151,37 +151,37 @@ func init() {
|
|||||||
// The atoi routines return NumErrors wrapping
|
// The atoi routines return NumErrors wrapping
|
||||||
// the error and the string. Convert the tables above.
|
// the error and the string. Convert the tables above.
|
||||||
for i := range atoui64tests {
|
for i := range atoui64tests {
|
||||||
test := &atoui64tests[i];
|
test := &atoui64tests[i]
|
||||||
if test.err != nil {
|
if test.err != nil {
|
||||||
test.err = &NumError{test.in, test.err}
|
test.err = &NumError{test.in, test.err}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := range btoui64tests {
|
for i := range btoui64tests {
|
||||||
test := &btoui64tests[i];
|
test := &btoui64tests[i]
|
||||||
if test.err != nil {
|
if test.err != nil {
|
||||||
test.err = &NumError{test.in, test.err}
|
test.err = &NumError{test.in, test.err}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := range atoi64tests {
|
for i := range atoi64tests {
|
||||||
test := &atoi64tests[i];
|
test := &atoi64tests[i]
|
||||||
if test.err != nil {
|
if test.err != nil {
|
||||||
test.err = &NumError{test.in, test.err}
|
test.err = &NumError{test.in, test.err}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := range btoi64tests {
|
for i := range btoi64tests {
|
||||||
test := &btoi64tests[i];
|
test := &btoi64tests[i]
|
||||||
if test.err != nil {
|
if test.err != nil {
|
||||||
test.err = &NumError{test.in, test.err}
|
test.err = &NumError{test.in, test.err}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := range atoui32tests {
|
for i := range atoui32tests {
|
||||||
test := &atoui32tests[i];
|
test := &atoui32tests[i]
|
||||||
if test.err != nil {
|
if test.err != nil {
|
||||||
test.err = &NumError{test.in, test.err}
|
test.err = &NumError{test.in, test.err}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := range atoi32tests {
|
for i := range atoi32tests {
|
||||||
test := &atoi32tests[i];
|
test := &atoi32tests[i]
|
||||||
if test.err != nil {
|
if test.err != nil {
|
||||||
test.err = &NumError{test.in, test.err}
|
test.err = &NumError{test.in, test.err}
|
||||||
}
|
}
|
||||||
@ -190,8 +190,8 @@ func init() {
|
|||||||
|
|
||||||
func TestAtoui64(t *testing.T) {
|
func TestAtoui64(t *testing.T) {
|
||||||
for i := range atoui64tests {
|
for i := range atoui64tests {
|
||||||
test := &atoui64tests[i];
|
test := &atoui64tests[i]
|
||||||
out, err := Atoui64(test.in);
|
out, err := Atoui64(test.in)
|
||||||
if test.out != out || !reflect.DeepEqual(test.err, err) {
|
if test.out != out || !reflect.DeepEqual(test.err, err) {
|
||||||
t.Errorf("Atoui64(%q) = %v, %v want %v, %v\n",
|
t.Errorf("Atoui64(%q) = %v, %v want %v, %v\n",
|
||||||
test.in, out, err, test.out, test.err)
|
test.in, out, err, test.out, test.err)
|
||||||
@ -201,8 +201,8 @@ func TestAtoui64(t *testing.T) {
|
|||||||
|
|
||||||
func TestBtoui64(t *testing.T) {
|
func TestBtoui64(t *testing.T) {
|
||||||
for i := range btoui64tests {
|
for i := range btoui64tests {
|
||||||
test := &btoui64tests[i];
|
test := &btoui64tests[i]
|
||||||
out, err := Btoui64(test.in, 0);
|
out, err := Btoui64(test.in, 0)
|
||||||
if test.out != out || !reflect.DeepEqual(test.err, err) {
|
if test.out != out || !reflect.DeepEqual(test.err, err) {
|
||||||
t.Errorf("Btoui64(%q) = %v, %v want %v, %v\n",
|
t.Errorf("Btoui64(%q) = %v, %v want %v, %v\n",
|
||||||
test.in, out, err, test.out, test.err)
|
test.in, out, err, test.out, test.err)
|
||||||
@ -212,8 +212,8 @@ func TestBtoui64(t *testing.T) {
|
|||||||
|
|
||||||
func TestAtoi64(t *testing.T) {
|
func TestAtoi64(t *testing.T) {
|
||||||
for i := range atoi64tests {
|
for i := range atoi64tests {
|
||||||
test := &atoi64tests[i];
|
test := &atoi64tests[i]
|
||||||
out, err := Atoi64(test.in);
|
out, err := Atoi64(test.in)
|
||||||
if test.out != out || !reflect.DeepEqual(test.err, err) {
|
if test.out != out || !reflect.DeepEqual(test.err, err) {
|
||||||
t.Errorf("Atoi64(%q) = %v, %v want %v, %v\n",
|
t.Errorf("Atoi64(%q) = %v, %v want %v, %v\n",
|
||||||
test.in, out, err, test.out, test.err)
|
test.in, out, err, test.out, test.err)
|
||||||
@ -223,8 +223,8 @@ func TestAtoi64(t *testing.T) {
|
|||||||
|
|
||||||
func TestBtoi64(t *testing.T) {
|
func TestBtoi64(t *testing.T) {
|
||||||
for i := range btoi64tests {
|
for i := range btoi64tests {
|
||||||
test := &btoi64tests[i];
|
test := &btoi64tests[i]
|
||||||
out, err := Btoi64(test.in, 0);
|
out, err := Btoi64(test.in, 0)
|
||||||
if test.out != out || !reflect.DeepEqual(test.err, err) {
|
if test.out != out || !reflect.DeepEqual(test.err, err) {
|
||||||
t.Errorf("Btoi64(%q) = %v, %v want %v, %v\n",
|
t.Errorf("Btoi64(%q) = %v, %v want %v, %v\n",
|
||||||
test.in, out, err, test.out, test.err)
|
test.in, out, err, test.out, test.err)
|
||||||
@ -236,8 +236,8 @@ func TestAtoui(t *testing.T) {
|
|||||||
switch IntSize {
|
switch IntSize {
|
||||||
case 32:
|
case 32:
|
||||||
for i := range atoui32tests {
|
for i := range atoui32tests {
|
||||||
test := &atoui32tests[i];
|
test := &atoui32tests[i]
|
||||||
out, err := Atoui(test.in);
|
out, err := Atoui(test.in)
|
||||||
if test.out != uint32(out) || !reflect.DeepEqual(test.err, err) {
|
if test.out != uint32(out) || !reflect.DeepEqual(test.err, err) {
|
||||||
t.Errorf("Atoui(%q) = %v, %v want %v, %v\n",
|
t.Errorf("Atoui(%q) = %v, %v want %v, %v\n",
|
||||||
test.in, out, err, test.out, test.err)
|
test.in, out, err, test.out, test.err)
|
||||||
@ -245,8 +245,8 @@ func TestAtoui(t *testing.T) {
|
|||||||
}
|
}
|
||||||
case 64:
|
case 64:
|
||||||
for i := range atoui64tests {
|
for i := range atoui64tests {
|
||||||
test := &atoui64tests[i];
|
test := &atoui64tests[i]
|
||||||
out, err := Atoui(test.in);
|
out, err := Atoui(test.in)
|
||||||
if test.out != uint64(out) || !reflect.DeepEqual(test.err, err) {
|
if test.out != uint64(out) || !reflect.DeepEqual(test.err, err) {
|
||||||
t.Errorf("Atoui(%q) = %v, %v want %v, %v\n",
|
t.Errorf("Atoui(%q) = %v, %v want %v, %v\n",
|
||||||
test.in, out, err, test.out, test.err)
|
test.in, out, err, test.out, test.err)
|
||||||
@ -259,8 +259,8 @@ func TestAtoi(t *testing.T) {
|
|||||||
switch IntSize {
|
switch IntSize {
|
||||||
case 32:
|
case 32:
|
||||||
for i := range atoi32tests {
|
for i := range atoi32tests {
|
||||||
test := &atoi32tests[i];
|
test := &atoi32tests[i]
|
||||||
out, err := Atoi(test.in);
|
out, err := Atoi(test.in)
|
||||||
if test.out != int32(out) || !reflect.DeepEqual(test.err, err) {
|
if test.out != int32(out) || !reflect.DeepEqual(test.err, err) {
|
||||||
t.Errorf("Atoi(%q) = %v, %v want %v, %v\n",
|
t.Errorf("Atoi(%q) = %v, %v want %v, %v\n",
|
||||||
test.in, out, err, test.out, test.err)
|
test.in, out, err, test.out, test.err)
|
||||||
@ -268,8 +268,8 @@ func TestAtoi(t *testing.T) {
|
|||||||
}
|
}
|
||||||
case 64:
|
case 64:
|
||||||
for i := range atoi64tests {
|
for i := range atoi64tests {
|
||||||
test := &atoi64tests[i];
|
test := &atoi64tests[i]
|
||||||
out, err := Atoi(test.in);
|
out, err := Atoi(test.in)
|
||||||
if test.out != int64(out) || !reflect.DeepEqual(test.err, err) {
|
if test.out != int64(out) || !reflect.DeepEqual(test.err, err) {
|
||||||
t.Errorf("Atoi(%q) = %v, %v want %v, %v\n",
|
t.Errorf("Atoi(%q) = %v, %v want %v, %v\n",
|
||||||
test.in, out, err, test.out, test.err)
|
test.in, out, err, test.out, test.err)
|
||||||
|
@ -14,13 +14,13 @@ package strconv
|
|||||||
type decimal struct {
|
type decimal struct {
|
||||||
// TODO(rsc): Can make d[] a bit smaller and add
|
// TODO(rsc): Can make d[] a bit smaller and add
|
||||||
// truncated bool;
|
// truncated bool;
|
||||||
d [2000]byte; // digits
|
d [2000]byte // digits
|
||||||
nd int; // number of digits used
|
nd int // number of digits used
|
||||||
dp int; // decimal point
|
dp int // decimal point
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *decimal) String() string {
|
func (a *decimal) String() string {
|
||||||
n := 10 + a.nd;
|
n := 10 + a.nd
|
||||||
if a.dp > 0 {
|
if a.dp > 0 {
|
||||||
n += a.dp
|
n += a.dp
|
||||||
}
|
}
|
||||||
@ -28,48 +28,48 @@ func (a *decimal) String() string {
|
|||||||
n += -a.dp
|
n += -a.dp
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := make([]byte, n);
|
buf := make([]byte, n)
|
||||||
w := 0;
|
w := 0
|
||||||
switch {
|
switch {
|
||||||
case a.nd == 0:
|
case a.nd == 0:
|
||||||
return "0"
|
return "0"
|
||||||
|
|
||||||
case a.dp <= 0:
|
case a.dp <= 0:
|
||||||
// zeros fill space between decimal point and digits
|
// zeros fill space between decimal point and digits
|
||||||
buf[w] = '0';
|
buf[w] = '0'
|
||||||
w++;
|
w++
|
||||||
buf[w] = '.';
|
buf[w] = '.'
|
||||||
w++;
|
w++
|
||||||
w += digitZero(buf[w : w+-a.dp]);
|
w += digitZero(buf[w : w+-a.dp])
|
||||||
w += copy(buf[w:w+a.nd], a.d[0:a.nd]);
|
w += copy(buf[w:w+a.nd], a.d[0:a.nd])
|
||||||
|
|
||||||
case a.dp < a.nd:
|
case a.dp < a.nd:
|
||||||
// decimal point in middle of digits
|
// decimal point in middle of digits
|
||||||
w += copy(buf[w:w+a.dp], a.d[0:a.dp]);
|
w += copy(buf[w:w+a.dp], a.d[0:a.dp])
|
||||||
buf[w] = '.';
|
buf[w] = '.'
|
||||||
w++;
|
w++
|
||||||
w += copy(buf[w:w+a.nd-a.dp], a.d[a.dp:a.nd]);
|
w += copy(buf[w:w+a.nd-a.dp], a.d[a.dp:a.nd])
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// zeros fill space between digits and decimal point
|
// zeros fill space between digits and decimal point
|
||||||
w += copy(buf[w:w+a.nd], a.d[0:a.nd]);
|
w += copy(buf[w:w+a.nd], a.d[0:a.nd])
|
||||||
w += digitZero(buf[w : w+a.dp-a.nd]);
|
w += digitZero(buf[w : w+a.dp-a.nd])
|
||||||
}
|
}
|
||||||
return string(buf[0:w]);
|
return string(buf[0:w])
|
||||||
}
|
}
|
||||||
|
|
||||||
func copy(dst []byte, src []byte) int {
|
func copy(dst []byte, src []byte) int {
|
||||||
for i := 0; i < len(dst); i++ {
|
for i := 0; i < len(dst); i++ {
|
||||||
dst[i] = src[i]
|
dst[i] = src[i]
|
||||||
}
|
}
|
||||||
return len(dst);
|
return len(dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
func digitZero(dst []byte) int {
|
func digitZero(dst []byte) int {
|
||||||
for i := 0; i < len(dst); i++ {
|
for i := 0; i < len(dst); i++ {
|
||||||
dst[i] = '0'
|
dst[i] = '0'
|
||||||
}
|
}
|
||||||
return len(dst);
|
return len(dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
// trim trailing zeros from number.
|
// trim trailing zeros from number.
|
||||||
@ -86,32 +86,32 @@ func trim(a *decimal) {
|
|||||||
|
|
||||||
// Assign v to a.
|
// Assign v to a.
|
||||||
func (a *decimal) Assign(v uint64) {
|
func (a *decimal) Assign(v uint64) {
|
||||||
var buf [50]byte;
|
var buf [50]byte
|
||||||
|
|
||||||
// Write reversed decimal in buf.
|
// Write reversed decimal in buf.
|
||||||
n := 0;
|
n := 0
|
||||||
for v > 0 {
|
for v > 0 {
|
||||||
v1 := v / 10;
|
v1 := v / 10
|
||||||
v -= 10 * v1;
|
v -= 10 * v1
|
||||||
buf[n] = byte(v + '0');
|
buf[n] = byte(v + '0')
|
||||||
n++;
|
n++
|
||||||
v = v1;
|
v = v1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse again to produce forward decimal in a.d.
|
// Reverse again to produce forward decimal in a.d.
|
||||||
a.nd = 0;
|
a.nd = 0
|
||||||
for n--; n >= 0; n-- {
|
for n--; n >= 0; n-- {
|
||||||
a.d[a.nd] = buf[n];
|
a.d[a.nd] = buf[n]
|
||||||
a.nd++;
|
a.nd++
|
||||||
}
|
}
|
||||||
a.dp = a.nd;
|
a.dp = a.nd
|
||||||
trim(a);
|
trim(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDecimal(i uint64) *decimal {
|
func newDecimal(i uint64) *decimal {
|
||||||
a := new(decimal);
|
a := new(decimal)
|
||||||
a.Assign(i);
|
a.Assign(i)
|
||||||
return a;
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maximum shift that we can do in one pass without overflow.
|
// Maximum shift that we can do in one pass without overflow.
|
||||||
@ -120,50 +120,50 @@ const maxShift = 27
|
|||||||
|
|
||||||
// Binary shift right (* 2) by k bits. k <= maxShift to avoid overflow.
|
// Binary shift right (* 2) by k bits. k <= maxShift to avoid overflow.
|
||||||
func rightShift(a *decimal, k uint) {
|
func rightShift(a *decimal, k uint) {
|
||||||
r := 0; // read pointer
|
r := 0 // read pointer
|
||||||
w := 0; // write pointer
|
w := 0 // write pointer
|
||||||
|
|
||||||
// Pick up enough leading digits to cover first shift.
|
// Pick up enough leading digits to cover first shift.
|
||||||
n := 0;
|
n := 0
|
||||||
for ; n>>k == 0; r++ {
|
for ; n>>k == 0; r++ {
|
||||||
if r >= a.nd {
|
if r >= a.nd {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
// a == 0; shouldn't get here, but handle anyway.
|
// a == 0; shouldn't get here, but handle anyway.
|
||||||
a.nd = 0;
|
a.nd = 0
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
for n>>k == 0 {
|
for n>>k == 0 {
|
||||||
n = n * 10;
|
n = n * 10
|
||||||
r++;
|
r++
|
||||||
}
|
}
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
c := int(a.d[r]);
|
c := int(a.d[r])
|
||||||
n = n*10 + c - '0';
|
n = n*10 + c - '0'
|
||||||
}
|
}
|
||||||
a.dp -= r - 1;
|
a.dp -= r - 1
|
||||||
|
|
||||||
// Pick up a digit, put down a digit.
|
// Pick up a digit, put down a digit.
|
||||||
for ; r < a.nd; r++ {
|
for ; r < a.nd; r++ {
|
||||||
c := int(a.d[r]);
|
c := int(a.d[r])
|
||||||
dig := n >> k;
|
dig := n >> k
|
||||||
n -= dig << k;
|
n -= dig << k
|
||||||
a.d[w] = byte(dig + '0');
|
a.d[w] = byte(dig + '0')
|
||||||
w++;
|
w++
|
||||||
n = n*10 + c - '0';
|
n = n*10 + c - '0'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put down extra digits.
|
// Put down extra digits.
|
||||||
for n > 0 {
|
for n > 0 {
|
||||||
dig := n >> k;
|
dig := n >> k
|
||||||
n -= dig << k;
|
n -= dig << k
|
||||||
a.d[w] = byte(dig + '0');
|
a.d[w] = byte(dig + '0')
|
||||||
w++;
|
w++
|
||||||
n = n * 10;
|
n = n * 10
|
||||||
}
|
}
|
||||||
|
|
||||||
a.nd = w;
|
a.nd = w
|
||||||
trim(a);
|
trim(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cheat sheet for left shift: table indexed by shift count giving
|
// Cheat sheet for left shift: table indexed by shift count giving
|
||||||
@ -177,8 +177,8 @@ func rightShift(a *decimal, k uint) {
|
|||||||
// Credit for this trick goes to Ken.
|
// Credit for this trick goes to Ken.
|
||||||
|
|
||||||
type leftCheat struct {
|
type leftCheat struct {
|
||||||
delta int; // number of new digits
|
delta int // number of new digits
|
||||||
cutoff string; // minus one digit if original < a.
|
cutoff string // minus one digit if original < a.
|
||||||
}
|
}
|
||||||
|
|
||||||
var leftcheats = []leftCheat{
|
var leftcheats = []leftCheat{
|
||||||
@ -234,42 +234,42 @@ func prefixIsLessThan(b []byte, s string) bool {
|
|||||||
return b[i] < s[i]
|
return b[i] < s[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Binary shift left (/ 2) by k bits. k <= maxShift to avoid overflow.
|
// Binary shift left (/ 2) by k bits. k <= maxShift to avoid overflow.
|
||||||
func leftShift(a *decimal, k uint) {
|
func leftShift(a *decimal, k uint) {
|
||||||
delta := leftcheats[k].delta;
|
delta := leftcheats[k].delta
|
||||||
if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) {
|
if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) {
|
||||||
delta--
|
delta--
|
||||||
}
|
}
|
||||||
|
|
||||||
r := a.nd; // read index
|
r := a.nd // read index
|
||||||
w := a.nd + delta; // write index
|
w := a.nd + delta // write index
|
||||||
n := 0;
|
n := 0
|
||||||
|
|
||||||
// Pick up a digit, put down a digit.
|
// Pick up a digit, put down a digit.
|
||||||
for r--; r >= 0; r-- {
|
for r--; r >= 0; r-- {
|
||||||
n += (int(a.d[r]) - '0') << k;
|
n += (int(a.d[r]) - '0') << k
|
||||||
quo := n / 10;
|
quo := n / 10
|
||||||
rem := n - 10*quo;
|
rem := n - 10*quo
|
||||||
w--;
|
w--
|
||||||
a.d[w] = byte(rem + '0');
|
a.d[w] = byte(rem + '0')
|
||||||
n = quo;
|
n = quo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put down extra digits.
|
// Put down extra digits.
|
||||||
for n > 0 {
|
for n > 0 {
|
||||||
quo := n / 10;
|
quo := n / 10
|
||||||
rem := n - 10*quo;
|
rem := n - 10*quo
|
||||||
w--;
|
w--
|
||||||
a.d[w] = byte(rem + '0');
|
a.d[w] = byte(rem + '0')
|
||||||
n = quo;
|
n = quo
|
||||||
}
|
}
|
||||||
|
|
||||||
a.nd += delta;
|
a.nd += delta
|
||||||
a.dp += delta;
|
a.dp += delta
|
||||||
trim(a);
|
trim(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Binary shift left (k > 0) or right (k < 0).
|
// Binary shift left (k > 0) or right (k < 0).
|
||||||
@ -280,18 +280,18 @@ func (a *decimal) Shift(k int) *decimal {
|
|||||||
// nothing to do: a == 0
|
// nothing to do: a == 0
|
||||||
case k > 0:
|
case k > 0:
|
||||||
for k > maxShift {
|
for k > maxShift {
|
||||||
leftShift(a, maxShift);
|
leftShift(a, maxShift)
|
||||||
k -= maxShift;
|
k -= maxShift
|
||||||
}
|
}
|
||||||
leftShift(a, uint(k));
|
leftShift(a, uint(k))
|
||||||
case k < 0:
|
case k < 0:
|
||||||
for k < -maxShift {
|
for k < -maxShift {
|
||||||
rightShift(a, maxShift);
|
rightShift(a, maxShift)
|
||||||
k += maxShift;
|
k += maxShift
|
||||||
}
|
}
|
||||||
rightShift(a, uint(-k));
|
rightShift(a, uint(-k))
|
||||||
}
|
}
|
||||||
return a;
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we chop a at nd digits, should we round up?
|
// If we chop a at nd digits, should we round up?
|
||||||
@ -303,7 +303,7 @@ func shouldRoundUp(a *decimal, nd int) bool {
|
|||||||
return (a.d[nd-1]-'0')%2 != 0
|
return (a.d[nd-1]-'0')%2 != 0
|
||||||
}
|
}
|
||||||
// not halfway - digit tells all
|
// not halfway - digit tells all
|
||||||
return a.d[nd] >= '5';
|
return a.d[nd] >= '5'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round a to nd digits (or fewer).
|
// Round a to nd digits (or fewer).
|
||||||
@ -315,7 +315,7 @@ func (a *decimal) Round(nd int) *decimal {
|
|||||||
if shouldRoundUp(a, nd) {
|
if shouldRoundUp(a, nd) {
|
||||||
return a.RoundUp(nd)
|
return a.RoundUp(nd)
|
||||||
}
|
}
|
||||||
return a.RoundDown(nd);
|
return a.RoundDown(nd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round a down to nd digits (or fewer).
|
// Round a down to nd digits (or fewer).
|
||||||
@ -324,9 +324,9 @@ func (a *decimal) RoundDown(nd int) *decimal {
|
|||||||
if nd <= 0 || nd >= a.nd {
|
if nd <= 0 || nd >= a.nd {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
a.nd = nd;
|
a.nd = nd
|
||||||
trim(a);
|
trim(a)
|
||||||
return a;
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round a up to nd digits (or fewer).
|
// Round a up to nd digits (or fewer).
|
||||||
@ -338,20 +338,20 @@ func (a *decimal) RoundUp(nd int) *decimal {
|
|||||||
|
|
||||||
// round up
|
// round up
|
||||||
for i := nd - 1; i >= 0; i-- {
|
for i := nd - 1; i >= 0; i-- {
|
||||||
c := a.d[i];
|
c := a.d[i]
|
||||||
if c < '9' { // can stop after this digit
|
if c < '9' { // can stop after this digit
|
||||||
a.d[i]++;
|
a.d[i]++
|
||||||
a.nd = i + 1;
|
a.nd = i + 1
|
||||||
return a;
|
return a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Number is all 9s.
|
// Number is all 9s.
|
||||||
// Change to single 1 with adjusted decimal point.
|
// Change to single 1 with adjusted decimal point.
|
||||||
a.d[0] = '1';
|
a.d[0] = '1'
|
||||||
a.nd = 1;
|
a.nd = 1
|
||||||
a.dp++;
|
a.dp++
|
||||||
return a;
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract integer part, rounded appropriately.
|
// Extract integer part, rounded appropriately.
|
||||||
@ -360,8 +360,8 @@ func (a *decimal) RoundedInteger() uint64 {
|
|||||||
if a.dp > 20 {
|
if a.dp > 20 {
|
||||||
return 0xFFFFFFFFFFFFFFFF
|
return 0xFFFFFFFFFFFFFFFF
|
||||||
}
|
}
|
||||||
var i int;
|
var i int
|
||||||
n := uint64(0);
|
n := uint64(0)
|
||||||
for i = 0; i < a.dp && i < a.nd; i++ {
|
for i = 0; i < a.dp && i < a.nd; i++ {
|
||||||
n = n*10 + uint64(a.d[i]-'0')
|
n = n*10 + uint64(a.d[i]-'0')
|
||||||
}
|
}
|
||||||
@ -371,5 +371,5 @@ func (a *decimal) RoundedInteger() uint64 {
|
|||||||
if shouldRoundUp(a, a.dp) {
|
if shouldRoundUp(a, a.dp) {
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
return n;
|
return n
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,14 @@
|
|||||||
package strconv_test
|
package strconv_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "strconv";
|
. "strconv"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type shiftTest struct {
|
type shiftTest struct {
|
||||||
i uint64;
|
i uint64
|
||||||
shift int;
|
shift int
|
||||||
out string;
|
out string
|
||||||
}
|
}
|
||||||
|
|
||||||
var shifttests = []shiftTest{
|
var shifttests = []shiftTest{
|
||||||
@ -31,8 +31,8 @@ var shifttests = []shiftTest{
|
|||||||
|
|
||||||
func TestDecimalShift(t *testing.T) {
|
func TestDecimalShift(t *testing.T) {
|
||||||
for i := 0; i < len(shifttests); i++ {
|
for i := 0; i < len(shifttests); i++ {
|
||||||
test := &shifttests[i];
|
test := &shifttests[i]
|
||||||
s := NewDecimal(test.i).Shift(test.shift).String();
|
s := NewDecimal(test.i).Shift(test.shift).String()
|
||||||
if s != test.out {
|
if s != test.out {
|
||||||
t.Errorf("Decimal %v << %v = %v, want %v\n",
|
t.Errorf("Decimal %v << %v = %v, want %v\n",
|
||||||
test.i, test.shift, s, test.out)
|
test.i, test.shift, s, test.out)
|
||||||
@ -41,10 +41,10 @@ func TestDecimalShift(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type roundTest struct {
|
type roundTest struct {
|
||||||
i uint64;
|
i uint64
|
||||||
nd int;
|
nd int
|
||||||
down, round, up string;
|
down, round, up string
|
||||||
int uint64;
|
int uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
var roundtests = []roundTest{
|
var roundtests = []roundTest{
|
||||||
@ -67,18 +67,18 @@ var roundtests = []roundTest{
|
|||||||
|
|
||||||
func TestDecimalRound(t *testing.T) {
|
func TestDecimalRound(t *testing.T) {
|
||||||
for i := 0; i < len(roundtests); i++ {
|
for i := 0; i < len(roundtests); i++ {
|
||||||
test := &roundtests[i];
|
test := &roundtests[i]
|
||||||
s := NewDecimal(test.i).RoundDown(test.nd).String();
|
s := NewDecimal(test.i).RoundDown(test.nd).String()
|
||||||
if s != test.down {
|
if s != test.down {
|
||||||
t.Errorf("Decimal %v RoundDown %d = %v, want %v\n",
|
t.Errorf("Decimal %v RoundDown %d = %v, want %v\n",
|
||||||
test.i, test.nd, s, test.down)
|
test.i, test.nd, s, test.down)
|
||||||
}
|
}
|
||||||
s = NewDecimal(test.i).Round(test.nd).String();
|
s = NewDecimal(test.i).Round(test.nd).String()
|
||||||
if s != test.round {
|
if s != test.round {
|
||||||
t.Errorf("Decimal %v Round %d = %v, want %v\n",
|
t.Errorf("Decimal %v Round %d = %v, want %v\n",
|
||||||
test.i, test.nd, s, test.down)
|
test.i, test.nd, s, test.down)
|
||||||
}
|
}
|
||||||
s = NewDecimal(test.i).RoundUp(test.nd).String();
|
s = NewDecimal(test.i).RoundUp(test.nd).String()
|
||||||
if s != test.up {
|
if s != test.up {
|
||||||
t.Errorf("Decimal %v RoundUp %d = %v, want %v\n",
|
t.Errorf("Decimal %v RoundUp %d = %v, want %v\n",
|
||||||
test.i, test.nd, s, test.up)
|
test.i, test.nd, s, test.up)
|
||||||
@ -87,9 +87,9 @@ func TestDecimalRound(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type roundIntTest struct {
|
type roundIntTest struct {
|
||||||
i uint64;
|
i uint64
|
||||||
shift int;
|
shift int
|
||||||
int uint64;
|
int uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
var roundinttests = []roundIntTest{
|
var roundinttests = []roundIntTest{
|
||||||
@ -107,8 +107,8 @@ var roundinttests = []roundIntTest{
|
|||||||
|
|
||||||
func TestDecimalRoundedInteger(t *testing.T) {
|
func TestDecimalRoundedInteger(t *testing.T) {
|
||||||
for i := 0; i < len(roundinttests); i++ {
|
for i := 0; i < len(roundinttests); i++ {
|
||||||
test := roundinttests[i];
|
test := roundinttests[i]
|
||||||
int := NewDecimal(test.i).Shift(test.shift).RoundedInteger();
|
int := NewDecimal(test.i).Shift(test.shift).RoundedInteger()
|
||||||
if int != test.int {
|
if int != test.int {
|
||||||
t.Errorf("Decimal %v >> %v RoundedInteger = %v, want %v\n",
|
t.Errorf("Decimal %v >> %v RoundedInteger = %v, want %v\n",
|
||||||
test.i, test.shift, int, test.int)
|
test.i, test.shift, int, test.int)
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
package strconv_test
|
package strconv_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio";
|
"bufio"
|
||||||
"fmt";
|
"fmt"
|
||||||
"os";
|
"os"
|
||||||
"strconv";
|
"strconv"
|
||||||
"strings";
|
"strings"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func pow2(i int) float64 {
|
func pow2(i int) float64 {
|
||||||
@ -22,124 +22,124 @@ func pow2(i int) float64 {
|
|||||||
case i == 1:
|
case i == 1:
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
return pow2(i/2) * pow2(i-i/2);
|
return pow2(i/2) * pow2(i-i/2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper around strconv.Atof64. Handles dddddp+ddd (binary exponent)
|
// Wrapper around strconv.Atof64. Handles dddddp+ddd (binary exponent)
|
||||||
// itself, passes the rest on to strconv.Atof64.
|
// itself, passes the rest on to strconv.Atof64.
|
||||||
func myatof64(s string) (f float64, ok bool) {
|
func myatof64(s string) (f float64, ok bool) {
|
||||||
a := strings.Split(s, "p", 2);
|
a := strings.Split(s, "p", 2)
|
||||||
if len(a) == 2 {
|
if len(a) == 2 {
|
||||||
n, err := strconv.Atoi64(a[0]);
|
n, err := strconv.Atoi64(a[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
e, err1 := strconv.Atoi(a[1]);
|
e, err1 := strconv.Atoi(a[1])
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
println("bad e", a[1]);
|
println("bad e", a[1])
|
||||||
return 0, false;
|
return 0, false
|
||||||
}
|
}
|
||||||
v := float64(n);
|
v := float64(n)
|
||||||
// We expect that v*pow2(e) fits in a float64,
|
// We expect that v*pow2(e) fits in a float64,
|
||||||
// but pow2(e) by itself may not. Be careful.
|
// but pow2(e) by itself may not. Be careful.
|
||||||
if e <= -1000 {
|
if e <= -1000 {
|
||||||
v *= pow2(-1000);
|
v *= pow2(-1000)
|
||||||
e += 1000;
|
e += 1000
|
||||||
for e < 0 {
|
for e < 0 {
|
||||||
v /= 2;
|
v /= 2
|
||||||
e++;
|
e++
|
||||||
}
|
}
|
||||||
return v, true;
|
return v, true
|
||||||
}
|
}
|
||||||
if e >= 1000 {
|
if e >= 1000 {
|
||||||
v *= pow2(1000);
|
v *= pow2(1000)
|
||||||
e -= 1000;
|
e -= 1000
|
||||||
for e > 0 {
|
for e > 0 {
|
||||||
v *= 2;
|
v *= 2
|
||||||
e--;
|
e--
|
||||||
}
|
}
|
||||||
return v, true;
|
return v, true
|
||||||
}
|
}
|
||||||
return v * pow2(e), true;
|
return v * pow2(e), true
|
||||||
}
|
}
|
||||||
f1, err := strconv.Atof64(s);
|
f1, err := strconv.Atof64(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
return f1, true;
|
return f1, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper around strconv.Atof32. Handles dddddp+ddd (binary exponent)
|
// Wrapper around strconv.Atof32. Handles dddddp+ddd (binary exponent)
|
||||||
// itself, passes the rest on to strconv.Atof32.
|
// itself, passes the rest on to strconv.Atof32.
|
||||||
func myatof32(s string) (f float32, ok bool) {
|
func myatof32(s string) (f float32, ok bool) {
|
||||||
a := strings.Split(s, "p", 2);
|
a := strings.Split(s, "p", 2)
|
||||||
if len(a) == 2 {
|
if len(a) == 2 {
|
||||||
n, err := strconv.Atoi(a[0]);
|
n, err := strconv.Atoi(a[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
println("bad n", a[0]);
|
println("bad n", a[0])
|
||||||
return 0, false;
|
return 0, false
|
||||||
}
|
}
|
||||||
e, err1 := strconv.Atoi(a[1]);
|
e, err1 := strconv.Atoi(a[1])
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
println("bad p", a[1]);
|
println("bad p", a[1])
|
||||||
return 0, false;
|
return 0, false
|
||||||
}
|
}
|
||||||
return float32(float64(n) * pow2(e)), true;
|
return float32(float64(n) * pow2(e)), true
|
||||||
}
|
}
|
||||||
f1, err1 := strconv.Atof32(s);
|
f1, err1 := strconv.Atof32(s)
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
return f1, true;
|
return f1, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFp(t *testing.T) {
|
func TestFp(t *testing.T) {
|
||||||
f, err := os.Open("testfp.txt", os.O_RDONLY, 0);
|
f, err := os.Open("testfp.txt", os.O_RDONLY, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panicln("testfp: open testfp.txt:", err.String())
|
panicln("testfp: open testfp.txt:", err.String())
|
||||||
}
|
}
|
||||||
defer f.Close();
|
defer f.Close()
|
||||||
|
|
||||||
b := bufio.NewReader(f);
|
b := bufio.NewReader(f)
|
||||||
|
|
||||||
lineno := 0;
|
lineno := 0
|
||||||
for {
|
for {
|
||||||
line, err2 := b.ReadString('\n');
|
line, err2 := b.ReadString('\n')
|
||||||
if err2 == os.EOF {
|
if err2 == os.EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
panicln("testfp: read testfp.txt:", err2.String())
|
panicln("testfp: read testfp.txt:", err2.String())
|
||||||
}
|
}
|
||||||
line = line[0 : len(line)-1];
|
line = line[0 : len(line)-1]
|
||||||
lineno++;
|
lineno++
|
||||||
if len(line) == 0 || line[0] == '#' {
|
if len(line) == 0 || line[0] == '#' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
a := strings.Split(line, " ", 0);
|
a := strings.Split(line, " ", 0)
|
||||||
if len(a) != 4 {
|
if len(a) != 4 {
|
||||||
t.Error("testfp.txt:", lineno, ": wrong field count\n");
|
t.Error("testfp.txt:", lineno, ": wrong field count\n")
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
var s string;
|
var s string
|
||||||
var v float64;
|
var v float64
|
||||||
switch a[0] {
|
switch a[0] {
|
||||||
case "float64":
|
case "float64":
|
||||||
var ok bool;
|
var ok bool
|
||||||
v, ok = myatof64(a[2]);
|
v, ok = myatof64(a[2])
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error("testfp.txt:", lineno, ": cannot atof64 ", a[2]);
|
t.Error("testfp.txt:", lineno, ": cannot atof64 ", a[2])
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
s = fmt.Sprintf(a[1], v);
|
s = fmt.Sprintf(a[1], v)
|
||||||
case "float32":
|
case "float32":
|
||||||
v1, ok := myatof32(a[2]);
|
v1, ok := myatof32(a[2])
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error("testfp.txt:", lineno, ": cannot atof32 ", a[2]);
|
t.Error("testfp.txt:", lineno, ": cannot atof32 ", a[2])
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
s = fmt.Sprintf(a[1], v1);
|
s = fmt.Sprintf(a[1], v1)
|
||||||
v = float64(v1);
|
v = float64(v1)
|
||||||
}
|
}
|
||||||
if s != a[3] {
|
if s != a[3] {
|
||||||
t.Error("testfp.txt:", lineno, ": ", a[0], " ", a[1], " ", a[2], " (", v, ") ",
|
t.Error("testfp.txt:", lineno, ": ", a[0], " ", a[1], " ", a[2], " (", v, ") ",
|
||||||
|
@ -14,9 +14,9 @@ import "math"
|
|||||||
|
|
||||||
// TODO: move elsewhere?
|
// TODO: move elsewhere?
|
||||||
type floatInfo struct {
|
type floatInfo struct {
|
||||||
mantbits uint;
|
mantbits uint
|
||||||
expbits uint;
|
expbits uint
|
||||||
bias int;
|
bias int
|
||||||
}
|
}
|
||||||
|
|
||||||
var float32info = floatInfo{23, 8, -127}
|
var float32info = floatInfo{23, 8, -127}
|
||||||
@ -26,11 +26,11 @@ func floatsize() int {
|
|||||||
// Figure out whether float is float32 or float64.
|
// Figure out whether float is float32 or float64.
|
||||||
// 1e-35 is representable in both, but 1e-70
|
// 1e-35 is representable in both, but 1e-70
|
||||||
// is too small for a float32.
|
// is too small for a float32.
|
||||||
var f float = 1e-35;
|
var f float = 1e-35
|
||||||
if f*f == 0 {
|
if f*f == 0 {
|
||||||
return 32
|
return 32
|
||||||
}
|
}
|
||||||
return 64;
|
return 64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Floatsize gives the size of the float type, either 32 or 64.
|
// Floatsize gives the size of the float type, either 32 or 64.
|
||||||
@ -69,13 +69,13 @@ func Ftoa(f float, fmt byte, prec int) string {
|
|||||||
if FloatSize == 32 {
|
if FloatSize == 32 {
|
||||||
return Ftoa32(float32(f), fmt, prec)
|
return Ftoa32(float32(f), fmt, prec)
|
||||||
}
|
}
|
||||||
return Ftoa64(float64(f), fmt, prec);
|
return Ftoa64(float64(f), fmt, prec)
|
||||||
}
|
}
|
||||||
|
|
||||||
func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
|
func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
|
||||||
neg := bits>>flt.expbits>>flt.mantbits != 0;
|
neg := bits>>flt.expbits>>flt.mantbits != 0
|
||||||
exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1);
|
exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1)
|
||||||
mant := bits & (uint64(1)<<flt.mantbits - 1);
|
mant := bits & (uint64(1)<<flt.mantbits - 1)
|
||||||
|
|
||||||
switch exp {
|
switch exp {
|
||||||
case 1<<flt.expbits - 1:
|
case 1<<flt.expbits - 1:
|
||||||
@ -86,7 +86,7 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
|
|||||||
if neg {
|
if neg {
|
||||||
return "-Inf"
|
return "-Inf"
|
||||||
}
|
}
|
||||||
return "+Inf";
|
return "+Inf"
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
// denormalized
|
// denormalized
|
||||||
@ -96,7 +96,7 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
|
|||||||
// add implicit top bit
|
// add implicit top bit
|
||||||
mant |= uint64(1) << flt.mantbits
|
mant |= uint64(1) << flt.mantbits
|
||||||
}
|
}
|
||||||
exp += flt.bias;
|
exp += flt.bias
|
||||||
|
|
||||||
// Pick off easy binary format.
|
// Pick off easy binary format.
|
||||||
if fmt == 'b' {
|
if fmt == 'b' {
|
||||||
@ -107,14 +107,14 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
|
|||||||
// The shift is exp - flt.mantbits because mant is a 1-bit integer
|
// The shift is exp - flt.mantbits because mant is a 1-bit integer
|
||||||
// followed by a flt.mantbits fraction, and we are treating it as
|
// followed by a flt.mantbits fraction, and we are treating it as
|
||||||
// a 1+flt.mantbits-bit integer.
|
// a 1+flt.mantbits-bit integer.
|
||||||
d := newDecimal(mant).Shift(exp - int(flt.mantbits));
|
d := newDecimal(mant).Shift(exp - int(flt.mantbits))
|
||||||
|
|
||||||
// Round appropriately.
|
// Round appropriately.
|
||||||
// Negative precision means "only as much as needed to be exact."
|
// Negative precision means "only as much as needed to be exact."
|
||||||
shortest := false;
|
shortest := false
|
||||||
if prec < 0 {
|
if prec < 0 {
|
||||||
shortest = true;
|
shortest = true
|
||||||
roundShortest(d, mant, exp, flt);
|
roundShortest(d, mant, exp, flt)
|
||||||
switch fmt {
|
switch fmt {
|
||||||
case 'e', 'E':
|
case 'e', 'E':
|
||||||
prec = d.nd - 1
|
prec = d.nd - 1
|
||||||
@ -133,7 +133,7 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
|
|||||||
if prec == 0 {
|
if prec == 0 {
|
||||||
prec = 1
|
prec = 1
|
||||||
}
|
}
|
||||||
d.Round(prec);
|
d.Round(prec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,18 +150,18 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
|
|||||||
// %e is used if the exponent from the conversion
|
// %e is used if the exponent from the conversion
|
||||||
// is less than -4 or greater than or equal to the precision.
|
// is less than -4 or greater than or equal to the precision.
|
||||||
// if precision was the shortest possible, use precision 6 for this decision.
|
// if precision was the shortest possible, use precision 6 for this decision.
|
||||||
eprec := prec;
|
eprec := prec
|
||||||
if shortest {
|
if shortest {
|
||||||
eprec = 6
|
eprec = 6
|
||||||
}
|
}
|
||||||
exp := d.dp - 1;
|
exp := d.dp - 1
|
||||||
if exp < -4 || exp >= eprec {
|
if exp < -4 || exp >= eprec {
|
||||||
return fmtE(neg, d, prec-1, fmt+'e'-'g')
|
return fmtE(neg, d, prec-1, fmt+'e'-'g')
|
||||||
}
|
}
|
||||||
return fmtF(neg, d, max(prec-d.dp, 0));
|
return fmtF(neg, d, max(prec-d.dp, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
return "%" + string(fmt);
|
return "%" + string(fmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round d (= mant * 2^exp) to the shortest number of digits
|
// Round d (= mant * 2^exp) to the shortest number of digits
|
||||||
@ -170,8 +170,8 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
|
|||||||
func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
|
func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
|
||||||
// If mantissa is zero, the number is zero; stop now.
|
// If mantissa is zero, the number is zero; stop now.
|
||||||
if mant == 0 {
|
if mant == 0 {
|
||||||
d.nd = 0;
|
d.nd = 0
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(rsc): Unless exp == minexp, if the number of digits in d
|
// TODO(rsc): Unless exp == minexp, if the number of digits in d
|
||||||
@ -186,7 +186,7 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
|
|||||||
// d = mant << (exp - mantbits)
|
// d = mant << (exp - mantbits)
|
||||||
// Next highest floating point number is mant+1 << exp-mantbits.
|
// Next highest floating point number is mant+1 << exp-mantbits.
|
||||||
// Our upper bound is halfway inbetween, mant*2+1 << exp-mantbits-1.
|
// Our upper bound is halfway inbetween, mant*2+1 << exp-mantbits-1.
|
||||||
upper := newDecimal(mant*2 + 1).Shift(exp - int(flt.mantbits) - 1);
|
upper := newDecimal(mant*2 + 1).Shift(exp - int(flt.mantbits) - 1)
|
||||||
|
|
||||||
// d = mant << (exp - mantbits)
|
// d = mant << (exp - mantbits)
|
||||||
// Next lowest floating point number is mant-1 << exp-mantbits,
|
// Next lowest floating point number is mant-1 << exp-mantbits,
|
||||||
@ -194,33 +194,33 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
|
|||||||
// in which case the next lowest is mant*2-1 << exp-mantbits-1.
|
// in which case the next lowest is mant*2-1 << exp-mantbits-1.
|
||||||
// Either way, call it mantlo << explo-mantbits.
|
// Either way, call it mantlo << explo-mantbits.
|
||||||
// Our lower bound is halfway inbetween, mantlo*2+1 << explo-mantbits-1.
|
// Our lower bound is halfway inbetween, mantlo*2+1 << explo-mantbits-1.
|
||||||
minexp := flt.bias + 1; // minimum possible exponent
|
minexp := flt.bias + 1 // minimum possible exponent
|
||||||
var mantlo uint64;
|
var mantlo uint64
|
||||||
var explo int;
|
var explo int
|
||||||
if mant > 1<<flt.mantbits || exp == minexp {
|
if mant > 1<<flt.mantbits || exp == minexp {
|
||||||
mantlo = mant - 1;
|
mantlo = mant - 1
|
||||||
explo = exp;
|
explo = exp
|
||||||
} else {
|
} else {
|
||||||
mantlo = mant*2 - 1;
|
mantlo = mant*2 - 1
|
||||||
explo = exp - 1;
|
explo = exp - 1
|
||||||
}
|
}
|
||||||
lower := newDecimal(mantlo*2 + 1).Shift(explo - int(flt.mantbits) - 1);
|
lower := newDecimal(mantlo*2 + 1).Shift(explo - int(flt.mantbits) - 1)
|
||||||
|
|
||||||
// The upper and lower bounds are possible outputs only if
|
// The upper and lower bounds are possible outputs only if
|
||||||
// the original mantissa is even, so that IEEE round-to-even
|
// the original mantissa is even, so that IEEE round-to-even
|
||||||
// would round to the original mantissa and not the neighbors.
|
// would round to the original mantissa and not the neighbors.
|
||||||
inclusive := mant%2 == 0;
|
inclusive := mant%2 == 0
|
||||||
|
|
||||||
// Now we can figure out the minimum number of digits required.
|
// Now we can figure out the minimum number of digits required.
|
||||||
// Walk along until d has distinguished itself from upper and lower.
|
// Walk along until d has distinguished itself from upper and lower.
|
||||||
for i := 0; i < d.nd; i++ {
|
for i := 0; i < d.nd; i++ {
|
||||||
var l, m, u byte; // lower, middle, upper digits
|
var l, m, u byte // lower, middle, upper digits
|
||||||
if i < lower.nd {
|
if i < lower.nd {
|
||||||
l = lower.d[i]
|
l = lower.d[i]
|
||||||
} else {
|
} else {
|
||||||
l = '0'
|
l = '0'
|
||||||
}
|
}
|
||||||
m = d.d[i];
|
m = d.d[i]
|
||||||
if i < upper.nd {
|
if i < upper.nd {
|
||||||
u = upper.d[i]
|
u = upper.d[i]
|
||||||
} else {
|
} else {
|
||||||
@ -229,37 +229,37 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
|
|||||||
|
|
||||||
// Okay to round down (truncate) if lower has a different digit
|
// Okay to round down (truncate) if lower has a different digit
|
||||||
// or if lower is inclusive and is exactly the result of rounding down.
|
// or if lower is inclusive and is exactly the result of rounding down.
|
||||||
okdown := l != m || (inclusive && l == m && i+1 == lower.nd);
|
okdown := l != m || (inclusive && l == m && i+1 == lower.nd)
|
||||||
|
|
||||||
// Okay to round up if upper has a different digit and
|
// Okay to round up if upper has a different digit and
|
||||||
// either upper is inclusive or upper is bigger than the result of rounding up.
|
// either upper is inclusive or upper is bigger than the result of rounding up.
|
||||||
okup := m != u && (inclusive || i+1 < upper.nd);
|
okup := m != u && (inclusive || i+1 < upper.nd)
|
||||||
|
|
||||||
// If it's okay to do either, then round to the nearest one.
|
// If it's okay to do either, then round to the nearest one.
|
||||||
// If it's okay to do only one, do it.
|
// If it's okay to do only one, do it.
|
||||||
switch {
|
switch {
|
||||||
case okdown && okup:
|
case okdown && okup:
|
||||||
d.Round(i + 1);
|
d.Round(i + 1)
|
||||||
return;
|
return
|
||||||
case okdown:
|
case okdown:
|
||||||
d.RoundDown(i + 1);
|
d.RoundDown(i + 1)
|
||||||
return;
|
return
|
||||||
case okup:
|
case okup:
|
||||||
d.RoundUp(i + 1);
|
d.RoundUp(i + 1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// %e: -d.ddddde±dd
|
// %e: -d.ddddde±dd
|
||||||
func fmtE(neg bool, d *decimal, prec int, fmt byte) string {
|
func fmtE(neg bool, d *decimal, prec int, fmt byte) string {
|
||||||
buf := make([]byte, 3+max(prec, 0)+30); // "-0." + prec digits + exp
|
buf := make([]byte, 3+max(prec, 0)+30) // "-0." + prec digits + exp
|
||||||
w := 0; // write index
|
w := 0 // write index
|
||||||
|
|
||||||
// sign
|
// sign
|
||||||
if neg {
|
if neg {
|
||||||
buf[w] = '-';
|
buf[w] = '-'
|
||||||
w++;
|
w++
|
||||||
}
|
}
|
||||||
|
|
||||||
// first digit
|
// first digit
|
||||||
@ -268,141 +268,141 @@ func fmtE(neg bool, d *decimal, prec int, fmt byte) string {
|
|||||||
} else {
|
} else {
|
||||||
buf[w] = d.d[0]
|
buf[w] = d.d[0]
|
||||||
}
|
}
|
||||||
w++;
|
w++
|
||||||
|
|
||||||
// .moredigits
|
// .moredigits
|
||||||
if prec > 0 {
|
if prec > 0 {
|
||||||
buf[w] = '.';
|
buf[w] = '.'
|
||||||
w++;
|
w++
|
||||||
for i := 0; i < prec; i++ {
|
for i := 0; i < prec; i++ {
|
||||||
if 1+i < d.nd {
|
if 1+i < d.nd {
|
||||||
buf[w] = d.d[1+i]
|
buf[w] = d.d[1+i]
|
||||||
} else {
|
} else {
|
||||||
buf[w] = '0'
|
buf[w] = '0'
|
||||||
}
|
}
|
||||||
w++;
|
w++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// e±
|
// e±
|
||||||
buf[w] = fmt;
|
buf[w] = fmt
|
||||||
w++;
|
w++
|
||||||
exp := d.dp - 1;
|
exp := d.dp - 1
|
||||||
if d.nd == 0 { // special case: 0 has exponent 0
|
if d.nd == 0 { // special case: 0 has exponent 0
|
||||||
exp = 0
|
exp = 0
|
||||||
}
|
}
|
||||||
if exp < 0 {
|
if exp < 0 {
|
||||||
buf[w] = '-';
|
buf[w] = '-'
|
||||||
exp = -exp;
|
exp = -exp
|
||||||
} else {
|
} else {
|
||||||
buf[w] = '+'
|
buf[w] = '+'
|
||||||
}
|
}
|
||||||
w++;
|
w++
|
||||||
|
|
||||||
// dddd
|
// dddd
|
||||||
// count digits
|
// count digits
|
||||||
n := 0;
|
n := 0
|
||||||
for e := exp; e > 0; e /= 10 {
|
for e := exp; e > 0; e /= 10 {
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
// leading zeros
|
// leading zeros
|
||||||
for i := n; i < 2; i++ {
|
for i := n; i < 2; i++ {
|
||||||
buf[w] = '0';
|
buf[w] = '0'
|
||||||
w++;
|
w++
|
||||||
}
|
}
|
||||||
// digits
|
// digits
|
||||||
w += n;
|
w += n
|
||||||
n = 0;
|
n = 0
|
||||||
for e := exp; e > 0; e /= 10 {
|
for e := exp; e > 0; e /= 10 {
|
||||||
n++;
|
n++
|
||||||
buf[w-n] = byte(e%10 + '0');
|
buf[w-n] = byte(e%10 + '0')
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(buf[0:w]);
|
return string(buf[0:w])
|
||||||
}
|
}
|
||||||
|
|
||||||
// %f: -ddddddd.ddddd
|
// %f: -ddddddd.ddddd
|
||||||
func fmtF(neg bool, d *decimal, prec int) string {
|
func fmtF(neg bool, d *decimal, prec int) string {
|
||||||
buf := make([]byte, 1+max(d.dp, 1)+1+max(prec, 0));
|
buf := make([]byte, 1+max(d.dp, 1)+1+max(prec, 0))
|
||||||
w := 0;
|
w := 0
|
||||||
|
|
||||||
// sign
|
// sign
|
||||||
if neg {
|
if neg {
|
||||||
buf[w] = '-';
|
buf[w] = '-'
|
||||||
w++;
|
w++
|
||||||
}
|
}
|
||||||
|
|
||||||
// integer, padded with zeros as needed.
|
// integer, padded with zeros as needed.
|
||||||
if d.dp > 0 {
|
if d.dp > 0 {
|
||||||
var i int;
|
var i int
|
||||||
for i = 0; i < d.dp && i < d.nd; i++ {
|
for i = 0; i < d.dp && i < d.nd; i++ {
|
||||||
buf[w] = d.d[i];
|
buf[w] = d.d[i]
|
||||||
w++;
|
w++
|
||||||
}
|
}
|
||||||
for ; i < d.dp; i++ {
|
for ; i < d.dp; i++ {
|
||||||
buf[w] = '0';
|
buf[w] = '0'
|
||||||
w++;
|
w++
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buf[w] = '0';
|
buf[w] = '0'
|
||||||
w++;
|
w++
|
||||||
}
|
}
|
||||||
|
|
||||||
// fraction
|
// fraction
|
||||||
if prec > 0 {
|
if prec > 0 {
|
||||||
buf[w] = '.';
|
buf[w] = '.'
|
||||||
w++;
|
w++
|
||||||
for i := 0; i < prec; i++ {
|
for i := 0; i < prec; i++ {
|
||||||
if d.dp+i < 0 || d.dp+i >= d.nd {
|
if d.dp+i < 0 || d.dp+i >= d.nd {
|
||||||
buf[w] = '0'
|
buf[w] = '0'
|
||||||
} else {
|
} else {
|
||||||
buf[w] = d.d[d.dp+i]
|
buf[w] = d.d[d.dp+i]
|
||||||
}
|
}
|
||||||
w++;
|
w++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(buf[0:w]);
|
return string(buf[0:w])
|
||||||
}
|
}
|
||||||
|
|
||||||
// %b: -ddddddddp+ddd
|
// %b: -ddddddddp+ddd
|
||||||
func fmtB(neg bool, mant uint64, exp int, flt *floatInfo) string {
|
func fmtB(neg bool, mant uint64, exp int, flt *floatInfo) string {
|
||||||
var buf [50]byte;
|
var buf [50]byte
|
||||||
w := len(buf);
|
w := len(buf)
|
||||||
exp -= int(flt.mantbits);
|
exp -= int(flt.mantbits)
|
||||||
esign := byte('+');
|
esign := byte('+')
|
||||||
if exp < 0 {
|
if exp < 0 {
|
||||||
esign = '-';
|
esign = '-'
|
||||||
exp = -exp;
|
exp = -exp
|
||||||
}
|
}
|
||||||
n := 0;
|
n := 0
|
||||||
for exp > 0 || n < 1 {
|
for exp > 0 || n < 1 {
|
||||||
n++;
|
n++
|
||||||
w--;
|
w--
|
||||||
buf[w] = byte(exp%10 + '0');
|
buf[w] = byte(exp%10 + '0')
|
||||||
exp /= 10;
|
exp /= 10
|
||||||
}
|
}
|
||||||
w--;
|
w--
|
||||||
buf[w] = esign;
|
buf[w] = esign
|
||||||
w--;
|
w--
|
||||||
buf[w] = 'p';
|
buf[w] = 'p'
|
||||||
n = 0;
|
n = 0
|
||||||
for mant > 0 || n < 1 {
|
for mant > 0 || n < 1 {
|
||||||
n++;
|
n++
|
||||||
w--;
|
w--
|
||||||
buf[w] = byte(mant%10 + '0');
|
buf[w] = byte(mant%10 + '0')
|
||||||
mant /= 10;
|
mant /= 10
|
||||||
}
|
}
|
||||||
if neg {
|
if neg {
|
||||||
w--;
|
w--
|
||||||
buf[w] = '-';
|
buf[w] = '-'
|
||||||
}
|
}
|
||||||
return string(buf[w:]);
|
return string(buf[w:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func max(a, b int) int {
|
func max(a, b int) int {
|
||||||
if a > b {
|
if a > b {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
return b;
|
return b
|
||||||
}
|
}
|
||||||
|
@ -5,23 +5,23 @@
|
|||||||
package strconv_test
|
package strconv_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math";
|
"math"
|
||||||
. "strconv";
|
. "strconv"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ftoaTest struct {
|
type ftoaTest struct {
|
||||||
f float64;
|
f float64
|
||||||
fmt byte;
|
fmt byte
|
||||||
prec int;
|
prec int
|
||||||
s string;
|
s string
|
||||||
}
|
}
|
||||||
|
|
||||||
func fdiv(a, b float64) float64 { return a / b } // keep compiler in the dark
|
func fdiv(a, b float64) float64 { return a / b } // keep compiler in the dark
|
||||||
|
|
||||||
const (
|
const (
|
||||||
below1e23 = 99999999999999974834176;
|
below1e23 = 99999999999999974834176
|
||||||
above1e23 = 100000000000000008388608;
|
above1e23 = 100000000000000008388608
|
||||||
)
|
)
|
||||||
|
|
||||||
var ftoatests = []ftoaTest{
|
var ftoatests = []ftoaTest{
|
||||||
@ -104,13 +104,13 @@ func TestFtoa(t *testing.T) {
|
|||||||
panic("floatsize: ", FloatSize)
|
panic("floatsize: ", FloatSize)
|
||||||
}
|
}
|
||||||
for i := 0; i < len(ftoatests); i++ {
|
for i := 0; i < len(ftoatests); i++ {
|
||||||
test := &ftoatests[i];
|
test := &ftoatests[i]
|
||||||
s := Ftoa64(test.f, test.fmt, test.prec);
|
s := Ftoa64(test.f, test.fmt, test.prec)
|
||||||
if s != test.s {
|
if s != test.s {
|
||||||
t.Error("test", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
|
t.Error("test", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
|
||||||
}
|
}
|
||||||
if float64(float32(test.f)) == test.f && test.fmt != 'b' {
|
if float64(float32(test.f)) == test.f && test.fmt != 'b' {
|
||||||
s := Ftoa32(float32(test.f), test.fmt, test.prec);
|
s := Ftoa32(float32(test.f), test.fmt, test.prec)
|
||||||
if s != test.s {
|
if s != test.s {
|
||||||
t.Error("test32", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
|
t.Error("test32", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ package strconv
|
|||||||
func NewDecimal(i uint64) *decimal { return newDecimal(i) }
|
func NewDecimal(i uint64) *decimal { return newDecimal(i) }
|
||||||
|
|
||||||
func SetOptimize(b bool) bool {
|
func SetOptimize(b bool) bool {
|
||||||
old := optimize;
|
old := optimize
|
||||||
optimize = b;
|
optimize = b
|
||||||
return old;
|
return old
|
||||||
}
|
}
|
||||||
|
@ -11,16 +11,16 @@ func Uitob64(u uint64, base uint) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Assemble decimal in reverse order.
|
// Assemble decimal in reverse order.
|
||||||
var buf [32]byte;
|
var buf [32]byte
|
||||||
j := len(buf);
|
j := len(buf)
|
||||||
b := uint64(base);
|
b := uint64(base)
|
||||||
for u > 0 {
|
for u > 0 {
|
||||||
j--;
|
j--
|
||||||
buf[j] = "0123456789abcdefghijklmnopqrstuvwxyz"[u%b];
|
buf[j] = "0123456789abcdefghijklmnopqrstuvwxyz"[u%b]
|
||||||
u /= b;
|
u /= b
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(buf[j:]);
|
return string(buf[j:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Itob64 returns the string representation of i in the given base.
|
// Itob64 returns the string representation of i in the given base.
|
||||||
@ -32,7 +32,7 @@ func Itob64(i int64, base uint) string {
|
|||||||
if i < 0 {
|
if i < 0 {
|
||||||
return "-" + Uitob64(-uint64(i), base)
|
return "-" + Uitob64(-uint64(i), base)
|
||||||
}
|
}
|
||||||
return Uitob64(uint64(i), base);
|
return Uitob64(uint64(i), base)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Itoa64 returns the decimal string representation of i.
|
// Itoa64 returns the decimal string representation of i.
|
||||||
|
@ -5,14 +5,14 @@
|
|||||||
package strconv_test
|
package strconv_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "strconv";
|
. "strconv"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type itob64Test struct {
|
type itob64Test struct {
|
||||||
in int64;
|
in int64
|
||||||
base uint;
|
base uint
|
||||||
out string;
|
out string
|
||||||
}
|
}
|
||||||
|
|
||||||
var itob64tests = []itob64Test{
|
var itob64tests = []itob64Test{
|
||||||
@ -59,14 +59,14 @@ var itob64tests = []itob64Test{
|
|||||||
|
|
||||||
func TestItoa(t *testing.T) {
|
func TestItoa(t *testing.T) {
|
||||||
for _, test := range itob64tests {
|
for _, test := range itob64tests {
|
||||||
s := Itob64(test.in, test.base);
|
s := Itob64(test.in, test.base)
|
||||||
if s != test.out {
|
if s != test.out {
|
||||||
t.Errorf("Itob64(%v, %v) = %v want %v\n",
|
t.Errorf("Itob64(%v, %v) = %v want %v\n",
|
||||||
test.in, test.base, s, test.out)
|
test.in, test.base, s, test.out)
|
||||||
}
|
}
|
||||||
|
|
||||||
if test.in >= 0 {
|
if test.in >= 0 {
|
||||||
s := Uitob64(uint64(test.in), test.base);
|
s := Uitob64(uint64(test.in), test.base)
|
||||||
if s != test.out {
|
if s != test.out {
|
||||||
t.Errorf("Uitob64(%v, %v) = %v want %v\n",
|
t.Errorf("Uitob64(%v, %v) = %v want %v\n",
|
||||||
test.in, test.base, s, test.out)
|
test.in, test.base, s, test.out)
|
||||||
@ -74,14 +74,14 @@ func TestItoa(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if int64(int(test.in)) == test.in {
|
if int64(int(test.in)) == test.in {
|
||||||
s := Itob(int(test.in), test.base);
|
s := Itob(int(test.in), test.base)
|
||||||
if s != test.out {
|
if s != test.out {
|
||||||
t.Errorf("Itob(%v, %v) = %v want %v\n",
|
t.Errorf("Itob(%v, %v) = %v want %v\n",
|
||||||
test.in, test.base, s, test.out)
|
test.in, test.base, s, test.out)
|
||||||
}
|
}
|
||||||
|
|
||||||
if test.in >= 0 {
|
if test.in >= 0 {
|
||||||
s := Uitob(uint(test.in), test.base);
|
s := Uitob(uint(test.in), test.base)
|
||||||
if s != test.out {
|
if s != test.out {
|
||||||
t.Errorf("Uitob(%v, %v) = %v want %v\n",
|
t.Errorf("Uitob(%v, %v) = %v want %v\n",
|
||||||
test.in, test.base, s, test.out)
|
test.in, test.base, s, test.out)
|
||||||
@ -90,14 +90,14 @@ func TestItoa(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if test.base == 10 {
|
if test.base == 10 {
|
||||||
s := Itoa64(test.in);
|
s := Itoa64(test.in)
|
||||||
if s != test.out {
|
if s != test.out {
|
||||||
t.Errorf("Itoa64(%v) = %v want %v\n",
|
t.Errorf("Itoa64(%v) = %v want %v\n",
|
||||||
test.in, s, test.out)
|
test.in, s, test.out)
|
||||||
}
|
}
|
||||||
|
|
||||||
if test.in >= 0 {
|
if test.in >= 0 {
|
||||||
s := Uitob64(uint64(test.in), test.base);
|
s := Uitob64(uint64(test.in), test.base)
|
||||||
if s != test.out {
|
if s != test.out {
|
||||||
t.Errorf("Uitob64(%v, %v) = %v want %v\n",
|
t.Errorf("Uitob64(%v, %v) = %v want %v\n",
|
||||||
test.in, test.base, s, test.out)
|
test.in, test.base, s, test.out)
|
||||||
@ -105,14 +105,14 @@ func TestItoa(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if int64(int(test.in)) == test.in {
|
if int64(int(test.in)) == test.in {
|
||||||
s := Itoa(int(test.in));
|
s := Itoa(int(test.in))
|
||||||
if s != test.out {
|
if s != test.out {
|
||||||
t.Errorf("Itoa(%v) = %v want %v\n",
|
t.Errorf("Itoa(%v) = %v want %v\n",
|
||||||
test.in, s, test.out)
|
test.in, s, test.out)
|
||||||
}
|
}
|
||||||
|
|
||||||
if test.in >= 0 {
|
if test.in >= 0 {
|
||||||
s := Uitoa(uint(test.in));
|
s := Uitoa(uint(test.in))
|
||||||
if s != test.out {
|
if s != test.out {
|
||||||
t.Errorf("Uitoa(%v) = %v want %v\n",
|
t.Errorf("Uitoa(%v) = %v want %v\n",
|
||||||
test.in, s, test.out)
|
test.in, s, test.out)
|
||||||
@ -124,9 +124,9 @@ func TestItoa(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type uitob64Test struct {
|
type uitob64Test struct {
|
||||||
in uint64;
|
in uint64
|
||||||
base uint;
|
base uint
|
||||||
out string;
|
out string
|
||||||
}
|
}
|
||||||
|
|
||||||
var uitob64tests = []uitob64Test{
|
var uitob64tests = []uitob64Test{
|
||||||
@ -139,14 +139,14 @@ var uitob64tests = []uitob64Test{
|
|||||||
|
|
||||||
func TestUitoa(t *testing.T) {
|
func TestUitoa(t *testing.T) {
|
||||||
for _, test := range uitob64tests {
|
for _, test := range uitob64tests {
|
||||||
s := Uitob64(test.in, test.base);
|
s := Uitob64(test.in, test.base)
|
||||||
if s != test.out {
|
if s != test.out {
|
||||||
t.Errorf("Uitob64(%v, %v) = %v want %v\n",
|
t.Errorf("Uitob64(%v, %v) = %v want %v\n",
|
||||||
test.in, test.base, s, test.out)
|
test.in, test.base, s, test.out)
|
||||||
}
|
}
|
||||||
|
|
||||||
if uint64(uint(test.in)) == test.in {
|
if uint64(uint(test.in)) == test.in {
|
||||||
s := Uitob(uint(test.in), test.base);
|
s := Uitob(uint(test.in), test.base)
|
||||||
if s != test.out {
|
if s != test.out {
|
||||||
t.Errorf("Uitob(%v, %v) = %v want %v\n",
|
t.Errorf("Uitob(%v, %v) = %v want %v\n",
|
||||||
test.in, test.base, s, test.out)
|
test.in, test.base, s, test.out)
|
||||||
@ -154,14 +154,14 @@ func TestUitoa(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if test.base == 10 {
|
if test.base == 10 {
|
||||||
s := Uitoa64(test.in);
|
s := Uitoa64(test.in)
|
||||||
if s != test.out {
|
if s != test.out {
|
||||||
t.Errorf("Uitoa64(%v) = %v want %v\n",
|
t.Errorf("Uitoa64(%v) = %v want %v\n",
|
||||||
test.in, s, test.out)
|
test.in, s, test.out)
|
||||||
}
|
}
|
||||||
|
|
||||||
if uint64(uint(test.in)) == test.in {
|
if uint64(uint(test.in)) == test.in {
|
||||||
s := Uitoa(uint(test.in));
|
s := Uitoa(uint(test.in))
|
||||||
if s != test.out {
|
if s != test.out {
|
||||||
t.Errorf("Uitoa(%v) = %v want %v\n",
|
t.Errorf("Uitoa(%v) = %v want %v\n",
|
||||||
test.in, s, test.out)
|
test.in, s, test.out)
|
||||||
|
@ -5,11 +5,11 @@
|
|||||||
package strconv
|
package strconv
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes";
|
"bytes"
|
||||||
"os";
|
"os"
|
||||||
"strings";
|
"strings"
|
||||||
"unicode";
|
"unicode"
|
||||||
"utf8";
|
"utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
const lowerhex = "0123456789abcdef"
|
const lowerhex = "0123456789abcdef"
|
||||||
@ -19,8 +19,8 @@ const lowerhex = "0123456789abcdef"
|
|||||||
// sequences (\t, \n, \xFF, \u0100) for control characters
|
// sequences (\t, \n, \xFF, \u0100) for control characters
|
||||||
// and non-ASCII characters.
|
// and non-ASCII characters.
|
||||||
func Quote(s string) string {
|
func Quote(s string) string {
|
||||||
var buf bytes.Buffer;
|
var buf bytes.Buffer
|
||||||
buf.WriteByte('"');
|
buf.WriteByte('"')
|
||||||
for ; len(s) > 0; s = s[1:] {
|
for ; len(s) > 0; s = s[1:] {
|
||||||
switch c := s[0]; {
|
switch c := s[0]; {
|
||||||
case c == '"':
|
case c == '"':
|
||||||
@ -45,18 +45,18 @@ func Quote(s string) string {
|
|||||||
buf.WriteString(`\v`)
|
buf.WriteString(`\v`)
|
||||||
|
|
||||||
case c >= utf8.RuneSelf && utf8.FullRuneInString(s):
|
case c >= utf8.RuneSelf && utf8.FullRuneInString(s):
|
||||||
r, size := utf8.DecodeRuneInString(s);
|
r, size := utf8.DecodeRuneInString(s)
|
||||||
if r == utf8.RuneError && size == 1 {
|
if r == utf8.RuneError && size == 1 {
|
||||||
goto EscX
|
goto EscX
|
||||||
}
|
}
|
||||||
s = s[size-1:]; // next iteration will slice off 1 more
|
s = s[size-1:] // next iteration will slice off 1 more
|
||||||
if r < 0x10000 {
|
if r < 0x10000 {
|
||||||
buf.WriteString(`\u`);
|
buf.WriteString(`\u`)
|
||||||
for j := uint(0); j < 4; j++ {
|
for j := uint(0); j < 4; j++ {
|
||||||
buf.WriteByte(lowerhex[(r>>(12-4*j))&0xF])
|
buf.WriteByte(lowerhex[(r>>(12-4*j))&0xF])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buf.WriteString(`\U`);
|
buf.WriteString(`\U`)
|
||||||
for j := uint(0); j < 8; j++ {
|
for j := uint(0); j < 8; j++ {
|
||||||
buf.WriteByte(lowerhex[(r>>(28-4*j))&0xF])
|
buf.WriteByte(lowerhex[(r>>(28-4*j))&0xF])
|
||||||
}
|
}
|
||||||
@ -64,13 +64,13 @@ func Quote(s string) string {
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
EscX:
|
EscX:
|
||||||
buf.WriteString(`\x`);
|
buf.WriteString(`\x`)
|
||||||
buf.WriteByte(lowerhex[c>>4]);
|
buf.WriteByte(lowerhex[c>>4])
|
||||||
buf.WriteByte(lowerhex[c&0xF]);
|
buf.WriteByte(lowerhex[c&0xF])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buf.WriteByte('"');
|
buf.WriteByte('"')
|
||||||
return buf.String();
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanBackquote returns whether the string s would be
|
// CanBackquote returns whether the string s would be
|
||||||
@ -81,11 +81,11 @@ func CanBackquote(s string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func unhex(b byte) (v int, ok bool) {
|
func unhex(b byte) (v int, ok bool) {
|
||||||
c := int(b);
|
c := int(b)
|
||||||
switch {
|
switch {
|
||||||
case '0' <= c && c <= '9':
|
case '0' <= c && c <= '9':
|
||||||
return c - '0', true
|
return c - '0', true
|
||||||
@ -94,7 +94,7 @@ func unhex(b byte) (v int, ok bool) {
|
|||||||
case 'A' <= c && c <= 'F':
|
case 'A' <= c && c <= 'F':
|
||||||
return c - 'A' + 10, true
|
return c - 'A' + 10, true
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnquoteChar decodes the first character or byte in the escaped string
|
// UnquoteChar decodes the first character or byte in the escaped string
|
||||||
@ -114,22 +114,22 @@ func UnquoteChar(s string, quote byte) (value int, multibyte bool, tail string,
|
|||||||
// easy cases
|
// easy cases
|
||||||
switch c := s[0]; {
|
switch c := s[0]; {
|
||||||
case c == quote && (quote == '\'' || quote == '"'):
|
case c == quote && (quote == '\'' || quote == '"'):
|
||||||
err = os.EINVAL;
|
err = os.EINVAL
|
||||||
return;
|
return
|
||||||
case c >= utf8.RuneSelf:
|
case c >= utf8.RuneSelf:
|
||||||
r, size := utf8.DecodeRuneInString(s);
|
r, size := utf8.DecodeRuneInString(s)
|
||||||
return r, true, s[size:], nil;
|
return r, true, s[size:], nil
|
||||||
case c != '\\':
|
case c != '\\':
|
||||||
return int(s[0]), false, s[1:], nil
|
return int(s[0]), false, s[1:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// hard case: c is backslash
|
// hard case: c is backslash
|
||||||
if len(s) <= 1 {
|
if len(s) <= 1 {
|
||||||
err = os.EINVAL;
|
err = os.EINVAL
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
c := s[1];
|
c := s[1]
|
||||||
s = s[2:];
|
s = s[2:]
|
||||||
|
|
||||||
switch c {
|
switch c {
|
||||||
case 'a':
|
case 'a':
|
||||||
@ -147,7 +147,7 @@ func UnquoteChar(s string, quote byte) (value int, multibyte bool, tail string,
|
|||||||
case 'v':
|
case 'v':
|
||||||
value = '\v'
|
value = '\v'
|
||||||
case 'x', 'u', 'U':
|
case 'x', 'u', 'U':
|
||||||
n := 0;
|
n := 0
|
||||||
switch c {
|
switch c {
|
||||||
case 'x':
|
case 'x':
|
||||||
n = 2
|
n = 2
|
||||||
@ -156,64 +156,64 @@ func UnquoteChar(s string, quote byte) (value int, multibyte bool, tail string,
|
|||||||
case 'U':
|
case 'U':
|
||||||
n = 8
|
n = 8
|
||||||
}
|
}
|
||||||
v := 0;
|
v := 0
|
||||||
if len(s) < n {
|
if len(s) < n {
|
||||||
err = os.EINVAL;
|
err = os.EINVAL
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
for j := 0; j < n; j++ {
|
for j := 0; j < n; j++ {
|
||||||
x, ok := unhex(s[j]);
|
x, ok := unhex(s[j])
|
||||||
if !ok {
|
if !ok {
|
||||||
err = os.EINVAL;
|
err = os.EINVAL
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
v = v<<4 | x;
|
v = v<<4 | x
|
||||||
}
|
}
|
||||||
s = s[n:];
|
s = s[n:]
|
||||||
if c == 'x' {
|
if c == 'x' {
|
||||||
// single-byte string, possibly not UTF-8
|
// single-byte string, possibly not UTF-8
|
||||||
value = v;
|
value = v
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
if v > unicode.MaxRune {
|
if v > unicode.MaxRune {
|
||||||
err = os.EINVAL;
|
err = os.EINVAL
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
value = v;
|
value = v
|
||||||
multibyte = true;
|
multibyte = true
|
||||||
case '0', '1', '2', '3', '4', '5', '6', '7':
|
case '0', '1', '2', '3', '4', '5', '6', '7':
|
||||||
v := int(c) - '0';
|
v := int(c) - '0'
|
||||||
if len(s) < 2 {
|
if len(s) < 2 {
|
||||||
err = os.EINVAL;
|
err = os.EINVAL
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
for j := 0; j < 2; j++ { // one digit already; two more
|
for j := 0; j < 2; j++ { // one digit already; two more
|
||||||
x := int(s[j]) - '0';
|
x := int(s[j]) - '0'
|
||||||
if x < 0 || x > 7 {
|
if x < 0 || x > 7 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
v = (v << 3) | x;
|
v = (v << 3) | x
|
||||||
}
|
}
|
||||||
s = s[2:];
|
s = s[2:]
|
||||||
if v > 255 {
|
if v > 255 {
|
||||||
err = os.EINVAL;
|
err = os.EINVAL
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
value = v;
|
value = v
|
||||||
case '\\':
|
case '\\':
|
||||||
value = '\\'
|
value = '\\'
|
||||||
case '\'', '"':
|
case '\'', '"':
|
||||||
if c != quote {
|
if c != quote {
|
||||||
err = os.EINVAL;
|
err = os.EINVAL
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
value = int(c);
|
value = int(c)
|
||||||
default:
|
default:
|
||||||
err = os.EINVAL;
|
err = os.EINVAL
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
tail = s;
|
tail = s
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unquote interprets s as a single-quoted, double-quoted,
|
// Unquote interprets s as a single-quoted, double-quoted,
|
||||||
@ -222,33 +222,33 @@ func UnquoteChar(s string, quote byte) (value int, multibyte bool, tail string,
|
|||||||
// character literal; Unquote returns the corresponding
|
// character literal; Unquote returns the corresponding
|
||||||
// one-character string.)
|
// one-character string.)
|
||||||
func Unquote(s string) (t string, err os.Error) {
|
func Unquote(s string) (t string, err os.Error) {
|
||||||
n := len(s);
|
n := len(s)
|
||||||
if n < 2 {
|
if n < 2 {
|
||||||
return "", os.EINVAL
|
return "", os.EINVAL
|
||||||
}
|
}
|
||||||
quote := s[0];
|
quote := s[0]
|
||||||
if quote != s[n-1] {
|
if quote != s[n-1] {
|
||||||
return "", os.EINVAL
|
return "", os.EINVAL
|
||||||
}
|
}
|
||||||
s = s[1 : n-1];
|
s = s[1 : n-1]
|
||||||
|
|
||||||
if quote == '`' {
|
if quote == '`' {
|
||||||
if strings.Index(s, "`") >= 0 {
|
if strings.Index(s, "`") >= 0 {
|
||||||
return "", os.EINVAL
|
return "", os.EINVAL
|
||||||
}
|
}
|
||||||
return s, nil;
|
return s, nil
|
||||||
}
|
}
|
||||||
if quote != '"' && quote != '\'' {
|
if quote != '"' && quote != '\'' {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer;
|
var buf bytes.Buffer
|
||||||
for len(s) > 0 {
|
for len(s) > 0 {
|
||||||
c, multibyte, ss, err := UnquoteChar(s, quote);
|
c, multibyte, ss, err := UnquoteChar(s, quote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
s = ss;
|
s = ss
|
||||||
if c < utf8.RuneSelf || !multibyte {
|
if c < utf8.RuneSelf || !multibyte {
|
||||||
buf.WriteByte(byte(c))
|
buf.WriteByte(byte(c))
|
||||||
} else {
|
} else {
|
||||||
@ -259,5 +259,5 @@ func Unquote(s string) (t string, err os.Error) {
|
|||||||
return "", os.EINVAL
|
return "", os.EINVAL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return buf.String(), nil;
|
return buf.String(), nil
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,14 @@
|
|||||||
package strconv_test
|
package strconv_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os";
|
"os"
|
||||||
. "strconv";
|
. "strconv"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type quoteTest struct {
|
type quoteTest struct {
|
||||||
in string;
|
in string
|
||||||
out string;
|
out string
|
||||||
}
|
}
|
||||||
|
|
||||||
var quotetests = []quoteTest{
|
var quotetests = []quoteTest{
|
||||||
@ -26,7 +26,7 @@ var quotetests = []quoteTest{
|
|||||||
|
|
||||||
func TestQuote(t *testing.T) {
|
func TestQuote(t *testing.T) {
|
||||||
for i := 0; i < len(quotetests); i++ {
|
for i := 0; i < len(quotetests); i++ {
|
||||||
tt := quotetests[i];
|
tt := quotetests[i]
|
||||||
if out := Quote(tt.in); out != tt.out {
|
if out := Quote(tt.in); out != tt.out {
|
||||||
t.Errorf("Quote(%s) = %s, want %s", tt.in, out, tt.out)
|
t.Errorf("Quote(%s) = %s, want %s", tt.in, out, tt.out)
|
||||||
}
|
}
|
||||||
@ -34,8 +34,8 @@ func TestQuote(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type canBackquoteTest struct {
|
type canBackquoteTest struct {
|
||||||
in string;
|
in string
|
||||||
out bool;
|
out bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var canbackquotetests = []canBackquoteTest{
|
var canbackquotetests = []canBackquoteTest{
|
||||||
@ -81,7 +81,7 @@ var canbackquotetests = []canBackquoteTest{
|
|||||||
|
|
||||||
func TestCanBackquote(t *testing.T) {
|
func TestCanBackquote(t *testing.T) {
|
||||||
for i := 0; i < len(canbackquotetests); i++ {
|
for i := 0; i < len(canbackquotetests); i++ {
|
||||||
tt := canbackquotetests[i];
|
tt := canbackquotetests[i]
|
||||||
if out := CanBackquote(tt.in); out != tt.out {
|
if out := CanBackquote(tt.in); out != tt.out {
|
||||||
t.Errorf("CanBackquote(%q) = %v, want %v", tt.in, out, tt.out)
|
t.Errorf("CanBackquote(%q) = %v, want %v", tt.in, out, tt.out)
|
||||||
}
|
}
|
||||||
@ -147,7 +147,7 @@ var misquoted = []string{
|
|||||||
|
|
||||||
func TestUnquote(t *testing.T) {
|
func TestUnquote(t *testing.T) {
|
||||||
for i := 0; i < len(unquotetests); i++ {
|
for i := 0; i < len(unquotetests); i++ {
|
||||||
tt := unquotetests[i];
|
tt := unquotetests[i]
|
||||||
if out, err := Unquote(tt.in); err != nil && out != tt.out {
|
if out, err := Unquote(tt.in); err != nil && out != tt.out {
|
||||||
t.Errorf("Unquote(%#q) = %q, %v want %q, nil", tt.in, out, err, tt.out)
|
t.Errorf("Unquote(%#q) = %q, %v want %q, nil", tt.in, out, err, tt.out)
|
||||||
}
|
}
|
||||||
@ -155,14 +155,14 @@ func TestUnquote(t *testing.T) {
|
|||||||
|
|
||||||
// run the quote tests too, backward
|
// run the quote tests too, backward
|
||||||
for i := 0; i < len(quotetests); i++ {
|
for i := 0; i < len(quotetests); i++ {
|
||||||
tt := quotetests[i];
|
tt := quotetests[i]
|
||||||
if in, err := Unquote(tt.out); in != tt.in {
|
if in, err := Unquote(tt.out); in != tt.in {
|
||||||
t.Errorf("Unquote(%#q) = %q, %v, want %q, nil", tt.out, in, err, tt.in)
|
t.Errorf("Unquote(%#q) = %q, %v, want %q, nil", tt.out, in, err, tt.in)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(misquoted); i++ {
|
for i := 0; i < len(misquoted); i++ {
|
||||||
s := misquoted[i];
|
s := misquoted[i]
|
||||||
if out, err := Unquote(s); out != "" || err != os.EINVAL {
|
if out, err := Unquote(s); out != "" || err != os.EINVAL {
|
||||||
t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", os.EINVAL)
|
t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", os.EINVAL)
|
||||||
}
|
}
|
||||||
|
@ -11,26 +11,26 @@ import "os"
|
|||||||
type Reader string
|
type Reader string
|
||||||
|
|
||||||
func (r *Reader) Read(b []byte) (n int, err os.Error) {
|
func (r *Reader) Read(b []byte) (n int, err os.Error) {
|
||||||
s := *r;
|
s := *r
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
return 0, os.EOF
|
return 0, os.EOF
|
||||||
}
|
}
|
||||||
for n < len(s) && n < len(b) {
|
for n < len(s) && n < len(b) {
|
||||||
b[n] = s[n];
|
b[n] = s[n]
|
||||||
n++;
|
n++
|
||||||
}
|
}
|
||||||
*r = s[n:];
|
*r = s[n:]
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) ReadByte() (b byte, err os.Error) {
|
func (r *Reader) ReadByte() (b byte, err os.Error) {
|
||||||
s := *r;
|
s := *r
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
return 0, os.EOF
|
return 0, os.EOF
|
||||||
}
|
}
|
||||||
b = s[0];
|
b = s[0]
|
||||||
*r = s[1:];
|
*r = s[1:]
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewReader returns a new Reader reading from s.
|
// NewReader returns a new Reader reading from s.
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
package strings
|
package strings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"unicode";
|
"unicode"
|
||||||
"utf8";
|
"utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
// explode splits s into an array of UTF-8 sequences, one per Unicode character (still strings) up to a maximum of n (n <= 0 means no limit).
|
// explode splits s into an array of UTF-8 sequences, one per Unicode character (still strings) up to a maximum of n (n <= 0 means no limit).
|
||||||
@ -16,21 +16,21 @@ func explode(s string, n int) []string {
|
|||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
n = len(s)
|
n = len(s)
|
||||||
}
|
}
|
||||||
a := make([]string, n);
|
a := make([]string, n)
|
||||||
var size, rune int;
|
var size, rune int
|
||||||
na := 0;
|
na := 0
|
||||||
for len(s) > 0 {
|
for len(s) > 0 {
|
||||||
if na+1 >= n {
|
if na+1 >= n {
|
||||||
a[na] = s;
|
a[na] = s
|
||||||
na++;
|
na++
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
rune, size = utf8.DecodeRuneInString(s);
|
rune, size = utf8.DecodeRuneInString(s)
|
||||||
s = s[size:];
|
s = s[size:]
|
||||||
a[na] = string(rune);
|
a[na] = string(rune)
|
||||||
na++;
|
na++
|
||||||
}
|
}
|
||||||
return a[0:na];
|
return a[0:na]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count counts the number of non-overlapping instances of sep in s.
|
// Count counts the number of non-overlapping instances of sep in s.
|
||||||
@ -38,24 +38,24 @@ func Count(s, sep string) int {
|
|||||||
if sep == "" {
|
if sep == "" {
|
||||||
return utf8.RuneCountInString(s) + 1
|
return utf8.RuneCountInString(s) + 1
|
||||||
}
|
}
|
||||||
c := sep[0];
|
c := sep[0]
|
||||||
n := 0;
|
n := 0
|
||||||
for i := 0; i+len(sep) <= len(s); i++ {
|
for i := 0; i+len(sep) <= len(s); i++ {
|
||||||
if s[i] == c && (len(sep) == 1 || s[i:i+len(sep)] == sep) {
|
if s[i] == c && (len(sep) == 1 || s[i:i+len(sep)] == sep) {
|
||||||
n++;
|
n++
|
||||||
i += len(sep) - 1;
|
i += len(sep) - 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return n;
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
|
// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
|
||||||
func Index(s, sep string) int {
|
func Index(s, sep string) int {
|
||||||
n := len(sep);
|
n := len(sep)
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
c := sep[0];
|
c := sep[0]
|
||||||
if n == 1 {
|
if n == 1 {
|
||||||
// special case worth making fast
|
// special case worth making fast
|
||||||
for i := 0; i < len(s); i++ {
|
for i := 0; i < len(s); i++ {
|
||||||
@ -63,23 +63,23 @@ func Index(s, sep string) int {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1
|
||||||
}
|
}
|
||||||
for i := 0; i+n <= len(s); i++ {
|
for i := 0; i+n <= len(s); i++ {
|
||||||
if s[i] == c && (n == 1 || s[i:i+n] == sep) {
|
if s[i] == c && (n == 1 || s[i:i+n] == sep) {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// LastIndex returns the index of the last instance of sep in s, or -1 if sep is not present in s.
|
// LastIndex returns the index of the last instance of sep in s, or -1 if sep is not present in s.
|
||||||
func LastIndex(s, sep string) int {
|
func LastIndex(s, sep string) int {
|
||||||
n := len(sep);
|
n := len(sep)
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return len(s)
|
return len(s)
|
||||||
}
|
}
|
||||||
c := sep[0];
|
c := sep[0]
|
||||||
if n == 1 {
|
if n == 1 {
|
||||||
// special case worth making fast
|
// special case worth making fast
|
||||||
for i := len(s) - 1; i >= 0; i-- {
|
for i := len(s) - 1; i >= 0; i-- {
|
||||||
@ -87,14 +87,14 @@ func LastIndex(s, sep string) int {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1
|
||||||
}
|
}
|
||||||
for i := len(s) - n; i >= 0; i-- {
|
for i := len(s) - n; i >= 0; i-- {
|
||||||
if s[i] == c && (n == 1 || s[i:i+n] == sep) {
|
if s[i] == c && (n == 1 || s[i:i+n] == sep) {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic split: splits after each instance of sep,
|
// Generic split: splits after each instance of sep,
|
||||||
@ -106,20 +106,20 @@ func genSplit(s, sep string, sepSave, n int) []string {
|
|||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
n = Count(s, sep) + 1
|
n = Count(s, sep) + 1
|
||||||
}
|
}
|
||||||
c := sep[0];
|
c := sep[0]
|
||||||
start := 0;
|
start := 0
|
||||||
a := make([]string, n);
|
a := make([]string, n)
|
||||||
na := 0;
|
na := 0
|
||||||
for i := 0; i+len(sep) <= len(s) && na+1 < n; i++ {
|
for i := 0; i+len(sep) <= len(s) && na+1 < n; i++ {
|
||||||
if s[i] == c && (len(sep) == 1 || s[i:i+len(sep)] == sep) {
|
if s[i] == c && (len(sep) == 1 || s[i:i+len(sep)] == sep) {
|
||||||
a[na] = s[start : i+sepSave];
|
a[na] = s[start : i+sepSave]
|
||||||
na++;
|
na++
|
||||||
start = i + len(sep);
|
start = i + len(sep)
|
||||||
i += len(sep) - 1;
|
i += len(sep) - 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a[na] = s[start:];
|
a[na] = s[start:]
|
||||||
return a[0 : na+1];
|
return a[0 : na+1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split splits the string s around each instance of sep, returning an array of substrings of s.
|
// Split splits the string s around each instance of sep, returning an array of substrings of s.
|
||||||
@ -143,28 +143,28 @@ func Join(a []string, sep string) string {
|
|||||||
if len(a) == 1 {
|
if len(a) == 1 {
|
||||||
return a[0]
|
return a[0]
|
||||||
}
|
}
|
||||||
n := len(sep) * (len(a) - 1);
|
n := len(sep) * (len(a) - 1)
|
||||||
for i := 0; i < len(a); i++ {
|
for i := 0; i < len(a); i++ {
|
||||||
n += len(a[i])
|
n += len(a[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
b := make([]byte, n);
|
b := make([]byte, n)
|
||||||
bp := 0;
|
bp := 0
|
||||||
for i := 0; i < len(a); i++ {
|
for i := 0; i < len(a); i++ {
|
||||||
s := a[i];
|
s := a[i]
|
||||||
for j := 0; j < len(s); j++ {
|
for j := 0; j < len(s); j++ {
|
||||||
b[bp] = s[j];
|
b[bp] = s[j]
|
||||||
bp++;
|
bp++
|
||||||
}
|
}
|
||||||
if i+1 < len(a) {
|
if i+1 < len(a) {
|
||||||
s = sep;
|
s = sep
|
||||||
for j := 0; j < len(s); j++ {
|
for j := 0; j < len(s); j++ {
|
||||||
b[bp] = s[j];
|
b[bp] = s[j]
|
||||||
bp++;
|
bp++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return string(b);
|
return string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasPrefix tests whether the string s begins with prefix.
|
// HasPrefix tests whether the string s begins with prefix.
|
||||||
@ -184,42 +184,42 @@ func Map(mapping func(rune int) int, s string) string {
|
|||||||
// In the worst case, the string can grow when mapped, making
|
// In the worst case, the string can grow when mapped, making
|
||||||
// things unpleasant. But it's so rare we barge in assuming it's
|
// things unpleasant. But it's so rare we barge in assuming it's
|
||||||
// fine. It could also shrink but that falls out naturally.
|
// fine. It could also shrink but that falls out naturally.
|
||||||
maxbytes := len(s); // length of b
|
maxbytes := len(s) // length of b
|
||||||
nbytes := 0; // number of bytes encoded in b
|
nbytes := 0 // number of bytes encoded in b
|
||||||
b := make([]byte, maxbytes);
|
b := make([]byte, maxbytes)
|
||||||
for _, c := range s {
|
for _, c := range s {
|
||||||
rune := mapping(c);
|
rune := mapping(c)
|
||||||
if rune >= 0 {
|
if rune >= 0 {
|
||||||
wid := 1;
|
wid := 1
|
||||||
if rune >= utf8.RuneSelf {
|
if rune >= utf8.RuneSelf {
|
||||||
wid = utf8.RuneLen(rune)
|
wid = utf8.RuneLen(rune)
|
||||||
}
|
}
|
||||||
if nbytes+wid > maxbytes {
|
if nbytes+wid > maxbytes {
|
||||||
// Grow the buffer.
|
// Grow the buffer.
|
||||||
maxbytes = maxbytes*2 + utf8.UTFMax;
|
maxbytes = maxbytes*2 + utf8.UTFMax
|
||||||
nb := make([]byte, maxbytes);
|
nb := make([]byte, maxbytes)
|
||||||
for i, c := range b[0:nbytes] {
|
for i, c := range b[0:nbytes] {
|
||||||
nb[i] = c
|
nb[i] = c
|
||||||
}
|
}
|
||||||
b = nb;
|
b = nb
|
||||||
}
|
}
|
||||||
nbytes += utf8.EncodeRune(rune, b[nbytes:maxbytes]);
|
nbytes += utf8.EncodeRune(rune, b[nbytes:maxbytes])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return string(b[0:nbytes]);
|
return string(b[0:nbytes])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repeat returns a new string consisting of count copies of the string s.
|
// Repeat returns a new string consisting of count copies of the string s.
|
||||||
func Repeat(s string, count int) string {
|
func Repeat(s string, count int) string {
|
||||||
b := make([]byte, len(s)*count);
|
b := make([]byte, len(s)*count)
|
||||||
bp := 0;
|
bp := 0
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
for j := 0; j < len(s); j++ {
|
for j := 0; j < len(s); j++ {
|
||||||
b[bp] = s[j];
|
b[bp] = s[j]
|
||||||
bp++;
|
bp++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return string(b);
|
return string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -235,21 +235,21 @@ func ToTitle(s string) string { return Map(unicode.ToTitle, s) }
|
|||||||
// Trim returns a slice of the string s, with all leading and trailing white space
|
// Trim returns a slice of the string s, with all leading and trailing white space
|
||||||
// removed, as defined by Unicode.
|
// removed, as defined by Unicode.
|
||||||
func TrimSpace(s string) string {
|
func TrimSpace(s string) string {
|
||||||
start, end := 0, len(s);
|
start, end := 0, len(s)
|
||||||
for start < end {
|
for start < end {
|
||||||
wid := 1;
|
wid := 1
|
||||||
rune := int(s[start]);
|
rune := int(s[start])
|
||||||
if rune >= utf8.RuneSelf {
|
if rune >= utf8.RuneSelf {
|
||||||
rune, wid = utf8.DecodeRuneInString(s[start:end])
|
rune, wid = utf8.DecodeRuneInString(s[start:end])
|
||||||
}
|
}
|
||||||
if !unicode.IsSpace(rune) {
|
if !unicode.IsSpace(rune) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
start += wid;
|
start += wid
|
||||||
}
|
}
|
||||||
for start < end {
|
for start < end {
|
||||||
wid := 1;
|
wid := 1
|
||||||
rune := int(s[end-1]);
|
rune := int(s[end-1])
|
||||||
if rune >= utf8.RuneSelf {
|
if rune >= utf8.RuneSelf {
|
||||||
// Back up carefully looking for beginning of rune. Mustn't pass start.
|
// Back up carefully looking for beginning of rune. Mustn't pass start.
|
||||||
for wid = 2; start <= end-wid && !utf8.RuneStart(s[end-wid]); wid++ {
|
for wid = 2; start <= end-wid && !utf8.RuneStart(s[end-wid]); wid++ {
|
||||||
@ -257,32 +257,32 @@ func TrimSpace(s string) string {
|
|||||||
if start > end-wid { // invalid UTF-8 sequence; stop processing
|
if start > end-wid { // invalid UTF-8 sequence; stop processing
|
||||||
return s[start:end]
|
return s[start:end]
|
||||||
}
|
}
|
||||||
rune, wid = utf8.DecodeRuneInString(s[end-wid : end]);
|
rune, wid = utf8.DecodeRuneInString(s[end-wid : end])
|
||||||
}
|
}
|
||||||
if !unicode.IsSpace(rune) {
|
if !unicode.IsSpace(rune) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
end -= wid;
|
end -= wid
|
||||||
}
|
}
|
||||||
return s[start:end];
|
return s[start:end]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytes returns a new slice containing the bytes in s.
|
// Bytes returns a new slice containing the bytes in s.
|
||||||
func Bytes(s string) []byte {
|
func Bytes(s string) []byte {
|
||||||
b := make([]byte, len(s));
|
b := make([]byte, len(s))
|
||||||
for i := 0; i < len(s); i++ {
|
for i := 0; i < len(s); i++ {
|
||||||
b[i] = s[i]
|
b[i] = s[i]
|
||||||
}
|
}
|
||||||
return b;
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Runes returns a slice of runes (Unicode code points) equivalent to the string s.
|
// Runes returns a slice of runes (Unicode code points) equivalent to the string s.
|
||||||
func Runes(s string) []int {
|
func Runes(s string) []int {
|
||||||
t := make([]int, utf8.RuneCountInString(s));
|
t := make([]int, utf8.RuneCountInString(s))
|
||||||
i := 0;
|
i := 0
|
||||||
for _, r := range s {
|
for _, r := range s {
|
||||||
t[i] = r;
|
t[i] = r
|
||||||
i++;
|
i++
|
||||||
}
|
}
|
||||||
return t;
|
return t
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
package strings_test
|
package strings_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "strings";
|
. "strings"
|
||||||
"testing";
|
"testing"
|
||||||
"unicode";
|
"unicode"
|
||||||
"utf8";
|
"utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
func eq(a, b []string) bool {
|
func eq(a, b []string) bool {
|
||||||
@ -20,7 +20,7 @@ func eq(a, b []string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
var abcd = "abcd"
|
var abcd = "abcd"
|
||||||
@ -29,9 +29,9 @@ var commas = "1,2,3,4"
|
|||||||
var dots = "1....2....3....4"
|
var dots = "1....2....3....4"
|
||||||
|
|
||||||
type IndexTest struct {
|
type IndexTest struct {
|
||||||
s string;
|
s string
|
||||||
sep string;
|
sep string
|
||||||
out int;
|
out int
|
||||||
}
|
}
|
||||||
|
|
||||||
var indexTests = []IndexTest{
|
var indexTests = []IndexTest{
|
||||||
@ -76,7 +76,7 @@ var lastIndexTests = []IndexTest{
|
|||||||
// in failure reports.
|
// in failure reports.
|
||||||
func runIndexTests(t *testing.T, f func(s, sep string) int, funcName string, testCases []IndexTest) {
|
func runIndexTests(t *testing.T, f func(s, sep string) int, funcName string, testCases []IndexTest) {
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
actual := f(test.s, test.sep);
|
actual := f(test.s, test.sep)
|
||||||
if actual != test.out {
|
if actual != test.out {
|
||||||
t.Errorf("%s(%q,%q) = %v; want %v", funcName, test.s, test.sep, actual, test.out)
|
t.Errorf("%s(%q,%q) = %v; want %v", funcName, test.s, test.sep, actual, test.out)
|
||||||
}
|
}
|
||||||
@ -89,9 +89,9 @@ func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", last
|
|||||||
|
|
||||||
|
|
||||||
type ExplodeTest struct {
|
type ExplodeTest struct {
|
||||||
s string;
|
s string
|
||||||
n int;
|
n int
|
||||||
a []string;
|
a []string
|
||||||
}
|
}
|
||||||
|
|
||||||
var explodetests = []ExplodeTest{
|
var explodetests = []ExplodeTest{
|
||||||
@ -102,12 +102,12 @@ var explodetests = []ExplodeTest{
|
|||||||
|
|
||||||
func TestExplode(t *testing.T) {
|
func TestExplode(t *testing.T) {
|
||||||
for _, tt := range explodetests {
|
for _, tt := range explodetests {
|
||||||
a := Split(tt.s, "", tt.n);
|
a := Split(tt.s, "", tt.n)
|
||||||
if !eq(a, tt.a) {
|
if !eq(a, tt.a) {
|
||||||
t.Errorf("explode(%q, %d) = %v; want %v", tt.s, tt.n, a, tt.a);
|
t.Errorf("explode(%q, %d) = %v; want %v", tt.s, tt.n, a, tt.a)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
s := Join(a, "");
|
s := Join(a, "")
|
||||||
if s != tt.s {
|
if s != tt.s {
|
||||||
t.Errorf(`Join(explode(%q, %d), "") = %q`, tt.s, tt.n, s)
|
t.Errorf(`Join(explode(%q, %d), "") = %q`, tt.s, tt.n, s)
|
||||||
}
|
}
|
||||||
@ -115,10 +115,10 @@ func TestExplode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SplitTest struct {
|
type SplitTest struct {
|
||||||
s string;
|
s string
|
||||||
sep string;
|
sep string
|
||||||
n int;
|
n int
|
||||||
a []string;
|
a []string
|
||||||
}
|
}
|
||||||
|
|
||||||
var splittests = []SplitTest{
|
var splittests = []SplitTest{
|
||||||
@ -138,12 +138,12 @@ var splittests = []SplitTest{
|
|||||||
|
|
||||||
func TestSplit(t *testing.T) {
|
func TestSplit(t *testing.T) {
|
||||||
for _, tt := range splittests {
|
for _, tt := range splittests {
|
||||||
a := Split(tt.s, tt.sep, tt.n);
|
a := Split(tt.s, tt.sep, tt.n)
|
||||||
if !eq(a, tt.a) {
|
if !eq(a, tt.a) {
|
||||||
t.Errorf("Split(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, a, tt.a);
|
t.Errorf("Split(%q, %q, %d) = %v; want %v", tt.s, tt.sep, tt.n, a, tt.a)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
s := Join(a, tt.sep);
|
s := Join(a, tt.sep)
|
||||||
if s != tt.s {
|
if s != tt.s {
|
||||||
t.Errorf("Join(Split(%q, %q, %d), %q) = %q", tt.s, tt.sep, tt.n, tt.sep, s)
|
t.Errorf("Join(Split(%q, %q, %d), %q) = %q", tt.s, tt.sep, tt.n, tt.sep, s)
|
||||||
}
|
}
|
||||||
@ -168,12 +168,12 @@ var splitaftertests = []SplitTest{
|
|||||||
|
|
||||||
func TestSplitAfter(t *testing.T) {
|
func TestSplitAfter(t *testing.T) {
|
||||||
for _, tt := range splitaftertests {
|
for _, tt := range splitaftertests {
|
||||||
a := SplitAfter(tt.s, tt.sep, tt.n);
|
a := SplitAfter(tt.s, tt.sep, tt.n)
|
||||||
if !eq(a, tt.a) {
|
if !eq(a, tt.a) {
|
||||||
t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, a, tt.a);
|
t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, a, tt.a)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
s := Join(a, "");
|
s := Join(a, "")
|
||||||
if s != tt.s {
|
if s != tt.s {
|
||||||
t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s)
|
t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s)
|
||||||
}
|
}
|
||||||
@ -182,14 +182,14 @@ func TestSplitAfter(t *testing.T) {
|
|||||||
|
|
||||||
// Test case for any function which accepts and returns a single string.
|
// Test case for any function which accepts and returns a single string.
|
||||||
type StringTest struct {
|
type StringTest struct {
|
||||||
in, out string;
|
in, out string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute f on each test case. funcName should be the name of f; it's used
|
// Execute f on each test case. funcName should be the name of f; it's used
|
||||||
// in failure reports.
|
// in failure reports.
|
||||||
func runStringTests(t *testing.T, f func(string) string, funcName string, testCases []StringTest) {
|
func runStringTests(t *testing.T, f func(string) string, funcName string, testCases []StringTest) {
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
actual := f(tc.in);
|
actual := f(tc.in)
|
||||||
if actual != tc.out {
|
if actual != tc.out {
|
||||||
t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out)
|
t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out)
|
||||||
}
|
}
|
||||||
@ -228,54 +228,54 @@ var trimSpaceTests = []StringTest{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func tenRunes(rune int) string {
|
func tenRunes(rune int) string {
|
||||||
r := make([]int, 10);
|
r := make([]int, 10)
|
||||||
for i := range r {
|
for i := range r {
|
||||||
r[i] = rune
|
r[i] = rune
|
||||||
}
|
}
|
||||||
return string(r);
|
return string(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// User-defined self-inverse mapping function
|
// User-defined self-inverse mapping function
|
||||||
func rot13(rune int) int {
|
func rot13(rune int) int {
|
||||||
step := 13;
|
step := 13
|
||||||
if rune >= 'a' && rune <= 'z' {
|
if rune >= 'a' && rune <= 'z' {
|
||||||
return ((rune - 'a' + step) % 26) + 'a'
|
return ((rune - 'a' + step) % 26) + 'a'
|
||||||
}
|
}
|
||||||
if rune >= 'A' && rune <= 'Z' {
|
if rune >= 'A' && rune <= 'Z' {
|
||||||
return ((rune - 'A' + step) % 26) + 'A'
|
return ((rune - 'A' + step) % 26) + 'A'
|
||||||
}
|
}
|
||||||
return rune;
|
return rune
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMap(t *testing.T) {
|
func TestMap(t *testing.T) {
|
||||||
// Run a couple of awful growth/shrinkage tests
|
// Run a couple of awful growth/shrinkage tests
|
||||||
a := tenRunes('a');
|
a := tenRunes('a')
|
||||||
// 1. Grow. This triggers two reallocations in Map.
|
// 1. Grow. This triggers two reallocations in Map.
|
||||||
maxRune := func(rune int) int { return unicode.MaxRune };
|
maxRune := func(rune int) int { return unicode.MaxRune }
|
||||||
m := Map(maxRune, a);
|
m := Map(maxRune, a)
|
||||||
expect := tenRunes(unicode.MaxRune);
|
expect := tenRunes(unicode.MaxRune)
|
||||||
if m != expect {
|
if m != expect {
|
||||||
t.Errorf("growing: expected %q got %q", expect, m)
|
t.Errorf("growing: expected %q got %q", expect, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Shrink
|
// 2. Shrink
|
||||||
minRune := func(rune int) int { return 'a' };
|
minRune := func(rune int) int { return 'a' }
|
||||||
m = Map(minRune, tenRunes(unicode.MaxRune));
|
m = Map(minRune, tenRunes(unicode.MaxRune))
|
||||||
expect = a;
|
expect = a
|
||||||
if m != expect {
|
if m != expect {
|
||||||
t.Errorf("shrinking: expected %q got %q", expect, m)
|
t.Errorf("shrinking: expected %q got %q", expect, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Rot13
|
// 3. Rot13
|
||||||
m = Map(rot13, "a to zed");
|
m = Map(rot13, "a to zed")
|
||||||
expect = "n gb mrq";
|
expect = "n gb mrq"
|
||||||
if m != expect {
|
if m != expect {
|
||||||
t.Errorf("rot13: expected %q got %q", expect, m)
|
t.Errorf("rot13: expected %q got %q", expect, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Rot13^2
|
// 4. Rot13^2
|
||||||
m = Map(rot13, Map(rot13, "a to zed"));
|
m = Map(rot13, Map(rot13, "a to zed"))
|
||||||
expect = "a to zed";
|
expect = "a to zed"
|
||||||
if m != expect {
|
if m != expect {
|
||||||
t.Errorf("rot13: expected %q got %q", expect, m)
|
t.Errorf("rot13: expected %q got %q", expect, m)
|
||||||
}
|
}
|
||||||
@ -285,10 +285,10 @@ func TestMap(t *testing.T) {
|
|||||||
if unicode.Is(unicode.Latin, rune) {
|
if unicode.Is(unicode.Latin, rune) {
|
||||||
return rune
|
return rune
|
||||||
}
|
}
|
||||||
return -1;
|
return -1
|
||||||
};
|
}
|
||||||
m = Map(dropNotLatin, "Hello, 세계");
|
m = Map(dropNotLatin, "Hello, 세계")
|
||||||
expect = "Hello";
|
expect = "Hello"
|
||||||
if m != expect {
|
if m != expect {
|
||||||
t.Errorf("drop: expected %q got %q", expect, m)
|
t.Errorf("drop: expected %q got %q", expect, m)
|
||||||
}
|
}
|
||||||
@ -304,31 +304,31 @@ func equal(m string, s1, s2 string, t *testing.T) bool {
|
|||||||
if s1 == s2 {
|
if s1 == s2 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
e1 := Split(s1, "", 0);
|
e1 := Split(s1, "", 0)
|
||||||
e2 := Split(s2, "", 0);
|
e2 := Split(s2, "", 0)
|
||||||
for i, c1 := range e1 {
|
for i, c1 := range e1 {
|
||||||
if i > len(e2) {
|
if i > len(e2) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
r1, _ := utf8.DecodeRuneInString(c1);
|
r1, _ := utf8.DecodeRuneInString(c1)
|
||||||
r2, _ := utf8.DecodeRuneInString(e2[i]);
|
r2, _ := utf8.DecodeRuneInString(e2[i])
|
||||||
if r1 != r2 {
|
if r1 != r2 {
|
||||||
t.Errorf("%s diff at %d: U+%04X U+%04X", m, i, r1, r2)
|
t.Errorf("%s diff at %d: U+%04X U+%04X", m, i, r1, r2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCaseConsistency(t *testing.T) {
|
func TestCaseConsistency(t *testing.T) {
|
||||||
// Make a string of all the runes.
|
// Make a string of all the runes.
|
||||||
a := make([]int, unicode.MaxRune+1);
|
a := make([]int, unicode.MaxRune+1)
|
||||||
for i := range a {
|
for i := range a {
|
||||||
a[i] = i
|
a[i] = i
|
||||||
}
|
}
|
||||||
s := string(a);
|
s := string(a)
|
||||||
// convert the cases.
|
// convert the cases.
|
||||||
upper := ToUpper(s);
|
upper := ToUpper(s)
|
||||||
lower := ToLower(s);
|
lower := ToLower(s)
|
||||||
|
|
||||||
// Consistency checks
|
// Consistency checks
|
||||||
if n := utf8.RuneCountInString(upper); n != unicode.MaxRune+1 {
|
if n := utf8.RuneCountInString(upper); n != unicode.MaxRune+1 {
|
||||||
@ -360,8 +360,8 @@ func TestCaseConsistency(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RepeatTest struct {
|
type RepeatTest struct {
|
||||||
in, out string;
|
in, out string
|
||||||
count int;
|
count int
|
||||||
}
|
}
|
||||||
|
|
||||||
var RepeatTests = []RepeatTest{
|
var RepeatTests = []RepeatTest{
|
||||||
@ -376,10 +376,10 @@ var RepeatTests = []RepeatTest{
|
|||||||
|
|
||||||
func TestRepeat(t *testing.T) {
|
func TestRepeat(t *testing.T) {
|
||||||
for _, tt := range RepeatTests {
|
for _, tt := range RepeatTests {
|
||||||
a := Repeat(tt.in, tt.count);
|
a := Repeat(tt.in, tt.count)
|
||||||
if !equal("Repeat(s)", a, tt.out, t) {
|
if !equal("Repeat(s)", a, tt.out, t) {
|
||||||
t.Errorf("Repeat(%v, %d) = %v; want %v", tt.in, tt.count, a, tt.out);
|
t.Errorf("Repeat(%v, %d) = %v; want %v", tt.in, tt.count, a, tt.out)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -393,13 +393,13 @@ func runesEqual(a, b []int) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
type RunesTest struct {
|
type RunesTest struct {
|
||||||
in string;
|
in string
|
||||||
out []int;
|
out []int
|
||||||
lossy bool;
|
lossy bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var RunesTests = []RunesTest{
|
var RunesTests = []RunesTest{
|
||||||
@ -414,14 +414,14 @@ var RunesTests = []RunesTest{
|
|||||||
|
|
||||||
func TestRunes(t *testing.T) {
|
func TestRunes(t *testing.T) {
|
||||||
for _, tt := range RunesTests {
|
for _, tt := range RunesTests {
|
||||||
a := Runes(tt.in);
|
a := Runes(tt.in)
|
||||||
if !runesEqual(a, tt.out) {
|
if !runesEqual(a, tt.out) {
|
||||||
t.Errorf("Runes(%q) = %v; want %v", tt.in, a, tt.out);
|
t.Errorf("Runes(%q) = %v; want %v", tt.in, a, tt.out)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if !tt.lossy {
|
if !tt.lossy {
|
||||||
// can only test reassembly if we didn't lose information
|
// can only test reassembly if we didn't lose information
|
||||||
s := string(a);
|
s := string(a)
|
||||||
if s != tt.in {
|
if s != tt.in {
|
||||||
t.Errorf("string(Runes(%q)) = %x; want %x", tt.in, s, tt.in)
|
t.Errorf("string(Runes(%q)) = %x; want %x", tt.in, s, tt.in)
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@ func cas(val *uint32, old, new uint32) bool
|
|||||||
// Mutexes can be created as part of other structures;
|
// Mutexes can be created as part of other structures;
|
||||||
// the zero value for a Mutex is an unlocked mutex.
|
// the zero value for a Mutex is an unlocked mutex.
|
||||||
type Mutex struct {
|
type Mutex struct {
|
||||||
key uint32;
|
key uint32
|
||||||
sema uint32;
|
sema uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add delta to *val, and return the new *val in a thread-safe way. If multiple
|
// Add delta to *val, and return the new *val in a thread-safe way. If multiple
|
||||||
@ -25,13 +25,13 @@ type Mutex struct {
|
|||||||
// serialized, and all the deltas will be added in an undefined order.
|
// serialized, and all the deltas will be added in an undefined order.
|
||||||
func xadd(val *uint32, delta int32) (new uint32) {
|
func xadd(val *uint32, delta int32) (new uint32) {
|
||||||
for {
|
for {
|
||||||
v := *val;
|
v := *val
|
||||||
nv := v + uint32(delta);
|
nv := v + uint32(delta)
|
||||||
if cas(val, v, nv) {
|
if cas(val, v, nv) {
|
||||||
return nv
|
return nv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic("unreached");
|
panic("unreached")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock locks m.
|
// Lock locks m.
|
||||||
@ -42,7 +42,7 @@ func (m *Mutex) Lock() {
|
|||||||
// changed from 0 to 1; we hold lock
|
// changed from 0 to 1; we hold lock
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
runtime.Semacquire(&m.sema);
|
runtime.Semacquire(&m.sema)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock unlocks m.
|
// Unlock unlocks m.
|
||||||
@ -56,5 +56,5 @@ func (m *Mutex) Unlock() {
|
|||||||
// changed from 1 to 0; no contention
|
// changed from 1 to 0; no contention
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
runtime.Semrelease(&m.sema);
|
runtime.Semrelease(&m.sema)
|
||||||
}
|
}
|
||||||
|
@ -7,23 +7,23 @@
|
|||||||
package sync_test
|
package sync_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime";
|
"runtime"
|
||||||
. "sync";
|
. "sync"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HammerSemaphore(s *uint32, loops int, cdone chan bool) {
|
func HammerSemaphore(s *uint32, loops int, cdone chan bool) {
|
||||||
for i := 0; i < loops; i++ {
|
for i := 0; i < loops; i++ {
|
||||||
runtime.Semacquire(s);
|
runtime.Semacquire(s)
|
||||||
runtime.Semrelease(s);
|
runtime.Semrelease(s)
|
||||||
}
|
}
|
||||||
cdone <- true;
|
cdone <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSemaphore(t *testing.T) {
|
func TestSemaphore(t *testing.T) {
|
||||||
s := new(uint32);
|
s := new(uint32)
|
||||||
*s = 1;
|
*s = 1
|
||||||
c := make(chan bool);
|
c := make(chan bool)
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
go HammerSemaphore(s, 1000, c)
|
go HammerSemaphore(s, 1000, c)
|
||||||
}
|
}
|
||||||
@ -33,37 +33,37 @@ func TestSemaphore(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkUncontendedSemaphore(b *testing.B) {
|
func BenchmarkUncontendedSemaphore(b *testing.B) {
|
||||||
s := new(uint32);
|
s := new(uint32)
|
||||||
*s = 1;
|
*s = 1
|
||||||
HammerSemaphore(s, b.N, make(chan bool, 2));
|
HammerSemaphore(s, b.N, make(chan bool, 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkContendedSemaphore(b *testing.B) {
|
func BenchmarkContendedSemaphore(b *testing.B) {
|
||||||
b.StopTimer();
|
b.StopTimer()
|
||||||
s := new(uint32);
|
s := new(uint32)
|
||||||
*s = 1;
|
*s = 1
|
||||||
c := make(chan bool);
|
c := make(chan bool)
|
||||||
runtime.GOMAXPROCS(2);
|
runtime.GOMAXPROCS(2)
|
||||||
b.StartTimer();
|
b.StartTimer()
|
||||||
|
|
||||||
go HammerSemaphore(s, b.N/2, c);
|
go HammerSemaphore(s, b.N/2, c)
|
||||||
go HammerSemaphore(s, b.N/2, c);
|
go HammerSemaphore(s, b.N/2, c)
|
||||||
<-c;
|
<-c
|
||||||
<-c;
|
<-c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func HammerMutex(m *Mutex, loops int, cdone chan bool) {
|
func HammerMutex(m *Mutex, loops int, cdone chan bool) {
|
||||||
for i := 0; i < loops; i++ {
|
for i := 0; i < loops; i++ {
|
||||||
m.Lock();
|
m.Lock()
|
||||||
m.Unlock();
|
m.Unlock()
|
||||||
}
|
}
|
||||||
cdone <- true;
|
cdone <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMutex(t *testing.T) {
|
func TestMutex(t *testing.T) {
|
||||||
m := new(Mutex);
|
m := new(Mutex)
|
||||||
c := make(chan bool);
|
c := make(chan bool)
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
go HammerMutex(m, 1000, c)
|
go HammerMutex(m, 1000, c)
|
||||||
}
|
}
|
||||||
@ -73,19 +73,19 @@ func TestMutex(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkUncontendedMutex(b *testing.B) {
|
func BenchmarkUncontendedMutex(b *testing.B) {
|
||||||
m := new(Mutex);
|
m := new(Mutex)
|
||||||
HammerMutex(m, b.N, make(chan bool, 2));
|
HammerMutex(m, b.N, make(chan bool, 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkContendedMutex(b *testing.B) {
|
func BenchmarkContendedMutex(b *testing.B) {
|
||||||
b.StopTimer();
|
b.StopTimer()
|
||||||
m := new(Mutex);
|
m := new(Mutex)
|
||||||
c := make(chan bool);
|
c := make(chan bool)
|
||||||
runtime.GOMAXPROCS(2);
|
runtime.GOMAXPROCS(2)
|
||||||
b.StartTimer();
|
b.StartTimer()
|
||||||
|
|
||||||
go HammerMutex(m, b.N/2, c);
|
go HammerMutex(m, b.N/2, c)
|
||||||
go HammerMutex(m, b.N/2, c);
|
go HammerMutex(m, b.N/2, c)
|
||||||
<-c;
|
<-c
|
||||||
<-c;
|
<-c
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,9 @@ package sync
|
|||||||
// Writers take priority over Readers: no new RLocks
|
// Writers take priority over Readers: no new RLocks
|
||||||
// are granted while a blocked Lock call is waiting.
|
// are granted while a blocked Lock call is waiting.
|
||||||
type RWMutex struct {
|
type RWMutex struct {
|
||||||
w Mutex; // held if there are pending readers or writers
|
w Mutex // held if there are pending readers or writers
|
||||||
r Mutex; // held if the w is being rd
|
r Mutex // held if the w is being rd
|
||||||
readerCount uint32; // number of pending readers
|
readerCount uint32 // number of pending readers
|
||||||
}
|
}
|
||||||
|
|
||||||
// RLock locks rw for reading.
|
// RLock locks rw for reading.
|
||||||
@ -32,13 +32,13 @@ func (rw *RWMutex) RLock() {
|
|||||||
// C: rw.RLock() // granted
|
// C: rw.RLock() // granted
|
||||||
// B: rw.RUnlock()
|
// B: rw.RUnlock()
|
||||||
// ... (new readers come and go indefinitely, W is starving)
|
// ... (new readers come and go indefinitely, W is starving)
|
||||||
rw.r.Lock();
|
rw.r.Lock()
|
||||||
if xadd(&rw.readerCount, 1) == 1 {
|
if xadd(&rw.readerCount, 1) == 1 {
|
||||||
// The first reader locks rw.w, so writers will be blocked
|
// The first reader locks rw.w, so writers will be blocked
|
||||||
// while the readers have the RLock.
|
// while the readers have the RLock.
|
||||||
rw.w.Lock()
|
rw.w.Lock()
|
||||||
}
|
}
|
||||||
rw.r.Unlock();
|
rw.r.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RUnlock undoes a single RLock call;
|
// RUnlock undoes a single RLock call;
|
||||||
@ -59,9 +59,9 @@ func (rw *RWMutex) RUnlock() {
|
|||||||
// a blocked Lock call excludes new readers from acquiring
|
// a blocked Lock call excludes new readers from acquiring
|
||||||
// the lock.
|
// the lock.
|
||||||
func (rw *RWMutex) Lock() {
|
func (rw *RWMutex) Lock() {
|
||||||
rw.r.Lock();
|
rw.r.Lock()
|
||||||
rw.w.Lock();
|
rw.w.Lock()
|
||||||
rw.r.Unlock();
|
rw.r.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock unlocks rw for writing.
|
// Unlock unlocks rw for writing.
|
||||||
|
@ -7,26 +7,26 @@
|
|||||||
package sync_test
|
package sync_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt";
|
"fmt"
|
||||||
"runtime";
|
"runtime"
|
||||||
. "sync";
|
. "sync"
|
||||||
"testing";
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func parallelReader(m *RWMutex, clocked, cunlock, cdone chan bool) {
|
func parallelReader(m *RWMutex, clocked, cunlock, cdone chan bool) {
|
||||||
m.RLock();
|
m.RLock()
|
||||||
clocked <- true;
|
clocked <- true
|
||||||
<-cunlock;
|
<-cunlock
|
||||||
m.RUnlock();
|
m.RUnlock()
|
||||||
cdone <- true;
|
cdone <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func doTestParallelReaders(numReaders, gomaxprocs int) {
|
func doTestParallelReaders(numReaders, gomaxprocs int) {
|
||||||
runtime.GOMAXPROCS(gomaxprocs);
|
runtime.GOMAXPROCS(gomaxprocs)
|
||||||
var m RWMutex;
|
var m RWMutex
|
||||||
clocked := make(chan bool);
|
clocked := make(chan bool)
|
||||||
cunlock := make(chan bool);
|
cunlock := make(chan bool)
|
||||||
cdone := make(chan bool);
|
cdone := make(chan bool)
|
||||||
for i := 0; i < numReaders; i++ {
|
for i := 0; i < numReaders; i++ {
|
||||||
go parallelReader(&m, clocked, cunlock, cdone)
|
go parallelReader(&m, clocked, cunlock, cdone)
|
||||||
}
|
}
|
||||||
@ -44,53 +44,53 @@ func doTestParallelReaders(numReaders, gomaxprocs int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestParallelReaders(t *testing.T) {
|
func TestParallelReaders(t *testing.T) {
|
||||||
doTestParallelReaders(1, 4);
|
doTestParallelReaders(1, 4)
|
||||||
doTestParallelReaders(3, 4);
|
doTestParallelReaders(3, 4)
|
||||||
doTestParallelReaders(4, 2);
|
doTestParallelReaders(4, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func reader(rwm *RWMutex, num_iterations int, activity *uint32, cdone chan bool) {
|
func reader(rwm *RWMutex, num_iterations int, activity *uint32, cdone chan bool) {
|
||||||
for i := 0; i < num_iterations; i++ {
|
for i := 0; i < num_iterations; i++ {
|
||||||
rwm.RLock();
|
rwm.RLock()
|
||||||
n := Xadd(activity, 1);
|
n := Xadd(activity, 1)
|
||||||
if n < 1 || n >= 10000 {
|
if n < 1 || n >= 10000 {
|
||||||
panic(fmt.Sprintf("wlock(%d)\n", n))
|
panic(fmt.Sprintf("wlock(%d)\n", n))
|
||||||
}
|
}
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
}
|
}
|
||||||
Xadd(activity, -1);
|
Xadd(activity, -1)
|
||||||
rwm.RUnlock();
|
rwm.RUnlock()
|
||||||
}
|
}
|
||||||
cdone <- true;
|
cdone <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func writer(rwm *RWMutex, num_iterations int, activity *uint32, cdone chan bool) {
|
func writer(rwm *RWMutex, num_iterations int, activity *uint32, cdone chan bool) {
|
||||||
for i := 0; i < num_iterations; i++ {
|
for i := 0; i < num_iterations; i++ {
|
||||||
rwm.Lock();
|
rwm.Lock()
|
||||||
n := Xadd(activity, 10000);
|
n := Xadd(activity, 10000)
|
||||||
if n != 10000 {
|
if n != 10000 {
|
||||||
panic(fmt.Sprintf("wlock(%d)\n", n))
|
panic(fmt.Sprintf("wlock(%d)\n", n))
|
||||||
}
|
}
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
}
|
}
|
||||||
Xadd(activity, -10000);
|
Xadd(activity, -10000)
|
||||||
rwm.Unlock();
|
rwm.Unlock()
|
||||||
}
|
}
|
||||||
cdone <- true;
|
cdone <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func HammerRWMutex(gomaxprocs, numReaders, num_iterations int) {
|
func HammerRWMutex(gomaxprocs, numReaders, num_iterations int) {
|
||||||
runtime.GOMAXPROCS(gomaxprocs);
|
runtime.GOMAXPROCS(gomaxprocs)
|
||||||
// Number of active readers + 10000 * number of active writers.
|
// Number of active readers + 10000 * number of active writers.
|
||||||
var activity uint32;
|
var activity uint32
|
||||||
var rwm RWMutex;
|
var rwm RWMutex
|
||||||
cdone := make(chan bool);
|
cdone := make(chan bool)
|
||||||
go writer(&rwm, num_iterations, &activity, cdone);
|
go writer(&rwm, num_iterations, &activity, cdone)
|
||||||
var i int;
|
var i int
|
||||||
for i = 0; i < numReaders/2; i++ {
|
for i = 0; i < numReaders/2; i++ {
|
||||||
go reader(&rwm, num_iterations, &activity, cdone)
|
go reader(&rwm, num_iterations, &activity, cdone)
|
||||||
}
|
}
|
||||||
go writer(&rwm, num_iterations, &activity, cdone);
|
go writer(&rwm, num_iterations, &activity, cdone)
|
||||||
for ; i < numReaders; i++ {
|
for ; i < numReaders; i++ {
|
||||||
go reader(&rwm, num_iterations, &activity, cdone)
|
go reader(&rwm, num_iterations, &activity, cdone)
|
||||||
}
|
}
|
||||||
@ -101,14 +101,14 @@ func HammerRWMutex(gomaxprocs, numReaders, num_iterations int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRWMutex(t *testing.T) {
|
func TestRWMutex(t *testing.T) {
|
||||||
HammerRWMutex(1, 1, 1000);
|
HammerRWMutex(1, 1, 1000)
|
||||||
HammerRWMutex(1, 3, 1000);
|
HammerRWMutex(1, 3, 1000)
|
||||||
HammerRWMutex(1, 10, 1000);
|
HammerRWMutex(1, 10, 1000)
|
||||||
HammerRWMutex(4, 1, 1000);
|
HammerRWMutex(4, 1, 1000)
|
||||||
HammerRWMutex(4, 3, 1000);
|
HammerRWMutex(4, 3, 1000)
|
||||||
HammerRWMutex(4, 10, 1000);
|
HammerRWMutex(4, 10, 1000)
|
||||||
HammerRWMutex(10, 1, 1000);
|
HammerRWMutex(10, 1, 1000)
|
||||||
HammerRWMutex(10, 3, 1000);
|
HammerRWMutex(10, 3, 1000)
|
||||||
HammerRWMutex(10, 10, 1000);
|
HammerRWMutex(10, 10, 1000)
|
||||||
HammerRWMutex(10, 5, 10000);
|
HammerRWMutex(10, 5, 10000)
|
||||||
}
|
}
|
||||||
|
@ -9,20 +9,20 @@ func str(val int) string { // do it here rather than with fmt to avoid dependenc
|
|||||||
if val < 0 {
|
if val < 0 {
|
||||||
return "-" + str(-val)
|
return "-" + str(-val)
|
||||||
}
|
}
|
||||||
var buf [32]byte; // big enough for int64
|
var buf [32]byte // big enough for int64
|
||||||
i := len(buf) - 1;
|
i := len(buf) - 1
|
||||||
for val >= 10 {
|
for val >= 10 {
|
||||||
buf[i] = byte(val%10 + '0');
|
buf[i] = byte(val%10 + '0')
|
||||||
i--;
|
i--
|
||||||
val /= 10;
|
val /= 10
|
||||||
}
|
}
|
||||||
buf[i] = byte(val + '0');
|
buf[i] = byte(val + '0')
|
||||||
return string(buf[i:]);
|
return string(buf[i:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func Errstr(errno int) string {
|
func Errstr(errno int) string {
|
||||||
if errno < 0 || errno >= int(len(errors)) {
|
if errno < 0 || errno >= int(len(errors)) {
|
||||||
return "error " + str(errno)
|
return "error " + str(errno)
|
||||||
}
|
}
|
||||||
return errors[errno];
|
return errors[errno]
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync";
|
"sync"
|
||||||
"unsafe";
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Lock synchronizing creation of new file descriptors with fork.
|
// Lock synchronizing creation of new file descriptors with fork.
|
||||||
@ -63,18 +63,18 @@ var ForkLock sync.RWMutex
|
|||||||
// Convert array of string to array
|
// Convert array of string to array
|
||||||
// of NUL-terminated byte pointer.
|
// of NUL-terminated byte pointer.
|
||||||
func StringArrayPtr(ss []string) []*byte {
|
func StringArrayPtr(ss []string) []*byte {
|
||||||
bb := make([]*byte, len(ss)+1);
|
bb := make([]*byte, len(ss)+1)
|
||||||
for i := 0; i < len(ss); i++ {
|
for i := 0; i < len(ss); i++ {
|
||||||
bb[i] = StringBytePtr(ss[i])
|
bb[i] = StringBytePtr(ss[i])
|
||||||
}
|
}
|
||||||
bb[len(ss)] = nil;
|
bb[len(ss)] = nil
|
||||||
return bb;
|
return bb
|
||||||
}
|
}
|
||||||
|
|
||||||
func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
|
func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
|
||||||
|
|
||||||
func SetNonblock(fd int, nonblocking bool) (errno int) {
|
func SetNonblock(fd int, nonblocking bool) (errno int) {
|
||||||
flag, err := fcntl(fd, F_GETFL, 0);
|
flag, err := fcntl(fd, F_GETFL, 0)
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -83,8 +83,8 @@ func SetNonblock(fd int, nonblocking bool) (errno int) {
|
|||||||
} else {
|
} else {
|
||||||
flag &= ^O_NONBLOCK
|
flag &= ^O_NONBLOCK
|
||||||
}
|
}
|
||||||
_, err = fcntl(fd, F_SETFL, flag);
|
_, err = fcntl(fd, F_SETFL, flag)
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -99,15 +99,15 @@ func SetNonblock(fd int, nonblocking bool) (errno int) {
|
|||||||
func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, traceme bool, dir *byte, fd []int, pipe int) (pid int, err int) {
|
func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, traceme bool, dir *byte, fd []int, pipe int) (pid int, err int) {
|
||||||
// Declare all variables at top in case any
|
// Declare all variables at top in case any
|
||||||
// declarations require heap allocation (e.g., err1).
|
// declarations require heap allocation (e.g., err1).
|
||||||
var r1, r2, err1 uintptr;
|
var r1, r2, err1 uintptr
|
||||||
var nextfd int;
|
var nextfd int
|
||||||
var i int;
|
var i int
|
||||||
|
|
||||||
darwin := OS == "darwin";
|
darwin := OS == "darwin"
|
||||||
|
|
||||||
// About to call fork.
|
// About to call fork.
|
||||||
// No more allocation or calls of non-assembly functions.
|
// No more allocation or calls of non-assembly functions.
|
||||||
r1, r2, err1 = RawSyscall(SYS_FORK, 0, 0, 0);
|
r1, r2, err1 = RawSyscall(SYS_FORK, 0, 0, 0)
|
||||||
if err1 != 0 {
|
if err1 != 0 {
|
||||||
return 0, int(err1)
|
return 0, int(err1)
|
||||||
}
|
}
|
||||||
@ -129,7 +129,7 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, traceme bool, d
|
|||||||
|
|
||||||
// Enable tracing if requested.
|
// Enable tracing if requested.
|
||||||
if traceme {
|
if traceme {
|
||||||
_, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0);
|
_, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0)
|
||||||
if err1 != 0 {
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, traceme bool, d
|
|||||||
|
|
||||||
// Chdir
|
// Chdir
|
||||||
if dir != nil {
|
if dir != nil {
|
||||||
_, _, err1 = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0);
|
_, _, err1 = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0)
|
||||||
if err1 != 0 {
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
@ -145,25 +145,25 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, traceme bool, d
|
|||||||
|
|
||||||
// Pass 1: look for fd[i] < i and move those up above len(fd)
|
// Pass 1: look for fd[i] < i and move those up above len(fd)
|
||||||
// so that pass 2 won't stomp on an fd it needs later.
|
// so that pass 2 won't stomp on an fd it needs later.
|
||||||
nextfd = int(len(fd));
|
nextfd = int(len(fd))
|
||||||
if pipe < nextfd {
|
if pipe < nextfd {
|
||||||
_, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0);
|
_, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0)
|
||||||
if err1 != 0 {
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC);
|
RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
|
||||||
pipe = nextfd;
|
pipe = nextfd
|
||||||
nextfd++;
|
nextfd++
|
||||||
}
|
}
|
||||||
for i = 0; i < len(fd); i++ {
|
for i = 0; i < len(fd); i++ {
|
||||||
if fd[i] >= 0 && fd[i] < int(i) {
|
if fd[i] >= 0 && fd[i] < int(i) {
|
||||||
_, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0);
|
_, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0)
|
||||||
if err1 != 0 {
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC);
|
RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
|
||||||
fd[i] = nextfd;
|
fd[i] = nextfd
|
||||||
nextfd++;
|
nextfd++
|
||||||
if nextfd == pipe { // don't stomp on pipe
|
if nextfd == pipe { // don't stomp on pipe
|
||||||
nextfd++
|
nextfd++
|
||||||
}
|
}
|
||||||
@ -173,21 +173,21 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, traceme bool, d
|
|||||||
// Pass 2: dup fd[i] down onto i.
|
// Pass 2: dup fd[i] down onto i.
|
||||||
for i = 0; i < len(fd); i++ {
|
for i = 0; i < len(fd); i++ {
|
||||||
if fd[i] == -1 {
|
if fd[i] == -1 {
|
||||||
RawSyscall(SYS_CLOSE, uintptr(i), 0, 0);
|
RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if fd[i] == int(i) {
|
if fd[i] == int(i) {
|
||||||
// dup2(i, i) won't clear close-on-exec flag on Linux,
|
// dup2(i, i) won't clear close-on-exec flag on Linux,
|
||||||
// probably not elsewhere either.
|
// probably not elsewhere either.
|
||||||
_, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), F_SETFD, 0);
|
_, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), F_SETFD, 0)
|
||||||
if err1 != 0 {
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
// The new fd is created NOT close-on-exec,
|
// The new fd is created NOT close-on-exec,
|
||||||
// which is exactly what we want.
|
// which is exactly what we want.
|
||||||
_, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(i), 0);
|
_, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(i), 0)
|
||||||
if err1 != 0 {
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
@ -205,11 +205,11 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []*byte, traceme bool, d
|
|||||||
_, _, err1 = RawSyscall(SYS_EXECVE,
|
_, _, err1 = RawSyscall(SYS_EXECVE,
|
||||||
uintptr(unsafe.Pointer(argv0)),
|
uintptr(unsafe.Pointer(argv0)),
|
||||||
uintptr(unsafe.Pointer(&argv[0])),
|
uintptr(unsafe.Pointer(&argv[0])),
|
||||||
uintptr(unsafe.Pointer(&envv[0])));
|
uintptr(unsafe.Pointer(&envv[0])))
|
||||||
|
|
||||||
childerror:
|
childerror:
|
||||||
// send error code on pipe
|
// send error code on pipe
|
||||||
RawSyscall(SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err1)), uintptr(unsafe.Sizeof(err1)));
|
RawSyscall(SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err1)), uintptr(unsafe.Sizeof(err1)))
|
||||||
for {
|
for {
|
||||||
RawSyscall(SYS_EXIT, 253, 0, 0)
|
RawSyscall(SYS_EXIT, 253, 0, 0)
|
||||||
}
|
}
|
||||||
@ -217,23 +217,23 @@ childerror:
|
|||||||
// Calling panic is not actually safe,
|
// Calling panic is not actually safe,
|
||||||
// but the for loop above won't break
|
// but the for loop above won't break
|
||||||
// and this shuts up the compiler.
|
// and this shuts up the compiler.
|
||||||
panic("unreached");
|
panic("unreached")
|
||||||
}
|
}
|
||||||
|
|
||||||
func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir string, fd []int) (pid int, err int) {
|
func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir string, fd []int) (pid int, err int) {
|
||||||
var p [2]int;
|
var p [2]int
|
||||||
var n int;
|
var n int
|
||||||
var err1 uintptr;
|
var err1 uintptr
|
||||||
var wstatus WaitStatus;
|
var wstatus WaitStatus
|
||||||
|
|
||||||
p[0] = -1;
|
p[0] = -1
|
||||||
p[1] = -1;
|
p[1] = -1
|
||||||
|
|
||||||
// Convert args to C form.
|
// Convert args to C form.
|
||||||
argv0p := StringBytePtr(argv0);
|
argv0p := StringBytePtr(argv0)
|
||||||
argvp := StringArrayPtr(argv);
|
argvp := StringArrayPtr(argv)
|
||||||
envvp := StringArrayPtr(envv);
|
envvp := StringArrayPtr(envv)
|
||||||
var dirp *byte;
|
var dirp *byte
|
||||||
if len(dir) > 0 {
|
if len(dir) > 0 {
|
||||||
dirp = StringBytePtr(dir)
|
dirp = StringBytePtr(dir)
|
||||||
}
|
}
|
||||||
@ -241,7 +241,7 @@ func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir stri
|
|||||||
// Acquire the fork lock so that no other threads
|
// Acquire the fork lock so that no other threads
|
||||||
// create new fds that are not yet close-on-exec
|
// create new fds that are not yet close-on-exec
|
||||||
// before we fork.
|
// before we fork.
|
||||||
ForkLock.Lock();
|
ForkLock.Lock()
|
||||||
|
|
||||||
// Allocate child status pipe close on exec.
|
// Allocate child status pipe close on exec.
|
||||||
if err = Pipe(&p); err != 0 {
|
if err = Pipe(&p); err != 0 {
|
||||||
@ -255,22 +255,22 @@ func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Kick off child.
|
// Kick off child.
|
||||||
pid, err = forkAndExecInChild(argv0p, argvp, envvp, traceme, dirp, fd, p[1]);
|
pid, err = forkAndExecInChild(argv0p, argvp, envvp, traceme, dirp, fd, p[1])
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
error:
|
error:
|
||||||
if p[0] >= 0 {
|
if p[0] >= 0 {
|
||||||
Close(p[0]);
|
Close(p[0])
|
||||||
Close(p[1]);
|
Close(p[1])
|
||||||
}
|
}
|
||||||
ForkLock.Unlock();
|
ForkLock.Unlock()
|
||||||
return 0, err;
|
return 0, err
|
||||||
}
|
}
|
||||||
ForkLock.Unlock();
|
ForkLock.Unlock()
|
||||||
|
|
||||||
// Read child error status from pipe.
|
// Read child error status from pipe.
|
||||||
Close(p[1]);
|
Close(p[1])
|
||||||
n, err = read(p[0], (*byte)(unsafe.Pointer(&err1)), unsafe.Sizeof(err1));
|
n, err = read(p[0], (*byte)(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
|
||||||
Close(p[0]);
|
Close(p[0])
|
||||||
if err != 0 || n != 0 {
|
if err != 0 || n != 0 {
|
||||||
if n == unsafe.Sizeof(err1) {
|
if n == unsafe.Sizeof(err1) {
|
||||||
err = int(err1)
|
err = int(err1)
|
||||||
@ -281,15 +281,15 @@ func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir stri
|
|||||||
|
|
||||||
// Child failed; wait for it to exit, to make sure
|
// Child failed; wait for it to exit, to make sure
|
||||||
// the zombies don't accumulate.
|
// the zombies don't accumulate.
|
||||||
_, err1 := Wait4(pid, &wstatus, 0, nil);
|
_, err1 := Wait4(pid, &wstatus, 0, nil)
|
||||||
for err1 == EINTR {
|
for err1 == EINTR {
|
||||||
_, err1 = Wait4(pid, &wstatus, 0, nil)
|
_, err1 = Wait4(pid, &wstatus, 0, nil)
|
||||||
}
|
}
|
||||||
return 0, err;
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read got EOF, so pipe closed on exec, so exec succeeded.
|
// Read got EOF, so pipe closed on exec, so exec succeeded.
|
||||||
return pid, 0;
|
return pid, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Combination of fork and exec, careful to be thread safe.
|
// Combination of fork and exec, careful to be thread safe.
|
||||||
@ -307,6 +307,6 @@ func Exec(argv0 string, argv []string, envv []string) (err int) {
|
|||||||
_, _, err1 := RawSyscall(SYS_EXECVE,
|
_, _, err1 := RawSyscall(SYS_EXECVE,
|
||||||
uintptr(unsafe.Pointer(StringBytePtr(argv0))),
|
uintptr(unsafe.Pointer(StringBytePtr(argv0))),
|
||||||
uintptr(unsafe.Pointer(&StringArrayPtr(argv)[0])),
|
uintptr(unsafe.Pointer(&StringArrayPtr(argv)[0])),
|
||||||
uintptr(unsafe.Pointer(&StringArrayPtr(envv)[0])));
|
uintptr(unsafe.Pointer(&StringArrayPtr(envv)[0])))
|
||||||
return int(err1);
|
return int(err1)
|
||||||
}
|
}
|
||||||
|
@ -18,11 +18,11 @@ func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
|
|||||||
// StringByteSlice returns a NUL-terminated slice of bytes
|
// StringByteSlice returns a NUL-terminated slice of bytes
|
||||||
// containing the text of s.
|
// containing the text of s.
|
||||||
func StringByteSlice(s string) []byte {
|
func StringByteSlice(s string) []byte {
|
||||||
a := make([]byte, len(s)+1);
|
a := make([]byte, len(s)+1)
|
||||||
for i := 0; i < len(s); i++ {
|
for i := 0; i < len(s); i++ {
|
||||||
a[i] = s[i]
|
a[i] = s[i]
|
||||||
}
|
}
|
||||||
return a;
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringBytePtr returns a pointer to a NUL-terminated array of bytes
|
// StringBytePtr returns a pointer to a NUL-terminated array of bytes
|
||||||
|
@ -34,7 +34,7 @@ func Getwd() (string, int) { return "", ENOTSUP }
|
|||||||
//sys setgroups(ngid int, gid *_Gid_t) (errno int)
|
//sys setgroups(ngid int, gid *_Gid_t) (errno int)
|
||||||
|
|
||||||
func Getgroups() (gids []int, errno int) {
|
func Getgroups() (gids []int, errno int) {
|
||||||
n, err := getgroups(0, nil);
|
n, err := getgroups(0, nil)
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return nil, errno
|
return nil, errno
|
||||||
}
|
}
|
||||||
@ -47,16 +47,16 @@ func Getgroups() (gids []int, errno int) {
|
|||||||
return nil, EINVAL
|
return nil, EINVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
a := make([]_Gid_t, n);
|
a := make([]_Gid_t, n)
|
||||||
n, err = getgroups(n, &a[0]);
|
n, err = getgroups(n, &a[0])
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return nil, errno
|
return nil, errno
|
||||||
}
|
}
|
||||||
gids = make([]int, n);
|
gids = make([]int, n)
|
||||||
for i, v := range a[0:n] {
|
for i, v := range a[0:n] {
|
||||||
gids[i] = int(v)
|
gids[i] = int(v)
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setgroups(gids []int) (errno int) {
|
func Setgroups(gids []int) (errno int) {
|
||||||
@ -64,11 +64,11 @@ func Setgroups(gids []int) (errno int) {
|
|||||||
return setgroups(0, nil)
|
return setgroups(0, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
a := make([]_Gid_t, len(gids));
|
a := make([]_Gid_t, len(gids))
|
||||||
for i, v := range gids {
|
for i, v := range gids {
|
||||||
a[i] = _Gid_t(v)
|
a[i] = _Gid_t(v)
|
||||||
}
|
}
|
||||||
return setgroups(len(a), &a[0]);
|
return setgroups(len(a), &a[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait status is 7 bits at bottom, either 0 (exited),
|
// Wait status is 7 bits at bottom, either 0 (exited),
|
||||||
@ -80,12 +80,12 @@ func Setgroups(gids []int) (errno int) {
|
|||||||
type WaitStatus uint32
|
type WaitStatus uint32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
mask = 0x7F;
|
mask = 0x7F
|
||||||
core = 0x80;
|
core = 0x80
|
||||||
shift = 8;
|
shift = 8
|
||||||
|
|
||||||
exited = 0;
|
exited = 0
|
||||||
stopped = 0x7F;
|
stopped = 0x7F
|
||||||
)
|
)
|
||||||
|
|
||||||
func (w WaitStatus) Exited() bool { return w&mask == exited }
|
func (w WaitStatus) Exited() bool { return w&mask == exited }
|
||||||
@ -94,17 +94,17 @@ func (w WaitStatus) ExitStatus() int {
|
|||||||
if w&mask != exited {
|
if w&mask != exited {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return int(w >> shift);
|
return int(w >> shift)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
|
func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
|
||||||
|
|
||||||
func (w WaitStatus) Signal() int {
|
func (w WaitStatus) Signal() int {
|
||||||
sig := int(w & mask);
|
sig := int(w & mask)
|
||||||
if sig == stopped || sig == 0 {
|
if sig == stopped || sig == 0 {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return sig;
|
return sig
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
|
func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
|
||||||
@ -117,7 +117,7 @@ func (w WaitStatus) StopSignal() int {
|
|||||||
if !w.Stopped() {
|
if !w.Stopped() {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return int(w>>shift) & 0xFF;
|
return int(w>>shift) & 0xFF
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WaitStatus) TrapCause() int {
|
func (w WaitStatus) TrapCause() int {
|
||||||
@ -128,12 +128,12 @@ func (w WaitStatus) TrapCause() int {
|
|||||||
//sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int)
|
//sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int)
|
||||||
|
|
||||||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
|
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
|
||||||
var status _C_int;
|
var status _C_int
|
||||||
wpid, errno = wait4(pid, &status, options, rusage);
|
wpid, errno = wait4(pid, &status, options, rusage)
|
||||||
if wstatus != nil {
|
if wstatus != nil {
|
||||||
*wstatus = WaitStatus(status)
|
*wstatus = WaitStatus(status)
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys pipe() (r int, w int, errno int)
|
//sys pipe() (r int, w int, errno int)
|
||||||
@ -142,13 +142,13 @@ func Pipe(p []int) (errno int) {
|
|||||||
if len(p) != 2 {
|
if len(p) != 2 {
|
||||||
return EINVAL
|
return EINVAL
|
||||||
}
|
}
|
||||||
p[0], p[1], errno = pipe();
|
p[0], p[1], errno = pipe()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Sleep(ns int64) (errno int) {
|
func Sleep(ns int64) (errno int) {
|
||||||
tv := NsecToTimeval(ns);
|
tv := NsecToTimeval(ns)
|
||||||
return Select(0, nil, nil, nil, &tv);
|
return Select(0, nil, nil, nil, &tv)
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int)
|
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int)
|
||||||
@ -165,173 +165,173 @@ func Sleep(ns int64) (errno int) {
|
|||||||
var SocketDisableIPv6 bool
|
var SocketDisableIPv6 bool
|
||||||
|
|
||||||
type Sockaddr interface {
|
type Sockaddr interface {
|
||||||
sockaddr() (ptr uintptr, len _Socklen, errno int); // lowercase; only we can define Sockaddrs
|
sockaddr() (ptr uintptr, len _Socklen, errno int) // lowercase; only we can define Sockaddrs
|
||||||
}
|
}
|
||||||
|
|
||||||
type SockaddrInet4 struct {
|
type SockaddrInet4 struct {
|
||||||
Port int;
|
Port int
|
||||||
Addr [4]byte;
|
Addr [4]byte
|
||||||
raw RawSockaddrInet4;
|
raw RawSockaddrInet4
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) {
|
func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) {
|
||||||
if sa.Port < 0 || sa.Port > 0xFFFF {
|
if sa.Port < 0 || sa.Port > 0xFFFF {
|
||||||
return 0, 0, EINVAL
|
return 0, 0, EINVAL
|
||||||
}
|
}
|
||||||
sa.raw.Len = SizeofSockaddrInet4;
|
sa.raw.Len = SizeofSockaddrInet4
|
||||||
sa.raw.Family = AF_INET;
|
sa.raw.Family = AF_INET
|
||||||
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
|
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
|
||||||
p[0] = byte(sa.Port >> 8);
|
p[0] = byte(sa.Port >> 8)
|
||||||
p[1] = byte(sa.Port);
|
p[1] = byte(sa.Port)
|
||||||
for i := 0; i < len(sa.Addr); i++ {
|
for i := 0; i < len(sa.Addr); i++ {
|
||||||
sa.raw.Addr[i] = sa.Addr[i]
|
sa.raw.Addr[i] = sa.Addr[i]
|
||||||
}
|
}
|
||||||
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0;
|
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0
|
||||||
}
|
}
|
||||||
|
|
||||||
type SockaddrInet6 struct {
|
type SockaddrInet6 struct {
|
||||||
Port int;
|
Port int
|
||||||
Addr [16]byte;
|
Addr [16]byte
|
||||||
raw RawSockaddrInet6;
|
raw RawSockaddrInet6
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) {
|
func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) {
|
||||||
if sa.Port < 0 || sa.Port > 0xFFFF {
|
if sa.Port < 0 || sa.Port > 0xFFFF {
|
||||||
return 0, 0, EINVAL
|
return 0, 0, EINVAL
|
||||||
}
|
}
|
||||||
sa.raw.Len = SizeofSockaddrInet6;
|
sa.raw.Len = SizeofSockaddrInet6
|
||||||
sa.raw.Family = AF_INET6;
|
sa.raw.Family = AF_INET6
|
||||||
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
|
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
|
||||||
p[0] = byte(sa.Port >> 8);
|
p[0] = byte(sa.Port >> 8)
|
||||||
p[1] = byte(sa.Port);
|
p[1] = byte(sa.Port)
|
||||||
for i := 0; i < len(sa.Addr); i++ {
|
for i := 0; i < len(sa.Addr); i++ {
|
||||||
sa.raw.Addr[i] = sa.Addr[i]
|
sa.raw.Addr[i] = sa.Addr[i]
|
||||||
}
|
}
|
||||||
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0;
|
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0
|
||||||
}
|
}
|
||||||
|
|
||||||
type SockaddrUnix struct {
|
type SockaddrUnix struct {
|
||||||
Name string;
|
Name string
|
||||||
raw RawSockaddrUnix;
|
raw RawSockaddrUnix
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
|
func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
|
||||||
name := sa.Name;
|
name := sa.Name
|
||||||
n := len(name);
|
n := len(name)
|
||||||
if n >= len(sa.raw.Path) || n == 0 {
|
if n >= len(sa.raw.Path) || n == 0 {
|
||||||
return 0, 0, EINVAL
|
return 0, 0, EINVAL
|
||||||
}
|
}
|
||||||
sa.raw.Len = byte(3 + n); // 2 for Family, Len; 1 for NUL
|
sa.raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL
|
||||||
sa.raw.Family = AF_UNIX;
|
sa.raw.Family = AF_UNIX
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
sa.raw.Path[i] = int8(name[i])
|
sa.raw.Path[i] = int8(name[i])
|
||||||
}
|
}
|
||||||
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0;
|
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
|
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
|
||||||
switch rsa.Addr.Family {
|
switch rsa.Addr.Family {
|
||||||
case AF_UNIX:
|
case AF_UNIX:
|
||||||
pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa));
|
pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
|
||||||
if pp.Len < 3 || pp.Len > SizeofSockaddrUnix {
|
if pp.Len < 3 || pp.Len > SizeofSockaddrUnix {
|
||||||
return nil, EINVAL
|
return nil, EINVAL
|
||||||
}
|
}
|
||||||
sa := new(SockaddrUnix);
|
sa := new(SockaddrUnix)
|
||||||
n := int(pp.Len) - 3; // subtract leading Family, Len, terminating NUL
|
n := int(pp.Len) - 3 // subtract leading Family, Len, terminating NUL
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
if pp.Path[i] == 0 {
|
if pp.Path[i] == 0 {
|
||||||
// found early NUL; assume Len is overestimating
|
// found early NUL; assume Len is overestimating
|
||||||
n = i;
|
n = i
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]));
|
bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))
|
||||||
sa.Name = string(bytes[0:n]);
|
sa.Name = string(bytes[0:n])
|
||||||
return sa, 0;
|
return sa, 0
|
||||||
|
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
|
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
|
||||||
sa := new(SockaddrInet4);
|
sa := new(SockaddrInet4)
|
||||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port));
|
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||||
sa.Port = int(p[0])<<8 + int(p[1]);
|
sa.Port = int(p[0])<<8 + int(p[1])
|
||||||
for i := 0; i < len(sa.Addr); i++ {
|
for i := 0; i < len(sa.Addr); i++ {
|
||||||
sa.Addr[i] = pp.Addr[i]
|
sa.Addr[i] = pp.Addr[i]
|
||||||
}
|
}
|
||||||
return sa, 0;
|
return sa, 0
|
||||||
|
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
|
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
|
||||||
sa := new(SockaddrInet6);
|
sa := new(SockaddrInet6)
|
||||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port));
|
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||||
sa.Port = int(p[0])<<8 + int(p[1]);
|
sa.Port = int(p[0])<<8 + int(p[1])
|
||||||
for i := 0; i < len(sa.Addr); i++ {
|
for i := 0; i < len(sa.Addr); i++ {
|
||||||
sa.Addr[i] = pp.Addr[i]
|
sa.Addr[i] = pp.Addr[i]
|
||||||
}
|
}
|
||||||
return sa, 0;
|
return sa, 0
|
||||||
}
|
}
|
||||||
return nil, EAFNOSUPPORT;
|
return nil, EAFNOSUPPORT
|
||||||
}
|
}
|
||||||
|
|
||||||
func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
|
func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
|
||||||
var rsa RawSockaddrAny;
|
var rsa RawSockaddrAny
|
||||||
var len _Socklen = SizeofSockaddrAny;
|
var len _Socklen = SizeofSockaddrAny
|
||||||
nfd, errno = accept(fd, &rsa, &len);
|
nfd, errno = accept(fd, &rsa, &len)
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sa, errno = anyToSockaddr(&rsa);
|
sa, errno = anyToSockaddr(&rsa)
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
Close(nfd);
|
Close(nfd)
|
||||||
nfd = 0;
|
nfd = 0
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getsockname(fd int) (sa Sockaddr, errno int) {
|
func Getsockname(fd int) (sa Sockaddr, errno int) {
|
||||||
var rsa RawSockaddrAny;
|
var rsa RawSockaddrAny
|
||||||
var len _Socklen = SizeofSockaddrAny;
|
var len _Socklen = SizeofSockaddrAny
|
||||||
if errno = getsockname(fd, &rsa, &len); errno != 0 {
|
if errno = getsockname(fd, &rsa, &len); errno != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return anyToSockaddr(&rsa);
|
return anyToSockaddr(&rsa)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getpeername(fd int) (sa Sockaddr, errno int) {
|
func Getpeername(fd int) (sa Sockaddr, errno int) {
|
||||||
var rsa RawSockaddrAny;
|
var rsa RawSockaddrAny
|
||||||
var len _Socklen = SizeofSockaddrAny;
|
var len _Socklen = SizeofSockaddrAny
|
||||||
if errno = getpeername(fd, &rsa, &len); errno != 0 {
|
if errno = getpeername(fd, &rsa, &len); errno != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return anyToSockaddr(&rsa);
|
return anyToSockaddr(&rsa)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Bind(fd int, sa Sockaddr) (errno int) {
|
func Bind(fd int, sa Sockaddr) (errno int) {
|
||||||
ptr, n, err := sa.sockaddr();
|
ptr, n, err := sa.sockaddr()
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return bind(fd, ptr, n);
|
return bind(fd, ptr, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Connect(fd int, sa Sockaddr) (errno int) {
|
func Connect(fd int, sa Sockaddr) (errno int) {
|
||||||
ptr, n, err := sa.sockaddr();
|
ptr, n, err := sa.sockaddr()
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return connect(fd, ptr, n);
|
return connect(fd, ptr, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Socket(domain, typ, proto int) (fd, errno int) {
|
func Socket(domain, typ, proto int) (fd, errno int) {
|
||||||
if domain == AF_INET6 && SocketDisableIPv6 {
|
if domain == AF_INET6 && SocketDisableIPv6 {
|
||||||
return -1, EAFNOSUPPORT
|
return -1, EAFNOSUPPORT
|
||||||
}
|
}
|
||||||
fd, errno = socket(domain, typ, proto);
|
fd, errno = socket(domain, typ, proto)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetsockoptInt(fd, level, opt int, value int) (errno int) {
|
func SetsockoptInt(fd, level, opt int, value int) (errno int) {
|
||||||
var n = int32(value);
|
var n = int32(value)
|
||||||
return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4);
|
return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
|
func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
|
||||||
@ -346,44 +346,44 @@ func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
|
|||||||
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int)
|
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int)
|
||||||
|
|
||||||
func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
|
func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
|
||||||
var rsa RawSockaddrAny;
|
var rsa RawSockaddrAny
|
||||||
var len _Socklen = SizeofSockaddrAny;
|
var len _Socklen = SizeofSockaddrAny
|
||||||
if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 {
|
if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
from, errno = anyToSockaddr(&rsa);
|
from, errno = anyToSockaddr(&rsa)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int)
|
//sys sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int)
|
||||||
|
|
||||||
func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
|
func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
|
||||||
ptr, n, err := to.sockaddr();
|
ptr, n, err := to.sockaddr()
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return sendto(fd, p, flags, ptr, n);
|
return sendto(fd, p, flags, ptr, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int)
|
//sys kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int)
|
||||||
|
|
||||||
func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, errno int) {
|
func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, errno int) {
|
||||||
var change, event uintptr;
|
var change, event uintptr
|
||||||
if len(changes) > 0 {
|
if len(changes) > 0 {
|
||||||
change = uintptr(unsafe.Pointer(&changes[0]))
|
change = uintptr(unsafe.Pointer(&changes[0]))
|
||||||
}
|
}
|
||||||
if len(events) > 0 {
|
if len(events) > 0 {
|
||||||
event = uintptr(unsafe.Pointer(&events[0]))
|
event = uintptr(unsafe.Pointer(&events[0]))
|
||||||
}
|
}
|
||||||
return kevent(kq, change, len(changes), event, len(events), timeout);
|
return kevent(kq, change, len(changes), event, len(events), timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) = SYS___SYSCTL
|
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) = SYS___SYSCTL
|
||||||
|
|
||||||
// Translate "kern.hostname" to []_C_int{0,1,2,3}.
|
// Translate "kern.hostname" to []_C_int{0,1,2,3}.
|
||||||
func nametomib(name string) (mib []_C_int, errno int) {
|
func nametomib(name string) (mib []_C_int, errno int) {
|
||||||
const CTL_MAXNAME = 12;
|
const CTL_MAXNAME = 12
|
||||||
const siz = uintptr(unsafe.Sizeof(mib[0]));
|
const siz = uintptr(unsafe.Sizeof(mib[0]))
|
||||||
|
|
||||||
// NOTE(rsc): It seems strange to set the buffer to have
|
// NOTE(rsc): It seems strange to set the buffer to have
|
||||||
// size CTL_MAXNAME+2 but use only CTL_MAXNAME
|
// size CTL_MAXNAME+2 but use only CTL_MAXNAME
|
||||||
@ -392,29 +392,29 @@ func nametomib(name string) (mib []_C_int, errno int) {
|
|||||||
// I am scared that if we don't include the +2 here, the kernel
|
// I am scared that if we don't include the +2 here, the kernel
|
||||||
// will silently write 2 words farther than we specify
|
// will silently write 2 words farther than we specify
|
||||||
// and we'll get memory corruption.
|
// and we'll get memory corruption.
|
||||||
var buf [CTL_MAXNAME + 2]_C_int;
|
var buf [CTL_MAXNAME + 2]_C_int
|
||||||
n := uintptr(CTL_MAXNAME) * siz;
|
n := uintptr(CTL_MAXNAME) * siz
|
||||||
|
|
||||||
p := (*byte)(unsafe.Pointer(&buf[0]));
|
p := (*byte)(unsafe.Pointer(&buf[0]))
|
||||||
bytes := StringByteSlice(name);
|
bytes := StringByteSlice(name)
|
||||||
|
|
||||||
// Magic sysctl: "setting" 0.3 to a string name
|
// Magic sysctl: "setting" 0.3 to a string name
|
||||||
// lets you read back the array of integers form.
|
// lets you read back the array of integers form.
|
||||||
if errno = sysctl([]_C_int{0, 3}, p, &n, &bytes[0], uintptr(len(name))); errno != 0 {
|
if errno = sysctl([]_C_int{0, 3}, p, &n, &bytes[0], uintptr(len(name))); errno != 0 {
|
||||||
return nil, errno
|
return nil, errno
|
||||||
}
|
}
|
||||||
return buf[0 : n/siz], 0;
|
return buf[0 : n/siz], 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func Sysctl(name string) (value string, errno int) {
|
func Sysctl(name string) (value string, errno int) {
|
||||||
// Translate name to mib number.
|
// Translate name to mib number.
|
||||||
mib, errno := nametomib(name);
|
mib, errno := nametomib(name)
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return "", errno
|
return "", errno
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find size.
|
// Find size.
|
||||||
n := uintptr(0);
|
n := uintptr(0)
|
||||||
if errno = sysctl(mib, nil, &n, nil, 0); errno != 0 {
|
if errno = sysctl(mib, nil, &n, nil, 0); errno != 0 {
|
||||||
return "", errno
|
return "", errno
|
||||||
}
|
}
|
||||||
@ -423,7 +423,7 @@ func Sysctl(name string) (value string, errno int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read into buffer of that size.
|
// Read into buffer of that size.
|
||||||
buf := make([]byte, n);
|
buf := make([]byte, n)
|
||||||
if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 {
|
if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 {
|
||||||
return "", errno
|
return "", errno
|
||||||
}
|
}
|
||||||
@ -432,26 +432,26 @@ func Sysctl(name string) (value string, errno int) {
|
|||||||
if n > 0 && buf[n-1] == '\x00' {
|
if n > 0 && buf[n-1] == '\x00' {
|
||||||
n--
|
n--
|
||||||
}
|
}
|
||||||
return string(buf[0:n]), 0;
|
return string(buf[0:n]), 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func SysctlUint32(name string) (value uint32, errno int) {
|
func SysctlUint32(name string) (value uint32, errno int) {
|
||||||
// Translate name to mib number.
|
// Translate name to mib number.
|
||||||
mib, errno := nametomib(name);
|
mib, errno := nametomib(name)
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return 0, errno
|
return 0, errno
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read into buffer of that size.
|
// Read into buffer of that size.
|
||||||
n := uintptr(4);
|
n := uintptr(4)
|
||||||
buf := make([]byte, 4);
|
buf := make([]byte, 4)
|
||||||
if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 {
|
if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 {
|
||||||
return 0, errno
|
return 0, errno
|
||||||
}
|
}
|
||||||
if n != 4 {
|
if n != 4 {
|
||||||
return 0, EIO
|
return 0, EIO
|
||||||
}
|
}
|
||||||
return *(*uint32)(unsafe.Pointer(&buf[0])), 0;
|
return *(*uint32)(unsafe.Pointer(&buf[0])), 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: wrap
|
// TODO: wrap
|
||||||
|
@ -9,18 +9,18 @@ func Getpagesize() int { return 4096 }
|
|||||||
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
||||||
|
|
||||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||||
ts.Sec = int32(nsec / 1e9);
|
ts.Sec = int32(nsec / 1e9)
|
||||||
ts.Nsec = int32(nsec % 1e9);
|
ts.Nsec = int32(nsec % 1e9)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
|
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
|
||||||
|
|
||||||
func NsecToTimeval(nsec int64) (tv Timeval) {
|
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||||
nsec += 999; // round up to microsecond
|
nsec += 999 // round up to microsecond
|
||||||
tv.Usec = int32(nsec % 1e9 / 1e3);
|
tv.Usec = int32(nsec % 1e9 / 1e3)
|
||||||
tv.Sec = int32(nsec / 1e9);
|
tv.Sec = int32(nsec / 1e9)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys gettimeofday(tp *Timeval) (sec int32, usec int32, errno int)
|
//sys gettimeofday(tp *Timeval) (sec int32, usec int32, errno int)
|
||||||
@ -28,14 +28,14 @@ func Gettimeofday(tv *Timeval) (errno int) {
|
|||||||
// The tv passed to gettimeofday must be non-nil
|
// The tv passed to gettimeofday must be non-nil
|
||||||
// but is otherwise unused. The answers come back
|
// but is otherwise unused. The answers come back
|
||||||
// in the two registers.
|
// in the two registers.
|
||||||
sec, usec, err := gettimeofday(tv);
|
sec, usec, err := gettimeofday(tv)
|
||||||
tv.Sec = int32(sec);
|
tv.Sec = int32(sec)
|
||||||
tv.Usec = int32(usec);
|
tv.Usec = int32(usec)
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetKevent(k *Kevent_t, fd, mode, flags int) {
|
func SetKevent(k *Kevent_t, fd, mode, flags int) {
|
||||||
k.Ident = uint32(fd);
|
k.Ident = uint32(fd)
|
||||||
k.Filter = int16(mode);
|
k.Filter = int16(mode)
|
||||||
k.Flags = uint16(flags);
|
k.Flags = uint16(flags)
|
||||||
}
|
}
|
||||||
|
@ -9,18 +9,18 @@ func Getpagesize() int { return 4096 }
|
|||||||
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
||||||
|
|
||||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||||
ts.Sec = nsec / 1e9;
|
ts.Sec = nsec / 1e9
|
||||||
ts.Nsec = nsec % 1e9;
|
ts.Nsec = nsec % 1e9
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
|
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
|
||||||
|
|
||||||
func NsecToTimeval(nsec int64) (tv Timeval) {
|
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||||
nsec += 999; // round up to microsecond
|
nsec += 999 // round up to microsecond
|
||||||
tv.Usec = int32(nsec % 1e9 / 1e3);
|
tv.Usec = int32(nsec % 1e9 / 1e3)
|
||||||
tv.Sec = int64(nsec / 1e9);
|
tv.Sec = int64(nsec / 1e9)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys gettimeofday(tp *Timeval) (sec int64, usec int32, errno int)
|
//sys gettimeofday(tp *Timeval) (sec int64, usec int32, errno int)
|
||||||
@ -28,14 +28,14 @@ func Gettimeofday(tv *Timeval) (errno int) {
|
|||||||
// The tv passed to gettimeofday must be non-nil
|
// The tv passed to gettimeofday must be non-nil
|
||||||
// but is otherwise unused. The answers come back
|
// but is otherwise unused. The answers come back
|
||||||
// in the two registers.
|
// in the two registers.
|
||||||
sec, usec, err := gettimeofday(tv);
|
sec, usec, err := gettimeofday(tv)
|
||||||
tv.Sec = sec;
|
tv.Sec = sec
|
||||||
tv.Usec = usec;
|
tv.Usec = usec
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetKevent(k *Kevent_t, fd, mode, flags int) {
|
func SetKevent(k *Kevent_t, fd, mode, flags int) {
|
||||||
k.Ident = uint64(fd);
|
k.Ident = uint64(fd)
|
||||||
k.Filter = int16(mode);
|
k.Filter = int16(mode)
|
||||||
k.Flags = uint16(flags);
|
k.Flags = uint16(flags)
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ func Getwd() (string, int) { return "", ENOTSUP }
|
|||||||
//sys setgroups(ngid int, gid *_Gid_t) (errno int)
|
//sys setgroups(ngid int, gid *_Gid_t) (errno int)
|
||||||
|
|
||||||
func Getgroups() (gids []int, errno int) {
|
func Getgroups() (gids []int, errno int) {
|
||||||
n, err := getgroups(0, nil);
|
n, err := getgroups(0, nil)
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return nil, errno
|
return nil, errno
|
||||||
}
|
}
|
||||||
@ -47,16 +47,16 @@ func Getgroups() (gids []int, errno int) {
|
|||||||
return nil, EINVAL
|
return nil, EINVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
a := make([]_Gid_t, n);
|
a := make([]_Gid_t, n)
|
||||||
n, err = getgroups(n, &a[0]);
|
n, err = getgroups(n, &a[0])
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return nil, errno
|
return nil, errno
|
||||||
}
|
}
|
||||||
gids = make([]int, n);
|
gids = make([]int, n)
|
||||||
for i, v := range a[0:n] {
|
for i, v := range a[0:n] {
|
||||||
gids[i] = int(v)
|
gids[i] = int(v)
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setgroups(gids []int) (errno int) {
|
func Setgroups(gids []int) (errno int) {
|
||||||
@ -64,11 +64,11 @@ func Setgroups(gids []int) (errno int) {
|
|||||||
return setgroups(0, nil)
|
return setgroups(0, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
a := make([]_Gid_t, len(gids));
|
a := make([]_Gid_t, len(gids))
|
||||||
for i, v := range gids {
|
for i, v := range gids {
|
||||||
a[i] = _Gid_t(v)
|
a[i] = _Gid_t(v)
|
||||||
}
|
}
|
||||||
return setgroups(len(a), &a[0]);
|
return setgroups(len(a), &a[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait status is 7 bits at bottom, either 0 (exited),
|
// Wait status is 7 bits at bottom, either 0 (exited),
|
||||||
@ -80,12 +80,12 @@ func Setgroups(gids []int) (errno int) {
|
|||||||
type WaitStatus uint32
|
type WaitStatus uint32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
mask = 0x7F;
|
mask = 0x7F
|
||||||
core = 0x80;
|
core = 0x80
|
||||||
shift = 8;
|
shift = 8
|
||||||
|
|
||||||
exited = 0;
|
exited = 0
|
||||||
stopped = 0x7F;
|
stopped = 0x7F
|
||||||
)
|
)
|
||||||
|
|
||||||
func (w WaitStatus) Exited() bool { return w&mask == exited }
|
func (w WaitStatus) Exited() bool { return w&mask == exited }
|
||||||
@ -94,17 +94,17 @@ func (w WaitStatus) ExitStatus() int {
|
|||||||
if w&mask != exited {
|
if w&mask != exited {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return int(w >> shift);
|
return int(w >> shift)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
|
func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
|
||||||
|
|
||||||
func (w WaitStatus) Signal() int {
|
func (w WaitStatus) Signal() int {
|
||||||
sig := int(w & mask);
|
sig := int(w & mask)
|
||||||
if sig == stopped || sig == 0 {
|
if sig == stopped || sig == 0 {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return sig;
|
return sig
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
|
func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
|
||||||
@ -117,7 +117,7 @@ func (w WaitStatus) StopSignal() int {
|
|||||||
if !w.Stopped() {
|
if !w.Stopped() {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return int(w>>shift) & 0xFF;
|
return int(w>>shift) & 0xFF
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WaitStatus) TrapCause() int {
|
func (w WaitStatus) TrapCause() int {
|
||||||
@ -128,12 +128,12 @@ func (w WaitStatus) TrapCause() int {
|
|||||||
//sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int)
|
//sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int)
|
||||||
|
|
||||||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
|
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
|
||||||
var status _C_int;
|
var status _C_int
|
||||||
wpid, errno = wait4(pid, &status, options, rusage);
|
wpid, errno = wait4(pid, &status, options, rusage)
|
||||||
if wstatus != nil {
|
if wstatus != nil {
|
||||||
*wstatus = WaitStatus(status)
|
*wstatus = WaitStatus(status)
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys pipe() (r int, w int, errno int)
|
//sys pipe() (r int, w int, errno int)
|
||||||
@ -142,13 +142,13 @@ func Pipe(p []int) (errno int) {
|
|||||||
if len(p) != 2 {
|
if len(p) != 2 {
|
||||||
return EINVAL
|
return EINVAL
|
||||||
}
|
}
|
||||||
p[0], p[1], errno = pipe();
|
p[0], p[1], errno = pipe()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Sleep(ns int64) (errno int) {
|
func Sleep(ns int64) (errno int) {
|
||||||
tv := NsecToTimeval(ns);
|
tv := NsecToTimeval(ns)
|
||||||
return Select(0, nil, nil, nil, &tv);
|
return Select(0, nil, nil, nil, &tv)
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int)
|
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int)
|
||||||
@ -165,173 +165,173 @@ func Sleep(ns int64) (errno int) {
|
|||||||
var SocketDisableIPv6 bool
|
var SocketDisableIPv6 bool
|
||||||
|
|
||||||
type Sockaddr interface {
|
type Sockaddr interface {
|
||||||
sockaddr() (ptr uintptr, len _Socklen, errno int); // lowercase; only we can define Sockaddrs
|
sockaddr() (ptr uintptr, len _Socklen, errno int) // lowercase; only we can define Sockaddrs
|
||||||
}
|
}
|
||||||
|
|
||||||
type SockaddrInet4 struct {
|
type SockaddrInet4 struct {
|
||||||
Port int;
|
Port int
|
||||||
Addr [4]byte;
|
Addr [4]byte
|
||||||
raw RawSockaddrInet4;
|
raw RawSockaddrInet4
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) {
|
func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) {
|
||||||
if sa.Port < 0 || sa.Port > 0xFFFF {
|
if sa.Port < 0 || sa.Port > 0xFFFF {
|
||||||
return 0, 0, EINVAL
|
return 0, 0, EINVAL
|
||||||
}
|
}
|
||||||
sa.raw.Len = SizeofSockaddrInet4;
|
sa.raw.Len = SizeofSockaddrInet4
|
||||||
sa.raw.Family = AF_INET;
|
sa.raw.Family = AF_INET
|
||||||
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
|
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
|
||||||
p[0] = byte(sa.Port >> 8);
|
p[0] = byte(sa.Port >> 8)
|
||||||
p[1] = byte(sa.Port);
|
p[1] = byte(sa.Port)
|
||||||
for i := 0; i < len(sa.Addr); i++ {
|
for i := 0; i < len(sa.Addr); i++ {
|
||||||
sa.raw.Addr[i] = sa.Addr[i]
|
sa.raw.Addr[i] = sa.Addr[i]
|
||||||
}
|
}
|
||||||
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0;
|
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0
|
||||||
}
|
}
|
||||||
|
|
||||||
type SockaddrInet6 struct {
|
type SockaddrInet6 struct {
|
||||||
Port int;
|
Port int
|
||||||
Addr [16]byte;
|
Addr [16]byte
|
||||||
raw RawSockaddrInet6;
|
raw RawSockaddrInet6
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) {
|
func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) {
|
||||||
if sa.Port < 0 || sa.Port > 0xFFFF {
|
if sa.Port < 0 || sa.Port > 0xFFFF {
|
||||||
return 0, 0, EINVAL
|
return 0, 0, EINVAL
|
||||||
}
|
}
|
||||||
sa.raw.Len = SizeofSockaddrInet6;
|
sa.raw.Len = SizeofSockaddrInet6
|
||||||
sa.raw.Family = AF_INET6;
|
sa.raw.Family = AF_INET6
|
||||||
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
|
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
|
||||||
p[0] = byte(sa.Port >> 8);
|
p[0] = byte(sa.Port >> 8)
|
||||||
p[1] = byte(sa.Port);
|
p[1] = byte(sa.Port)
|
||||||
for i := 0; i < len(sa.Addr); i++ {
|
for i := 0; i < len(sa.Addr); i++ {
|
||||||
sa.raw.Addr[i] = sa.Addr[i]
|
sa.raw.Addr[i] = sa.Addr[i]
|
||||||
}
|
}
|
||||||
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0;
|
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0
|
||||||
}
|
}
|
||||||
|
|
||||||
type SockaddrUnix struct {
|
type SockaddrUnix struct {
|
||||||
Name string;
|
Name string
|
||||||
raw RawSockaddrUnix;
|
raw RawSockaddrUnix
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
|
func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
|
||||||
name := sa.Name;
|
name := sa.Name
|
||||||
n := len(name);
|
n := len(name)
|
||||||
if n >= len(sa.raw.Path) || n == 0 {
|
if n >= len(sa.raw.Path) || n == 0 {
|
||||||
return 0, 0, EINVAL
|
return 0, 0, EINVAL
|
||||||
}
|
}
|
||||||
sa.raw.Len = byte(3 + n); // 2 for Family, Len; 1 for NUL
|
sa.raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL
|
||||||
sa.raw.Family = AF_UNIX;
|
sa.raw.Family = AF_UNIX
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
sa.raw.Path[i] = int8(name[i])
|
sa.raw.Path[i] = int8(name[i])
|
||||||
}
|
}
|
||||||
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0;
|
return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
|
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
|
||||||
switch rsa.Addr.Family {
|
switch rsa.Addr.Family {
|
||||||
case AF_UNIX:
|
case AF_UNIX:
|
||||||
pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa));
|
pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
|
||||||
if pp.Len < 3 || pp.Len > SizeofSockaddrUnix {
|
if pp.Len < 3 || pp.Len > SizeofSockaddrUnix {
|
||||||
return nil, EINVAL
|
return nil, EINVAL
|
||||||
}
|
}
|
||||||
sa := new(SockaddrUnix);
|
sa := new(SockaddrUnix)
|
||||||
n := int(pp.Len) - 3; // subtract leading Family, Len, terminating NUL
|
n := int(pp.Len) - 3 // subtract leading Family, Len, terminating NUL
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
if pp.Path[i] == 0 {
|
if pp.Path[i] == 0 {
|
||||||
// found early NUL; assume Len is overestimating
|
// found early NUL; assume Len is overestimating
|
||||||
n = i;
|
n = i
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]));
|
bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))
|
||||||
sa.Name = string(bytes[0:n]);
|
sa.Name = string(bytes[0:n])
|
||||||
return sa, 0;
|
return sa, 0
|
||||||
|
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
|
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
|
||||||
sa := new(SockaddrInet4);
|
sa := new(SockaddrInet4)
|
||||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port));
|
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||||
sa.Port = int(p[0])<<8 + int(p[1]);
|
sa.Port = int(p[0])<<8 + int(p[1])
|
||||||
for i := 0; i < len(sa.Addr); i++ {
|
for i := 0; i < len(sa.Addr); i++ {
|
||||||
sa.Addr[i] = pp.Addr[i]
|
sa.Addr[i] = pp.Addr[i]
|
||||||
}
|
}
|
||||||
return sa, 0;
|
return sa, 0
|
||||||
|
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
|
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
|
||||||
sa := new(SockaddrInet6);
|
sa := new(SockaddrInet6)
|
||||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port));
|
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||||
sa.Port = int(p[0])<<8 + int(p[1]);
|
sa.Port = int(p[0])<<8 + int(p[1])
|
||||||
for i := 0; i < len(sa.Addr); i++ {
|
for i := 0; i < len(sa.Addr); i++ {
|
||||||
sa.Addr[i] = pp.Addr[i]
|
sa.Addr[i] = pp.Addr[i]
|
||||||
}
|
}
|
||||||
return sa, 0;
|
return sa, 0
|
||||||
}
|
}
|
||||||
return nil, EAFNOSUPPORT;
|
return nil, EAFNOSUPPORT
|
||||||
}
|
}
|
||||||
|
|
||||||
func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
|
func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
|
||||||
var rsa RawSockaddrAny;
|
var rsa RawSockaddrAny
|
||||||
var len _Socklen = SizeofSockaddrAny;
|
var len _Socklen = SizeofSockaddrAny
|
||||||
nfd, errno = accept(fd, &rsa, &len);
|
nfd, errno = accept(fd, &rsa, &len)
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sa, errno = anyToSockaddr(&rsa);
|
sa, errno = anyToSockaddr(&rsa)
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
Close(nfd);
|
Close(nfd)
|
||||||
nfd = 0;
|
nfd = 0
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getsockname(fd int) (sa Sockaddr, errno int) {
|
func Getsockname(fd int) (sa Sockaddr, errno int) {
|
||||||
var rsa RawSockaddrAny;
|
var rsa RawSockaddrAny
|
||||||
var len _Socklen = SizeofSockaddrAny;
|
var len _Socklen = SizeofSockaddrAny
|
||||||
if errno = getsockname(fd, &rsa, &len); errno != 0 {
|
if errno = getsockname(fd, &rsa, &len); errno != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return anyToSockaddr(&rsa);
|
return anyToSockaddr(&rsa)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getpeername(fd int) (sa Sockaddr, errno int) {
|
func Getpeername(fd int) (sa Sockaddr, errno int) {
|
||||||
var rsa RawSockaddrAny;
|
var rsa RawSockaddrAny
|
||||||
var len _Socklen = SizeofSockaddrAny;
|
var len _Socklen = SizeofSockaddrAny
|
||||||
if errno = getpeername(fd, &rsa, &len); errno != 0 {
|
if errno = getpeername(fd, &rsa, &len); errno != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return anyToSockaddr(&rsa);
|
return anyToSockaddr(&rsa)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Bind(fd int, sa Sockaddr) (errno int) {
|
func Bind(fd int, sa Sockaddr) (errno int) {
|
||||||
ptr, n, err := sa.sockaddr();
|
ptr, n, err := sa.sockaddr()
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return bind(fd, ptr, n);
|
return bind(fd, ptr, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Connect(fd int, sa Sockaddr) (errno int) {
|
func Connect(fd int, sa Sockaddr) (errno int) {
|
||||||
ptr, n, err := sa.sockaddr();
|
ptr, n, err := sa.sockaddr()
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return connect(fd, ptr, n);
|
return connect(fd, ptr, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Socket(domain, typ, proto int) (fd, errno int) {
|
func Socket(domain, typ, proto int) (fd, errno int) {
|
||||||
if domain == AF_INET6 && SocketDisableIPv6 {
|
if domain == AF_INET6 && SocketDisableIPv6 {
|
||||||
return -1, EAFNOSUPPORT
|
return -1, EAFNOSUPPORT
|
||||||
}
|
}
|
||||||
fd, errno = socket(domain, typ, proto);
|
fd, errno = socket(domain, typ, proto)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetsockoptInt(fd, level, opt int, value int) (errno int) {
|
func SetsockoptInt(fd, level, opt int, value int) (errno int) {
|
||||||
var n = int32(value);
|
var n = int32(value)
|
||||||
return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4);
|
return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
|
func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
|
||||||
@ -346,44 +346,44 @@ func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
|
|||||||
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int)
|
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int)
|
||||||
|
|
||||||
func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
|
func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
|
||||||
var rsa RawSockaddrAny;
|
var rsa RawSockaddrAny
|
||||||
var len _Socklen = SizeofSockaddrAny;
|
var len _Socklen = SizeofSockaddrAny
|
||||||
if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 {
|
if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
from, errno = anyToSockaddr(&rsa);
|
from, errno = anyToSockaddr(&rsa)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int)
|
//sys sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int)
|
||||||
|
|
||||||
func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
|
func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
|
||||||
ptr, n, err := to.sockaddr();
|
ptr, n, err := to.sockaddr()
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return sendto(fd, p, flags, ptr, n);
|
return sendto(fd, p, flags, ptr, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int)
|
//sys kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int)
|
||||||
|
|
||||||
func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, errno int) {
|
func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, errno int) {
|
||||||
var change, event uintptr;
|
var change, event uintptr
|
||||||
if len(changes) > 0 {
|
if len(changes) > 0 {
|
||||||
change = uintptr(unsafe.Pointer(&changes[0]))
|
change = uintptr(unsafe.Pointer(&changes[0]))
|
||||||
}
|
}
|
||||||
if len(events) > 0 {
|
if len(events) > 0 {
|
||||||
event = uintptr(unsafe.Pointer(&events[0]))
|
event = uintptr(unsafe.Pointer(&events[0]))
|
||||||
}
|
}
|
||||||
return kevent(kq, change, len(changes), event, len(events), timeout);
|
return kevent(kq, change, len(changes), event, len(events), timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) = SYS___SYSCTL
|
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) = SYS___SYSCTL
|
||||||
|
|
||||||
// Translate "kern.hostname" to []_C_int{0,1,2,3}.
|
// Translate "kern.hostname" to []_C_int{0,1,2,3}.
|
||||||
func nametomib(name string) (mib []_C_int, errno int) {
|
func nametomib(name string) (mib []_C_int, errno int) {
|
||||||
const CTL_MAXNAME = 12;
|
const CTL_MAXNAME = 12
|
||||||
const siz = uintptr(unsafe.Sizeof(mib[0]));
|
const siz = uintptr(unsafe.Sizeof(mib[0]))
|
||||||
|
|
||||||
// NOTE(rsc): It seems strange to set the buffer to have
|
// NOTE(rsc): It seems strange to set the buffer to have
|
||||||
// size CTL_MAXNAME+2 but use only CTL_MAXNAME
|
// size CTL_MAXNAME+2 but use only CTL_MAXNAME
|
||||||
@ -392,29 +392,29 @@ func nametomib(name string) (mib []_C_int, errno int) {
|
|||||||
// I am scared that if we don't include the +2 here, the kernel
|
// I am scared that if we don't include the +2 here, the kernel
|
||||||
// will silently write 2 words farther than we specify
|
// will silently write 2 words farther than we specify
|
||||||
// and we'll get memory corruption.
|
// and we'll get memory corruption.
|
||||||
var buf [CTL_MAXNAME + 2]_C_int;
|
var buf [CTL_MAXNAME + 2]_C_int
|
||||||
n := uintptr(CTL_MAXNAME) * siz;
|
n := uintptr(CTL_MAXNAME) * siz
|
||||||
|
|
||||||
p := (*byte)(unsafe.Pointer(&buf[0]));
|
p := (*byte)(unsafe.Pointer(&buf[0]))
|
||||||
bytes := StringByteSlice(name);
|
bytes := StringByteSlice(name)
|
||||||
|
|
||||||
// Magic sysctl: "setting" 0.3 to a string name
|
// Magic sysctl: "setting" 0.3 to a string name
|
||||||
// lets you read back the array of integers form.
|
// lets you read back the array of integers form.
|
||||||
if errno = sysctl([]_C_int{0, 3}, p, &n, &bytes[0], uintptr(len(name))); errno != 0 {
|
if errno = sysctl([]_C_int{0, 3}, p, &n, &bytes[0], uintptr(len(name))); errno != 0 {
|
||||||
return nil, errno
|
return nil, errno
|
||||||
}
|
}
|
||||||
return buf[0 : n/siz], 0;
|
return buf[0 : n/siz], 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func Sysctl(name string) (value string, errno int) {
|
func Sysctl(name string) (value string, errno int) {
|
||||||
// Translate name to mib number.
|
// Translate name to mib number.
|
||||||
mib, errno := nametomib(name);
|
mib, errno := nametomib(name)
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return "", errno
|
return "", errno
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find size.
|
// Find size.
|
||||||
n := uintptr(0);
|
n := uintptr(0)
|
||||||
if errno = sysctl(mib, nil, &n, nil, 0); errno != 0 {
|
if errno = sysctl(mib, nil, &n, nil, 0); errno != 0 {
|
||||||
return "", errno
|
return "", errno
|
||||||
}
|
}
|
||||||
@ -423,7 +423,7 @@ func Sysctl(name string) (value string, errno int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read into buffer of that size.
|
// Read into buffer of that size.
|
||||||
buf := make([]byte, n);
|
buf := make([]byte, n)
|
||||||
if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 {
|
if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 {
|
||||||
return "", errno
|
return "", errno
|
||||||
}
|
}
|
||||||
@ -432,26 +432,26 @@ func Sysctl(name string) (value string, errno int) {
|
|||||||
if n > 0 && buf[n-1] == '\x00' {
|
if n > 0 && buf[n-1] == '\x00' {
|
||||||
n--
|
n--
|
||||||
}
|
}
|
||||||
return string(buf[0:n]), 0;
|
return string(buf[0:n]), 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func SysctlUint32(name string) (value uint32, errno int) {
|
func SysctlUint32(name string) (value uint32, errno int) {
|
||||||
// Translate name to mib number.
|
// Translate name to mib number.
|
||||||
mib, errno := nametomib(name);
|
mib, errno := nametomib(name)
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return 0, errno
|
return 0, errno
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read into buffer of that size.
|
// Read into buffer of that size.
|
||||||
n := uintptr(4);
|
n := uintptr(4)
|
||||||
buf := make([]byte, 4);
|
buf := make([]byte, 4)
|
||||||
if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 {
|
if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 {
|
||||||
return 0, errno
|
return 0, errno
|
||||||
}
|
}
|
||||||
if n != 4 {
|
if n != 4 {
|
||||||
return 0, EIO
|
return 0, EIO
|
||||||
}
|
}
|
||||||
return *(*uint32)(unsafe.Pointer(&buf[0])), 0;
|
return *(*uint32)(unsafe.Pointer(&buf[0])), 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: wrap
|
// TODO: wrap
|
||||||
|
@ -9,22 +9,22 @@ func Getpagesize() int { return 4096 }
|
|||||||
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
||||||
|
|
||||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||||
ts.Sec = int32(nsec / 1e9);
|
ts.Sec = int32(nsec / 1e9)
|
||||||
ts.Nsec = int32(nsec % 1e9);
|
ts.Nsec = int32(nsec % 1e9)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
|
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
|
||||||
|
|
||||||
func NsecToTimeval(nsec int64) (tv Timeval) {
|
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||||
nsec += 999; // round up to microsecond
|
nsec += 999 // round up to microsecond
|
||||||
tv.Usec = int32(nsec % 1e9 / 1e3);
|
tv.Usec = int32(nsec % 1e9 / 1e3)
|
||||||
tv.Sec = int32(nsec / 1e9);
|
tv.Sec = int32(nsec / 1e9)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetKevent(k *Kevent_t, fd, mode, flags int) {
|
func SetKevent(k *Kevent_t, fd, mode, flags int) {
|
||||||
k.Ident = uint32(fd);
|
k.Ident = uint32(fd)
|
||||||
k.Filter = int16(mode);
|
k.Filter = int16(mode)
|
||||||
k.Flags = uint16(flags);
|
k.Flags = uint16(flags)
|
||||||
}
|
}
|
||||||
|
@ -9,22 +9,22 @@ func Getpagesize() int { return 4096 }
|
|||||||
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
||||||
|
|
||||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||||
ts.Sec = nsec / 1e9;
|
ts.Sec = nsec / 1e9
|
||||||
ts.Nsec = nsec % 1e9;
|
ts.Nsec = nsec % 1e9
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
|
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
|
||||||
|
|
||||||
func NsecToTimeval(nsec int64) (tv Timeval) {
|
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||||
nsec += 999; // round up to microsecond
|
nsec += 999 // round up to microsecond
|
||||||
tv.Usec = nsec % 1e9 / 1e3;
|
tv.Usec = nsec % 1e9 / 1e3
|
||||||
tv.Sec = int64(nsec / 1e9);
|
tv.Sec = int64(nsec / 1e9)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetKevent(k *Kevent_t, fd, mode, flags int) {
|
func SetKevent(k *Kevent_t, fd, mode, flags int) {
|
||||||
k.Ident = uint64(fd);
|
k.Ident = uint64(fd)
|
||||||
k.Filter = int16(mode);
|
k.Filter = int16(mode)
|
||||||
k.Flags = uint16(flags);
|
k.Flags = uint16(flags)
|
||||||
}
|
}
|
||||||
|
@ -24,11 +24,11 @@ func Pipe(p []int) (errno int) {
|
|||||||
if len(p) != 2 {
|
if len(p) != 2 {
|
||||||
return EINVAL
|
return EINVAL
|
||||||
}
|
}
|
||||||
var pp [2]_C_int;
|
var pp [2]_C_int
|
||||||
errno = pipe(&pp);
|
errno = pipe(&pp)
|
||||||
p[0] = int(pp[0]);
|
p[0] = int(pp[0])
|
||||||
p[1] = int(pp[1]);
|
p[1] = int(pp[1])
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys utimes(path string, times *[2]Timeval) (errno int)
|
//sys utimes(path string, times *[2]Timeval) (errno int)
|
||||||
@ -36,7 +36,7 @@ func Utimes(path string, tv []Timeval) (errno int) {
|
|||||||
if len(tv) != 2 {
|
if len(tv) != 2 {
|
||||||
return EINVAL
|
return EINVAL
|
||||||
}
|
}
|
||||||
return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])));
|
return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys futimesat(dirfd int, path string, times *[2]Timeval) (errno int)
|
//sys futimesat(dirfd int, path string, times *[2]Timeval) (errno int)
|
||||||
@ -44,15 +44,15 @@ func Futimesat(dirfd int, path string, tv []Timeval) (errno int) {
|
|||||||
if len(tv) != 2 {
|
if len(tv) != 2 {
|
||||||
return EINVAL
|
return EINVAL
|
||||||
}
|
}
|
||||||
return futimesat(dirfd, path, (*[2]Timeval)(unsafe.Pointer(&tv[0])));
|
return futimesat(dirfd, path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImplementsGetwd = true
|
const ImplementsGetwd = true
|
||||||
|
|
||||||
//sys Getcwd(buf []byte) (n int, errno int)
|
//sys Getcwd(buf []byte) (n int, errno int)
|
||||||
func Getwd() (wd string, errno int) {
|
func Getwd() (wd string, errno int) {
|
||||||
var buf [PathMax]byte;
|
var buf [PathMax]byte
|
||||||
n, err := Getcwd(&buf);
|
n, err := Getcwd(&buf)
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -60,11 +60,11 @@ func Getwd() (wd string, errno int) {
|
|||||||
if n < 1 || n > len(buf) || buf[n-1] != 0 {
|
if n < 1 || n > len(buf) || buf[n-1] != 0 {
|
||||||
return "", EINVAL
|
return "", EINVAL
|
||||||
}
|
}
|
||||||
return string(buf[0 : n-1]), 0;
|
return string(buf[0 : n-1]), 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getgroups() (gids []int, errno int) {
|
func Getgroups() (gids []int, errno int) {
|
||||||
n, err := getgroups(0, nil);
|
n, err := getgroups(0, nil)
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return nil, errno
|
return nil, errno
|
||||||
}
|
}
|
||||||
@ -77,16 +77,16 @@ func Getgroups() (gids []int, errno int) {
|
|||||||
return nil, EINVAL
|
return nil, EINVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
a := make([]_Gid_t, n);
|
a := make([]_Gid_t, n)
|
||||||
n, err = getgroups(n, &a[0]);
|
n, err = getgroups(n, &a[0])
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return nil, errno
|
return nil, errno
|
||||||
}
|
}
|
||||||
gids = make([]int, n);
|
gids = make([]int, n)
|
||||||
for i, v := range a[0:n] {
|
for i, v := range a[0:n] {
|
||||||
gids[i] = int(v)
|
gids[i] = int(v)
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setgroups(gids []int) (errno int) {
|
func Setgroups(gids []int) (errno int) {
|
||||||
@ -94,11 +94,11 @@ func Setgroups(gids []int) (errno int) {
|
|||||||
return setgroups(0, nil)
|
return setgroups(0, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
a := make([]_Gid_t, len(gids));
|
a := make([]_Gid_t, len(gids))
|
||||||
for i, v := range gids {
|
for i, v := range gids {
|
||||||
a[i] = _Gid_t(v)
|
a[i] = _Gid_t(v)
|
||||||
}
|
}
|
||||||
return setgroups(len(a), &a[0]);
|
return setgroups(len(a), &a[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
type WaitStatus uint32
|
type WaitStatus uint32
|
||||||
@ -113,11 +113,11 @@ type WaitStatus uint32
|
|||||||
// from stopped via the core dump bit.
|
// from stopped via the core dump bit.
|
||||||
|
|
||||||
const (
|
const (
|
||||||
mask = 0x7F;
|
mask = 0x7F
|
||||||
core = 0x80;
|
core = 0x80
|
||||||
exited = 0x00;
|
exited = 0x00
|
||||||
stopped = 0x7F;
|
stopped = 0x7F
|
||||||
shift = 8;
|
shift = 8
|
||||||
)
|
)
|
||||||
|
|
||||||
func (w WaitStatus) Exited() bool { return w&mask == exited }
|
func (w WaitStatus) Exited() bool { return w&mask == exited }
|
||||||
@ -134,44 +134,44 @@ func (w WaitStatus) ExitStatus() int {
|
|||||||
if !w.Exited() {
|
if !w.Exited() {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return int(w>>shift) & 0xFF;
|
return int(w>>shift) & 0xFF
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WaitStatus) Signal() int {
|
func (w WaitStatus) Signal() int {
|
||||||
if !w.Signaled() {
|
if !w.Signaled() {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return int(w & mask);
|
return int(w & mask)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WaitStatus) StopSignal() int {
|
func (w WaitStatus) StopSignal() int {
|
||||||
if !w.Stopped() {
|
if !w.Stopped() {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return int(w>>shift) & 0xFF;
|
return int(w>>shift) & 0xFF
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WaitStatus) TrapCause() int {
|
func (w WaitStatus) TrapCause() int {
|
||||||
if w.StopSignal() != SIGTRAP {
|
if w.StopSignal() != SIGTRAP {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return int(w>>shift) >> 8;
|
return int(w>>shift) >> 8
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int)
|
//sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int)
|
||||||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
|
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
|
||||||
var status _C_int;
|
var status _C_int
|
||||||
wpid, errno = wait4(pid, &status, options, rusage);
|
wpid, errno = wait4(pid, &status, options, rusage)
|
||||||
if wstatus != nil {
|
if wstatus != nil {
|
||||||
*wstatus = WaitStatus(status)
|
*wstatus = WaitStatus(status)
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Sleep(nsec int64) (errno int) {
|
func Sleep(nsec int64) (errno int) {
|
||||||
tv := NsecToTimeval(nsec);
|
tv := NsecToTimeval(nsec)
|
||||||
_, err := Select(0, nil, nil, nil, &tv);
|
_, err := Select(0, nil, nil, nil, &tv)
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// For testing: clients can set this flag to force
|
// For testing: clients can set this flag to force
|
||||||
@ -179,61 +179,61 @@ func Sleep(nsec int64) (errno int) {
|
|||||||
var SocketDisableIPv6 bool
|
var SocketDisableIPv6 bool
|
||||||
|
|
||||||
type Sockaddr interface {
|
type Sockaddr interface {
|
||||||
sockaddr() (ptr uintptr, len _Socklen, errno int); // lowercase; only we can define Sockaddrs
|
sockaddr() (ptr uintptr, len _Socklen, errno int) // lowercase; only we can define Sockaddrs
|
||||||
}
|
}
|
||||||
|
|
||||||
type SockaddrInet4 struct {
|
type SockaddrInet4 struct {
|
||||||
Port int;
|
Port int
|
||||||
Addr [4]byte;
|
Addr [4]byte
|
||||||
raw RawSockaddrInet4;
|
raw RawSockaddrInet4
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) {
|
func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) {
|
||||||
if sa.Port < 0 || sa.Port > 0xFFFF {
|
if sa.Port < 0 || sa.Port > 0xFFFF {
|
||||||
return 0, 0, EINVAL
|
return 0, 0, EINVAL
|
||||||
}
|
}
|
||||||
sa.raw.Family = AF_INET;
|
sa.raw.Family = AF_INET
|
||||||
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
|
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
|
||||||
p[0] = byte(sa.Port >> 8);
|
p[0] = byte(sa.Port >> 8)
|
||||||
p[1] = byte(sa.Port);
|
p[1] = byte(sa.Port)
|
||||||
for i := 0; i < len(sa.Addr); i++ {
|
for i := 0; i < len(sa.Addr); i++ {
|
||||||
sa.raw.Addr[i] = sa.Addr[i]
|
sa.raw.Addr[i] = sa.Addr[i]
|
||||||
}
|
}
|
||||||
return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet4, 0;
|
return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet4, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
type SockaddrInet6 struct {
|
type SockaddrInet6 struct {
|
||||||
Port int;
|
Port int
|
||||||
Addr [16]byte;
|
Addr [16]byte
|
||||||
raw RawSockaddrInet6;
|
raw RawSockaddrInet6
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) {
|
func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) {
|
||||||
if sa.Port < 0 || sa.Port > 0xFFFF {
|
if sa.Port < 0 || sa.Port > 0xFFFF {
|
||||||
return 0, 0, EINVAL
|
return 0, 0, EINVAL
|
||||||
}
|
}
|
||||||
sa.raw.Family = AF_INET6;
|
sa.raw.Family = AF_INET6
|
||||||
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
|
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
|
||||||
p[0] = byte(sa.Port >> 8);
|
p[0] = byte(sa.Port >> 8)
|
||||||
p[1] = byte(sa.Port);
|
p[1] = byte(sa.Port)
|
||||||
for i := 0; i < len(sa.Addr); i++ {
|
for i := 0; i < len(sa.Addr); i++ {
|
||||||
sa.raw.Addr[i] = sa.Addr[i]
|
sa.raw.Addr[i] = sa.Addr[i]
|
||||||
}
|
}
|
||||||
return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet6, 0;
|
return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet6, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
type SockaddrUnix struct {
|
type SockaddrUnix struct {
|
||||||
Name string;
|
Name string
|
||||||
raw RawSockaddrUnix;
|
raw RawSockaddrUnix
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
|
func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
|
||||||
name := sa.Name;
|
name := sa.Name
|
||||||
n := len(name);
|
n := len(name)
|
||||||
if n >= len(sa.raw.Path) || n == 0 {
|
if n >= len(sa.raw.Path) || n == 0 {
|
||||||
return 0, 0, EINVAL
|
return 0, 0, EINVAL
|
||||||
}
|
}
|
||||||
sa.raw.Family = AF_UNIX;
|
sa.raw.Family = AF_UNIX
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
sa.raw.Path[i] = int8(name[i])
|
sa.raw.Path[i] = int8(name[i])
|
||||||
}
|
}
|
||||||
@ -242,14 +242,14 @@ func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// length is family, name, NUL.
|
// length is family, name, NUL.
|
||||||
return uintptr(unsafe.Pointer(&sa.raw)), 1 + _Socklen(n) + 1, 0;
|
return uintptr(unsafe.Pointer(&sa.raw)), 1 + _Socklen(n) + 1, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
|
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
|
||||||
switch rsa.Addr.Family {
|
switch rsa.Addr.Family {
|
||||||
case AF_UNIX:
|
case AF_UNIX:
|
||||||
pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa));
|
pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
|
||||||
sa := new(SockaddrUnix);
|
sa := new(SockaddrUnix)
|
||||||
if pp.Path[0] == 0 {
|
if pp.Path[0] == 0 {
|
||||||
// "Abstract" Unix domain socket.
|
// "Abstract" Unix domain socket.
|
||||||
// Rewrite leading NUL as @ for textual display.
|
// Rewrite leading NUL as @ for textual display.
|
||||||
@ -264,97 +264,97 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
|
|||||||
// abstract Unix domain sockets--they are supposed
|
// abstract Unix domain sockets--they are supposed
|
||||||
// to be uninterpreted fixed-size binary blobs--but
|
// to be uninterpreted fixed-size binary blobs--but
|
||||||
// everyone uses this convention.
|
// everyone uses this convention.
|
||||||
n := 0;
|
n := 0
|
||||||
for n < len(pp.Path) && pp.Path[n] != 0 {
|
for n < len(pp.Path) && pp.Path[n] != 0 {
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]));
|
bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))
|
||||||
sa.Name = string(bytes[0:n]);
|
sa.Name = string(bytes[0:n])
|
||||||
return sa, 0;
|
return sa, 0
|
||||||
|
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
|
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
|
||||||
sa := new(SockaddrInet4);
|
sa := new(SockaddrInet4)
|
||||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port));
|
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||||
sa.Port = int(p[0])<<8 + int(p[1]);
|
sa.Port = int(p[0])<<8 + int(p[1])
|
||||||
for i := 0; i < len(sa.Addr); i++ {
|
for i := 0; i < len(sa.Addr); i++ {
|
||||||
sa.Addr[i] = pp.Addr[i]
|
sa.Addr[i] = pp.Addr[i]
|
||||||
}
|
}
|
||||||
return sa, 0;
|
return sa, 0
|
||||||
|
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
|
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
|
||||||
sa := new(SockaddrInet6);
|
sa := new(SockaddrInet6)
|
||||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port));
|
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||||
sa.Port = int(p[0])<<8 + int(p[1]);
|
sa.Port = int(p[0])<<8 + int(p[1])
|
||||||
for i := 0; i < len(sa.Addr); i++ {
|
for i := 0; i < len(sa.Addr); i++ {
|
||||||
sa.Addr[i] = pp.Addr[i]
|
sa.Addr[i] = pp.Addr[i]
|
||||||
}
|
}
|
||||||
return sa, 0;
|
return sa, 0
|
||||||
}
|
}
|
||||||
return nil, EAFNOSUPPORT;
|
return nil, EAFNOSUPPORT
|
||||||
}
|
}
|
||||||
|
|
||||||
func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
|
func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
|
||||||
var rsa RawSockaddrAny;
|
var rsa RawSockaddrAny
|
||||||
var len _Socklen = SizeofSockaddrAny;
|
var len _Socklen = SizeofSockaddrAny
|
||||||
nfd, errno = accept(fd, &rsa, &len);
|
nfd, errno = accept(fd, &rsa, &len)
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sa, errno = anyToSockaddr(&rsa);
|
sa, errno = anyToSockaddr(&rsa)
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
Close(nfd);
|
Close(nfd)
|
||||||
nfd = 0;
|
nfd = 0
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getsockname(fd int) (sa Sockaddr, errno int) {
|
func Getsockname(fd int) (sa Sockaddr, errno int) {
|
||||||
var rsa RawSockaddrAny;
|
var rsa RawSockaddrAny
|
||||||
var len _Socklen = SizeofSockaddrAny;
|
var len _Socklen = SizeofSockaddrAny
|
||||||
if errno = getsockname(fd, &rsa, &len); errno != 0 {
|
if errno = getsockname(fd, &rsa, &len); errno != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return anyToSockaddr(&rsa);
|
return anyToSockaddr(&rsa)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getpeername(fd int) (sa Sockaddr, errno int) {
|
func Getpeername(fd int) (sa Sockaddr, errno int) {
|
||||||
var rsa RawSockaddrAny;
|
var rsa RawSockaddrAny
|
||||||
var len _Socklen = SizeofSockaddrAny;
|
var len _Socklen = SizeofSockaddrAny
|
||||||
if errno = getpeername(fd, &rsa, &len); errno != 0 {
|
if errno = getpeername(fd, &rsa, &len); errno != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return anyToSockaddr(&rsa);
|
return anyToSockaddr(&rsa)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Bind(fd int, sa Sockaddr) (errno int) {
|
func Bind(fd int, sa Sockaddr) (errno int) {
|
||||||
ptr, n, err := sa.sockaddr();
|
ptr, n, err := sa.sockaddr()
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return bind(fd, ptr, n);
|
return bind(fd, ptr, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Connect(fd int, sa Sockaddr) (errno int) {
|
func Connect(fd int, sa Sockaddr) (errno int) {
|
||||||
ptr, n, err := sa.sockaddr();
|
ptr, n, err := sa.sockaddr()
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return connect(fd, ptr, n);
|
return connect(fd, ptr, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Socket(domain, typ, proto int) (fd, errno int) {
|
func Socket(domain, typ, proto int) (fd, errno int) {
|
||||||
if domain == AF_INET6 && SocketDisableIPv6 {
|
if domain == AF_INET6 && SocketDisableIPv6 {
|
||||||
return -1, EAFNOSUPPORT
|
return -1, EAFNOSUPPORT
|
||||||
}
|
}
|
||||||
fd, errno = socket(domain, typ, proto);
|
fd, errno = socket(domain, typ, proto)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetsockoptInt(fd, level, opt int, value int) (errno int) {
|
func SetsockoptInt(fd, level, opt int, value int) (errno int) {
|
||||||
var n = int32(value);
|
var n = int32(value)
|
||||||
return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4);
|
return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
|
func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
|
||||||
@ -366,21 +366,21 @@ func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
|
func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
|
||||||
var rsa RawSockaddrAny;
|
var rsa RawSockaddrAny
|
||||||
var len _Socklen = SizeofSockaddrAny;
|
var len _Socklen = SizeofSockaddrAny
|
||||||
if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 {
|
if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
from, errno = anyToSockaddr(&rsa);
|
from, errno = anyToSockaddr(&rsa)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
|
func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
|
||||||
ptr, n, err := to.sockaddr();
|
ptr, n, err := to.sockaddr()
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return sendto(fd, p, flags, ptr, n);
|
return sendto(fd, p, flags, ptr, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (errno int)
|
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (errno int)
|
||||||
@ -392,37 +392,37 @@ func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, errno in
|
|||||||
// The ptrace syscall differs from glibc's ptrace.
|
// The ptrace syscall differs from glibc's ptrace.
|
||||||
// Peeks returns the word in *data, not as the return value.
|
// Peeks returns the word in *data, not as the return value.
|
||||||
|
|
||||||
var buf [sizeofPtr]byte;
|
var buf [sizeofPtr]byte
|
||||||
|
|
||||||
// Leading edge. PEEKTEXT/PEEKDATA don't require aligned
|
// Leading edge. PEEKTEXT/PEEKDATA don't require aligned
|
||||||
// access (PEEKUSER warns that it might), but if we don't
|
// access (PEEKUSER warns that it might), but if we don't
|
||||||
// align our reads, we might straddle an unmapped page
|
// align our reads, we might straddle an unmapped page
|
||||||
// boundary and not get the bytes leading up to the page
|
// boundary and not get the bytes leading up to the page
|
||||||
// boundary.
|
// boundary.
|
||||||
n := 0;
|
n := 0
|
||||||
if addr%sizeofPtr != 0 {
|
if addr%sizeofPtr != 0 {
|
||||||
errno = ptrace(req, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])));
|
errno = ptrace(req, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return 0, errno
|
return 0, errno
|
||||||
}
|
}
|
||||||
n += copy(out, buf[addr%sizeofPtr:]);
|
n += copy(out, buf[addr%sizeofPtr:])
|
||||||
out = out[n:];
|
out = out[n:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remainder.
|
// Remainder.
|
||||||
for len(out) > 0 {
|
for len(out) > 0 {
|
||||||
// We use an internal buffer to gaurantee alignment.
|
// We use an internal buffer to gaurantee alignment.
|
||||||
// It's not documented if this is necessary, but we're paranoid.
|
// It's not documented if this is necessary, but we're paranoid.
|
||||||
errno = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])));
|
errno = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return n, errno
|
return n, errno
|
||||||
}
|
}
|
||||||
copied := copy(out, &buf);
|
copied := copy(out, &buf)
|
||||||
n += copied;
|
n += copied
|
||||||
out = out[copied:];
|
out = out[copied:]
|
||||||
}
|
}
|
||||||
|
|
||||||
return n, 0;
|
return n, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func PtracePeekText(pid int, addr uintptr, out []byte) (count int, errno int) {
|
func PtracePeekText(pid int, addr uintptr, out []byte) (count int, errno int) {
|
||||||
@ -438,50 +438,50 @@ func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (c
|
|||||||
// with the possibility of straddling an invalid page.
|
// with the possibility of straddling an invalid page.
|
||||||
|
|
||||||
// Leading edge.
|
// Leading edge.
|
||||||
n := 0;
|
n := 0
|
||||||
if addr%sizeofPtr != 0 {
|
if addr%sizeofPtr != 0 {
|
||||||
var buf [sizeofPtr]byte;
|
var buf [sizeofPtr]byte
|
||||||
errno = ptrace(peekReq, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])));
|
errno = ptrace(peekReq, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return 0, errno
|
return 0, errno
|
||||||
}
|
}
|
||||||
n += copy(buf[addr%sizeofPtr:], data);
|
n += copy(buf[addr%sizeofPtr:], data)
|
||||||
word := *((*uintptr)(unsafe.Pointer(&buf[0])));
|
word := *((*uintptr)(unsafe.Pointer(&buf[0])))
|
||||||
errno = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word);
|
errno = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word)
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return 0, errno
|
return 0, errno
|
||||||
}
|
}
|
||||||
data = data[n:];
|
data = data[n:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interior.
|
// Interior.
|
||||||
for len(data) > sizeofPtr {
|
for len(data) > sizeofPtr {
|
||||||
word := *((*uintptr)(unsafe.Pointer(&data[0])));
|
word := *((*uintptr)(unsafe.Pointer(&data[0])))
|
||||||
errno = ptrace(pokeReq, pid, addr+uintptr(n), word);
|
errno = ptrace(pokeReq, pid, addr+uintptr(n), word)
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return n, errno
|
return n, errno
|
||||||
}
|
}
|
||||||
n += sizeofPtr;
|
n += sizeofPtr
|
||||||
data = data[sizeofPtr:];
|
data = data[sizeofPtr:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trailing edge.
|
// Trailing edge.
|
||||||
if len(data) > 0 {
|
if len(data) > 0 {
|
||||||
var buf [sizeofPtr]byte;
|
var buf [sizeofPtr]byte
|
||||||
errno = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])));
|
errno = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return n, errno
|
return n, errno
|
||||||
}
|
}
|
||||||
copy(&buf, data);
|
copy(&buf, data)
|
||||||
word := *((*uintptr)(unsafe.Pointer(&buf[0])));
|
word := *((*uintptr)(unsafe.Pointer(&buf[0])))
|
||||||
errno = ptrace(pokeReq, pid, addr+uintptr(n), word);
|
errno = ptrace(pokeReq, pid, addr+uintptr(n), word)
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return n, errno
|
return n, errno
|
||||||
}
|
}
|
||||||
n += len(data);
|
n += len(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
return n, 0;
|
return n, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func PtracePokeText(pid int, addr uintptr, data []byte) (count int, errno int) {
|
func PtracePokeText(pid int, addr uintptr, data []byte) (count int, errno int) {
|
||||||
@ -505,10 +505,10 @@ func PtraceSetOptions(pid int, options int) (errno int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func PtraceGetEventMsg(pid int) (msg uint, errno int) {
|
func PtraceGetEventMsg(pid int) (msg uint, errno int) {
|
||||||
var data _C_long;
|
var data _C_long
|
||||||
errno = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data)));
|
errno = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data)))
|
||||||
msg = uint(data);
|
msg = uint(data)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func PtraceCont(pid int, signal int) (errno int) {
|
func PtraceCont(pid int, signal int) (errno int) {
|
||||||
|
@ -11,18 +11,18 @@ func Getpagesize() int { return 4096 }
|
|||||||
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
||||||
|
|
||||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||||
ts.Sec = int32(nsec / 1e9);
|
ts.Sec = int32(nsec / 1e9)
|
||||||
ts.Nsec = int32(nsec % 1e9);
|
ts.Nsec = int32(nsec % 1e9)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
|
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
|
||||||
|
|
||||||
func NsecToTimeval(nsec int64) (tv Timeval) {
|
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||||
nsec += 999; // round up to microsecond
|
nsec += 999 // round up to microsecond
|
||||||
tv.Sec = int32(nsec / 1e9);
|
tv.Sec = int32(nsec / 1e9)
|
||||||
tv.Usec = int32(nsec % 1e9 / 1e3);
|
tv.Usec = int32(nsec % 1e9 / 1e3)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 64-bit file system and 32-bit uid calls
|
// 64-bit file system and 32-bit uid calls
|
||||||
@ -64,100 +64,100 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, errno int)
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// see linux/net.h
|
// see linux/net.h
|
||||||
_SOCKET = 1;
|
_SOCKET = 1
|
||||||
_BIND = 2;
|
_BIND = 2
|
||||||
_CONNECT = 3;
|
_CONNECT = 3
|
||||||
_LISTEN = 4;
|
_LISTEN = 4
|
||||||
_ACCEPT = 5;
|
_ACCEPT = 5
|
||||||
_GETSOCKNAME = 6;
|
_GETSOCKNAME = 6
|
||||||
_GETPEERNAME = 7;
|
_GETPEERNAME = 7
|
||||||
_SOCKETPAIR = 8;
|
_SOCKETPAIR = 8
|
||||||
_SEND = 9;
|
_SEND = 9
|
||||||
_RECV = 10;
|
_RECV = 10
|
||||||
_SENDTO = 11;
|
_SENDTO = 11
|
||||||
_RECVFROM = 12;
|
_RECVFROM = 12
|
||||||
_SHUTDOWN = 13;
|
_SHUTDOWN = 13
|
||||||
_SETSOCKOPT = 14;
|
_SETSOCKOPT = 14
|
||||||
_GETSOCKOPT = 15;
|
_GETSOCKOPT = 15
|
||||||
_SENDMSG = 16;
|
_SENDMSG = 16
|
||||||
_RECVMSG = 17;
|
_RECVMSG = 17
|
||||||
)
|
)
|
||||||
|
|
||||||
func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, errno int)
|
func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, errno int)
|
||||||
|
|
||||||
func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
|
func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
|
||||||
fd, errno = socketcall(_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0);
|
fd, errno = socketcall(_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func getsockname(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
|
func getsockname(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
|
||||||
_, errno = socketcall(_GETSOCKNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0);
|
_, errno = socketcall(_GETSOCKNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func getpeername(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
|
func getpeername(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
|
||||||
_, errno = socketcall(_GETPEERNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0);
|
_, errno = socketcall(_GETPEERNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
|
func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
|
||||||
_, errno = socketcall(_BIND, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0);
|
_, errno = socketcall(_BIND, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
|
func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
|
||||||
_, errno = socketcall(_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0);
|
_, errno = socketcall(_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func socket(domain int, typ int, proto int) (fd int, errno int) {
|
func socket(domain int, typ int, proto int) (fd int, errno int) {
|
||||||
fd, errno = socketcall(_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto), 0, 0, 0);
|
fd, errno = socketcall(_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto), 0, 0, 0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int) {
|
func setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int) {
|
||||||
_, errno = socketcall(_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0);
|
_, errno = socketcall(_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func recvfrom(s int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
|
func recvfrom(s int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
|
||||||
var base uintptr;
|
var base uintptr
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
base = uintptr(unsafe.Pointer(&p[0]))
|
base = uintptr(unsafe.Pointer(&p[0]))
|
||||||
}
|
}
|
||||||
n, errno = socketcall(_RECVFROM, uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)));
|
n, errno = socketcall(_RECVFROM, uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendto(s int, p []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
|
func sendto(s int, p []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
|
||||||
var base uintptr;
|
var base uintptr
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
base = uintptr(unsafe.Pointer(&p[0]))
|
base = uintptr(unsafe.Pointer(&p[0]))
|
||||||
}
|
}
|
||||||
_, errno = socketcall(_SENDTO, uintptr(s), base, uintptr(len(p)), uintptr(flags), to, uintptr(addrlen));
|
_, errno = socketcall(_SENDTO, uintptr(s), base, uintptr(len(p)), uintptr(flags), to, uintptr(addrlen))
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Listen(s int, n int) (errno int) {
|
func Listen(s int, n int) (errno int) {
|
||||||
_, errno = socketcall(_LISTEN, uintptr(s), uintptr(n), 0, 0, 0, 0);
|
_, errno = socketcall(_LISTEN, uintptr(s), uintptr(n), 0, 0, 0, 0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Shutdown(s, how int) (errno int) {
|
func Shutdown(s, how int) (errno int) {
|
||||||
_, errno = socketcall(_SHUTDOWN, uintptr(s), uintptr(how), 0, 0, 0, 0);
|
_, errno = socketcall(_SHUTDOWN, uintptr(s), uintptr(how), 0, 0, 0, 0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fstatfs(fd int, buf *Statfs_t) (errno int) {
|
func Fstatfs(fd int, buf *Statfs_t) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FSTATFS64, uintptr(fd), uintptr(unsafe.Sizeof(*buf)), uintptr(unsafe.Pointer(buf)));
|
_, _, e1 := Syscall(SYS_FSTATFS64, uintptr(fd), uintptr(unsafe.Sizeof(*buf)), uintptr(unsafe.Pointer(buf)))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Statfs(path string, buf *Statfs_t) (errno int) {
|
func Statfs(path string, buf *Statfs_t) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Sizeof(*buf)), uintptr(unsafe.Pointer(buf)));
|
_, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Sizeof(*buf)), uintptr(unsafe.Pointer(buf)))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *PtraceRegs) PC() uint64 { return uint64(uint32(r.Eip)) }
|
func (r *PtraceRegs) PC() uint64 { return uint64(uint32(r.Eip)) }
|
||||||
|
@ -47,18 +47,18 @@ func Getpagesize() int { return 4096 }
|
|||||||
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
||||||
|
|
||||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||||
ts.Sec = nsec / 1e9;
|
ts.Sec = nsec / 1e9
|
||||||
ts.Nsec = nsec % 1e9;
|
ts.Nsec = nsec % 1e9
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
|
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
|
||||||
|
|
||||||
func NsecToTimeval(nsec int64) (tv Timeval) {
|
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||||
nsec += 999; // round up to microsecond
|
nsec += 999 // round up to microsecond
|
||||||
tv.Sec = nsec / 1e9;
|
tv.Sec = nsec / 1e9
|
||||||
tv.Usec = nsec % 1e9 / 1e3;
|
tv.Usec = nsec % 1e9 / 1e3
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *PtraceRegs) PC() uint64 { return r.Rip }
|
func (r *PtraceRegs) PC() uint64 { return r.Rip }
|
||||||
|
@ -9,16 +9,16 @@ func Getpagesize() int { return 4096 }
|
|||||||
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
|
||||||
|
|
||||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||||
ts.Sec = int32(nsec / 1e9);
|
ts.Sec = int32(nsec / 1e9)
|
||||||
ts.Nsec = int32(nsec % 1e9);
|
ts.Nsec = int32(nsec % 1e9)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func NsecToTimeval(nsec int64) (tv Timeval) {
|
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||||
nsec += 999; // round up to microsecond
|
nsec += 999 // round up to microsecond
|
||||||
tv.Sec = int32(nsec / 1e9);
|
tv.Sec = int32(nsec / 1e9)
|
||||||
tv.Usec = int32(nsec % 1e9 / 1e3);
|
tv.Usec = int32(nsec % 1e9 / 1e3)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int)
|
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int)
|
||||||
|
@ -54,8 +54,8 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
|
|||||||
if int64(int32(offset)) != offset {
|
if int64(int32(offset)) != offset {
|
||||||
return 0, ERANGE
|
return 0, ERANGE
|
||||||
}
|
}
|
||||||
o, _, e := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence));
|
o, _, e := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
|
||||||
return int64(o), int(e);
|
return int64(o), int(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sleep by waiting on a condition variable that will never be signaled.
|
// Sleep by waiting on a condition variable that will never be signaled.
|
||||||
@ -63,34 +63,34 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
|
|||||||
var tcv, tmu int
|
var tcv, tmu int
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
tmu, _ = MutexCreate();
|
tmu, _ = MutexCreate()
|
||||||
tcv, _ = CondCreate();
|
tcv, _ = CondCreate()
|
||||||
}
|
}
|
||||||
|
|
||||||
func Sleep(ns int64) (errno int) {
|
func Sleep(ns int64) (errno int) {
|
||||||
ts := NsecToTimespec(ns);
|
ts := NsecToTimespec(ns)
|
||||||
var tv Timeval;
|
var tv Timeval
|
||||||
if errno = Gettimeofday(&tv); errno != 0 {
|
if errno = Gettimeofday(&tv); errno != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ts.Sec += tv.Sec;
|
ts.Sec += tv.Sec
|
||||||
ts.Nsec += tv.Usec * 1000;
|
ts.Nsec += tv.Usec * 1000
|
||||||
switch {
|
switch {
|
||||||
case ts.Nsec >= 1e9:
|
case ts.Nsec >= 1e9:
|
||||||
ts.Nsec -= 1e9;
|
ts.Nsec -= 1e9
|
||||||
ts.Sec++;
|
ts.Sec++
|
||||||
case ts.Nsec <= -1e9:
|
case ts.Nsec <= -1e9:
|
||||||
ts.Nsec += 1e9;
|
ts.Nsec += 1e9
|
||||||
ts.Sec--;
|
ts.Sec--
|
||||||
}
|
}
|
||||||
if errno = MutexLock(tmu); errno != 0 {
|
if errno = MutexLock(tmu); errno != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
errno = CondTimedWaitAbs(tcv, tmu, &ts);
|
errno = CondTimedWaitAbs(tcv, tmu, &ts)
|
||||||
if e := MutexUnlock(tmu); e != 0 && errno == 0 {
|
if e := MutexUnlock(tmu); e != 0 && errno == 0 {
|
||||||
errno = e
|
errno = e
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implemented in NaCl but not here; maybe later:
|
// Implemented in NaCl but not here; maybe later:
|
||||||
@ -111,7 +111,7 @@ func Sleep(ns int64) (errno int) {
|
|||||||
// Not implemented in NaCl but needed to compile other packages.
|
// Not implemented in NaCl but needed to compile other packages.
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SIGTRAP = 5;
|
SIGTRAP = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
func Pipe(p []int) (errno int) { return ENACL }
|
func Pipe(p []int) (errno int) { return ENACL }
|
||||||
@ -199,50 +199,50 @@ func Getppid() (ppid int) { return -1 }
|
|||||||
func Getgroups() (gids []int, errno int) { return nil, ENACL }
|
func Getgroups() (gids []int, errno int) { return nil, ENACL }
|
||||||
|
|
||||||
type Sockaddr interface {
|
type Sockaddr interface {
|
||||||
sockaddr();
|
sockaddr()
|
||||||
}
|
}
|
||||||
|
|
||||||
type SockaddrInet4 struct {
|
type SockaddrInet4 struct {
|
||||||
Port int;
|
Port int
|
||||||
Addr [4]byte;
|
Addr [4]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*SockaddrInet4) sockaddr() {}
|
func (*SockaddrInet4) sockaddr() {}
|
||||||
|
|
||||||
type SockaddrInet6 struct {
|
type SockaddrInet6 struct {
|
||||||
Port int;
|
Port int
|
||||||
Addr [16]byte;
|
Addr [16]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*SockaddrInet6) sockaddr() {}
|
func (*SockaddrInet6) sockaddr() {}
|
||||||
|
|
||||||
type SockaddrUnix struct {
|
type SockaddrUnix struct {
|
||||||
Name string;
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*SockaddrUnix) sockaddr() {}
|
func (*SockaddrUnix) sockaddr() {}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AF_INET = 1 + iota;
|
AF_INET = 1 + iota
|
||||||
AF_INET6;
|
AF_INET6
|
||||||
AF_UNIX;
|
AF_UNIX
|
||||||
IPPROTO_TCP;
|
IPPROTO_TCP
|
||||||
SOCK_DGRAM;
|
SOCK_DGRAM
|
||||||
SOCK_STREAM;
|
SOCK_STREAM
|
||||||
SOL_SOCKET;
|
SOL_SOCKET
|
||||||
SOMAXCONN;
|
SOMAXCONN
|
||||||
SO_DONTROUTE;
|
SO_DONTROUTE
|
||||||
SO_KEEPALIVE;
|
SO_KEEPALIVE
|
||||||
SO_LINGER;
|
SO_LINGER
|
||||||
SO_RCVBUF;
|
SO_RCVBUF
|
||||||
SO_REUSEADDR;
|
SO_REUSEADDR
|
||||||
SO_SNDBUF;
|
SO_SNDBUF
|
||||||
TCP_NODELAY;
|
TCP_NODELAY
|
||||||
WNOHANG;
|
WNOHANG
|
||||||
WSTOPPED;
|
WSTOPPED
|
||||||
PTRACE_TRACEME;
|
PTRACE_TRACEME
|
||||||
SO_BROADCAST = 0;
|
SO_BROADCAST = 0
|
||||||
SHUT_RDWR = 0;
|
SHUT_RDWR = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
|
func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
|
||||||
@ -284,8 +284,8 @@ func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Linger struct {
|
type Linger struct {
|
||||||
Onoff int32;
|
Onoff int32
|
||||||
Linger int32;
|
Linger int32
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
|
func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
|
||||||
@ -295,22 +295,22 @@ func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
|
|||||||
func Listen(s int, n int) (errno int) { return ENACL }
|
func Listen(s int, n int) (errno int) { return ENACL }
|
||||||
|
|
||||||
type Rusage struct {
|
type Rusage struct {
|
||||||
Utime Timeval;
|
Utime Timeval
|
||||||
Stime Timeval;
|
Stime Timeval
|
||||||
Maxrss int32;
|
Maxrss int32
|
||||||
Ixrss int32;
|
Ixrss int32
|
||||||
Idrss int32;
|
Idrss int32
|
||||||
Isrss int32;
|
Isrss int32
|
||||||
Minflt int32;
|
Minflt int32
|
||||||
Majflt int32;
|
Majflt int32
|
||||||
Nswap int32;
|
Nswap int32
|
||||||
Inblock int32;
|
Inblock int32
|
||||||
Oublock int32;
|
Oublock int32
|
||||||
Msgsnd int32;
|
Msgsnd int32
|
||||||
Msgrcv int32;
|
Msgrcv int32
|
||||||
Nsignals int32;
|
Nsignals int32
|
||||||
Nvcsw int32;
|
Nvcsw int32
|
||||||
Nivcsw int32;
|
Nivcsw int32
|
||||||
}
|
}
|
||||||
|
|
||||||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
|
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
|
||||||
|
@ -7,13 +7,13 @@ package syscall
|
|||||||
func Getpagesize() int { return 4096 }
|
func Getpagesize() int { return 4096 }
|
||||||
|
|
||||||
func NsecToTimeval(nsec int64) (tv Timeval) {
|
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||||
tv.Sec = int32(nsec / 1e9);
|
tv.Sec = int32(nsec / 1e9)
|
||||||
tv.Usec = int32(nsec % 1e9 / 1e3);
|
tv.Usec = int32(nsec % 1e9 / 1e3)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||||
ts.Sec = int32(nsec / 1e9);
|
ts.Sec = int32(nsec / 1e9)
|
||||||
ts.Nsec = int32(nsec % 1e9);
|
ts.Nsec = int32(nsec % 1e9)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -9,177 +9,177 @@ package syscall
|
|||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const (
|
const (
|
||||||
EMULTIHOP = 0x48;
|
EMULTIHOP = 0x48
|
||||||
EUNATCH = 0x31;
|
EUNATCH = 0x31
|
||||||
EAFNOSUPPORT = 0x61;
|
EAFNOSUPPORT = 0x61
|
||||||
EREMCHG = 0x4e;
|
EREMCHG = 0x4e
|
||||||
EACCES = 0xd;
|
EACCES = 0xd
|
||||||
EL3RST = 0x2f;
|
EL3RST = 0x2f
|
||||||
EDESTADDRREQ = 0x59;
|
EDESTADDRREQ = 0x59
|
||||||
EILSEQ = 0x54;
|
EILSEQ = 0x54
|
||||||
ESPIPE = 0x1d;
|
ESPIPE = 0x1d
|
||||||
EMLINK = 0x1f;
|
EMLINK = 0x1f
|
||||||
EOWNERDEAD = 0x82;
|
EOWNERDEAD = 0x82
|
||||||
ENOTTY = 0x19;
|
ENOTTY = 0x19
|
||||||
EBADE = 0x34;
|
EBADE = 0x34
|
||||||
EBADF = 0x9;
|
EBADF = 0x9
|
||||||
EBADR = 0x35;
|
EBADR = 0x35
|
||||||
EADV = 0x44;
|
EADV = 0x44
|
||||||
ERANGE = 0x22;
|
ERANGE = 0x22
|
||||||
ECANCELED = 0x7d;
|
ECANCELED = 0x7d
|
||||||
ETXTBSY = 0x1a;
|
ETXTBSY = 0x1a
|
||||||
ENOMEM = 0xc;
|
ENOMEM = 0xc
|
||||||
EINPROGRESS = 0x73;
|
EINPROGRESS = 0x73
|
||||||
ENOTEMPTY = 0x27;
|
ENOTEMPTY = 0x27
|
||||||
ENOTBLK = 0xf;
|
ENOTBLK = 0xf
|
||||||
EPROTOTYPE = 0x5b;
|
EPROTOTYPE = 0x5b
|
||||||
ERESTART = 0x55;
|
ERESTART = 0x55
|
||||||
EISNAM = 0x78;
|
EISNAM = 0x78
|
||||||
ENOMSG = 0x2a;
|
ENOMSG = 0x2a
|
||||||
EALREADY = 0x72;
|
EALREADY = 0x72
|
||||||
ETIMEDOUT = 0x6e;
|
ETIMEDOUT = 0x6e
|
||||||
ENODATA = 0x3d;
|
ENODATA = 0x3d
|
||||||
EINTR = 0x4;
|
EINTR = 0x4
|
||||||
ENOLINK = 0x43;
|
ENOLINK = 0x43
|
||||||
EPERM = 0x1;
|
EPERM = 0x1
|
||||||
ELOOP = 0x28;
|
ELOOP = 0x28
|
||||||
ENETDOWN = 0x64;
|
ENETDOWN = 0x64
|
||||||
ESTALE = 0x74;
|
ESTALE = 0x74
|
||||||
ENOTSOCK = 0x58;
|
ENOTSOCK = 0x58
|
||||||
ENOSR = 0x3f;
|
ENOSR = 0x3f
|
||||||
ECHILD = 0xa;
|
ECHILD = 0xa
|
||||||
ELNRNG = 0x30;
|
ELNRNG = 0x30
|
||||||
EPIPE = 0x20;
|
EPIPE = 0x20
|
||||||
EBADMSG = 0x4a;
|
EBADMSG = 0x4a
|
||||||
EBFONT = 0x3b;
|
EBFONT = 0x3b
|
||||||
EREMOTE = 0x42;
|
EREMOTE = 0x42
|
||||||
ETOOMANYREFS = 0x6d;
|
ETOOMANYREFS = 0x6d
|
||||||
EPFNOSUPPORT = 0x60;
|
EPFNOSUPPORT = 0x60
|
||||||
ENONET = 0x40;
|
ENONET = 0x40
|
||||||
EXFULL = 0x36;
|
EXFULL = 0x36
|
||||||
EBADSLT = 0x39;
|
EBADSLT = 0x39
|
||||||
ENOTNAM = 0x76;
|
ENOTNAM = 0x76
|
||||||
ENOCSI = 0x32;
|
ENOCSI = 0x32
|
||||||
EADDRINUSE = 0x62;
|
EADDRINUSE = 0x62
|
||||||
ENETRESET = 0x66;
|
ENETRESET = 0x66
|
||||||
EISDIR = 0x15;
|
EISDIR = 0x15
|
||||||
EIDRM = 0x2b;
|
EIDRM = 0x2b
|
||||||
ECOMM = 0x46;
|
ECOMM = 0x46
|
||||||
EBADFD = 0x4d;
|
EBADFD = 0x4d
|
||||||
EL2HLT = 0x33;
|
EL2HLT = 0x33
|
||||||
ENOKEY = 0x7e;
|
ENOKEY = 0x7e
|
||||||
EINVAL = 0x16;
|
EINVAL = 0x16
|
||||||
ESHUTDOWN = 0x6c;
|
ESHUTDOWN = 0x6c
|
||||||
EKEYREJECTED = 0x81;
|
EKEYREJECTED = 0x81
|
||||||
ELIBSCN = 0x51;
|
ELIBSCN = 0x51
|
||||||
ENAVAIL = 0x77;
|
ENAVAIL = 0x77
|
||||||
EOVERFLOW = 0x4b;
|
EOVERFLOW = 0x4b
|
||||||
EUCLEAN = 0x75;
|
EUCLEAN = 0x75
|
||||||
ENOMEDIUM = 0x7b;
|
ENOMEDIUM = 0x7b
|
||||||
EBUSY = 0x10;
|
EBUSY = 0x10
|
||||||
EPROTO = 0x47;
|
EPROTO = 0x47
|
||||||
ENODEV = 0x13;
|
ENODEV = 0x13
|
||||||
EKEYEXPIRED = 0x7f;
|
EKEYEXPIRED = 0x7f
|
||||||
EROFS = 0x1e;
|
EROFS = 0x1e
|
||||||
ELIBACC = 0x4f;
|
ELIBACC = 0x4f
|
||||||
E2BIG = 0x7;
|
E2BIG = 0x7
|
||||||
EDEADLK = 0x23;
|
EDEADLK = 0x23
|
||||||
ENOTDIR = 0x14;
|
ENOTDIR = 0x14
|
||||||
ECONNRESET = 0x68;
|
ECONNRESET = 0x68
|
||||||
ENXIO = 0x6;
|
ENXIO = 0x6
|
||||||
EBADRQC = 0x38;
|
EBADRQC = 0x38
|
||||||
ENAMETOOLONG = 0x24;
|
ENAMETOOLONG = 0x24
|
||||||
ESOCKTNOSUPPORT = 0x5e;
|
ESOCKTNOSUPPORT = 0x5e
|
||||||
ELIBEXEC = 0x53;
|
ELIBEXEC = 0x53
|
||||||
EDOTDOT = 0x49;
|
EDOTDOT = 0x49
|
||||||
EADDRNOTAVAIL = 0x63;
|
EADDRNOTAVAIL = 0x63
|
||||||
ETIME = 0x3e;
|
ETIME = 0x3e
|
||||||
EPROTONOSUPPORT = 0x5d;
|
EPROTONOSUPPORT = 0x5d
|
||||||
ENOTRECOVERABLE = 0x83;
|
ENOTRECOVERABLE = 0x83
|
||||||
EIO = 0x5;
|
EIO = 0x5
|
||||||
ENETUNREACH = 0x65;
|
ENETUNREACH = 0x65
|
||||||
EXDEV = 0x12;
|
EXDEV = 0x12
|
||||||
EDQUOT = 0x7a;
|
EDQUOT = 0x7a
|
||||||
EREMOTEIO = 0x79;
|
EREMOTEIO = 0x79
|
||||||
ENOSPC = 0x1c;
|
ENOSPC = 0x1c
|
||||||
ENOEXEC = 0x8;
|
ENOEXEC = 0x8
|
||||||
EMSGSIZE = 0x5a;
|
EMSGSIZE = 0x5a
|
||||||
EDOM = 0x21;
|
EDOM = 0x21
|
||||||
ENOSTR = 0x3c;
|
ENOSTR = 0x3c
|
||||||
EFBIG = 0x1b;
|
EFBIG = 0x1b
|
||||||
ESRCH = 0x3;
|
ESRCH = 0x3
|
||||||
ECHRNG = 0x2c;
|
ECHRNG = 0x2c
|
||||||
EHOSTDOWN = 0x70;
|
EHOSTDOWN = 0x70
|
||||||
ENOLCK = 0x25;
|
ENOLCK = 0x25
|
||||||
ENFILE = 0x17;
|
ENFILE = 0x17
|
||||||
ENOSYS = 0x26;
|
ENOSYS = 0x26
|
||||||
ENOTCONN = 0x6b;
|
ENOTCONN = 0x6b
|
||||||
ENOTSUP = 0x5f;
|
ENOTSUP = 0x5f
|
||||||
ESRMNT = 0x45;
|
ESRMNT = 0x45
|
||||||
EDEADLOCK = 0x23;
|
EDEADLOCK = 0x23
|
||||||
ECONNABORTED = 0x67;
|
ECONNABORTED = 0x67
|
||||||
ENOANO = 0x37;
|
ENOANO = 0x37
|
||||||
EISCONN = 0x6a;
|
EISCONN = 0x6a
|
||||||
EUSERS = 0x57;
|
EUSERS = 0x57
|
||||||
ENOPROTOOPT = 0x5c;
|
ENOPROTOOPT = 0x5c
|
||||||
EMFILE = 0x18;
|
EMFILE = 0x18
|
||||||
ENOBUFS = 0x69;
|
ENOBUFS = 0x69
|
||||||
EL3HLT = 0x2e;
|
EL3HLT = 0x2e
|
||||||
EFAULT = 0xe;
|
EFAULT = 0xe
|
||||||
EWOULDBLOCK = 0xb;
|
EWOULDBLOCK = 0xb
|
||||||
ELIBBAD = 0x50;
|
ELIBBAD = 0x50
|
||||||
ESTRPIPE = 0x56;
|
ESTRPIPE = 0x56
|
||||||
ECONNREFUSED = 0x6f;
|
ECONNREFUSED = 0x6f
|
||||||
EAGAIN = 0xb;
|
EAGAIN = 0xb
|
||||||
ELIBMAX = 0x52;
|
ELIBMAX = 0x52
|
||||||
EEXIST = 0x11;
|
EEXIST = 0x11
|
||||||
EL2NSYNC = 0x2d;
|
EL2NSYNC = 0x2d
|
||||||
ENOENT = 0x2;
|
ENOENT = 0x2
|
||||||
ENOPKG = 0x41;
|
ENOPKG = 0x41
|
||||||
EKEYREVOKED = 0x80;
|
EKEYREVOKED = 0x80
|
||||||
EHOSTUNREACH = 0x71;
|
EHOSTUNREACH = 0x71
|
||||||
ENOTUNIQ = 0x4c;
|
ENOTUNIQ = 0x4c
|
||||||
EOPNOTSUPP = 0x5f;
|
EOPNOTSUPP = 0x5f
|
||||||
EMEDIUMTYPE = 0x7c;
|
EMEDIUMTYPE = 0x7c
|
||||||
SIGBUS = 0x7;
|
SIGBUS = 0x7
|
||||||
SIGTTIN = 0x15;
|
SIGTTIN = 0x15
|
||||||
SIGPROF = 0x1b;
|
SIGPROF = 0x1b
|
||||||
SIGFPE = 0x8;
|
SIGFPE = 0x8
|
||||||
SIGHUP = 0x1;
|
SIGHUP = 0x1
|
||||||
SIGTTOU = 0x16;
|
SIGTTOU = 0x16
|
||||||
SIGSTKFLT = 0x10;
|
SIGSTKFLT = 0x10
|
||||||
SIGUSR1 = 0xa;
|
SIGUSR1 = 0xa
|
||||||
SIGURG = 0x17;
|
SIGURG = 0x17
|
||||||
SIGIO = 0x1d;
|
SIGIO = 0x1d
|
||||||
SIGQUIT = 0x3;
|
SIGQUIT = 0x3
|
||||||
SIGCLD = 0x11;
|
SIGCLD = 0x11
|
||||||
SHUT_RD = 0;
|
SHUT_RD = 0
|
||||||
SHUT_RDWR = 0x2;
|
SHUT_RDWR = 0x2
|
||||||
SHUT_WR = 0x1;
|
SHUT_WR = 0x1
|
||||||
SIGABRT = 0x6;
|
SIGABRT = 0x6
|
||||||
SIGTRAP = 0x5;
|
SIGTRAP = 0x5
|
||||||
SIGVTALRM = 0x1a;
|
SIGVTALRM = 0x1a
|
||||||
SIGPOLL = 0x1d;
|
SIGPOLL = 0x1d
|
||||||
SIGSEGV = 0xb;
|
SIGSEGV = 0xb
|
||||||
SIGCONT = 0x12;
|
SIGCONT = 0x12
|
||||||
SIGPIPE = 0xd;
|
SIGPIPE = 0xd
|
||||||
SIGWINCH = 0x1c;
|
SIGWINCH = 0x1c
|
||||||
SIGXFSZ = 0x19;
|
SIGXFSZ = 0x19
|
||||||
SIGCHLD = 0x11;
|
SIGCHLD = 0x11
|
||||||
SIGSYS = 0x1f;
|
SIGSYS = 0x1f
|
||||||
SIGSTOP = 0x13;
|
SIGSTOP = 0x13
|
||||||
SIGALRM = 0xe;
|
SIGALRM = 0xe
|
||||||
SIGUSR2 = 0xc;
|
SIGUSR2 = 0xc
|
||||||
SIGTSTP = 0x14;
|
SIGTSTP = 0x14
|
||||||
SIGKILL = 0x9;
|
SIGKILL = 0x9
|
||||||
SIGXCPU = 0x18;
|
SIGXCPU = 0x18
|
||||||
SIGUNUSED = 0x1f;
|
SIGUNUSED = 0x1f
|
||||||
SIGPWR = 0x1e;
|
SIGPWR = 0x1e
|
||||||
SIGILL = 0x4;
|
SIGILL = 0x4
|
||||||
SIGINT = 0x2;
|
SIGINT = 0x2
|
||||||
SIGIOT = 0x6;
|
SIGIOT = 0x6
|
||||||
SIGTERM = 0xf;
|
SIGTERM = 0xf
|
||||||
O_EXCL = 0x80;
|
O_EXCL = 0x80
|
||||||
)
|
)
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
|
@ -4,126 +4,126 @@
|
|||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
const (
|
const (
|
||||||
EPERM = 1;
|
EPERM = 1
|
||||||
ENOENT = 2;
|
ENOENT = 2
|
||||||
ESRCH = 3;
|
ESRCH = 3
|
||||||
EINTR = 4;
|
EINTR = 4
|
||||||
EIO = 5;
|
EIO = 5
|
||||||
ENXIO = 6;
|
ENXIO = 6
|
||||||
E2BIG = 7;
|
E2BIG = 7
|
||||||
ENOEXEC = 8;
|
ENOEXEC = 8
|
||||||
EBADF = 9;
|
EBADF = 9
|
||||||
ECHILD = 10;
|
ECHILD = 10
|
||||||
EAGAIN = 11;
|
EAGAIN = 11
|
||||||
ENOMEM = 12;
|
ENOMEM = 12
|
||||||
EACCES = 13;
|
EACCES = 13
|
||||||
EFAULT = 14;
|
EFAULT = 14
|
||||||
EBUSY = 16;
|
EBUSY = 16
|
||||||
EEXIST = 17;
|
EEXIST = 17
|
||||||
EXDEV = 18;
|
EXDEV = 18
|
||||||
ENODEV = 19;
|
ENODEV = 19
|
||||||
ENOTDIR = 20;
|
ENOTDIR = 20
|
||||||
EISDIR = 21;
|
EISDIR = 21
|
||||||
EINVAL = 22;
|
EINVAL = 22
|
||||||
ENFILE = 23;
|
ENFILE = 23
|
||||||
EMFILE = 24;
|
EMFILE = 24
|
||||||
ENOTTY = 25;
|
ENOTTY = 25
|
||||||
EFBIG = 27;
|
EFBIG = 27
|
||||||
ENOSPC = 28;
|
ENOSPC = 28
|
||||||
ESPIPE = 29;
|
ESPIPE = 29
|
||||||
EROFS = 30;
|
EROFS = 30
|
||||||
EMLINK = 31;
|
EMLINK = 31
|
||||||
EPIPE = 32;
|
EPIPE = 32
|
||||||
ENAMETOOLONG = 36;
|
ENAMETOOLONG = 36
|
||||||
ENOSYS = 38;
|
ENOSYS = 38
|
||||||
EDQUOT = 122;
|
EDQUOT = 122
|
||||||
EDOM = 33;
|
EDOM = 33
|
||||||
ERANGE = 34;
|
ERANGE = 34
|
||||||
ENOMSG = 35;
|
ENOMSG = 35
|
||||||
ECHRNG = 37;
|
ECHRNG = 37
|
||||||
EL3HLT = 39;
|
EL3HLT = 39
|
||||||
EL3RST = 40;
|
EL3RST = 40
|
||||||
ELNRNG = 41;
|
ELNRNG = 41
|
||||||
EUNATCH = 42;
|
EUNATCH = 42
|
||||||
ENOCSI = 43;
|
ENOCSI = 43
|
||||||
EL2HLT = 44;
|
EL2HLT = 44
|
||||||
EDEADLK = 45;
|
EDEADLK = 45
|
||||||
ENOLCK = 46;
|
ENOLCK = 46
|
||||||
EBADE = 50;
|
EBADE = 50
|
||||||
EBADR = 51;
|
EBADR = 51
|
||||||
EXFULL = 52;
|
EXFULL = 52
|
||||||
ENOANO = 53;
|
ENOANO = 53
|
||||||
EBADRQC = 54;
|
EBADRQC = 54
|
||||||
EBADSLT = 55;
|
EBADSLT = 55
|
||||||
EBFONT = 57;
|
EBFONT = 57
|
||||||
ENOSTR = 60;
|
ENOSTR = 60
|
||||||
ENODATA = 61;
|
ENODATA = 61
|
||||||
ETIME = 62;
|
ETIME = 62
|
||||||
ENOSR = 63;
|
ENOSR = 63
|
||||||
ENONET = 64;
|
ENONET = 64
|
||||||
ENOPKG = 65;
|
ENOPKG = 65
|
||||||
EREMOTE = 66;
|
EREMOTE = 66
|
||||||
ENOLINK = 67;
|
ENOLINK = 67
|
||||||
EADV = 68;
|
EADV = 68
|
||||||
ESRMNT = 69;
|
ESRMNT = 69
|
||||||
ECOMM = 70;
|
ECOMM = 70
|
||||||
EPROTO = 71;
|
EPROTO = 71
|
||||||
EMULTIHOP = 74;
|
EMULTIHOP = 74
|
||||||
ELBIN = 75;
|
ELBIN = 75
|
||||||
EDOTDOT = 76;
|
EDOTDOT = 76
|
||||||
EBADMSG = 77;
|
EBADMSG = 77
|
||||||
EFTYPE = 79;
|
EFTYPE = 79
|
||||||
ENOTUNIQ = 80;
|
ENOTUNIQ = 80
|
||||||
EBADFD = 81;
|
EBADFD = 81
|
||||||
EREMCHG = 82;
|
EREMCHG = 82
|
||||||
ELIBACC = 83;
|
ELIBACC = 83
|
||||||
ELIBBAD = 84;
|
ELIBBAD = 84
|
||||||
ELIBSCN = 85;
|
ELIBSCN = 85
|
||||||
ELIBMAX = 86;
|
ELIBMAX = 86
|
||||||
ELIBEXEC = 87;
|
ELIBEXEC = 87
|
||||||
ENMFILE = 89;
|
ENMFILE = 89
|
||||||
ENOTEMPTY = 90;
|
ENOTEMPTY = 90
|
||||||
ELOOP = 92;
|
ELOOP = 92
|
||||||
EOPNOTSUPP = 95;
|
EOPNOTSUPP = 95
|
||||||
EPFNOSUPPORT = 96;
|
EPFNOSUPPORT = 96
|
||||||
ECONNRESET = 104;
|
ECONNRESET = 104
|
||||||
ENOBUFS = 105;
|
ENOBUFS = 105
|
||||||
EAFNOSUPPORT = 106;
|
EAFNOSUPPORT = 106
|
||||||
EPROTOTYPE = 107;
|
EPROTOTYPE = 107
|
||||||
ENOTSOCK = 108;
|
ENOTSOCK = 108
|
||||||
ENOPROTOOPT = 109;
|
ENOPROTOOPT = 109
|
||||||
ESHUTDOWN = 110;
|
ESHUTDOWN = 110
|
||||||
ECONNREFUSED = 111;
|
ECONNREFUSED = 111
|
||||||
EADDRINUSE = 112;
|
EADDRINUSE = 112
|
||||||
ECONNABORTED = 113;
|
ECONNABORTED = 113
|
||||||
ENETUNREACH = 114;
|
ENETUNREACH = 114
|
||||||
ENETDOWN = 115;
|
ENETDOWN = 115
|
||||||
ETIMEDOUT = 116;
|
ETIMEDOUT = 116
|
||||||
EHOSTDOWN = 117;
|
EHOSTDOWN = 117
|
||||||
EHOSTUNREACH = 118;
|
EHOSTUNREACH = 118
|
||||||
EINPROGRESS = 119;
|
EINPROGRESS = 119
|
||||||
EALREADY = 120;
|
EALREADY = 120
|
||||||
EDESTADDRREQ = 121;
|
EDESTADDRREQ = 121
|
||||||
EPROTONOSUPPORT = 123;
|
EPROTONOSUPPORT = 123
|
||||||
ESOCKTNOSUPPORT = 124;
|
ESOCKTNOSUPPORT = 124
|
||||||
EADDRNOTAVAIL = 125;
|
EADDRNOTAVAIL = 125
|
||||||
ENETRESET = 126;
|
ENETRESET = 126
|
||||||
EISCONN = 127;
|
EISCONN = 127
|
||||||
ENOTCONN = 128;
|
ENOTCONN = 128
|
||||||
ETOOMANYREFS = 129;
|
ETOOMANYREFS = 129
|
||||||
EPROCLIM = 130;
|
EPROCLIM = 130
|
||||||
EUSERS = 131;
|
EUSERS = 131
|
||||||
ESTALE = 133;
|
ESTALE = 133
|
||||||
ENOMEDIUM = 135;
|
ENOMEDIUM = 135
|
||||||
ENOSHARE = 136;
|
ENOSHARE = 136
|
||||||
ECASECLASH = 137;
|
ECASECLASH = 137
|
||||||
EILSEQ = 138;
|
EILSEQ = 138
|
||||||
EOVERFLOW = 139;
|
EOVERFLOW = 139
|
||||||
ECANCELED = 140;
|
ECANCELED = 140
|
||||||
EL2NSYNC = 88;
|
EL2NSYNC = 88
|
||||||
EIDRM = 91;
|
EIDRM = 91
|
||||||
EMSGSIZE = 132;
|
EMSGSIZE = 132
|
||||||
ENACL = 99; /* otherwise unused */
|
ENACL = 99 /* otherwise unused */
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -6,662 +6,662 @@ package syscall
|
|||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
||||||
func getgroups(ngid int, gid *_Gid_t) (n int, errno int) {
|
func getgroups(ngid int, gid *_Gid_t) (n int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0);
|
r0, _, e1 := Syscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func setgroups(ngid int, gid *_Gid_t) (errno int) {
|
func setgroups(ngid int, gid *_Gid_t) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0);
|
_, _, e1 := Syscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) {
|
func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) {
|
||||||
r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0);
|
r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
|
||||||
wpid = int(r0);
|
wpid = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func pipe() (r int, w int, errno int) {
|
func pipe() (r int, w int, errno int) {
|
||||||
r0, r1, e1 := Syscall(SYS_PIPE, 0, 0, 0);
|
r0, r1, e1 := Syscall(SYS_PIPE, 0, 0, 0)
|
||||||
r = int(r0);
|
r = int(r0)
|
||||||
w = int(r1);
|
w = int(r1)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
|
func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)));
|
r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
|
||||||
fd = int(r0);
|
fd = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
|
func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen));
|
_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
|
func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen));
|
_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func socket(domain int, typ int, proto int) (fd int, errno int) {
|
func socket(domain int, typ int, proto int) (fd int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto));
|
r0, _, e1 := Syscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
|
||||||
fd = int(r0);
|
fd = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int) {
|
func setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int) {
|
||||||
_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0);
|
_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
|
func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)));
|
_, _, e1 := Syscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
|
func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)));
|
_, _, e1 := Syscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Shutdown(s int, how int) (errno int) {
|
func Shutdown(s int, how int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0);
|
_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
|
func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
|
||||||
var _p0 *byte;
|
var _p0 *byte
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
_p0 = &p[0]
|
_p0 = &p[0]
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)));
|
r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
|
func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
|
||||||
var _p0 *byte;
|
var _p0 *byte
|
||||||
if len(buf) > 0 {
|
if len(buf) > 0 {
|
||||||
_p0 = &buf[0]
|
_p0 = &buf[0]
|
||||||
}
|
}
|
||||||
_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen));
|
_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
|
func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
|
||||||
r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)));
|
r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) {
|
func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) {
|
||||||
var _p0 *_C_int;
|
var _p0 *_C_int
|
||||||
if len(mib) > 0 {
|
if len(mib) > 0 {
|
||||||
_p0 = &mib[0]
|
_p0 = &mib[0]
|
||||||
}
|
}
|
||||||
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(unsafe.Pointer(_p0)), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen));
|
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(unsafe.Pointer(_p0)), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func fcntl(fd int, cmd int, arg int) (val int, errno int) {
|
func fcntl(fd int, cmd int, arg int) (val int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg));
|
r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
|
||||||
val = int(r0);
|
val = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Access(path string, flags int) (errno int) {
|
func Access(path string, flags int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0);
|
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Adjtime(delta *Timeval, olddelta *Timeval) (errno int) {
|
func Adjtime(delta *Timeval, olddelta *Timeval) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0);
|
_, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Chdir(path string) (errno int) {
|
func Chdir(path string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0);
|
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Chflags(path string, flags int) (errno int) {
|
func Chflags(path string, flags int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0);
|
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Chmod(path string, mode int) (errno int) {
|
func Chmod(path string, mode int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0);
|
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Chown(path string, uid int, gid int) (errno int) {
|
func Chown(path string, uid int, gid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid));
|
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Chroot(path string) (errno int) {
|
func Chroot(path string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0);
|
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Close(fd int) (errno int) {
|
func Close(fd int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0);
|
_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Dup(fd int) (nfd int, errno int) {
|
func Dup(fd int) (nfd int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0);
|
r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0)
|
||||||
nfd = int(r0);
|
nfd = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Dup2(from int, to int) (errno int) {
|
func Dup2(from int, to int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0);
|
_, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Exit(code int) {
|
func Exit(code int) {
|
||||||
Syscall(SYS_EXIT, uintptr(code), 0, 0);
|
Syscall(SYS_EXIT, uintptr(code), 0, 0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fchdir(fd int) (errno int) {
|
func Fchdir(fd int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0);
|
_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fchflags(path string, flags int) (errno int) {
|
func Fchflags(path string, flags int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0);
|
_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fchmod(fd int, mode int) (errno int) {
|
func Fchmod(fd int, mode int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0);
|
_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fchown(fd int, uid int, gid int) (errno int) {
|
func Fchown(fd int, uid int, gid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid));
|
_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Flock(fd int, how int) (errno int) {
|
func Flock(fd int, how int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0);
|
_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fpathconf(fd int, name int) (val int, errno int) {
|
func Fpathconf(fd int, name int) (val int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0);
|
r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0)
|
||||||
val = int(r0);
|
val = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fstat(fd int, stat *Stat_t) (errno int) {
|
func Fstat(fd int, stat *Stat_t) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0);
|
_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fstatfs(fd int, stat *Statfs_t) (errno int) {
|
func Fstatfs(fd int, stat *Statfs_t) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0);
|
_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fsync(fd int) (errno int) {
|
func Fsync(fd int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0);
|
_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Ftruncate(fd int, length int64) (errno int) {
|
func Ftruncate(fd int, length int64) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), uintptr(length>>32));
|
_, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), uintptr(length>>32))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
|
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
|
||||||
var _p0 *byte;
|
var _p0 *byte
|
||||||
if len(buf) > 0 {
|
if len(buf) > 0 {
|
||||||
_p0 = &buf[0]
|
_p0 = &buf[0]
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0);
|
r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getdtablesize() (size int) {
|
func Getdtablesize() (size int) {
|
||||||
r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0)
|
||||||
size = int(r0);
|
size = int(r0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getegid() (egid int) {
|
func Getegid() (egid int) {
|
||||||
r0, _, _ := Syscall(SYS_GETEGID, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_GETEGID, 0, 0, 0)
|
||||||
egid = int(r0);
|
egid = int(r0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Geteuid() (uid int) {
|
func Geteuid() (uid int) {
|
||||||
r0, _, _ := Syscall(SYS_GETEUID, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_GETEUID, 0, 0, 0)
|
||||||
uid = int(r0);
|
uid = int(r0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
|
func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
|
||||||
var _p0 *Statfs_t;
|
var _p0 *Statfs_t
|
||||||
if len(buf) > 0 {
|
if len(buf) > 0 {
|
||||||
_p0 = &buf[0]
|
_p0 = &buf[0]
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags));
|
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags))
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getgid() (gid int) {
|
func Getgid() (gid int) {
|
||||||
r0, _, _ := Syscall(SYS_GETGID, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_GETGID, 0, 0, 0)
|
||||||
gid = int(r0);
|
gid = int(r0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getpgid(pid int) (pgid int, errno int) {
|
func Getpgid(pid int) (pgid int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_GETPGID, uintptr(pid), 0, 0);
|
r0, _, e1 := Syscall(SYS_GETPGID, uintptr(pid), 0, 0)
|
||||||
pgid = int(r0);
|
pgid = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getpgrp() (pgrp int) {
|
func Getpgrp() (pgrp int) {
|
||||||
r0, _, _ := Syscall(SYS_GETPGRP, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_GETPGRP, 0, 0, 0)
|
||||||
pgrp = int(r0);
|
pgrp = int(r0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getpid() (pid int) {
|
func Getpid() (pid int) {
|
||||||
r0, _, _ := Syscall(SYS_GETPID, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_GETPID, 0, 0, 0)
|
||||||
pid = int(r0);
|
pid = int(r0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getppid() (ppid int) {
|
func Getppid() (ppid int) {
|
||||||
r0, _, _ := Syscall(SYS_GETPPID, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_GETPPID, 0, 0, 0)
|
||||||
ppid = int(r0);
|
ppid = int(r0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getpriority(which int, who int) (prio int, errno int) {
|
func Getpriority(which int, who int) (prio int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0);
|
r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
|
||||||
prio = int(r0);
|
prio = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getrlimit(which int, lim *Rlimit) (errno int) {
|
func Getrlimit(which int, lim *Rlimit) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0);
|
_, _, e1 := Syscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getrusage(who int, rusage *Rusage) (errno int) {
|
func Getrusage(who int, rusage *Rusage) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0);
|
_, _, e1 := Syscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getsid(pid int) (sid int, errno int) {
|
func Getsid(pid int) (sid int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_GETSID, uintptr(pid), 0, 0);
|
r0, _, e1 := Syscall(SYS_GETSID, uintptr(pid), 0, 0)
|
||||||
sid = int(r0);
|
sid = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Gettimeofday(tv *Timeval) (errno int) {
|
func Gettimeofday(tv *Timeval) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0);
|
_, _, e1 := Syscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getuid() (uid int) {
|
func Getuid() (uid int) {
|
||||||
r0, _, _ := Syscall(SYS_GETUID, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_GETUID, 0, 0, 0)
|
||||||
uid = int(r0);
|
uid = int(r0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Issetugid() (tainted bool) {
|
func Issetugid() (tainted bool) {
|
||||||
r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0)
|
||||||
tainted = bool(r0 != 0);
|
tainted = bool(r0 != 0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Kill(pid int, signum int, posix int) (errno int) {
|
func Kill(pid int, signum int, posix int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix));
|
_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Kqueue() (fd int, errno int) {
|
func Kqueue() (fd int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0);
|
r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0)
|
||||||
fd = int(r0);
|
fd = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Lchown(path string, uid int, gid int) (errno int) {
|
func Lchown(path string, uid int, gid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid));
|
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Link(path string, link string) (errno int) {
|
func Link(path string, link string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0);
|
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Listen(s int, backlog int) (errno int) {
|
func Listen(s int, backlog int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0);
|
_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Lstat(path string, stat *Stat_t) (errno int) {
|
func Lstat(path string, stat *Stat_t) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0);
|
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Mkdir(path string, mode int) (errno int) {
|
func Mkdir(path string, mode int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0);
|
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Mkfifo(path string, mode int) (errno int) {
|
func Mkfifo(path string, mode int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0);
|
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Mknod(path string, mode int, dev int) (errno int) {
|
func Mknod(path string, mode int, dev int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev));
|
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Open(path string, mode int, perm int) (fd int, errno int) {
|
func Open(path string, mode int, perm int) (fd int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm));
|
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
|
||||||
fd = int(r0);
|
fd = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Pathconf(path string, name int) (val int, errno int) {
|
func Pathconf(path string, name int) (val int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0);
|
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
|
||||||
val = int(r0);
|
val = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Pread(fd int, p []byte, offset int64) (n int, errno int) {
|
func Pread(fd int, p []byte, offset int64) (n int, errno int) {
|
||||||
var _p0 *byte;
|
var _p0 *byte
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
_p0 = &p[0]
|
_p0 = &p[0]
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0);
|
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
|
func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
|
||||||
var _p0 *byte;
|
var _p0 *byte
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
_p0 = &p[0]
|
_p0 = &p[0]
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0);
|
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Read(fd int, p []byte) (n int, errno int) {
|
func Read(fd int, p []byte) (n int, errno int) {
|
||||||
var _p0 *byte;
|
var _p0 *byte
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
_p0 = &p[0]
|
_p0 = &p[0]
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)));
|
r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)))
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Readlink(path string, buf []byte) (n int, errno int) {
|
func Readlink(path string, buf []byte) (n int, errno int) {
|
||||||
var _p0 *byte;
|
var _p0 *byte
|
||||||
if len(buf) > 0 {
|
if len(buf) > 0 {
|
||||||
_p0 = &buf[0]
|
_p0 = &buf[0]
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)));
|
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)))
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Rename(from string, to string) (errno int) {
|
func Rename(from string, to string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0);
|
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Revoke(path string) (errno int) {
|
func Revoke(path string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0);
|
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Rmdir(path string) (errno int) {
|
func Rmdir(path string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0);
|
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
|
func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
|
||||||
r0, r1, e1 := Syscall6(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(offset>>32), uintptr(whence), 0, 0);
|
r0, r1, e1 := Syscall6(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(offset>>32), uintptr(whence), 0, 0)
|
||||||
newoffset = int64(int64(r1)<<32 | int64(r0));
|
newoffset = int64(int64(r1)<<32 | int64(r0))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int) {
|
func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int) {
|
||||||
_, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0);
|
_, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setegid(egid int) (errno int) {
|
func Setegid(egid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETEGID, uintptr(egid), 0, 0);
|
_, _, e1 := Syscall(SYS_SETEGID, uintptr(egid), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Seteuid(euid int) (errno int) {
|
func Seteuid(euid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETEUID, uintptr(euid), 0, 0);
|
_, _, e1 := Syscall(SYS_SETEUID, uintptr(euid), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setgid(gid int) (errno int) {
|
func Setgid(gid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETGID, uintptr(gid), 0, 0);
|
_, _, e1 := Syscall(SYS_SETGID, uintptr(gid), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setlogin(name string) (errno int) {
|
func Setlogin(name string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0);
|
_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setpgid(pid int, pgid int) (errno int) {
|
func Setpgid(pid int, pgid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0);
|
_, _, e1 := Syscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setpriority(which int, who int, prio int) (errno int) {
|
func Setpriority(which int, who int, prio int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio));
|
_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setregid(rgid int, egid int) (errno int) {
|
func Setregid(rgid int, egid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0);
|
_, _, e1 := Syscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setreuid(ruid int, euid int) (errno int) {
|
func Setreuid(ruid int, euid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0);
|
_, _, e1 := Syscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setrlimit(which int, lim *Rlimit) (errno int) {
|
func Setrlimit(which int, lim *Rlimit) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0);
|
_, _, e1 := Syscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setsid() (pid int, errno int) {
|
func Setsid() (pid int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_SETSID, 0, 0, 0);
|
r0, _, e1 := Syscall(SYS_SETSID, 0, 0, 0)
|
||||||
pid = int(r0);
|
pid = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Settimeofday(tp *Timeval) (errno int) {
|
func Settimeofday(tp *Timeval) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0);
|
_, _, e1 := Syscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setuid(uid int) (errno int) {
|
func Setuid(uid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETUID, uintptr(uid), 0, 0);
|
_, _, e1 := Syscall(SYS_SETUID, uintptr(uid), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Stat(path string, stat *Stat_t) (errno int) {
|
func Stat(path string, stat *Stat_t) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0);
|
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Statfs(path string, stat *Statfs_t) (errno int) {
|
func Statfs(path string, stat *Statfs_t) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0);
|
_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Symlink(path string, link string) (errno int) {
|
func Symlink(path string, link string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0);
|
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Sync() (errno int) {
|
func Sync() (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SYNC, 0, 0, 0);
|
_, _, e1 := Syscall(SYS_SYNC, 0, 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Truncate(path string, length int64) (errno int) {
|
func Truncate(path string, length int64) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), uintptr(length>>32));
|
_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), uintptr(length>>32))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Umask(newmask int) (errno int) {
|
func Umask(newmask int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_UMASK, uintptr(newmask), 0, 0);
|
_, _, e1 := Syscall(SYS_UMASK, uintptr(newmask), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Undelete(path string) (errno int) {
|
func Undelete(path string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0);
|
_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Unlink(path string) (errno int) {
|
func Unlink(path string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0);
|
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Unmount(path string, flags int) (errno int) {
|
func Unmount(path string, flags int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0);
|
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Write(fd int, p []byte) (n int, errno int) {
|
func Write(fd int, p []byte) (n int, errno int) {
|
||||||
var _p0 *byte;
|
var _p0 *byte
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
_p0 = &p[0]
|
_p0 = &p[0]
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)));
|
r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)))
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func read(fd int, buf *byte, nbuf int) (n int, errno int) {
|
func read(fd int, buf *byte, nbuf int) (n int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf));
|
r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func write(fd int, buf *byte, nbuf int) (n int, errno int) {
|
func write(fd int, buf *byte, nbuf int) (n int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf));
|
r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
@ -6,662 +6,662 @@ package syscall
|
|||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
||||||
func getgroups(ngid int, gid *_Gid_t) (n int, errno int) {
|
func getgroups(ngid int, gid *_Gid_t) (n int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0);
|
r0, _, e1 := Syscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func setgroups(ngid int, gid *_Gid_t) (errno int) {
|
func setgroups(ngid int, gid *_Gid_t) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0);
|
_, _, e1 := Syscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) {
|
func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) {
|
||||||
r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0);
|
r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
|
||||||
wpid = int(r0);
|
wpid = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func pipe() (r int, w int, errno int) {
|
func pipe() (r int, w int, errno int) {
|
||||||
r0, r1, e1 := Syscall(SYS_PIPE, 0, 0, 0);
|
r0, r1, e1 := Syscall(SYS_PIPE, 0, 0, 0)
|
||||||
r = int(r0);
|
r = int(r0)
|
||||||
w = int(r1);
|
w = int(r1)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
|
func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)));
|
r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
|
||||||
fd = int(r0);
|
fd = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
|
func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen));
|
_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
|
func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen));
|
_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func socket(domain int, typ int, proto int) (fd int, errno int) {
|
func socket(domain int, typ int, proto int) (fd int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto));
|
r0, _, e1 := Syscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
|
||||||
fd = int(r0);
|
fd = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int) {
|
func setsockopt(s int, level int, name int, val uintptr, vallen int) (errno int) {
|
||||||
_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0);
|
_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
|
func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)));
|
_, _, e1 := Syscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
|
func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)));
|
_, _, e1 := Syscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Shutdown(s int, how int) (errno int) {
|
func Shutdown(s int, how int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0);
|
_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
|
func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
|
||||||
var _p0 *byte;
|
var _p0 *byte
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
_p0 = &p[0]
|
_p0 = &p[0]
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)));
|
r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
|
func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
|
||||||
var _p0 *byte;
|
var _p0 *byte
|
||||||
if len(buf) > 0 {
|
if len(buf) > 0 {
|
||||||
_p0 = &buf[0]
|
_p0 = &buf[0]
|
||||||
}
|
}
|
||||||
_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen));
|
_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
|
func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
|
||||||
r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)));
|
r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) {
|
func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) {
|
||||||
var _p0 *_C_int;
|
var _p0 *_C_int
|
||||||
if len(mib) > 0 {
|
if len(mib) > 0 {
|
||||||
_p0 = &mib[0]
|
_p0 = &mib[0]
|
||||||
}
|
}
|
||||||
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(unsafe.Pointer(_p0)), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen));
|
_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(unsafe.Pointer(_p0)), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func fcntl(fd int, cmd int, arg int) (val int, errno int) {
|
func fcntl(fd int, cmd int, arg int) (val int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg));
|
r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
|
||||||
val = int(r0);
|
val = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Access(path string, flags int) (errno int) {
|
func Access(path string, flags int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0);
|
_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Adjtime(delta *Timeval, olddelta *Timeval) (errno int) {
|
func Adjtime(delta *Timeval, olddelta *Timeval) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0);
|
_, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Chdir(path string) (errno int) {
|
func Chdir(path string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0);
|
_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Chflags(path string, flags int) (errno int) {
|
func Chflags(path string, flags int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0);
|
_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Chmod(path string, mode int) (errno int) {
|
func Chmod(path string, mode int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0);
|
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Chown(path string, uid int, gid int) (errno int) {
|
func Chown(path string, uid int, gid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid));
|
_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Chroot(path string) (errno int) {
|
func Chroot(path string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0);
|
_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Close(fd int) (errno int) {
|
func Close(fd int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0);
|
_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Dup(fd int) (nfd int, errno int) {
|
func Dup(fd int) (nfd int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0);
|
r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0)
|
||||||
nfd = int(r0);
|
nfd = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Dup2(from int, to int) (errno int) {
|
func Dup2(from int, to int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0);
|
_, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Exit(code int) {
|
func Exit(code int) {
|
||||||
Syscall(SYS_EXIT, uintptr(code), 0, 0);
|
Syscall(SYS_EXIT, uintptr(code), 0, 0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fchdir(fd int) (errno int) {
|
func Fchdir(fd int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0);
|
_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fchflags(path string, flags int) (errno int) {
|
func Fchflags(path string, flags int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0);
|
_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fchmod(fd int, mode int) (errno int) {
|
func Fchmod(fd int, mode int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0);
|
_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fchown(fd int, uid int, gid int) (errno int) {
|
func Fchown(fd int, uid int, gid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid));
|
_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Flock(fd int, how int) (errno int) {
|
func Flock(fd int, how int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0);
|
_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fpathconf(fd int, name int) (val int, errno int) {
|
func Fpathconf(fd int, name int) (val int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0);
|
r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0)
|
||||||
val = int(r0);
|
val = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fstat(fd int, stat *Stat_t) (errno int) {
|
func Fstat(fd int, stat *Stat_t) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0);
|
_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fstatfs(fd int, stat *Statfs_t) (errno int) {
|
func Fstatfs(fd int, stat *Statfs_t) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0);
|
_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fsync(fd int) (errno int) {
|
func Fsync(fd int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0);
|
_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Ftruncate(fd int, length int64) (errno int) {
|
func Ftruncate(fd int, length int64) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0);
|
_, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
|
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
|
||||||
var _p0 *byte;
|
var _p0 *byte
|
||||||
if len(buf) > 0 {
|
if len(buf) > 0 {
|
||||||
_p0 = &buf[0]
|
_p0 = &buf[0]
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0);
|
r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getdtablesize() (size int) {
|
func Getdtablesize() (size int) {
|
||||||
r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_GETDTABLESIZE, 0, 0, 0)
|
||||||
size = int(r0);
|
size = int(r0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getegid() (egid int) {
|
func Getegid() (egid int) {
|
||||||
r0, _, _ := Syscall(SYS_GETEGID, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_GETEGID, 0, 0, 0)
|
||||||
egid = int(r0);
|
egid = int(r0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Geteuid() (uid int) {
|
func Geteuid() (uid int) {
|
||||||
r0, _, _ := Syscall(SYS_GETEUID, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_GETEUID, 0, 0, 0)
|
||||||
uid = int(r0);
|
uid = int(r0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
|
func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
|
||||||
var _p0 *Statfs_t;
|
var _p0 *Statfs_t
|
||||||
if len(buf) > 0 {
|
if len(buf) > 0 {
|
||||||
_p0 = &buf[0]
|
_p0 = &buf[0]
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags));
|
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags))
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getgid() (gid int) {
|
func Getgid() (gid int) {
|
||||||
r0, _, _ := Syscall(SYS_GETGID, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_GETGID, 0, 0, 0)
|
||||||
gid = int(r0);
|
gid = int(r0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getpgid(pid int) (pgid int, errno int) {
|
func Getpgid(pid int) (pgid int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_GETPGID, uintptr(pid), 0, 0);
|
r0, _, e1 := Syscall(SYS_GETPGID, uintptr(pid), 0, 0)
|
||||||
pgid = int(r0);
|
pgid = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getpgrp() (pgrp int) {
|
func Getpgrp() (pgrp int) {
|
||||||
r0, _, _ := Syscall(SYS_GETPGRP, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_GETPGRP, 0, 0, 0)
|
||||||
pgrp = int(r0);
|
pgrp = int(r0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getpid() (pid int) {
|
func Getpid() (pid int) {
|
||||||
r0, _, _ := Syscall(SYS_GETPID, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_GETPID, 0, 0, 0)
|
||||||
pid = int(r0);
|
pid = int(r0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getppid() (ppid int) {
|
func Getppid() (ppid int) {
|
||||||
r0, _, _ := Syscall(SYS_GETPPID, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_GETPPID, 0, 0, 0)
|
||||||
ppid = int(r0);
|
ppid = int(r0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getpriority(which int, who int) (prio int, errno int) {
|
func Getpriority(which int, who int) (prio int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0);
|
r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
|
||||||
prio = int(r0);
|
prio = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getrlimit(which int, lim *Rlimit) (errno int) {
|
func Getrlimit(which int, lim *Rlimit) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0);
|
_, _, e1 := Syscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getrusage(who int, rusage *Rusage) (errno int) {
|
func Getrusage(who int, rusage *Rusage) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0);
|
_, _, e1 := Syscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getsid(pid int) (sid int, errno int) {
|
func Getsid(pid int) (sid int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_GETSID, uintptr(pid), 0, 0);
|
r0, _, e1 := Syscall(SYS_GETSID, uintptr(pid), 0, 0)
|
||||||
sid = int(r0);
|
sid = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Gettimeofday(tv *Timeval) (errno int) {
|
func Gettimeofday(tv *Timeval) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0);
|
_, _, e1 := Syscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Getuid() (uid int) {
|
func Getuid() (uid int) {
|
||||||
r0, _, _ := Syscall(SYS_GETUID, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_GETUID, 0, 0, 0)
|
||||||
uid = int(r0);
|
uid = int(r0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Issetugid() (tainted bool) {
|
func Issetugid() (tainted bool) {
|
||||||
r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0);
|
r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0)
|
||||||
tainted = bool(r0 != 0);
|
tainted = bool(r0 != 0)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Kill(pid int, signum int, posix int) (errno int) {
|
func Kill(pid int, signum int, posix int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix));
|
_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Kqueue() (fd int, errno int) {
|
func Kqueue() (fd int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0);
|
r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0)
|
||||||
fd = int(r0);
|
fd = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Lchown(path string, uid int, gid int) (errno int) {
|
func Lchown(path string, uid int, gid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid));
|
_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Link(path string, link string) (errno int) {
|
func Link(path string, link string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0);
|
_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Listen(s int, backlog int) (errno int) {
|
func Listen(s int, backlog int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0);
|
_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Lstat(path string, stat *Stat_t) (errno int) {
|
func Lstat(path string, stat *Stat_t) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0);
|
_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Mkdir(path string, mode int) (errno int) {
|
func Mkdir(path string, mode int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0);
|
_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Mkfifo(path string, mode int) (errno int) {
|
func Mkfifo(path string, mode int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0);
|
_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Mknod(path string, mode int, dev int) (errno int) {
|
func Mknod(path string, mode int, dev int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev));
|
_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Open(path string, mode int, perm int) (fd int, errno int) {
|
func Open(path string, mode int, perm int) (fd int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm));
|
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
|
||||||
fd = int(r0);
|
fd = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Pathconf(path string, name int) (val int, errno int) {
|
func Pathconf(path string, name int) (val int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0);
|
r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
|
||||||
val = int(r0);
|
val = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Pread(fd int, p []byte, offset int64) (n int, errno int) {
|
func Pread(fd int, p []byte, offset int64) (n int, errno int) {
|
||||||
var _p0 *byte;
|
var _p0 *byte
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
_p0 = &p[0]
|
_p0 = &p[0]
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0);
|
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0)
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
|
func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
|
||||||
var _p0 *byte;
|
var _p0 *byte
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
_p0 = &p[0]
|
_p0 = &p[0]
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0);
|
r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0)
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Read(fd int, p []byte) (n int, errno int) {
|
func Read(fd int, p []byte) (n int, errno int) {
|
||||||
var _p0 *byte;
|
var _p0 *byte
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
_p0 = &p[0]
|
_p0 = &p[0]
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)));
|
r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)))
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Readlink(path string, buf []byte) (n int, errno int) {
|
func Readlink(path string, buf []byte) (n int, errno int) {
|
||||||
var _p0 *byte;
|
var _p0 *byte
|
||||||
if len(buf) > 0 {
|
if len(buf) > 0 {
|
||||||
_p0 = &buf[0]
|
_p0 = &buf[0]
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)));
|
r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)))
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Rename(from string, to string) (errno int) {
|
func Rename(from string, to string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0);
|
_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Revoke(path string) (errno int) {
|
func Revoke(path string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0);
|
_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Rmdir(path string) (errno int) {
|
func Rmdir(path string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0);
|
_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
|
func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence));
|
r0, _, e1 := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
|
||||||
newoffset = int64(r0);
|
newoffset = int64(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int) {
|
func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int) {
|
||||||
_, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0);
|
_, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setegid(egid int) (errno int) {
|
func Setegid(egid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETEGID, uintptr(egid), 0, 0);
|
_, _, e1 := Syscall(SYS_SETEGID, uintptr(egid), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Seteuid(euid int) (errno int) {
|
func Seteuid(euid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETEUID, uintptr(euid), 0, 0);
|
_, _, e1 := Syscall(SYS_SETEUID, uintptr(euid), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setgid(gid int) (errno int) {
|
func Setgid(gid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETGID, uintptr(gid), 0, 0);
|
_, _, e1 := Syscall(SYS_SETGID, uintptr(gid), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setlogin(name string) (errno int) {
|
func Setlogin(name string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0);
|
_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setpgid(pid int, pgid int) (errno int) {
|
func Setpgid(pid int, pgid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0);
|
_, _, e1 := Syscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setpriority(which int, who int, prio int) (errno int) {
|
func Setpriority(which int, who int, prio int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio));
|
_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setregid(rgid int, egid int) (errno int) {
|
func Setregid(rgid int, egid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0);
|
_, _, e1 := Syscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setreuid(ruid int, euid int) (errno int) {
|
func Setreuid(ruid int, euid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0);
|
_, _, e1 := Syscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setrlimit(which int, lim *Rlimit) (errno int) {
|
func Setrlimit(which int, lim *Rlimit) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0);
|
_, _, e1 := Syscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setsid() (pid int, errno int) {
|
func Setsid() (pid int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_SETSID, 0, 0, 0);
|
r0, _, e1 := Syscall(SYS_SETSID, 0, 0, 0)
|
||||||
pid = int(r0);
|
pid = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Settimeofday(tp *Timeval) (errno int) {
|
func Settimeofday(tp *Timeval) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0);
|
_, _, e1 := Syscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setuid(uid int) (errno int) {
|
func Setuid(uid int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SETUID, uintptr(uid), 0, 0);
|
_, _, e1 := Syscall(SYS_SETUID, uintptr(uid), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Stat(path string, stat *Stat_t) (errno int) {
|
func Stat(path string, stat *Stat_t) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0);
|
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Statfs(path string, stat *Statfs_t) (errno int) {
|
func Statfs(path string, stat *Statfs_t) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0);
|
_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Symlink(path string, link string) (errno int) {
|
func Symlink(path string, link string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0);
|
_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Sync() (errno int) {
|
func Sync() (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_SYNC, 0, 0, 0);
|
_, _, e1 := Syscall(SYS_SYNC, 0, 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Truncate(path string, length int64) (errno int) {
|
func Truncate(path string, length int64) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), 0);
|
_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Umask(newmask int) (errno int) {
|
func Umask(newmask int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_UMASK, uintptr(newmask), 0, 0);
|
_, _, e1 := Syscall(SYS_UMASK, uintptr(newmask), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Undelete(path string) (errno int) {
|
func Undelete(path string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0);
|
_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Unlink(path string) (errno int) {
|
func Unlink(path string) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0);
|
_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Unmount(path string, flags int) (errno int) {
|
func Unmount(path string, flags int) (errno int) {
|
||||||
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0);
|
_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Write(fd int, p []byte) (n int, errno int) {
|
func Write(fd int, p []byte) (n int, errno int) {
|
||||||
var _p0 *byte;
|
var _p0 *byte
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
_p0 = &p[0]
|
_p0 = &p[0]
|
||||||
}
|
}
|
||||||
r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)));
|
r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)))
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func read(fd int, buf *byte, nbuf int) (n int, errno int) {
|
func read(fd int, buf *byte, nbuf int) (n int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf));
|
r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func write(fd int, buf *byte, nbuf int) (n int, errno int) {
|
func write(fd int, buf *byte, nbuf int) (n int, errno int) {
|
||||||
r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf));
|
r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
|
||||||
n = int(r0);
|
n = int(r0)
|
||||||
errno = int(e1);
|
errno = int(e1)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user