libgo: Update to weekly.2011-12-14.

From-SVN: r183118
This commit is contained in:
Ian Lance Taylor 2012-01-12 01:31:45 +00:00
parent c6135f0633
commit 9a0e3259f4
167 changed files with 3547 additions and 1686 deletions

View File

@ -9943,7 +9943,11 @@ Call_expression::do_get_tree(Translate_context* context)
fn = build_fold_addr_expr_loc(location.gcc_location(), fn = build_fold_addr_expr_loc(location.gcc_location(),
excess_fndecl); excess_fndecl);
for (int i = 0; i < nargs; ++i) for (int i = 0; i < nargs; ++i)
args[i] = ::convert(excess_type, args[i]); {
if (SCALAR_FLOAT_TYPE_P(TREE_TYPE(args[i]))
|| COMPLEX_FLOAT_TYPE_P(TREE_TYPE(args[i])))
args[i] = ::convert(excess_type, args[i]);
}
} }
} }
} }

View File

@ -125,17 +125,108 @@ Gogo::define_builtin_function_trees()
NULL_TREE), NULL_TREE),
false); false);
// We provide sqrt for the math library. // We provide some functions for the math library.
define_builtin(BUILT_IN_SQRT, "__builtin_sqrt", "sqrt", tree math_function_type = build_function_type_list(double_type_node,
double_type_node,
NULL_TREE);
tree math_function_type_long =
build_function_type_list(long_double_type_node, long_double_type_node,
long_double_type_node, NULL_TREE);
tree math_function_type_two = build_function_type_list(double_type_node,
double_type_node,
double_type_node,
NULL_TREE);
tree math_function_type_long_two =
build_function_type_list(long_double_type_node, long_double_type_node,
long_double_type_node, NULL_TREE);
define_builtin(BUILT_IN_ACOS, "__builtin_acos", "acos",
math_function_type, true);
define_builtin(BUILT_IN_ACOSL, "__builtin_acosl", "acosl",
math_function_type_long, true);
define_builtin(BUILT_IN_ASIN, "__builtin_asin", "asin",
math_function_type, true);
define_builtin(BUILT_IN_ASINL, "__builtin_asinl", "asinl",
math_function_type_long, true);
define_builtin(BUILT_IN_ATAN, "__builtin_atan", "atan",
math_function_type, true);
define_builtin(BUILT_IN_ATANL, "__builtin_atanl", "atanl",
math_function_type_long, true);
define_builtin(BUILT_IN_ATAN2, "__builtin_atan2", "atan2",
math_function_type_two, true);
define_builtin(BUILT_IN_ATAN2L, "__builtin_atan2l", "atan2l",
math_function_type_long_two, true);
define_builtin(BUILT_IN_CEIL, "__builtin_ceil", "ceil",
math_function_type, true);
define_builtin(BUILT_IN_CEILL, "__builtin_ceill", "ceill",
math_function_type_long, true);
define_builtin(BUILT_IN_COS, "__builtin_cos", "cos",
math_function_type, true);
define_builtin(BUILT_IN_COSL, "__builtin_cosl", "cosl",
math_function_type_long, true);
define_builtin(BUILT_IN_EXP, "__builtin_exp", "exp",
math_function_type, true);
define_builtin(BUILT_IN_EXPL, "__builtin_expl", "expl",
math_function_type_long, true);
define_builtin(BUILT_IN_EXPM1, "__builtin_expm1", "expm1",
math_function_type, true);
define_builtin(BUILT_IN_EXPM1L, "__builtin_expm1l", "expm1l",
math_function_type_long, true);
define_builtin(BUILT_IN_FABS, "__builtin_fabs", "fabs",
math_function_type, true);
define_builtin(BUILT_IN_FABSL, "__builtin_fabsl", "fabsl",
math_function_type_long, true);
define_builtin(BUILT_IN_FLOOR, "__builtin_floor", "floor",
math_function_type, true);
define_builtin(BUILT_IN_FLOORL, "__builtin_floorl", "floorl",
math_function_type_long, true);
define_builtin(BUILT_IN_FMOD, "__builtin_fmod", "fmod",
math_function_type_two, true);
define_builtin(BUILT_IN_FMODL, "__builtin_fmodl", "fmodl",
math_function_type_long_two, true);
define_builtin(BUILT_IN_LDEXP, "__builtin_ldexp", "ldexp",
build_function_type_list(double_type_node, build_function_type_list(double_type_node,
double_type_node, double_type_node,
integer_type_node,
NULL_TREE), NULL_TREE),
true); true);
define_builtin(BUILT_IN_SQRTL, "__builtin_sqrtl", "sqrtl", define_builtin(BUILT_IN_LDEXPL, "__builtin_ldexpl", "ldexpl",
build_function_type_list(long_double_type_node, build_function_type_list(long_double_type_node,
long_double_type_node, long_double_type_node,
integer_type_node,
NULL_TREE), NULL_TREE),
true); true);
define_builtin(BUILT_IN_LOG, "__builtin_log", "log",
math_function_type, true);
define_builtin(BUILT_IN_LOGL, "__builtin_logl", "logl",
math_function_type_long, true);
define_builtin(BUILT_IN_LOG1P, "__builtin_log1p", "log1p",
math_function_type, true);
define_builtin(BUILT_IN_LOG1PL, "__builtin_log1pl", "log1pl",
math_function_type_long, true);
define_builtin(BUILT_IN_LOG10, "__builtin_log10", "log10",
math_function_type, true);
define_builtin(BUILT_IN_LOG10L, "__builtin_log10l", "log10l",
math_function_type_long, true);
define_builtin(BUILT_IN_LOG2, "__builtin_log2", "log2",
math_function_type, true);
define_builtin(BUILT_IN_LOG2L, "__builtin_log2l", "log2l",
math_function_type_long, true);
define_builtin(BUILT_IN_SIN, "__builtin_sin", "sin",
math_function_type, true);
define_builtin(BUILT_IN_SINL, "__builtin_sinl", "sinl",
math_function_type_long, true);
define_builtin(BUILT_IN_SQRT, "__builtin_sqrt", "sqrt",
math_function_type, true);
define_builtin(BUILT_IN_SQRTL, "__builtin_sqrtl", "sqrtl",
math_function_type_long, true);
define_builtin(BUILT_IN_TAN, "__builtin_tan", "tan",
math_function_type, true);
define_builtin(BUILT_IN_TANL, "__builtin_tanl", "tanl",
math_function_type_long, true);
define_builtin(BUILT_IN_TRUNC, "__builtin_trunc", "trunc",
math_function_type, true);
define_builtin(BUILT_IN_TRUNCL, "__builtin_truncl", "truncl",
math_function_type_long, true);
// We use __builtin_return_address in the thunk we build for // We use __builtin_return_address in the thunk we build for
// functions which call recover. // functions which call recover.

View File

@ -1,4 +1,4 @@
0c39eee85b0d 82fdc445f2ff
The first line of this file holds the Mercurial revision number of the The first line of this file holds the Mercurial revision number of the
last merge done from the master library sources. last merge done from the master library sources.

View File

@ -576,6 +576,7 @@ go_html_files = \
go/html/doctype.go \ go/html/doctype.go \
go/html/entity.go \ go/html/entity.go \
go/html/escape.go \ go/html/escape.go \
go/html/foreign.go \
go/html/node.go \ go/html/node.go \
go/html/parse.go \ go/html/parse.go \
go/html/render.go \ go/html/render.go \
@ -610,14 +611,11 @@ go_math_files = \
go/math/dim.go \ go/math/dim.go \
go/math/erf.go \ go/math/erf.go \
go/math/exp.go \ go/math/exp.go \
go/math/exp_port.go \
go/math/exp2.go \
go/math/expm1.go \ go/math/expm1.go \
go/math/floor.go \ go/math/floor.go \
go/math/frexp.go \ go/math/frexp.go \
go/math/gamma.go \ go/math/gamma.go \
go/math/hypot.go \ go/math/hypot.go \
go/math/hypot_port.go \
go/math/j0.go \ go/math/j0.go \
go/math/j1.go \ go/math/j1.go \
go/math/jn.go \ go/math/jn.go \
@ -638,7 +636,6 @@ go_math_files = \
go/math/sincos.go \ go/math/sincos.go \
go/math/sinh.go \ go/math/sinh.go \
go/math/sqrt.go \ go/math/sqrt.go \
go/math/sqrt_port.go \
go/math/tan.go \ go/math/tan.go \
go/math/tanh.go \ go/math/tanh.go \
go/math/unsafe.go go/math/unsafe.go
@ -888,7 +885,6 @@ go_testing_files = \
go_time_files = \ go_time_files = \
go/time/format.go \ go/time/format.go \
go/time/sleep.go \ go/time/sleep.go \
go/time/sys.go \
go/time/sys_unix.go \ go/time/sys_unix.go \
go/time/tick.go \ go/time/tick.go \
go/time/time.go \ go/time/time.go \

View File

@ -962,6 +962,7 @@ go_html_files = \
go/html/doctype.go \ go/html/doctype.go \
go/html/entity.go \ go/html/entity.go \
go/html/escape.go \ go/html/escape.go \
go/html/foreign.go \
go/html/node.go \ go/html/node.go \
go/html/parse.go \ go/html/parse.go \
go/html/render.go \ go/html/render.go \
@ -996,14 +997,11 @@ go_math_files = \
go/math/dim.go \ go/math/dim.go \
go/math/erf.go \ go/math/erf.go \
go/math/exp.go \ go/math/exp.go \
go/math/exp_port.go \
go/math/exp2.go \
go/math/expm1.go \ go/math/expm1.go \
go/math/floor.go \ go/math/floor.go \
go/math/frexp.go \ go/math/frexp.go \
go/math/gamma.go \ go/math/gamma.go \
go/math/hypot.go \ go/math/hypot.go \
go/math/hypot_port.go \
go/math/j0.go \ go/math/j0.go \
go/math/j1.go \ go/math/j1.go \
go/math/jn.go \ go/math/jn.go \
@ -1024,7 +1022,6 @@ go_math_files = \
go/math/sincos.go \ go/math/sincos.go \
go/math/sinh.go \ go/math/sinh.go \
go/math/sqrt.go \ go/math/sqrt.go \
go/math/sqrt_port.go \
go/math/tan.go \ go/math/tan.go \
go/math/tanh.go \ go/math/tanh.go \
go/math/unsafe.go go/math/unsafe.go
@ -1202,7 +1199,6 @@ go_testing_files = \
go_time_files = \ go_time_files = \
go/time/format.go \ go/time/format.go \
go/time/sleep.go \ go/time/sleep.go \
go/time/sys.go \
go/time/sys_unix.go \ go/time/sys_unix.go \
go/time/tick.go \ go/time/tick.go \
go/time/time.go \ go/time/time.go \

View File

@ -10,7 +10,6 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"reflect"
"testing" "testing"
"time" "time"
) )
@ -127,7 +126,7 @@ testLoop:
f.Close() f.Close()
continue testLoop continue testLoop
} }
if !reflect.DeepEqual(hdr, header) { if *hdr != *header {
t.Errorf("test %d, entry %d: Incorrect header:\nhave %+v\nwant %+v", t.Errorf("test %d, entry %d: Incorrect header:\nhave %+v\nwant %+v",
i, j, *hdr, *header) i, j, *hdr, *header)
} }
@ -201,7 +200,7 @@ func TestIncrementalRead(t *testing.T) {
} }
// check the header // check the header
if !reflect.DeepEqual(hdr, headers[nread]) { if *hdr != *headers[nread] {
t.Errorf("Incorrect header:\nhave %+v\nwant %+v", t.Errorf("Incorrect header:\nhave %+v\nwant %+v",
*hdr, headers[nread]) *hdr, headers[nread])
} }

View File

@ -9,6 +9,7 @@ import (
"encoding/binary" "encoding/binary"
"io" "io"
"io/ioutil" "io/ioutil"
"os"
"testing" "testing"
"time" "time"
) )
@ -25,7 +26,7 @@ type ZipTestFile struct {
Content []byte // if blank, will attempt to compare against File Content []byte // if blank, will attempt to compare against File
File string // name of file to compare to (relative to testdata/) File string // name of file to compare to (relative to testdata/)
Mtime string // modified time in format "mm-dd-yy hh:mm:ss" Mtime string // modified time in format "mm-dd-yy hh:mm:ss"
Mode uint32 Mode os.FileMode
} }
// Caution: The Mtime values found for the test files should correspond to // Caution: The Mtime values found for the test files should correspond to
@ -47,13 +48,13 @@ var tests = []ZipTest{
Name: "test.txt", Name: "test.txt",
Content: []byte("This is a test text file.\n"), Content: []byte("This is a test text file.\n"),
Mtime: "09-05-10 12:12:02", Mtime: "09-05-10 12:12:02",
Mode: 0x81a4, Mode: 0644,
}, },
{ {
Name: "gophercolor16x16.png", Name: "gophercolor16x16.png",
File: "gophercolor16x16.png", File: "gophercolor16x16.png",
Mtime: "09-05-10 15:52:58", Mtime: "09-05-10 15:52:58",
Mode: 0x81a4, Mode: 0644,
}, },
}, },
}, },
@ -64,6 +65,7 @@ var tests = []ZipTest{
Name: "r/r.zip", Name: "r/r.zip",
File: "r.zip", File: "r.zip",
Mtime: "03-04-10 00:24:16", Mtime: "03-04-10 00:24:16",
Mode: 0666,
}, },
}, },
}, },
@ -76,9 +78,43 @@ var tests = []ZipTest{
Name: "filename", Name: "filename",
Content: []byte("This is a test textfile.\n"), Content: []byte("This is a test textfile.\n"),
Mtime: "02-02-11 13:06:20", Mtime: "02-02-11 13:06:20",
Mode: 0666,
}, },
}, },
}, },
{
// created in windows XP file manager.
Name: "winxp.zip",
File: crossPlatform,
},
{
// created by Zip 3.0 under Linux
Name: "unix.zip",
File: crossPlatform,
},
}
var crossPlatform = []ZipTestFile{
{
Name: "hello",
Content: []byte("world \r\n"),
Mode: 0666,
},
{
Name: "dir/bar",
Content: []byte("foo \r\n"),
Mode: 0666,
},
{
Name: "dir/empty/",
Content: []byte{},
Mode: os.ModeDir | 0777,
},
{
Name: "readonly",
Content: []byte("important \r\n"),
Mode: 0444,
},
} }
func TestReader(t *testing.T) { func TestReader(t *testing.T) {
@ -159,13 +195,15 @@ func readTestFile(t *testing.T, ft ZipTestFile, f *File) {
t.Errorf("name=%q, want %q", f.Name, ft.Name) t.Errorf("name=%q, want %q", f.Name, ft.Name)
} }
mtime, err := time.Parse("01-02-06 15:04:05", ft.Mtime) if ft.Mtime != "" {
if err != nil { mtime, err := time.Parse("01-02-06 15:04:05", ft.Mtime)
t.Error(err) if err != nil {
return t.Error(err)
} return
if ft := f.ModTime(); !ft.Equal(mtime) { }
t.Errorf("%s: mtime=%s, want %s", f.Name, ft, mtime) if ft := f.ModTime(); !ft.Equal(mtime) {
t.Errorf("%s: mtime=%s, want %s", f.Name, ft, mtime)
}
} }
testFileMode(t, f, ft.Mode) testFileMode(t, f, ft.Mode)
@ -191,7 +229,7 @@ func readTestFile(t *testing.T, ft ZipTestFile, f *File) {
r.Close() r.Close()
var c []byte var c []byte
if len(ft.Content) != 0 { if ft.Content != nil {
c = ft.Content c = ft.Content
} else if c, err = ioutil.ReadFile("testdata/" + ft.File); err != nil { } else if c, err = ioutil.ReadFile("testdata/" + ft.File); err != nil {
t.Error(err) t.Error(err)
@ -211,7 +249,7 @@ func readTestFile(t *testing.T, ft ZipTestFile, f *File) {
} }
} }
func testFileMode(t *testing.T, f *File, want uint32) { func testFileMode(t *testing.T, f *File, want os.FileMode) {
mode, err := f.Mode() mode, err := f.Mode()
if want == 0 { if want == 0 {
if err == nil { if err == nil {
@ -220,7 +258,7 @@ func testFileMode(t *testing.T, f *File, want uint32) {
} else if err != nil { } else if err != nil {
t.Errorf("%s mode: %s", f.Name, err) t.Errorf("%s mode: %s", f.Name, err)
} else if mode != want { } else if mode != want {
t.Errorf("%s mode: want 0x%x, got 0x%x", f.Name, want, mode) t.Errorf("%s mode: want %v, got %v", f.Name, want, mode)
} }
} }

View File

@ -12,7 +12,7 @@ This package does not support ZIP64 or disk spanning.
package zip package zip
import ( import (
"errors" "os"
"time" "time"
) )
@ -32,7 +32,11 @@ const (
dataDescriptorLen = 12 dataDescriptorLen = 12
// Constants for the first byte in CreatorVersion // Constants for the first byte in CreatorVersion
creatorUnix = 3 creatorFAT = 0
creatorUnix = 3
creatorNTFS = 11
creatorVFAT = 14
creatorMacOSX = 19
) )
type FileHeader struct { type FileHeader struct {
@ -98,17 +102,85 @@ func (h *FileHeader) ModTime() time.Time {
return msDosTimeToTime(h.ModifiedDate, h.ModifiedTime) return msDosTimeToTime(h.ModifiedDate, h.ModifiedTime)
} }
// traditional names for Unix constants
const (
s_IFMT = 0xf000
s_IFDIR = 0x4000
s_IFREG = 0x8000
s_ISUID = 0x800
s_ISGID = 0x400
msdosDir = 0x10
msdosReadOnly = 0x01
)
// Mode returns the permission and mode bits for the FileHeader. // Mode returns the permission and mode bits for the FileHeader.
// An error is returned in case the information is not available. // An error is returned in case the information is not available.
func (h *FileHeader) Mode() (mode uint32, err error) { func (h *FileHeader) Mode() (mode os.FileMode, err error) {
if h.CreatorVersion>>8 == creatorUnix { switch h.CreatorVersion >> 8 {
return h.ExternalAttrs >> 16, nil case creatorUnix, creatorMacOSX:
mode = unixModeToFileMode(h.ExternalAttrs >> 16)
case creatorNTFS, creatorVFAT, creatorFAT:
mode = msdosModeToFileMode(h.ExternalAttrs)
} }
return 0, errors.New("file mode not available") if len(h.Name) > 0 && h.Name[len(h.Name)-1] == '/' {
mode |= os.ModeDir
}
return mode, nil
} }
// SetMode changes the permission and mode bits for the FileHeader. // SetMode changes the permission and mode bits for the FileHeader.
func (h *FileHeader) SetMode(mode uint32) { func (h *FileHeader) SetMode(mode os.FileMode) {
h.CreatorVersion = h.CreatorVersion&0xff | creatorUnix<<8 h.CreatorVersion = h.CreatorVersion&0xff | creatorUnix<<8
h.ExternalAttrs = mode << 16 h.ExternalAttrs = fileModeToUnixMode(mode) << 16
// set MSDOS attributes too, as the original zip does.
if mode&os.ModeDir != 0 {
h.ExternalAttrs |= msdosDir
}
if mode&0200 == 0 {
h.ExternalAttrs |= msdosReadOnly
}
}
func msdosModeToFileMode(m uint32) (mode os.FileMode) {
if m&msdosDir != 0 {
mode = os.ModeDir | 0777
} else {
mode = 0666
}
if m&msdosReadOnly != 0 {
mode &^= 0222
}
return mode
}
func fileModeToUnixMode(mode os.FileMode) uint32 {
var m uint32
if mode&os.ModeDir != 0 {
m = s_IFDIR
} else {
m = s_IFREG
}
if mode&os.ModeSetuid != 0 {
m |= s_ISUID
}
if mode&os.ModeSetgid != 0 {
m |= s_ISGID
}
return m | uint32(mode&0777)
}
func unixModeToFileMode(m uint32) os.FileMode {
var mode os.FileMode
if m&s_IFMT == s_IFDIR {
mode |= os.ModeDir
}
if m&s_ISGID != 0 {
mode |= os.ModeSetgid
}
if m&s_ISUID != 0 {
mode |= os.ModeSetuid
}
return mode | os.FileMode(m&0777)
} }

BIN
libgo/go/archive/zip/testdata/unix.zip vendored Normal file

Binary file not shown.

BIN
libgo/go/archive/zip/testdata/winxp.zip vendored Normal file

Binary file not shown.

View File

@ -8,6 +8,7 @@ import (
"bytes" "bytes"
"io/ioutil" "io/ioutil"
"math/rand" "math/rand"
"os"
"testing" "testing"
) )
@ -17,7 +18,7 @@ type WriteTest struct {
Name string Name string
Data []byte Data []byte
Method uint16 Method uint16
Mode uint32 Mode os.FileMode
} }
var writeTests = []WriteTest{ var writeTests = []WriteTest{
@ -25,12 +26,31 @@ var writeTests = []WriteTest{
Name: "foo", Name: "foo",
Data: []byte("Rabbits, guinea pigs, gophers, marsupial rats, and quolls."), Data: []byte("Rabbits, guinea pigs, gophers, marsupial rats, and quolls."),
Method: Store, Method: Store,
Mode: 0666,
}, },
{ {
Name: "bar", Name: "bar",
Data: nil, // large data set in the test Data: nil, // large data set in the test
Method: Deflate, Method: Deflate,
Mode: 0x81ed, Mode: 0644,
},
{
Name: "setuid",
Data: []byte("setuid file"),
Method: Deflate,
Mode: 0755 | os.ModeSetuid,
},
{
Name: "setgid",
Data: []byte("setgid file"),
Method: Deflate,
Mode: 0755 | os.ModeSetgid,
},
{
Name: "setgid",
Data: []byte("setgid file"),
Method: Deflate,
Mode: 0755 | os.ModeSetgid,
}, },
} }

View File

@ -52,12 +52,14 @@ type Reader struct {
lastRuneSize int lastRuneSize int
} }
const minReadBufferSize = 16
// NewReaderSize creates a new Reader whose buffer has the specified size, // NewReaderSize creates a new Reader whose buffer has the specified size,
// which must be greater than one. If the argument io.Reader is already a // which must be at least 16 bytes. If the argument io.Reader is already a
// Reader with large enough size, it returns the underlying Reader. // Reader with large enough size, it returns the underlying Reader.
// It returns the Reader and any error. // It returns the Reader and any error.
func NewReaderSize(rd io.Reader, size int) (*Reader, error) { func NewReaderSize(rd io.Reader, size int) (*Reader, error) {
if size <= 1 { if size < minReadBufferSize {
return nil, BufSizeError(size) return nil, BufSizeError(size)
} }
// Is it already a Reader? // Is it already a Reader?

View File

@ -135,9 +135,10 @@ var bufreaders = []bufReader{
{"lines", readLines}, {"lines", readLines},
} }
const minReadBufferSize = 16
var bufsizes = []int{ var bufsizes = []int{
2, 3, 4, 5, 6, 7, 8, 9, 10, minReadBufferSize, 23, 32, 46, 64, 93, 128, 1024, 4096,
23, 32, 46, 64, 93, 128, 1024, 4096,
} }
func TestReader(t *testing.T) { func TestReader(t *testing.T) {
@ -514,27 +515,32 @@ func TestWriteString(t *testing.T) {
} }
func TestBufferFull(t *testing.T) { func TestBufferFull(t *testing.T) {
buf, _ := NewReaderSize(strings.NewReader("hello, world"), 5) const longString = "And now, hello, world! It is the time for all good men to come to the aid of their party"
line, err := buf.ReadSlice(',') buf, err := NewReaderSize(strings.NewReader(longString), minReadBufferSize)
if string(line) != "hello" || err != ErrBufferFull { if err != nil {
t.Fatal("NewReaderSize:", err)
}
line, err := buf.ReadSlice('!')
if string(line) != "And now, hello, " || err != ErrBufferFull {
t.Errorf("first ReadSlice(,) = %q, %v", line, err) t.Errorf("first ReadSlice(,) = %q, %v", line, err)
} }
line, err = buf.ReadSlice(',') line, err = buf.ReadSlice('!')
if string(line) != "," || err != nil { if string(line) != "world!" || err != nil {
t.Errorf("second ReadSlice(,) = %q, %v", line, err) t.Errorf("second ReadSlice(,) = %q, %v", line, err)
} }
} }
func TestPeek(t *testing.T) { func TestPeek(t *testing.T) {
p := make([]byte, 10) p := make([]byte, 10)
buf, _ := NewReaderSize(strings.NewReader("abcdefghij"), 4) // string is 16 (minReadBufferSize) long.
buf, _ := NewReaderSize(strings.NewReader("abcdefghijklmnop"), minReadBufferSize)
if s, err := buf.Peek(1); string(s) != "a" || err != nil { if s, err := buf.Peek(1); string(s) != "a" || err != nil {
t.Fatalf("want %q got %q, err=%v", "a", string(s), err) t.Fatalf("want %q got %q, err=%v", "a", string(s), err)
} }
if s, err := buf.Peek(4); string(s) != "abcd" || err != nil { if s, err := buf.Peek(4); string(s) != "abcd" || err != nil {
t.Fatalf("want %q got %q, err=%v", "abcd", string(s), err) t.Fatalf("want %q got %q, err=%v", "abcd", string(s), err)
} }
if _, err := buf.Peek(5); err != ErrBufferFull { if _, err := buf.Peek(32); err != ErrBufferFull {
t.Fatalf("want ErrBufFull got %v", err) t.Fatalf("want ErrBufFull got %v", err)
} }
if _, err := buf.Read(p[0:3]); string(p[0:3]) != "abc" || err != nil { if _, err := buf.Read(p[0:3]); string(p[0:3]) != "abc" || err != nil {
@ -552,8 +558,8 @@ func TestPeek(t *testing.T) {
if s, err := buf.Peek(4); string(s) != "ghij" || err != nil { if s, err := buf.Peek(4); string(s) != "ghij" || err != nil {
t.Fatalf("want %q got %q, err=%v", "ghij", string(s), err) t.Fatalf("want %q got %q, err=%v", "ghij", string(s), err)
} }
if _, err := buf.Read(p[0:4]); string(p[0:4]) != "ghij" || err != nil { if _, err := buf.Read(p[0:]); string(p[0:]) != "ghijklmnop" || err != nil {
t.Fatalf("want %q got %q, err=%v", "ghij", string(p[0:3]), err) t.Fatalf("want %q got %q, err=%v", "ghijklmnop", string(p[0:minReadBufferSize]), err)
} }
if s, err := buf.Peek(0); string(s) != "" || err != nil { if s, err := buf.Peek(0); string(s) != "" || err != nil {
t.Fatalf("want %q got %q, err=%v", "", string(s), err) t.Fatalf("want %q got %q, err=%v", "", string(s), err)
@ -635,19 +641,25 @@ func TestReadLine(t *testing.T) {
} }
func TestLineTooLong(t *testing.T) { func TestLineTooLong(t *testing.T) {
buf := bytes.NewBuffer([]byte("aaabbbcc\n")) data := make([]byte, 0)
l, _ := NewReaderSize(buf, 3) for i := 0; i < minReadBufferSize*5/2; i++ {
data = append(data, '0'+byte(i%10))
}
buf := bytes.NewBuffer(data)
l, _ := NewReaderSize(buf, minReadBufferSize)
line, isPrefix, err := l.ReadLine() line, isPrefix, err := l.ReadLine()
if !isPrefix || !bytes.Equal(line, []byte("aaa")) || err != nil { if !isPrefix || !bytes.Equal(line, data[:minReadBufferSize]) || err != nil {
t.Errorf("bad result for first line: %x %s", line, err) t.Errorf("bad result for first line: got %q want %q %v", line, data[:minReadBufferSize], err)
} }
data = data[len(line):]
line, isPrefix, err = l.ReadLine() line, isPrefix, err = l.ReadLine()
if !isPrefix || !bytes.Equal(line, []byte("bbb")) || err != nil { if !isPrefix || !bytes.Equal(line, data[:minReadBufferSize]) || err != nil {
t.Errorf("bad result for second line: %x", line) t.Errorf("bad result for second line: got %q want %q %v", line, data[:minReadBufferSize], err)
} }
data = data[len(line):]
line, isPrefix, err = l.ReadLine() line, isPrefix, err = l.ReadLine()
if isPrefix || !bytes.Equal(line, []byte("cc")) || err != nil { if isPrefix || !bytes.Equal(line, data[:minReadBufferSize/2]) || err != nil {
t.Errorf("bad result for third line: %x", line) t.Errorf("bad result for third line: got %q want %q %v", line, data[:minReadBufferSize/2], err)
} }
line, isPrefix, err = l.ReadLine() line, isPrefix, err = l.ReadLine()
if isPrefix || err == nil { if isPrefix || err == nil {
@ -656,8 +668,8 @@ func TestLineTooLong(t *testing.T) {
} }
func TestReadAfterLines(t *testing.T) { func TestReadAfterLines(t *testing.T) {
line1 := "line1" line1 := "this is line1"
restData := "line2\nline 3\n" restData := "this is line2\nthis is line 3\n"
inbuf := bytes.NewBuffer([]byte(line1 + "\n" + restData)) inbuf := bytes.NewBuffer([]byte(line1 + "\n" + restData))
outbuf := new(bytes.Buffer) outbuf := new(bytes.Buffer)
maxLineLength := len(line1) + len(restData)/2 maxLineLength := len(line1) + len(restData)/2
@ -676,7 +688,7 @@ func TestReadAfterLines(t *testing.T) {
} }
func TestReadEmptyBuffer(t *testing.T) { func TestReadEmptyBuffer(t *testing.T) {
l, _ := NewReaderSize(bytes.NewBuffer(nil), 10) l, _ := NewReaderSize(bytes.NewBuffer(nil), minReadBufferSize)
line, isPrefix, err := l.ReadLine() line, isPrefix, err := l.ReadLine()
if err != io.EOF { if err != io.EOF {
t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err) t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
@ -684,7 +696,7 @@ func TestReadEmptyBuffer(t *testing.T) {
} }
func TestLinesAfterRead(t *testing.T) { func TestLinesAfterRead(t *testing.T) {
l, _ := NewReaderSize(bytes.NewBuffer([]byte("foo")), 10) l, _ := NewReaderSize(bytes.NewBuffer([]byte("foo")), minReadBufferSize)
_, err := ioutil.ReadAll(l) _, err := ioutil.ReadAll(l)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -715,34 +727,19 @@ type readLineResult struct {
} }
var readLineNewlinesTests = []struct { var readLineNewlinesTests = []struct {
input string input string
bufSize int expect []readLineResult
expect []readLineResult
}{ }{
{"h\r\nb\r\n", 2, []readLineResult{ {"012345678901234\r\n012345678901234\r\n", []readLineResult{
{[]byte("h"), true, nil}, {[]byte("012345678901234"), true, nil},
{nil, false, nil}, {nil, false, nil},
{[]byte("b"), true, nil}, {[]byte("012345678901234"), true, nil},
{nil, false, nil}, {nil, false, nil},
{nil, false, io.EOF}, {nil, false, io.EOF},
}}, }},
{"hello\r\nworld\r\n", 6, []readLineResult{ {"0123456789012345\r012345678901234\r", []readLineResult{
{[]byte("hello"), true, nil}, {[]byte("0123456789012345"), true, nil},
{nil, false, nil}, {[]byte("\r012345678901234"), true, nil},
{[]byte("world"), true, nil},
{nil, false, nil},
{nil, false, io.EOF},
}},
{"hello\rworld\r", 6, []readLineResult{
{[]byte("hello"), true, nil},
{[]byte("\rworld"), true, nil},
{[]byte("\r"), false, nil},
{nil, false, io.EOF},
}},
{"h\ri\r\n\r", 2, []readLineResult{
{[]byte("h"), true, nil},
{[]byte("\ri"), true, nil},
{nil, false, nil},
{[]byte("\r"), false, nil}, {[]byte("\r"), false, nil},
{nil, false, io.EOF}, {nil, false, io.EOF},
}}, }},
@ -750,12 +747,12 @@ var readLineNewlinesTests = []struct {
func TestReadLineNewlines(t *testing.T) { func TestReadLineNewlines(t *testing.T) {
for _, e := range readLineNewlinesTests { for _, e := range readLineNewlinesTests {
testReadLineNewlines(t, e.input, e.bufSize, e.expect) testReadLineNewlines(t, e.input, e.expect)
} }
} }
func testReadLineNewlines(t *testing.T, input string, bufSize int, expect []readLineResult) { func testReadLineNewlines(t *testing.T, input string, expect []readLineResult) {
b, err := NewReaderSize(strings.NewReader(input), bufSize) b, err := NewReaderSize(strings.NewReader(input), minReadBufferSize)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -37,7 +37,9 @@ func Compare(a, b []byte) int {
} }
// Equal returns a boolean reporting whether a == b. // Equal returns a boolean reporting whether a == b.
func Equal(a, b []byte) bool { func Equal(a, b []byte) bool
func equalPortable(a, b []byte) bool {
if len(a) != len(b) { if len(a) != len(b) {
return false return false
} }
@ -74,18 +76,33 @@ func explode(s []byte, n int) [][]byte {
// Count counts the number of non-overlapping instances of sep in s. // Count counts the number of non-overlapping instances of sep in s.
func Count(s, sep []byte) int { func Count(s, sep []byte) int {
if len(sep) == 0 { n := len(sep)
if n == 0 {
return utf8.RuneCount(s) + 1 return utf8.RuneCount(s) + 1
} }
c := sep[0] if n > len(s) {
n := 0 return 0
for i := 0; i+len(sep) <= len(s); i++ {
if s[i] == c && (len(sep) == 1 || Equal(s[i:i+len(sep)], sep)) {
n++
i += len(sep) - 1
}
} }
return n count := 0
c := sep[0]
i := 0
t := s[:len(s)-n+1]
for i < len(t) {
if t[i] != c {
o := IndexByte(t[i:], c)
if o < 0 {
break
}
i += o
}
if n == 1 || Equal(s[i:i+n], sep) {
count++
i += n
continue
}
i++
}
return count
} }
// Contains returns whether subslice is within b. // Contains returns whether subslice is within b.
@ -99,11 +116,27 @@ func Index(s, sep []byte) int {
if n == 0 { if n == 0 {
return 0 return 0
} }
if n > len(s) {
return -1
}
c := sep[0] c := sep[0]
for i := 0; i+n <= len(s); i++ { if n == 1 {
if s[i] == c && (n == 1 || Equal(s[i:i+n], sep)) { return IndexByte(s, c)
}
i := 0
t := s[:len(s)-n+1]
for i < len(t) {
if t[i] != c {
o := IndexByte(t[i:], c)
if o < 0 {
break
}
i += o
}
if Equal(s[i:i+n], sep) {
return i return i
} }
i++
} }
return -1 return -1
} }
@ -437,7 +470,7 @@ func Title(s []byte) []byte {
// Use a closure here to remember state. // Use a closure here to remember state.
// Hackish but effective. Depends on Map scanning in order and calling // Hackish but effective. Depends on Map scanning in order and calling
// the closure once per rune. // the closure once per rune.
prev := rune(' ') prev := ' '
return Map( return Map(
func(r rune) rune { func(r rune) rune {
if isSeparator(prev) { if isSeparator(prev) {

View File

@ -64,13 +64,17 @@ func TestCompare(t *testing.T) {
a := []byte(tt.a) a := []byte(tt.a)
b := []byte(tt.b) b := []byte(tt.b)
cmp := Compare(a, b) cmp := Compare(a, b)
eql := Equal(a, b)
if cmp != tt.i { if cmp != tt.i {
t.Errorf(`Compare(%q, %q) = %v`, tt.a, tt.b, cmp) t.Errorf(`Compare(%q, %q) = %v`, tt.a, tt.b, cmp)
} }
eql := Equal(a, b)
if eql != (tt.i == 0) { if eql != (tt.i == 0) {
t.Errorf(`Equal(%q, %q) = %v`, tt.a, tt.b, eql) t.Errorf(`Equal(%q, %q) = %v`, tt.a, tt.b, eql)
} }
eql = EqualPortable(a, b)
if eql != (tt.i == 0) {
t.Errorf(`EqualPortable(%q, %q) = %v`, tt.a, tt.b, eql)
}
} }
} }
@ -264,27 +268,18 @@ func TestIndexRune(t *testing.T) {
} }
} }
func BenchmarkIndexByte4K(b *testing.B) { bmIndex(b, IndexByte, 4<<10) }
func BenchmarkIndexByte4M(b *testing.B) { bmIndex(b, IndexByte, 4<<20) }
func BenchmarkIndexByte64M(b *testing.B) { bmIndex(b, IndexByte, 64<<20) }
func BenchmarkIndexBytePortable4K(b *testing.B) {
bmIndex(b, IndexBytePortable, 4<<10)
}
func BenchmarkIndexBytePortable4M(b *testing.B) {
bmIndex(b, IndexBytePortable, 4<<20)
}
func BenchmarkIndexBytePortable64M(b *testing.B) {
bmIndex(b, IndexBytePortable, 64<<20)
}
var bmbuf []byte var bmbuf []byte
func bmIndex(b *testing.B, index func([]byte, byte) int, n int) { func BenchmarkIndexByte32(b *testing.B) { bmIndexByte(b, IndexByte, 32) }
func BenchmarkIndexByte4K(b *testing.B) { bmIndexByte(b, IndexByte, 4<<10) }
func BenchmarkIndexByte4M(b *testing.B) { bmIndexByte(b, IndexByte, 4<<20) }
func BenchmarkIndexByte64M(b *testing.B) { bmIndexByte(b, IndexByte, 64<<20) }
func BenchmarkIndexBytePortable32(b *testing.B) { bmIndexByte(b, IndexBytePortable, 32) }
func BenchmarkIndexBytePortable4K(b *testing.B) { bmIndexByte(b, IndexBytePortable, 4<<10) }
func BenchmarkIndexBytePortable4M(b *testing.B) { bmIndexByte(b, IndexBytePortable, 4<<20) }
func BenchmarkIndexBytePortable64M(b *testing.B) { bmIndexByte(b, IndexBytePortable, 64<<20) }
func bmIndexByte(b *testing.B, index func([]byte, byte) int, n int) {
if len(bmbuf) < n { if len(bmbuf) < n {
bmbuf = make([]byte, n) bmbuf = make([]byte, n)
} }
@ -298,7 +293,127 @@ func bmIndex(b *testing.B, index func([]byte, byte) int, n int) {
panic("bad index") panic("bad index")
} }
} }
buf[n-1] = '0' buf[n-1] = '\x00'
}
func BenchmarkEqual32(b *testing.B) { bmEqual(b, Equal, 32) }
func BenchmarkEqual4K(b *testing.B) { bmEqual(b, Equal, 4<<10) }
func BenchmarkEqual4M(b *testing.B) { bmEqual(b, Equal, 4<<20) }
func BenchmarkEqual64M(b *testing.B) { bmEqual(b, Equal, 64<<20) }
func BenchmarkEqualPort32(b *testing.B) { bmEqual(b, EqualPortable, 32) }
func BenchmarkEqualPort4K(b *testing.B) { bmEqual(b, EqualPortable, 4<<10) }
func BenchmarkEqualPortable4M(b *testing.B) { bmEqual(b, EqualPortable, 4<<20) }
func BenchmarkEqualPortable64M(b *testing.B) { bmEqual(b, EqualPortable, 64<<20) }
func bmEqual(b *testing.B, equal func([]byte, []byte) bool, n int) {
if len(bmbuf) < 2*n {
bmbuf = make([]byte, 2*n)
}
b.SetBytes(int64(n))
buf1 := bmbuf[0:n]
buf2 := bmbuf[n : 2*n]
buf1[n-1] = 'x'
buf2[n-1] = 'x'
for i := 0; i < b.N; i++ {
eq := equal(buf1, buf2)
if !eq {
panic("bad equal")
}
}
buf1[n-1] = '\x00'
buf2[n-1] = '\x00'
}
func BenchmarkIndex32(b *testing.B) { bmIndex(b, Index, 32) }
func BenchmarkIndex4K(b *testing.B) { bmIndex(b, Index, 4<<10) }
func BenchmarkIndex4M(b *testing.B) { bmIndex(b, Index, 4<<20) }
func BenchmarkIndex64M(b *testing.B) { bmIndex(b, Index, 64<<20) }
func bmIndex(b *testing.B, index func([]byte, []byte) int, n int) {
if len(bmbuf) < n {
bmbuf = make([]byte, n)
}
b.SetBytes(int64(n))
buf := bmbuf[0:n]
buf[n-1] = 'x'
for i := 0; i < b.N; i++ {
j := index(buf, buf[n-7:])
if j != n-7 {
println("bad index", j)
panic("bad index")
}
}
buf[n-1] = '\x00'
}
func BenchmarkIndexEasy32(b *testing.B) { bmIndexEasy(b, Index, 32) }
func BenchmarkIndexEasy4K(b *testing.B) { bmIndexEasy(b, Index, 4<<10) }
func BenchmarkIndexEasy4M(b *testing.B) { bmIndexEasy(b, Index, 4<<20) }
func BenchmarkIndexEasy64M(b *testing.B) { bmIndexEasy(b, Index, 64<<20) }
func bmIndexEasy(b *testing.B, index func([]byte, []byte) int, n int) {
if len(bmbuf) < n {
bmbuf = make([]byte, n)
}
b.SetBytes(int64(n))
buf := bmbuf[0:n]
buf[n-1] = 'x'
buf[n-7] = 'x'
for i := 0; i < b.N; i++ {
j := index(buf, buf[n-7:])
if j != n-7 {
println("bad index", j)
panic("bad index")
}
}
buf[n-1] = '\x00'
buf[n-7] = '\x00'
}
func BenchmarkCount32(b *testing.B) { bmCount(b, Count, 32) }
func BenchmarkCount4K(b *testing.B) { bmCount(b, Count, 4<<10) }
func BenchmarkCount4M(b *testing.B) { bmCount(b, Count, 4<<20) }
func BenchmarkCount64M(b *testing.B) { bmCount(b, Count, 64<<20) }
func bmCount(b *testing.B, count func([]byte, []byte) int, n int) {
if len(bmbuf) < n {
bmbuf = make([]byte, n)
}
b.SetBytes(int64(n))
buf := bmbuf[0:n]
buf[n-1] = 'x'
for i := 0; i < b.N; i++ {
j := count(buf, buf[n-7:])
if j != 1 {
println("bad count", j)
panic("bad count")
}
}
buf[n-1] = '\x00'
}
func BenchmarkCountEasy32(b *testing.B) { bmCountEasy(b, Count, 32) }
func BenchmarkCountEasy4K(b *testing.B) { bmCountEasy(b, Count, 4<<10) }
func BenchmarkCountEasy4M(b *testing.B) { bmCountEasy(b, Count, 4<<20) }
func BenchmarkCountEasy64M(b *testing.B) { bmCountEasy(b, Count, 64<<20) }
func bmCountEasy(b *testing.B, count func([]byte, []byte) int, n int) {
if len(bmbuf) < n {
bmbuf = make([]byte, n)
}
b.SetBytes(int64(n))
buf := bmbuf[0:n]
buf[n-1] = 'x'
buf[n-7] = 'x'
for i := 0; i < b.N; i++ {
j := count(buf, buf[n-7:])
if j != 1 {
println("bad count", j)
panic("bad count")
}
}
buf[n-1] = '\x00'
buf[n-7] = '\x00'
} }
type ExplodeTest struct { type ExplodeTest struct {

View File

@ -6,3 +6,4 @@ package bytes
// Export func for testing // Export func for testing
var IndexBytePortable = indexBytePortable var IndexBytePortable = indexBytePortable
var EqualPortable = equalPortable

View File

@ -26,3 +26,17 @@ IndexByte (struct __go_open_array s, char b)
return -1; return -1;
return p - (char *) s.__values; return p - (char *) s.__values;
} }
/* Comparison. */
_Bool Equal (struct __go_open_array a, struct __go_open_array b)
asm ("libgo_bytes.bytes.Equal")
__attribute__ ((no_split_stack));
_Bool
Equal (struct __go_open_array a, struct __go_open_array b)
{
if (a.__count != b.__count)
return 0;
return __builtin_memcmp (a.__values, b.__values, a.__count) == 0;
}

View File

@ -319,7 +319,9 @@ Loop:
// For matches this long, we don't bother inserting each individual // For matches this long, we don't bother inserting each individual
// item into the table. // item into the table.
d.index += d.length d.index += d.length
d.hash = (int(d.window[d.index])<<hashShift + int(d.window[d.index+1])) if d.index < d.maxInsertIndex {
d.hash = (int(d.window[d.index])<<hashShift + int(d.window[d.index+1]))
}
} }
if d.ti == maxFlateBlockTokens { if d.ti == maxFlateBlockTokens {
// The block includes the current character // The block includes the current character

View File

@ -318,3 +318,15 @@ func TestWriterDict(t *testing.T) {
t.Fatalf("writer wrote %q want %q", b1.Bytes(), b.Bytes()) t.Fatalf("writer wrote %q want %q", b1.Bytes(), b.Bytes())
} }
} }
// See http://code.google.com/p/go/issues/detail?id=2508
func TestRegression2508(t *testing.T) {
w := NewWriter(ioutil.Discard, 1)
buf := make([]byte, 1024)
for i := 0; i < 131072; i++ {
if _, err := w.Write(buf); err != nil {
t.Fatalf("writer failed: %v", err)
}
}
w.Close()
}

View File

@ -96,6 +96,7 @@ func get4(p []byte) uint32 {
func (z *Decompressor) readString() (string, error) { func (z *Decompressor) readString() (string, error) {
var err error var err error
needconv := false
for i := 0; ; i++ { for i := 0; ; i++ {
if i >= len(z.buf) { if i >= len(z.buf) {
return "", HeaderError return "", HeaderError
@ -104,9 +105,18 @@ func (z *Decompressor) readString() (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
if z.buf[i] > 0x7f {
needconv = true
}
if z.buf[i] == 0 { if z.buf[i] == 0 {
// GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1). // GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
// TODO(nigeltao): Convert from ISO 8859-1 (Latin-1) to UTF-8. if needconv {
s := make([]rune, 0, i)
for _, v := range z.buf[0:i] {
s = append(s, rune(v))
}
return string(s), nil
}
return string(z.buf[0:i]), nil return string(z.buf[0:i]), nil
} }
} }

View File

@ -86,13 +86,25 @@ func (z *Compressor) writeBytes(b []byte) error {
// writeString writes a string (in ISO 8859-1 (Latin-1) format) to z.w. // writeString writes a string (in ISO 8859-1 (Latin-1) format) to z.w.
func (z *Compressor) writeString(s string) error { func (z *Compressor) writeString(s string) error {
// GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1). // GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
// TODO(nigeltao): Convert from UTF-8 to ISO 8859-1 (Latin-1). var err error
needconv := false
for _, v := range s { for _, v := range s {
if v == 0 || v > 0x7f { if v == 0 || v > 0xff {
return errors.New("gzip.Write: non-ASCII header string") return errors.New("gzip.Write: non-Latin-1 header string")
}
if v > 0x7f {
needconv = true
} }
} }
_, err := io.WriteString(z.w, s) if needconv {
b := make([]byte, 0, len(s))
for _, v := range s {
b = append(b, byte(v))
}
_, err = z.w.Write(b)
} else {
_, err = io.WriteString(z.w, s)
}
if err != nil { if err != nil {
return err return err
} }

View File

@ -5,6 +5,8 @@
package gzip package gzip
import ( import (
"bufio"
"bytes"
"io" "io"
"io/ioutil" "io/ioutil"
"testing" "testing"
@ -52,7 +54,8 @@ func TestEmpty(t *testing.T) {
func TestWriter(t *testing.T) { func TestWriter(t *testing.T) {
pipe(t, pipe(t,
func(compressor *Compressor) { func(compressor *Compressor) {
compressor.Comment = "comment" compressor.Comment = "Äußerung"
//compressor.Comment = "comment"
compressor.Extra = []byte("extra") compressor.Extra = []byte("extra")
compressor.ModTime = time.Unix(1e8, 0) compressor.ModTime = time.Unix(1e8, 0)
compressor.Name = "name" compressor.Name = "name"
@ -69,8 +72,8 @@ func TestWriter(t *testing.T) {
if string(b) != "payload" { if string(b) != "payload" {
t.Fatalf("payload is %q, want %q", string(b), "payload") t.Fatalf("payload is %q, want %q", string(b), "payload")
} }
if decompressor.Comment != "comment" { if decompressor.Comment != "Äußerung" {
t.Fatalf("comment is %q, want %q", decompressor.Comment, "comment") t.Fatalf("comment is %q, want %q", decompressor.Comment, "Äußerung")
} }
if string(decompressor.Extra) != "extra" { if string(decompressor.Extra) != "extra" {
t.Fatalf("extra is %q, want %q", decompressor.Extra, "extra") t.Fatalf("extra is %q, want %q", decompressor.Extra, "extra")
@ -83,3 +86,29 @@ func TestWriter(t *testing.T) {
} }
}) })
} }
func TestLatin1(t *testing.T) {
latin1 := []byte{0xc4, 'u', 0xdf, 'e', 'r', 'u', 'n', 'g', 0}
utf8 := "Äußerung"
z := Decompressor{r: bufio.NewReader(bytes.NewBuffer(latin1))}
s, err := z.readString()
if err != nil {
t.Fatalf("%v", err)
}
if s != utf8 {
t.Fatalf("string is %q, want %q", s, utf8)
}
buf := bytes.NewBuffer(make([]byte, 0, len(latin1)))
c := Compressor{w: buf}
if err = c.writeString(utf8); err != nil {
t.Fatalf("%v", err)
}
s = buf.String()
if s != string(latin1) {
t.Fatalf("string is %v, want %v", s, latin1)
}
//if s, err = buf.ReadString(0); err != nil {
//t.Fatalf("%v", err)
//}
}

View File

@ -91,6 +91,7 @@ func TestTe(t *testing.T) {
s2 := mul(s, 2) s2 := mul(s, 2)
s3 := mul(s, 3) s3 := mul(s, 3)
w := s2<<24 | s<<16 | s<<8 | s3 w := s2<<24 | s<<16 | s<<8 | s3
te := [][256]uint32{te0, te1, te2, te3}
for j := 0; j < 4; j++ { for j := 0; j < 4; j++ {
if x := te[j][i]; x != w { if x := te[j][i]; x != w {
t.Fatalf("te[%d][%d] = %#x, want %#x", j, i, x, w) t.Fatalf("te[%d][%d] = %#x, want %#x", j, i, x, w)
@ -110,6 +111,7 @@ func TestTd(t *testing.T) {
sd := mul(s, 0xd) sd := mul(s, 0xd)
se := mul(s, 0xe) se := mul(s, 0xe)
w := se<<24 | s9<<16 | sd<<8 | sb w := se<<24 | s9<<16 | sd<<8 | sb
td := [][256]uint32{td0, td1, td2, td3}
for j := 0; j < 4; j++ { for j := 0; j < 4; j++ {
if x := td[j][i]; x != w { if x := td[j][i]; x != w {
t.Fatalf("td[%d][%d] = %#x, want %#x", j, i, x, w) t.Fatalf("td[%d][%d] = %#x, want %#x", j, i, x, w)

View File

@ -56,10 +56,10 @@ func encryptBlock(xk []uint32, dst, src []byte) {
nr := len(xk)/4 - 2 // - 2: one above, one more below nr := len(xk)/4 - 2 // - 2: one above, one more below
k := 4 k := 4
for r := 0; r < nr; r++ { for r := 0; r < nr; r++ {
t0 = xk[k+0] ^ te[0][uint8(s0>>24)] ^ te[1][uint8(s1>>16)] ^ te[2][uint8(s2>>8)] ^ te[3][uint8(s3)] t0 = xk[k+0] ^ te0[uint8(s0>>24)] ^ te1[uint8(s1>>16)] ^ te2[uint8(s2>>8)] ^ te3[uint8(s3)]
t1 = xk[k+1] ^ te[0][uint8(s1>>24)] ^ te[1][uint8(s2>>16)] ^ te[2][uint8(s3>>8)] ^ te[3][uint8(s0)] t1 = xk[k+1] ^ te0[uint8(s1>>24)] ^ te1[uint8(s2>>16)] ^ te2[uint8(s3>>8)] ^ te3[uint8(s0)]
t2 = xk[k+2] ^ te[0][uint8(s2>>24)] ^ te[1][uint8(s3>>16)] ^ te[2][uint8(s0>>8)] ^ te[3][uint8(s1)] t2 = xk[k+2] ^ te0[uint8(s2>>24)] ^ te1[uint8(s3>>16)] ^ te2[uint8(s0>>8)] ^ te3[uint8(s1)]
t3 = xk[k+3] ^ te[0][uint8(s3>>24)] ^ te[1][uint8(s0>>16)] ^ te[2][uint8(s1>>8)] ^ te[3][uint8(s2)] t3 = xk[k+3] ^ te0[uint8(s3>>24)] ^ te1[uint8(s0>>16)] ^ te2[uint8(s1>>8)] ^ te3[uint8(s2)]
k += 4 k += 4
s0, s1, s2, s3 = t0, t1, t2, t3 s0, s1, s2, s3 = t0, t1, t2, t3
} }
@ -101,10 +101,10 @@ func decryptBlock(xk []uint32, dst, src []byte) {
nr := len(xk)/4 - 2 // - 2: one above, one more below nr := len(xk)/4 - 2 // - 2: one above, one more below
k := 4 k := 4
for r := 0; r < nr; r++ { for r := 0; r < nr; r++ {
t0 = xk[k+0] ^ td[0][uint8(s0>>24)] ^ td[1][uint8(s3>>16)] ^ td[2][uint8(s2>>8)] ^ td[3][uint8(s1)] t0 = xk[k+0] ^ td0[uint8(s0>>24)] ^ td1[uint8(s3>>16)] ^ td2[uint8(s2>>8)] ^ td3[uint8(s1)]
t1 = xk[k+1] ^ td[0][uint8(s1>>24)] ^ td[1][uint8(s0>>16)] ^ td[2][uint8(s3>>8)] ^ td[3][uint8(s2)] t1 = xk[k+1] ^ td0[uint8(s1>>24)] ^ td1[uint8(s0>>16)] ^ td2[uint8(s3>>8)] ^ td3[uint8(s2)]
t2 = xk[k+2] ^ td[0][uint8(s2>>24)] ^ td[1][uint8(s1>>16)] ^ td[2][uint8(s0>>8)] ^ td[3][uint8(s3)] t2 = xk[k+2] ^ td0[uint8(s2>>24)] ^ td1[uint8(s1>>16)] ^ td2[uint8(s0>>8)] ^ td3[uint8(s3)]
t3 = xk[k+3] ^ td[0][uint8(s3>>24)] ^ td[1][uint8(s2>>16)] ^ td[2][uint8(s1>>8)] ^ td[3][uint8(s0)] t3 = xk[k+3] ^ td0[uint8(s3>>24)] ^ td1[uint8(s2>>16)] ^ td2[uint8(s1>>8)] ^ td3[uint8(s0)]
k += 4 k += 4
s0, s1, s2, s3 = t0, t1, t2, t3 s0, s1, s2, s3 = t0, t1, t2, t3
} }
@ -168,7 +168,7 @@ func expandKey(key []byte, enc, dec []uint32) {
for j := 0; j < 4; j++ { for j := 0; j < 4; j++ {
x := enc[ei+j] x := enc[ei+j]
if i > 0 && i+4 < n { if i > 0 && i+4 < n {
x = td[0][sbox0[x>>24]] ^ td[1][sbox0[x>>16&0xff]] ^ td[2][sbox0[x>>8&0xff]] ^ td[3][sbox0[x&0xff]] x = td0[sbox0[x>>24]] ^ td1[sbox0[x>>16&0xff]] ^ td2[sbox0[x>>8&0xff]] ^ td3[sbox0[x&0xff]]
} }
dec[i+j] = x dec[i+j] = x
} }

View File

@ -80,283 +80,279 @@ var sbox1 = [256]byte{
// Lookup tables for encryption. // Lookup tables for encryption.
// These can be recomputed by adapting the tests in aes_test.go. // These can be recomputed by adapting the tests in aes_test.go.
var te = [4][256]uint32{ var te0 = [256]uint32{
{ 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554,
0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a,
0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b,
0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b,
0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f,
0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f,
0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5,
0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f,
0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb,
0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497,
0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed,
0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a,
0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594,
0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3,
0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504,
0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d,
0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739,
0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395,
0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883,
0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76,
0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4,
0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b,
0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0,
0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818,
0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651,
0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85,
0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12,
0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9,
0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7,
0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a,
0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8,
0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a,
0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a, }
}, var te1 = [256]uint32{
{ 0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5,
0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676,
0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0,
0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0,
0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc,
0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515,
0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a,
0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575,
0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0,
0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484,
0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b,
0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf,
0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585,
0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8,
0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5,
0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2,
0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717,
0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373,
0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888,
0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb,
0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c,
0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979,
0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9,
0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808,
0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6,
0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a,
0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e,
0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e,
0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494,
0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf,
0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868,
0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616,
0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616, }
}, var te2 = [256]uint32{
{ 0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5,
0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76,
0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0,
0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0,
0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc,
0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15,
0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a,
0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75,
0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0,
0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384,
0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b,
0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf,
0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185,
0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8,
0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5,
0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2,
0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17,
0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673,
0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88,
0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb,
0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c,
0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279,
0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9,
0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008,
0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6,
0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a,
0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e,
0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e,
0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394,
0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df,
0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068,
0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16,
0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16, }
}, var te3 = [256]uint32{
{ 0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491,
0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec,
0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb,
0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b,
0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83,
0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a,
0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f,
0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea,
0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b,
0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713,
0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6,
0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85,
0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411,
0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b,
0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1,
0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf,
0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e,
0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6,
0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b,
0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad,
0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8,
0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2,
0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049,
0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810,
0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197,
0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f,
0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c,
0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927,
0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733,
0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5,
0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0,
0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c,
0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c,
},
} }
// Lookup tables for decryption. // Lookup tables for decryption.
// These can be recomputed by adapting the tests in aes_test.go. // These can be recomputed by adapting the tests in aes_test.go.
var td = [4][256]uint32{ var td0 = [256]uint32{
{ 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393,
0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f,
0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6,
0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844,
0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4,
0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94,
0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a,
0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c,
0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a,
0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051,
0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff,
0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb,
0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e,
0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a,
0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16,
0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8,
0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34,
0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120,
0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0,
0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef,
0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4,
0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5,
0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b,
0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6,
0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0,
0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f,
0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f,
0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713,
0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c,
0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86,
0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541,
0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742,
0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742, }
}, var td1 = [256]uint32{
{ 0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303,
0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3,
0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9,
0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8,
0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a,
0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b,
0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab,
0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682,
0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe,
0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10,
0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015,
0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee,
0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72,
0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e,
0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a,
0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9,
0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e,
0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611,
0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3,
0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390,
0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf,
0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af,
0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb,
0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8,
0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266,
0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6,
0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551,
0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647,
0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1,
0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db,
0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95,
0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857,
0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857, }
}, var td2 = [256]uint32{
{ 0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3,
0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562,
0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3,
0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9,
0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce,
0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908,
0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655,
0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16,
0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6,
0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e,
0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050,
0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8,
0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a,
0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436,
0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12,
0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e,
0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb,
0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6,
0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1,
0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233,
0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad,
0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3,
0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b,
0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15,
0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2,
0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791,
0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665,
0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6,
0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47,
0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844,
0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d,
0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8,
0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8, }
}, var td3 = [256]uint32{
{ 0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b,
0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5,
0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b,
0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e,
0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d,
0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9,
0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66,
0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced,
0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4,
0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd,
0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60,
0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79,
0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c,
0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24,
0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c,
0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814,
0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b,
0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084,
0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077,
0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22,
0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f,
0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582,
0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb,
0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef,
0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035,
0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17,
0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46,
0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d,
0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a,
0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678,
0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff,
0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0,
0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0,
},
} }

View File

@ -185,6 +185,10 @@ func GenerateKey(priv *PrivateKey, rand io.Reader) error {
// larger message) using the private key, priv. It returns the signature as a // larger message) using the private key, priv. It returns the signature as a
// pair of integers. The security of the private key depends on the entropy of // pair of integers. The security of the private key depends on the entropy of
// rand. // rand.
//
// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
// to the byte-length of the subgroup. This function does not perform that
// truncation itself.
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
// FIPS 186-3, section 4.6 // FIPS 186-3, section 4.6
@ -218,10 +222,7 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
continue continue
} }
if n > len(hash) { z := k.SetBytes(hash)
n = len(hash)
}
z := k.SetBytes(hash[:n])
s = new(big.Int).Mul(priv.X, r) s = new(big.Int).Mul(priv.X, r)
s.Add(s, z) s.Add(s, z)
@ -238,7 +239,11 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
} }
// Verify verifies the signature in r, s of hash using the public key, pub. It // Verify verifies the signature in r, s of hash using the public key, pub. It
// returns true iff the signature is valid. // reports whether the signature is valid.
//
// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
// to the byte-length of the subgroup. This function does not perform that
// truncation itself.
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
// FIPS 186-3, section 4.7 // FIPS 186-3, section 4.7
@ -255,12 +260,7 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
if n&7 != 0 { if n&7 != 0 {
return false return false
} }
n >>= 3 z := new(big.Int).SetBytes(hash)
if n > len(hash) {
n = len(hash)
}
z := new(big.Int).SetBytes(hash[:n])
u1 := new(big.Int).Mul(z, w) u1 := new(big.Int).Mul(z, w)
u1.Mod(u1, pub.Q) u1.Mod(u1, pub.Q)

View File

@ -23,11 +23,11 @@ func TestOCSPDecode(t *testing.T) {
NextUpdate: time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC), NextUpdate: time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC),
} }
if !reflect.DeepEqual(resp.ThisUpdate, resp.ThisUpdate) { if !reflect.DeepEqual(resp.ThisUpdate, expected.ThisUpdate) {
t.Errorf("resp.ThisUpdate: got %d, want %d", resp.ThisUpdate, expected.ThisUpdate) t.Errorf("resp.ThisUpdate: got %d, want %d", resp.ThisUpdate, expected.ThisUpdate)
} }
if !reflect.DeepEqual(resp.NextUpdate, resp.NextUpdate) { if !reflect.DeepEqual(resp.NextUpdate, expected.NextUpdate) {
t.Errorf("resp.NextUpdate: got %d, want %d", resp.NextUpdate, expected.NextUpdate) t.Errorf("resp.NextUpdate: got %d, want %d", resp.NextUpdate, expected.NextUpdate)
} }

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build plan9
package tls package tls
func initDefaultRoots() { func initDefaultRoots() {

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build freebsd linux openbsd netbsd
package tls package tls
import ( import (

View File

@ -1068,7 +1068,12 @@ func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *de
engine.instr = make([]decInstr, 1) // one item engine.instr = make([]decInstr, 1) // one item
name := rt.String() // best we can do name := rt.String() // best we can do
if !dec.compatibleType(rt, remoteId, make(map[reflect.Type]typeId)) { if !dec.compatibleType(rt, remoteId, make(map[reflect.Type]typeId)) {
return nil, errors.New("gob: wrong type received for local value " + name + ": " + dec.typeString(remoteId)) remoteType := dec.typeString(remoteId)
// Common confusing case: local interface type, remote concrete type.
if ut.base.Kind() == reflect.Interface && remoteId != tInterface {
return nil, errors.New("gob: local interface type " + name + " can only be decoded from remote interface type; received concrete type " + remoteType)
}
return nil, errors.New("gob: decoding into local type " + name + ", received remote type " + remoteType)
} }
op, indir := dec.decOpFor(remoteId, rt, name, make(map[reflect.Type]*decOp)) op, indir := dec.decOpFor(remoteId, rt, name, make(map[reflect.Type]*decOp))
ovfl := errors.New(`value for "` + name + `" out of range`) ovfl := errors.New(`value for "` + name + `" out of range`)

View File

@ -309,7 +309,7 @@ var singleTests = []SingleTest{
{[7]int{4, 55, 1, 44, 22, 66, 1234}, &testArray, ""}, {[7]int{4, 55, 1, 44, 22, 66, 1234}, &testArray, ""},
// Decode errors // Decode errors
{172, &testFloat32, "wrong type"}, {172, &testFloat32, "type"},
} }
func TestSingletons(t *testing.T) { func TestSingletons(t *testing.T) {

View File

@ -339,13 +339,10 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
e.WriteString("null") e.WriteString("null")
break break
} }
// Slices can be marshalled as nil, but otherwise are handled if v.Type().Elem().Kind() == reflect.Uint8 {
// as arrays. // Byte slices get special treatment; arrays don't.
fallthrough s := v.Bytes()
case reflect.Array:
if v.Type() == byteSliceType {
e.WriteByte('"') e.WriteByte('"')
s := v.Interface().([]byte)
if len(s) < 1024 { if len(s) < 1024 {
// for small buffers, using Encode directly is much faster. // for small buffers, using Encode directly is much faster.
dst := make([]byte, base64.StdEncoding.EncodedLen(len(s))) dst := make([]byte, base64.StdEncoding.EncodedLen(len(s)))
@ -361,6 +358,10 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
e.WriteByte('"') e.WriteByte('"')
break break
} }
// Slices can be marshalled as nil, but otherwise are handled
// as arrays.
fallthrough
case reflect.Array:
e.WriteByte('[') e.WriteByte('[')
n := v.Len() n := v.Len()
for i := 0; i < n; i++ { for i := 0; i < n; i++ {

View File

@ -82,3 +82,28 @@ func TestStringTag(t *testing.T) {
t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2) t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2)
} }
} }
// byte slices are special even if they're renamed types.
type renamedByte byte
type renamedByteSlice []byte
type renamedRenamedByteSlice []renamedByte
func TestEncodeRenamedByteSlice(t *testing.T) {
s := renamedByteSlice("abc")
result, err := Marshal(s)
if err != nil {
t.Fatal(err)
}
expect := `"YWJj"`
if string(result) != expect {
t.Errorf(" got %s want %s", result, expect)
}
r := renamedRenamedByteSlice("abc")
result, err = Marshal(r)
if err != nil {
t.Fatal(err)
}
if string(result) != expect {
t.Errorf(" got %s want %s", result, expect)
}
}

Binary file not shown.

View File

@ -57,7 +57,7 @@ func TestInotifyEvents(t *testing.T) {
} }
// We expect this event to be received almost immediately, but let's wait 1 s to be sure // We expect this event to be received almost immediately, but let's wait 1 s to be sure
time.Sleep(1000e6) // 1000 ms time.Sleep(1 * time.Second)
if eventsReceived == 0 { if eventsReceived == 0 {
t.Fatal("inotify event hasn't been received after 1 second") t.Fatal("inotify event hasn't been received after 1 second")
} }
@ -69,7 +69,7 @@ func TestInotifyEvents(t *testing.T) {
select { select {
case <-done: case <-done:
t.Log("event channel closed") t.Log("event channel closed")
case <-time.After(1e9): case <-time.After(1 * time.Second):
t.Fatal("event stream was not closed after 1 second") t.Fatal("event stream was not closed after 1 second")
} }
} }
@ -84,7 +84,7 @@ func TestInotifyClose(t *testing.T) {
done = true done = true
}() }()
time.Sleep(50e6) // 50 ms time.Sleep(50 * time.Millisecond)
if !done { if !done {
t.Fatal("double Close() test failed: second Close() call didn't return") t.Fatal("double Close() test failed: second Close() call didn't return")
} }

View File

@ -177,7 +177,7 @@ func loadTestData() {
} }
if test.r == 0 { if test.r == 0 {
// save for CharacterByCharacterTests // save for CharacterByCharacterTests
test.r = int(r) test.r = rune(r)
} }
var buf [utf8.UTFMax]byte var buf [utf8.UTFMax]byte
sz := utf8.EncodeRune(buf[:], rune(r)) sz := utf8.EncodeRune(buf[:], rune(r))
@ -242,9 +242,9 @@ func doConformanceTests(t *Test, partn int) {
func CharacterByCharacterTests() { func CharacterByCharacterTests() {
tests := part[1].tests tests := part[1].tests
last := 0 var last rune = 0
for i := 0; i <= len(tests); i++ { // last one is special case for i := 0; i <= len(tests); i++ { // last one is special case
var r int var r rune
if i == len(tests) { if i == len(tests) {
r = 0x2FA1E // Don't have to go to 0x10FFFF r = 0x2FA1E // Don't have to go to 0x10FFFF
} else { } else {
@ -285,7 +285,7 @@ func PerformanceTest() {
norm.NFC.Append(nil, buf...) norm.NFC.Append(nil, buf...)
success <- true success <- true
}() }()
timeout := time.After(1e9) timeout := time.After(1 * time.Second)
select { select {
case <-success: case <-success:
// test completed before the timeout // test completed before the timeout

View File

@ -95,35 +95,26 @@ func convertAssign(dest, src interface{}) error {
switch dv.Kind() { switch dv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
s := asString(src) s := asString(src)
i64, err := strconv.ParseInt(s, 10, 64) i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
if err != nil { if err != nil {
return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err) return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
} }
if dv.OverflowInt(i64) {
return fmt.Errorf("string %q overflows %s", s, dv.Kind())
}
dv.SetInt(i64) dv.SetInt(i64)
return nil return nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
s := asString(src) s := asString(src)
u64, err := strconv.ParseUint(s, 10, 64) u64, err := strconv.ParseUint(s, 10, dv.Type().Bits())
if err != nil { if err != nil {
return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err) return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
} }
if dv.OverflowUint(u64) {
return fmt.Errorf("string %q overflows %s", s, dv.Kind())
}
dv.SetUint(u64) dv.SetUint(u64)
return nil return nil
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
s := asString(src) s := asString(src)
f64, err := strconv.ParseFloat(s, 64) f64, err := strconv.ParseFloat(s, dv.Type().Bits())
if err != nil { if err != nil {
return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err) return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
} }
if dv.OverflowFloat(f64) {
return fmt.Errorf("value %q overflows %s", s, dv.Kind())
}
dv.SetFloat(f64) dv.SetFloat(f64)
return nil return nil
} }

View File

@ -55,10 +55,10 @@ var conversionTests = []conversionTest{
// Strings to integers // Strings to integers
{s: "255", d: &scanuint8, wantuint: 255}, {s: "255", d: &scanuint8, wantuint: 255},
{s: "256", d: &scanuint8, wanterr: `string "256" overflows uint8`}, {s: "256", d: &scanuint8, wanterr: `converting string "256" to a uint8: strconv.ParseUint: parsing "256": value out of range`},
{s: "256", d: &scanuint16, wantuint: 256}, {s: "256", d: &scanuint16, wantuint: 256},
{s: "-1", d: &scanint, wantint: -1}, {s: "-1", d: &scanint, wantint: -1},
{s: "foo", d: &scanint, wanterr: `converting string "foo" to a int: parsing "foo": invalid syntax`}, {s: "foo", d: &scanint, wanterr: `converting string "foo" to a int: strconv.ParseInt: parsing "foo": invalid syntax`},
// True bools // True bools
{s: true, d: &scanbool, wantbool: true}, {s: true, d: &scanbool, wantbool: true},

View File

@ -134,6 +134,7 @@ func (db *DB) maxIdleConns() int {
func (db *DB) conn() (driver.Conn, error) { func (db *DB) conn() (driver.Conn, error) {
db.mu.Lock() db.mu.Lock()
if db.closed { if db.closed {
db.mu.Unlock()
return nil, errors.New("sql: database is closed") return nil, errors.New("sql: database is closed")
} }
if n := len(db.freeConn); n > 0 { if n := len(db.freeConn); n > 0 {

View File

@ -228,3 +228,16 @@ func TestTxStmt(t *testing.T) {
t.Fatalf("Commit = %v", err) t.Fatalf("Commit = %v", err)
} }
} }
// Tests fix for issue 2542, that we release a lock when querying on
// a closed connection.
func TestIssue2542Deadlock(t *testing.T) {
db := newTestDB(t, "people")
closeDB(t, db)
for i := 0; i < 2; i++ {
_, err := db.Query("SELECT|people|age,name|")
if err == nil {
t.Fatalf("expected error")
}
}
}

View File

@ -187,10 +187,10 @@ func (c *ClientConn) mainLoop() {
if err != nil { if err != nil {
break break
} }
// TODO(dfc) A note on blocking channel use. // TODO(dfc) A note on blocking channel use.
// The msg, win, data and dataExt channels of a clientChan can // The msg, win, data and dataExt channels of a clientChan can
// cause this loop to block indefinately if the consumer does // cause this loop to block indefinately if the consumer does
// not service them. // not service them.
switch packet[0] { switch packet[0] {
case msgChannelData: case msgChannelData:
if len(packet) < 9 { if len(packet) < 9 {
@ -200,7 +200,7 @@ func (c *ClientConn) mainLoop() {
peersId := uint32(packet[1])<<24 | uint32(packet[2])<<16 | uint32(packet[3])<<8 | uint32(packet[4]) peersId := uint32(packet[1])<<24 | uint32(packet[2])<<16 | uint32(packet[3])<<8 | uint32(packet[4])
if length := int(packet[5])<<24 | int(packet[6])<<16 | int(packet[7])<<8 | int(packet[8]); length > 0 { if length := int(packet[5])<<24 | int(packet[6])<<16 | int(packet[7])<<8 | int(packet[8]); length > 0 {
packet = packet[9:] packet = packet[9:]
c.getChan(peersId).stdout.data <- packet[:length] c.getChan(peersId).stdout.handleData(packet[:length])
} }
case msgChannelExtendedData: case msgChannelExtendedData:
if len(packet) < 13 { if len(packet) < 13 {
@ -211,11 +211,11 @@ func (c *ClientConn) mainLoop() {
datatype := uint32(packet[5])<<24 | uint32(packet[6])<<16 | uint32(packet[7])<<8 | uint32(packet[8]) datatype := uint32(packet[5])<<24 | uint32(packet[6])<<16 | uint32(packet[7])<<8 | uint32(packet[8])
if length := int(packet[9])<<24 | int(packet[10])<<16 | int(packet[11])<<8 | int(packet[12]); length > 0 { if length := int(packet[9])<<24 | int(packet[10])<<16 | int(packet[11])<<8 | int(packet[12]); length > 0 {
packet = packet[13:] packet = packet[13:]
// RFC 4254 5.2 defines data_type_code 1 to be data destined // RFC 4254 5.2 defines data_type_code 1 to be data destined
// for stderr on interactive sessions. Other data types are // for stderr on interactive sessions. Other data types are
// silently discarded. // silently discarded.
if datatype == 1 { if datatype == 1 {
c.getChan(peersId).stderr.data <- packet[:length] c.getChan(peersId).stderr.handleData(packet[:length])
} }
} }
default: default:
@ -228,12 +228,22 @@ func (c *ClientConn) mainLoop() {
c.getChan(msg.PeersId).msg <- msg c.getChan(msg.PeersId).msg <- msg
case *channelCloseMsg: case *channelCloseMsg:
ch := c.getChan(msg.PeersId) ch := c.getChan(msg.PeersId)
ch.theyClosed = true
close(ch.stdin.win) close(ch.stdin.win)
close(ch.stdout.data) ch.stdout.eof()
close(ch.stderr.data) ch.stderr.eof()
close(ch.msg)
if !ch.weClosed {
ch.weClosed = true
ch.sendClose()
}
c.chanlist.remove(msg.PeersId) c.chanlist.remove(msg.PeersId)
case *channelEOFMsg: case *channelEOFMsg:
c.getChan(msg.PeersId).msg <- msg ch := c.getChan(msg.PeersId)
ch.stdout.eof()
// RFC 4254 is mute on how EOF affects dataExt messages but
// it is logical to signal EOF at the same time.
ch.stderr.eof()
case *channelRequestSuccessMsg: case *channelRequestSuccessMsg:
c.getChan(msg.PeersId).msg <- msg c.getChan(msg.PeersId).msg <- msg
case *channelRequestFailureMsg: case *channelRequestFailureMsg:
@ -242,6 +252,8 @@ func (c *ClientConn) mainLoop() {
c.getChan(msg.PeersId).msg <- msg c.getChan(msg.PeersId).msg <- msg
case *windowAdjustMsg: case *windowAdjustMsg:
c.getChan(msg.PeersId).stdin.win <- int(msg.AdditionalBytes) c.getChan(msg.PeersId).stdin.win <- int(msg.AdditionalBytes)
case *disconnectMsg:
break
default: default:
fmt.Printf("mainLoop: unhandled message %T: %v\n", msg, msg) fmt.Printf("mainLoop: unhandled message %T: %v\n", msg, msg)
} }
@ -249,7 +261,7 @@ func (c *ClientConn) mainLoop() {
} }
} }
// Dial connects to the given network address using net.Dial and // Dial connects to the given network address using net.Dial and
// then initiates a SSH handshake, returning the resulting client connection. // then initiates a SSH handshake, returning the resulting client connection.
func Dial(network, addr string, config *ClientConfig) (*ClientConn, error) { func Dial(network, addr string, config *ClientConfig) (*ClientConn, error) {
conn, err := net.Dial(network, addr) conn, err := net.Dial(network, addr)
@ -259,18 +271,18 @@ func Dial(network, addr string, config *ClientConfig) (*ClientConn, error) {
return Client(conn, config) return Client(conn, config)
} }
// A ClientConfig structure is used to configure a ClientConn. After one has // A ClientConfig structure is used to configure a ClientConn. After one has
// been passed to an SSH function it must not be modified. // been passed to an SSH function it must not be modified.
type ClientConfig struct { type ClientConfig struct {
// Rand provides the source of entropy for key exchange. If Rand is // Rand provides the source of entropy for key exchange. If Rand is
// nil, the cryptographic random reader in package crypto/rand will // nil, the cryptographic random reader in package crypto/rand will
// be used. // be used.
Rand io.Reader Rand io.Reader
// The username to authenticate. // The username to authenticate.
User string User string
// A slice of ClientAuth methods. Only the first instance // A slice of ClientAuth methods. Only the first instance
// of a particular RFC 4252 method will be used during authentication. // of a particular RFC 4252 method will be used during authentication.
Auth []ClientAuth Auth []ClientAuth
@ -285,7 +297,7 @@ func (c *ClientConfig) rand() io.Reader {
return c.Rand return c.Rand
} }
// A clientChan represents a single RFC 4254 channel that is multiplexed // A clientChan represents a single RFC 4254 channel that is multiplexed
// over a single SSH connection. // over a single SSH connection.
type clientChan struct { type clientChan struct {
packetWriter packetWriter
@ -294,10 +306,13 @@ type clientChan struct {
stdout *chanReader // receives the payload of channelData messages stdout *chanReader // receives the payload of channelData messages
stderr *chanReader // receives the payload of channelExtendedData messages stderr *chanReader // receives the payload of channelExtendedData messages
msg chan interface{} // incoming messages msg chan interface{} // incoming messages
theyClosed bool // indicates the close msg has been received from the remote side
weClosed bool // incidates the close msg has been sent from our side
} }
// newClientChan returns a partially constructed *clientChan // newClientChan returns a partially constructed *clientChan
// using the local id provided. To be usable clientChan.peersId // using the local id provided. To be usable clientChan.peersId
// needs to be assigned once known. // needs to be assigned once known.
func newClientChan(t *transport, id uint32) *clientChan { func newClientChan(t *transport, id uint32) *clientChan {
c := &clientChan{ c := &clientChan{
@ -320,8 +335,8 @@ func newClientChan(t *transport, id uint32) *clientChan {
return c return c
} }
// waitForChannelOpenResponse, if successful, fills out // waitForChannelOpenResponse, if successful, fills out
// the peerId and records any initial window advertisement. // the peerId and records any initial window advertisement.
func (c *clientChan) waitForChannelOpenResponse() error { func (c *clientChan) waitForChannelOpenResponse() error {
switch msg := (<-c.msg).(type) { switch msg := (<-c.msg).(type) {
case *channelOpenConfirmMsg: case *channelOpenConfirmMsg:
@ -335,13 +350,29 @@ func (c *clientChan) waitForChannelOpenResponse() error {
return errors.New("unexpected packet") return errors.New("unexpected packet")
} }
// Close closes the channel. This does not close the underlying connection. // sendEOF sends EOF to the server. RFC 4254 Section 5.3
func (c *clientChan) Close() error { func (c *clientChan) sendEOF() error {
return c.writePacket(marshal(msgChannelEOF, channelEOFMsg{
PeersId: c.peersId,
}))
}
// sendClose signals the intent to close the channel.
func (c *clientChan) sendClose() error {
return c.writePacket(marshal(msgChannelClose, channelCloseMsg{ return c.writePacket(marshal(msgChannelClose, channelCloseMsg{
PeersId: c.peersId, PeersId: c.peersId,
})) }))
} }
// Close closes the channel. This does not close the underlying connection.
func (c *clientChan) Close() error {
if !c.weClosed {
c.weClosed = true
return c.sendClose()
}
return nil
}
// Thread safe channel list. // Thread safe channel list.
type chanlist struct { type chanlist struct {
// protects concurrent access to chans // protects concurrent access to chans
@ -413,7 +444,7 @@ func (w *chanWriter) Write(data []byte) (n int, err error) {
} }
func (w *chanWriter) Close() error { func (w *chanWriter) Close() error {
return w.clientChan.writePacket(marshal(msgChannelEOF, channelEOFMsg{w.clientChan.peersId})) return w.clientChan.sendEOF()
} }
// A chanReader represents stdout or stderr of a remote process. // A chanReader represents stdout or stderr of a remote process.
@ -422,10 +453,27 @@ type chanReader struct {
// If writes to this channel block, they will block mainLoop, making // If writes to this channel block, they will block mainLoop, making
// it unable to receive new messages from the remote side. // it unable to receive new messages from the remote side.
data chan []byte // receives data from remote data chan []byte // receives data from remote
dataClosed bool // protects data from being closed twice
clientChan *clientChan // the channel backing this reader clientChan *clientChan // the channel backing this reader
buf []byte buf []byte
} }
// eof signals to the consumer that there is no more data to be received.
func (r *chanReader) eof() {
if !r.dataClosed {
r.dataClosed = true
close(r.data)
}
}
// handleData sends buf to the reader's consumer. If r.data is closed
// the data will be silently discarded
func (r *chanReader) handleData(buf []byte) {
if !r.dataClosed {
r.data <- buf
}
}
// Read reads data from the remote process's stdout or stderr. // Read reads data from the remote process's stdout or stderr.
func (r *chanReader) Read(data []byte) (int, error) { func (r *chanReader) Read(data []byte) (int, error) {
var ok bool var ok bool

View File

@ -6,7 +6,7 @@ package ssh
// ClientConn functional tests. // ClientConn functional tests.
// These tests require a running ssh server listening on port 22 // These tests require a running ssh server listening on port 22
// on the local host. Functional tests will be skipped unless // on the local host. Functional tests will be skipped unless
// -ssh.user and -ssh.pass must be passed to gotest. // -ssh.user and -ssh.pass must be passed to gotest.
import ( import (

View File

@ -34,6 +34,20 @@ const (
SIGUSR2 Signal = "USR2" SIGUSR2 Signal = "USR2"
) )
var signals = map[Signal]int{
SIGABRT: 6,
SIGALRM: 14,
SIGFPE: 8,
SIGHUP: 1,
SIGILL: 4,
SIGINT: 2,
SIGKILL: 9,
SIGPIPE: 13,
SIGQUIT: 3,
SIGSEGV: 11,
SIGTERM: 15,
}
// A Session represents a connection to a remote command or shell. // A Session represents a connection to a remote command or shell.
type Session struct { type Session struct {
// Stdin specifies the remote process's standard input. // Stdin specifies the remote process's standard input.
@ -170,10 +184,17 @@ func (s *Session) Start(cmd string) error {
return s.start() return s.start()
} }
// Run runs cmd on the remote host and waits for it to terminate. // Run runs cmd on the remote host. Typically, the remote
// Typically, the remote server passes cmd to the shell for // server passes cmd to the shell for interpretation.
// interpretation. A Session only accepts one call to Run, // A Session only accepts one call to Run, Start or Shell.
// Start or Shell. //
// The returned error is nil if the command runs, has no problems
// copying stdin, stdout, and stderr, and exits with a zero exit
// status.
//
// If the command fails to run or doesn't complete successfully, the
// error is of type *ExitError. Other error types may be
// returned for I/O problems.
func (s *Session) Run(cmd string) error { func (s *Session) Run(cmd string) error {
err := s.Start(cmd) err := s.Start(cmd)
if err != nil { if err != nil {
@ -233,6 +254,14 @@ func (s *Session) start() error {
} }
// Wait waits for the remote command to exit. // Wait waits for the remote command to exit.
//
// The returned error is nil if the command runs, has no problems
// copying stdin, stdout, and stderr, and exits with a zero exit
// status.
//
// If the command fails to run or doesn't complete successfully, the
// error is of type *ExitError. Other error types may be
// returned for I/O problems.
func (s *Session) Wait() error { func (s *Session) Wait() error {
if !s.started { if !s.started {
return errors.New("ssh: session not started") return errors.New("ssh: session not started")
@ -255,21 +284,40 @@ func (s *Session) Wait() error {
} }
func (s *Session) wait() error { func (s *Session) wait() error {
for { wm := Waitmsg{status: -1}
switch msg := (<-s.msg).(type) {
// Wait for msg channel to be closed before returning.
for msg := range s.msg {
switch msg := msg.(type) {
case *channelRequestMsg: case *channelRequestMsg:
// TODO(dfc) improve this behavior to match os.Waitmsg
switch msg.Request { switch msg.Request {
case "exit-status": case "exit-status":
d := msg.RequestSpecificData d := msg.RequestSpecificData
status := int(d[0])<<24 | int(d[1])<<16 | int(d[2])<<8 | int(d[3]) wm.status = int(d[0])<<24 | int(d[1])<<16 | int(d[2])<<8 | int(d[3])
if status > 0 {
return fmt.Errorf("remote process exited with %d", status)
}
return nil
case "exit-signal": case "exit-signal":
// TODO(dfc) make a more readable error message signal, rest, ok := parseString(msg.RequestSpecificData)
return fmt.Errorf("%v", msg.RequestSpecificData) if !ok {
return fmt.Errorf("wait: could not parse request data: %v", msg.RequestSpecificData)
}
wm.signal = safeString(string(signal))
// skip coreDumped bool
if len(rest) == 0 {
return fmt.Errorf("wait: could not parse request data: %v", msg.RequestSpecificData)
}
rest = rest[1:]
errmsg, rest, ok := parseString(rest)
if !ok {
return fmt.Errorf("wait: could not parse request data: %v", msg.RequestSpecificData)
}
wm.msg = safeString(string(errmsg))
lang, _, ok := parseString(rest)
if !ok {
return fmt.Errorf("wait: could not parse request data: %v", msg.RequestSpecificData)
}
wm.lang = safeString(string(lang))
default: default:
return fmt.Errorf("wait: unexpected channel request: %v", msg) return fmt.Errorf("wait: unexpected channel request: %v", msg)
} }
@ -277,7 +325,20 @@ func (s *Session) wait() error {
return fmt.Errorf("wait: unexpected packet %T received: %v", msg, msg) return fmt.Errorf("wait: unexpected packet %T received: %v", msg, msg)
} }
} }
panic("unreachable") if wm.status == 0 {
return nil
}
if wm.status == -1 {
// exit-status was never sent from server
if wm.signal == "" {
return errors.New("wait: remote command exited without exit status or exit signal")
}
wm.status = 128
if _, ok := signals[Signal(wm.signal)]; ok {
wm.status += signals[Signal(wm.signal)]
}
}
return &ExitError{wm}
} }
func (s *Session) stdin() error { func (s *Session) stdin() error {
@ -391,3 +452,46 @@ func (c *ClientConn) NewSession() (*Session, error) {
clientChan: ch, clientChan: ch,
}, nil }, nil
} }
// An ExitError reports unsuccessful completion of a remote command.
type ExitError struct {
Waitmsg
}
func (e *ExitError) Error() string {
return e.Waitmsg.String()
}
// Waitmsg stores the information about an exited remote command
// as reported by Wait.
type Waitmsg struct {
status int
signal string
msg string
lang string
}
// ExitStatus returns the exit status of the remote command.
func (w Waitmsg) ExitStatus() int {
return w.status
}
// Signal returns the exit signal of the remote command if
// it was terminated violently.
func (w Waitmsg) Signal() string {
return w.signal
}
// Msg returns the exit message given by the remote command
func (w Waitmsg) Msg() string {
return w.msg
}
// Lang returns the language tag. See RFC 3066
func (w Waitmsg) Lang() string {
return w.lang
}
func (w Waitmsg) String() string {
return fmt.Sprintf("Process exited with: %v. Reason was: %v (%v)", w.status, w.msg, w.signal)
}

View File

@ -12,8 +12,10 @@ import (
"testing" "testing"
) )
type serverType func(*channel)
// dial constructs a new test server and returns a *ClientConn. // dial constructs a new test server and returns a *ClientConn.
func dial(t *testing.T) *ClientConn { func dial(handler serverType, t *testing.T) *ClientConn {
pw := password("tiger") pw := password("tiger")
serverConfig.PasswordCallback = func(user, pass string) bool { serverConfig.PasswordCallback = func(user, pass string) bool {
return user == "testuser" && pass == string(pw) return user == "testuser" && pass == string(pw)
@ -50,27 +52,7 @@ func dial(t *testing.T) *ClientConn {
continue continue
} }
ch.Accept() ch.Accept()
go func() { go handler(ch.(*channel))
defer ch.Close()
// this string is returned to stdout
shell := NewServerShell(ch, "golang")
shell.ReadLine()
type exitMsg struct {
PeersId uint32
Request string
WantReply bool
Status uint32
}
// TODO(dfc) converting to the concrete type should not be
// necessary to send a packet.
msg := exitMsg{
PeersId: ch.(*channel).theirId,
Request: "exit-status",
WantReply: false,
Status: 0,
}
ch.(*channel).serverConn.writePacket(marshal(msgChannelRequest, msg))
}()
} }
t.Log("done") t.Log("done")
}() }()
@ -91,7 +73,7 @@ func dial(t *testing.T) *ClientConn {
// Test a simple string is returned to session.Stdout. // Test a simple string is returned to session.Stdout.
func TestSessionShell(t *testing.T) { func TestSessionShell(t *testing.T) {
conn := dial(t) conn := dial(shellHandler, t)
defer conn.Close() defer conn.Close()
session, err := conn.NewSession() session, err := conn.NewSession()
if err != nil { if err != nil {
@ -116,7 +98,7 @@ func TestSessionShell(t *testing.T) {
// Test a simple string is returned via StdoutPipe. // Test a simple string is returned via StdoutPipe.
func TestSessionStdoutPipe(t *testing.T) { func TestSessionStdoutPipe(t *testing.T) {
conn := dial(t) conn := dial(shellHandler, t)
defer conn.Close() defer conn.Close()
session, err := conn.NewSession() session, err := conn.NewSession()
if err != nil { if err != nil {
@ -147,3 +129,237 @@ func TestSessionStdoutPipe(t *testing.T) {
t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual) t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual)
} }
} }
// Test non-0 exit status is returned correctly.
func TestExitStatusNonZero(t *testing.T) {
conn := dial(exitStatusNonZeroHandler, t)
defer conn.Close()
session, err := conn.NewSession()
if err != nil {
t.Fatalf("Unable to request new session: %s", err)
}
defer session.Close()
if err := session.Shell(); err != nil {
t.Fatalf("Unable to execute command: %s", err)
}
err = session.Wait()
if err == nil {
t.Fatalf("expected command to fail but it didn't")
}
e, ok := err.(*ExitError)
if !ok {
t.Fatalf("expected *ExitError but got %T", err)
}
if e.ExitStatus() != 15 {
t.Fatalf("expected command to exit with 15 but got %s", e.ExitStatus())
}
}
// Test 0 exit status is returned correctly.
func TestExitStatusZero(t *testing.T) {
conn := dial(exitStatusZeroHandler, t)
defer conn.Close()
session, err := conn.NewSession()
if err != nil {
t.Fatalf("Unable to request new session: %s", err)
}
defer session.Close()
if err := session.Shell(); err != nil {
t.Fatalf("Unable to execute command: %s", err)
}
err = session.Wait()
if err != nil {
t.Fatalf("expected nil but got %s", err)
}
}
// Test exit signal and status are both returned correctly.
func TestExitSignalAndStatus(t *testing.T) {
conn := dial(exitSignalAndStatusHandler, t)
defer conn.Close()
session, err := conn.NewSession()
if err != nil {
t.Fatalf("Unable to request new session: %s", err)
}
defer session.Close()
if err := session.Shell(); err != nil {
t.Fatalf("Unable to execute command: %s", err)
}
err = session.Wait()
if err == nil {
t.Fatalf("expected command to fail but it didn't")
}
e, ok := err.(*ExitError)
if !ok {
t.Fatalf("expected *ExitError but got %T", err)
}
if e.Signal() != "TERM" || e.ExitStatus() != 15 {
t.Fatalf("expected command to exit with signal TERM and status 15 but got signal %s and status %v", e.Signal(), e.ExitStatus())
}
}
// Test exit signal and status are both returned correctly.
func TestKnownExitSignalOnly(t *testing.T) {
conn := dial(exitSignalHandler, t)
defer conn.Close()
session, err := conn.NewSession()
if err != nil {
t.Fatalf("Unable to request new session: %s", err)
}
defer session.Close()
if err := session.Shell(); err != nil {
t.Fatalf("Unable to execute command: %s", err)
}
err = session.Wait()
if err == nil {
t.Fatalf("expected command to fail but it didn't")
}
e, ok := err.(*ExitError)
if !ok {
t.Fatalf("expected *ExitError but got %T", err)
}
if e.Signal() != "TERM" || e.ExitStatus() != 143 {
t.Fatalf("expected command to exit with signal TERM and status 143 but got signal %s and status %v", e.Signal(), e.ExitStatus())
}
}
// Test exit signal and status are both returned correctly.
func TestUnknownExitSignal(t *testing.T) {
conn := dial(exitSignalUnknownHandler, t)
defer conn.Close()
session, err := conn.NewSession()
if err != nil {
t.Fatalf("Unable to request new session: %s", err)
}
defer session.Close()
if err := session.Shell(); err != nil {
t.Fatalf("Unable to execute command: %s", err)
}
err = session.Wait()
if err == nil {
t.Fatalf("expected command to fail but it didn't")
}
e, ok := err.(*ExitError)
if !ok {
t.Fatalf("expected *ExitError but got %T", err)
}
if e.Signal() != "SYS" || e.ExitStatus() != 128 {
t.Fatalf("expected command to exit with signal SYS and status 128 but got signal %s and status %v", e.Signal(), e.ExitStatus())
}
}
// Test WaitMsg is not returned if the channel closes abruptly.
func TestExitWithoutStatusOrSignal(t *testing.T) {
conn := dial(exitWithoutSignalOrStatus, t)
defer conn.Close()
session, err := conn.NewSession()
if err != nil {
t.Fatalf("Unable to request new session: %s", err)
}
defer session.Close()
if err := session.Shell(); err != nil {
t.Fatalf("Unable to execute command: %s", err)
}
err = session.Wait()
if err == nil {
t.Fatalf("expected command to fail but it didn't")
}
_, ok := err.(*ExitError)
if ok {
// you can't actually test for errors.errorString
// because it's not exported.
t.Fatalf("expected *errorString but got %T", err)
}
}
type exitStatusMsg struct {
PeersId uint32
Request string
WantReply bool
Status uint32
}
type exitSignalMsg struct {
PeersId uint32
Request string
WantReply bool
Signal string
CoreDumped bool
Errmsg string
Lang string
}
func exitStatusZeroHandler(ch *channel) {
defer ch.Close()
// this string is returned to stdout
shell := NewServerShell(ch, "> ")
shell.ReadLine()
sendStatus(0, ch)
}
func exitStatusNonZeroHandler(ch *channel) {
defer ch.Close()
shell := NewServerShell(ch, "> ")
shell.ReadLine()
sendStatus(15, ch)
}
func exitSignalAndStatusHandler(ch *channel) {
defer ch.Close()
shell := NewServerShell(ch, "> ")
shell.ReadLine()
sendStatus(15, ch)
sendSignal("TERM", ch)
}
func exitSignalHandler(ch *channel) {
defer ch.Close()
shell := NewServerShell(ch, "> ")
shell.ReadLine()
sendSignal("TERM", ch)
}
func exitSignalUnknownHandler(ch *channel) {
defer ch.Close()
shell := NewServerShell(ch, "> ")
shell.ReadLine()
sendSignal("SYS", ch)
}
func exitWithoutSignalOrStatus(ch *channel) {
defer ch.Close()
shell := NewServerShell(ch, "> ")
shell.ReadLine()
}
func shellHandler(ch *channel) {
defer ch.Close()
// this string is returned to stdout
shell := NewServerShell(ch, "golang")
shell.ReadLine()
sendStatus(0, ch)
}
func sendStatus(status uint32, ch *channel) {
msg := exitStatusMsg{
PeersId: ch.theirId,
Request: "exit-status",
WantReply: false,
Status: status,
}
ch.serverConn.writePacket(marshal(msgChannelRequest, msg))
}
func sendSignal(signal string, ch *channel) {
sig := exitSignalMsg{
PeersId: ch.theirId,
Request: "exit-signal",
WantReply: false,
Signal: signal,
CoreDumped: false,
Errmsg: "Process terminated",
Lang: "en-GB-oed",
}
ch.serverConn.writePacket(marshal(msgChannelRequest, sig))
}

View File

@ -81,7 +81,7 @@ type gcParser struct {
func (p *gcParser) init(filename, id string, src io.Reader, imports map[string]*ast.Object) { func (p *gcParser) init(filename, id string, src io.Reader, imports map[string]*ast.Object) {
p.scanner.Init(src) p.scanner.Init(src)
p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) } p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanChars | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
p.scanner.Whitespace = 1<<'\t' | 1<<' ' p.scanner.Whitespace = 1<<'\t' | 1<<' '
p.scanner.Filename = filename // for good error messages p.scanner.Filename = filename // for good error messages
p.next() p.next()
@ -145,18 +145,14 @@ func GcImporter(imports map[string]*ast.Object, path string) (pkg *ast.Object, e
// Declare inserts a named object of the given kind in scope. // Declare inserts a named object of the given kind in scope.
func (p *gcParser) declare(scope *ast.Scope, kind ast.ObjKind, name string) *ast.Object { func (p *gcParser) declare(scope *ast.Scope, kind ast.ObjKind, name string) *ast.Object {
// a type may have been declared before - if it exists // the object may have been imported before - if it exists
// already in the respective package scope, return that // already in the respective package scope, return that object
// type if obj := scope.Lookup(name); obj != nil {
if kind == ast.Typ { assert(obj.Kind == kind)
if obj := scope.Lookup(name); obj != nil { return obj
assert(obj.Kind == ast.Typ)
return obj
}
} }
// any other object must be a newly declared object - // otherwise create a new object and insert it into the package scope
// create it and insert it into the package scope
obj := ast.NewObj(kind, name) obj := ast.NewObj(kind, name)
if scope.Insert(obj) != nil { if scope.Insert(obj) != nil {
p.errorf("already declared: %v %s", kind, obj.Name) p.errorf("already declared: %v %s", kind, obj.Name)
@ -199,14 +195,15 @@ func (p *gcParser) errorf(format string, args ...interface{}) {
func (p *gcParser) expect(tok rune) string { func (p *gcParser) expect(tok rune) string {
lit := p.lit lit := p.lit
if p.tok != tok { if p.tok != tok {
p.errorf("expected %q, got %q (%q)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit) panic(1)
p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
} }
p.next() p.next()
return lit return lit
} }
func (p *gcParser) expectSpecial(tok string) { func (p *gcParser) expectSpecial(tok string) {
sep := rune('x') // not white space sep := 'x' // not white space
i := 0 i := 0
for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' { for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' {
sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
@ -261,7 +258,7 @@ func (p *gcParser) parsePkgId() *ast.Object {
func (p *gcParser) parseDotIdent() string { func (p *gcParser) parseDotIdent() string {
ident := "" ident := ""
if p.tok != scanner.Int { if p.tok != scanner.Int {
sep := rune('x') // not white space sep := 'x' // not white space
for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' { for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' {
ident += p.lit ident += p.lit
sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
@ -645,6 +642,7 @@ func (p *gcParser) parseNumber() Const {
// Literal = bool_lit | int_lit | float_lit | complex_lit | string_lit . // Literal = bool_lit | int_lit | float_lit | complex_lit | string_lit .
// bool_lit = "true" | "false" . // bool_lit = "true" | "false" .
// complex_lit = "(" float_lit "+" float_lit ")" . // complex_lit = "(" float_lit "+" float_lit ")" .
// rune_lit = "(" int_lit "+" int_lit ")" .
// string_lit = `"` { unicode_char } `"` . // string_lit = `"` { unicode_char } `"` .
// //
func (p *gcParser) parseConstDecl() { func (p *gcParser) parseConstDecl() {
@ -674,21 +672,33 @@ func (p *gcParser) parseConstDecl() {
typ = Float64.Underlying typ = Float64.Underlying
} }
case '(': case '(':
// complex_lit // complex_lit or rune_lit
p.next() p.next()
if p.tok == scanner.Char {
p.next()
p.expect('+')
p.parseNumber()
p.expect(')')
// TODO: x = ...
break
}
re := p.parseNumber() re := p.parseNumber()
p.expect('+') p.expect('+')
im := p.parseNumber() im := p.parseNumber()
p.expect(')') p.expect(')')
x = Const{cmplx{re.val.(*big.Rat), im.val.(*big.Rat)}} x = Const{cmplx{re.val.(*big.Rat), im.val.(*big.Rat)}}
typ = Complex128.Underlying typ = Complex128.Underlying
case scanner.Char:
// TODO: x = ...
p.next()
case scanner.String: case scanner.String:
// string_lit // string_lit
x = MakeConst(token.STRING, p.lit) x = MakeConst(token.STRING, p.lit)
p.next() p.next()
typ = String.Underlying typ = String.Underlying
default: default:
p.error("expected literal") println(p.tok)
p.errorf("expected literal got %s", scanner.TokenString(p.tok))
} }
if obj.Type == nil { if obj.Type == nil {
obj.Type = typ obj.Type = typ

View File

@ -75,7 +75,7 @@ type Watcher struct {
// NewWatcher creates and returns a Watcher. // NewWatcher creates and returns a Watcher.
func NewWatcher() (*Watcher, error) { func NewWatcher() (*Watcher, error) {
port, e := syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 0) port, e := syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 0)
if e != 0 { if e != nil {
return nil, os.NewSyscallError("CreateIoCompletionPort", e) return nil, os.NewSyscallError("CreateIoCompletionPort", e)
} }
w := &Watcher{ w := &Watcher{
@ -147,7 +147,7 @@ func (w *Watcher) RemoveWatch(path string) error {
func (w *Watcher) wakeupReader() error { func (w *Watcher) wakeupReader() error {
e := syscall.PostQueuedCompletionStatus(w.port, 0, 0, nil) e := syscall.PostQueuedCompletionStatus(w.port, 0, 0, nil)
if e != 0 { if e != nil {
return os.NewSyscallError("PostQueuedCompletionStatus", e) return os.NewSyscallError("PostQueuedCompletionStatus", e)
} }
return nil return nil
@ -155,7 +155,7 @@ func (w *Watcher) wakeupReader() error {
func getDir(pathname string) (dir string, err error) { func getDir(pathname string) (dir string, err error) {
attr, e := syscall.GetFileAttributes(syscall.StringToUTF16Ptr(pathname)) attr, e := syscall.GetFileAttributes(syscall.StringToUTF16Ptr(pathname))
if e != 0 { if e != nil {
return "", os.NewSyscallError("GetFileAttributes", e) return "", os.NewSyscallError("GetFileAttributes", e)
} }
if attr&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { if attr&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
@ -173,11 +173,11 @@ func getIno(path string) (ino *inode, err error) {
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
nil, syscall.OPEN_EXISTING, nil, syscall.OPEN_EXISTING,
syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OVERLAPPED, 0) syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OVERLAPPED, 0)
if e != 0 { if e != nil {
return nil, os.NewSyscallError("CreateFile", e) return nil, os.NewSyscallError("CreateFile", e)
} }
var fi syscall.ByHandleFileInformation var fi syscall.ByHandleFileInformation
if e = syscall.GetFileInformationByHandle(h, &fi); e != 0 { if e = syscall.GetFileInformationByHandle(h, &fi); e != nil {
syscall.CloseHandle(h) syscall.CloseHandle(h)
return nil, os.NewSyscallError("GetFileInformationByHandle", e) return nil, os.NewSyscallError("GetFileInformationByHandle", e)
} }
@ -222,7 +222,7 @@ func (w *Watcher) addWatch(pathname string, flags uint64) error {
} }
watchEntry := w.watches.get(ino) watchEntry := w.watches.get(ino)
if watchEntry == nil { if watchEntry == nil {
if _, e := syscall.CreateIoCompletionPort(ino.handle, w.port, 0, 0); e != 0 { if _, e := syscall.CreateIoCompletionPort(ino.handle, w.port, 0, 0); e != nil {
syscall.CloseHandle(ino.handle) syscall.CloseHandle(ino.handle)
return os.NewSyscallError("CreateIoCompletionPort", e) return os.NewSyscallError("CreateIoCompletionPort", e)
} }
@ -295,7 +295,7 @@ func (w *Watcher) deleteWatch(watch *watch) {
// Must run within the I/O thread. // Must run within the I/O thread.
func (w *Watcher) startRead(watch *watch) error { func (w *Watcher) startRead(watch *watch) error {
if e := syscall.CancelIo(watch.ino.handle); e != 0 { if e := syscall.CancelIo(watch.ino.handle); e != nil {
w.Error <- os.NewSyscallError("CancelIo", e) w.Error <- os.NewSyscallError("CancelIo", e)
w.deleteWatch(watch) w.deleteWatch(watch)
} }
@ -304,7 +304,7 @@ func (w *Watcher) startRead(watch *watch) error {
mask |= toWindowsFlags(m) mask |= toWindowsFlags(m)
} }
if mask == 0 { if mask == 0 {
if e := syscall.CloseHandle(watch.ino.handle); e != 0 { if e := syscall.CloseHandle(watch.ino.handle); e != nil {
w.Error <- os.NewSyscallError("CloseHandle", e) w.Error <- os.NewSyscallError("CloseHandle", e)
} }
delete(w.watches[watch.ino.volume], watch.ino.index) delete(w.watches[watch.ino.volume], watch.ino.index)
@ -312,7 +312,7 @@ func (w *Watcher) startRead(watch *watch) error {
} }
e := syscall.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0], e := syscall.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0],
uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0) uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0)
if e != 0 { if e != nil {
err := os.NewSyscallError("ReadDirectoryChanges", e) err := os.NewSyscallError("ReadDirectoryChanges", e)
if e == syscall.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 { if e == syscall.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 {
// Watched directory was probably removed // Watched directory was probably removed
@ -354,7 +354,7 @@ func (w *Watcher) readEvents() {
} }
} }
var err error var err error
if e := syscall.CloseHandle(w.port); e != 0 { if e := syscall.CloseHandle(w.port); e != nil {
err = os.NewSyscallError("CloseHandle", e) err = os.NewSyscallError("CloseHandle", e)
} }
close(w.Event) close(w.Event)
@ -386,7 +386,7 @@ func (w *Watcher) readEvents() {
default: default:
w.Error <- os.NewSyscallError("GetQueuedCompletionPort", e) w.Error <- os.NewSyscallError("GetQueuedCompletionPort", e)
continue continue
case 0: case nil:
} }
var offset uint32 var offset uint32

View File

@ -21,7 +21,7 @@ func expect(t *testing.T, eventstream <-chan *Event, name string, mask uint32) {
if event.Name != name || event.Mask != mask { if event.Name != name || event.Mask != mask {
t.Fatal("did not receive expected event") t.Fatal("did not receive expected event")
} }
case <-time.After(1e9): case <-time.After(1 * time.Second):
t.Fatal("timed out waiting for event") t.Fatal("timed out waiting for event")
} }
} }
@ -108,7 +108,7 @@ func TestNotifyClose(t *testing.T) {
done = true done = true
}() }()
time.Sleep(50e6) // 50 ms time.Sleep(50 * time.Millisecond)
if !done { if !done {
t.Fatal("double Close() test failed: second Close() call didn't return") t.Fatal("double Close() test failed: second Close() call didn't return")
} }

View File

@ -18,8 +18,9 @@ func abortf(format string, a ...interface{}) {
os.Exit(1) os.Exit(1)
} }
func abortErrNo(funcname string, err int) { func abortErrNo(funcname string, err error) {
abortf("%s failed: %d %s\n", funcname, err, syscall.Errstr(err)) errno, _ := err.(syscall.Errno)
abortf("%s failed: %d %s\n", funcname, uint32(errno), err)
} }
// global vars // global vars
@ -33,7 +34,7 @@ var (
func WndProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) (rc uintptr) { func WndProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) (rc uintptr) {
switch msg { switch msg {
case WM_CREATE: case WM_CREATE:
var e int var e error
// CreateWindowEx // CreateWindowEx
bh, e = CreateWindowEx( bh, e = CreateWindowEx(
0, 0,
@ -42,7 +43,7 @@ func WndProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) (rc uintpt
WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON, WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,
75, 70, 140, 25, 75, 70, 140, 25,
hwnd, 1, mh, 0) hwnd, 1, mh, 0)
if e != 0 { if e != nil {
abortErrNo("CreateWindowEx", e) abortErrNo("CreateWindowEx", e)
} }
fmt.Printf("button handle is %x\n", bh) fmt.Printf("button handle is %x\n", bh)
@ -51,7 +52,7 @@ func WndProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) (rc uintpt
switch syscall.Handle(lparam) { switch syscall.Handle(lparam) {
case bh: case bh:
e := PostMessage(hwnd, WM_CLOSE, 0, 0) e := PostMessage(hwnd, WM_CLOSE, 0, 0)
if e != 0 { if e != nil {
abortErrNo("PostMessage", e) abortErrNo("PostMessage", e)
} }
default: default:
@ -69,23 +70,23 @@ func WndProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) (rc uintpt
} }
func rungui() int { func rungui() int {
var e int var e error
// GetModuleHandle // GetModuleHandle
mh, e = GetModuleHandle(nil) mh, e = GetModuleHandle(nil)
if e != 0 { if e != nil {
abortErrNo("GetModuleHandle", e) abortErrNo("GetModuleHandle", e)
} }
// Get icon we're going to use. // Get icon we're going to use.
myicon, e := LoadIcon(0, IDI_APPLICATION) myicon, e := LoadIcon(0, IDI_APPLICATION)
if e != 0 { if e != nil {
abortErrNo("LoadIcon", e) abortErrNo("LoadIcon", e)
} }
// Get cursor we're going to use. // Get cursor we're going to use.
mycursor, e := LoadCursor(0, IDC_ARROW) mycursor, e := LoadCursor(0, IDC_ARROW)
if e != 0 { if e != nil {
abortErrNo("LoadCursor", e) abortErrNo("LoadCursor", e)
} }
@ -104,7 +105,7 @@ func rungui() int {
wc.MenuName = nil wc.MenuName = nil
wc.ClassName = wcname wc.ClassName = wcname
wc.IconSm = myicon wc.IconSm = myicon
if _, e := RegisterClassEx(&wc); e != 0 { if _, e := RegisterClassEx(&wc); e != nil {
abortErrNo("RegisterClassEx", e) abortErrNo("RegisterClassEx", e)
} }
@ -116,7 +117,7 @@ func rungui() int {
WS_OVERLAPPEDWINDOW, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 300, 200, CW_USEDEFAULT, CW_USEDEFAULT, 300, 200,
0, 0, mh, 0) 0, 0, mh, 0)
if e != 0 { if e != nil {
abortErrNo("CreateWindowEx", e) abortErrNo("CreateWindowEx", e)
} }
fmt.Printf("main window handle is %x\n", wh) fmt.Printf("main window handle is %x\n", wh)
@ -125,7 +126,7 @@ func rungui() int {
ShowWindow(wh, SW_SHOWDEFAULT) ShowWindow(wh, SW_SHOWDEFAULT)
// UpdateWindow // UpdateWindow
if e := UpdateWindow(wh); e != 0 { if e := UpdateWindow(wh); e != nil {
abortErrNo("UpdateWindow", e) abortErrNo("UpdateWindow", e)
} }
@ -133,7 +134,7 @@ func rungui() int {
var m Msg var m Msg
for { for {
r, e := GetMessage(&m, 0, 0, 0) r, e := GetMessage(&m, 0, 0, 0)
if e != 0 { if e != nil {
abortErrNo("GetMessage", e) abortErrNo("GetMessage", e)
} }
if r == 0 { if r == 0 {

View File

@ -110,22 +110,22 @@ var (
IDI_INFORMATION = IDI_ASTERISK IDI_INFORMATION = IDI_ASTERISK
) )
//sys GetModuleHandle(modname *uint16) (handle syscall.Handle, errno int) = GetModuleHandleW //sys GetModuleHandle(modname *uint16) (handle syscall.Handle, err error) = GetModuleHandleW
//sys RegisterClassEx(wndclass *Wndclassex) (atom uint16, errno int) = user32.RegisterClassExW //sys RegisterClassEx(wndclass *Wndclassex) (atom uint16, err error) = user32.RegisterClassExW
//sys CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style uint32, x int32, y int32, width int32, height int32, wndparent syscall.Handle, menu syscall.Handle, instance syscall.Handle, param uintptr) (hwnd syscall.Handle, errno int) = user32.CreateWindowExW //sys CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style uint32, x int32, y int32, width int32, height int32, wndparent syscall.Handle, menu syscall.Handle, instance syscall.Handle, param uintptr) (hwnd syscall.Handle, err error) = user32.CreateWindowExW
//sys DefWindowProc(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (lresult uintptr) = user32.DefWindowProcW //sys DefWindowProc(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (lresult uintptr) = user32.DefWindowProcW
//sys DestroyWindow(hwnd syscall.Handle) (errno int) = user32.DestroyWindow //sys DestroyWindow(hwnd syscall.Handle) (err error) = user32.DestroyWindow
//sys PostQuitMessage(exitcode int32) = user32.PostQuitMessage //sys PostQuitMessage(exitcode int32) = user32.PostQuitMessage
//sys ShowWindow(hwnd syscall.Handle, cmdshow int32) (wasvisible bool) = user32.ShowWindow //sys ShowWindow(hwnd syscall.Handle, cmdshow int32) (wasvisible bool) = user32.ShowWindow
//sys UpdateWindow(hwnd syscall.Handle) (errno int) = user32.UpdateWindow //sys UpdateWindow(hwnd syscall.Handle) (err error) = user32.UpdateWindow
//sys GetMessage(msg *Msg, hwnd syscall.Handle, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, errno int) [failretval==-1] = user32.GetMessageW //sys GetMessage(msg *Msg, hwnd syscall.Handle, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, err error) [failretval==-1] = user32.GetMessageW
//sys TranslateMessage(msg *Msg) (done bool) = user32.TranslateMessage //sys TranslateMessage(msg *Msg) (done bool) = user32.TranslateMessage
//sys DispatchMessage(msg *Msg) (ret int32) = user32.DispatchMessageW //sys DispatchMessage(msg *Msg) (ret int32) = user32.DispatchMessageW
//sys LoadIcon(instance syscall.Handle, iconname *uint16) (icon syscall.Handle, errno int) = user32.LoadIconW //sys LoadIcon(instance syscall.Handle, iconname *uint16) (icon syscall.Handle, err error) = user32.LoadIconW
//sys LoadCursor(instance syscall.Handle, cursorname *uint16) (cursor syscall.Handle, errno int) = user32.LoadCursorW //sys LoadCursor(instance syscall.Handle, cursorname *uint16) (cursor syscall.Handle, err error) = user32.LoadCursorW
//sys SetCursor(cursor syscall.Handle) (precursor syscall.Handle, errno int) = user32.SetCursor //sys SetCursor(cursor syscall.Handle) (precursor syscall.Handle, err error) = user32.SetCursor
//sys SendMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (lresult uintptr) = user32.SendMessageW //sys SendMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (lresult uintptr) = user32.SendMessageW
//sys PostMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (errno int) = user32.PostMessageW //sys PostMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (err error) = user32.PostMessageW
func MakeIntResource(id uint16) *uint16 { func MakeIntResource(id uint16) *uint16 {
return (*uint16)(unsafe.Pointer(uintptr(id))) return (*uint16)(unsafe.Pointer(uintptr(id)))

View File

@ -28,47 +28,41 @@ var (
procPostMessageW = moduser32.NewProc("PostMessageW") procPostMessageW = moduser32.NewProc("PostMessageW")
) )
func GetModuleHandle(modname *uint16) (handle syscall.Handle, errno int) { func GetModuleHandle(modname *uint16) (handle syscall.Handle, err error) {
r0, _, e1 := syscall.Syscall(procGetModuleHandleW.Addr(), 1, uintptr(unsafe.Pointer(modname)), 0, 0) r0, _, e1 := syscall.Syscall(procGetModuleHandleW.Addr(), 1, uintptr(unsafe.Pointer(modname)), 0, 0)
handle = syscall.Handle(r0) handle = syscall.Handle(r0)
if handle == 0 { if handle == 0 {
if e1 != 0 { if e1 != 0 {
errno = int(e1) err = error(e1)
} else { } else {
errno = syscall.EINVAL err = syscall.EINVAL
} }
} else {
errno = 0
} }
return return
} }
func RegisterClassEx(wndclass *Wndclassex) (atom uint16, errno int) { func RegisterClassEx(wndclass *Wndclassex) (atom uint16, err error) {
r0, _, e1 := syscall.Syscall(procRegisterClassExW.Addr(), 1, uintptr(unsafe.Pointer(wndclass)), 0, 0) r0, _, e1 := syscall.Syscall(procRegisterClassExW.Addr(), 1, uintptr(unsafe.Pointer(wndclass)), 0, 0)
atom = uint16(r0) atom = uint16(r0)
if atom == 0 { if atom == 0 {
if e1 != 0 { if e1 != 0 {
errno = int(e1) err = error(e1)
} else { } else {
errno = syscall.EINVAL err = syscall.EINVAL
} }
} else {
errno = 0
} }
return return
} }
func CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style uint32, x int32, y int32, width int32, height int32, wndparent syscall.Handle, menu syscall.Handle, instance syscall.Handle, param uintptr) (hwnd syscall.Handle, errno int) { func CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style uint32, x int32, y int32, width int32, height int32, wndparent syscall.Handle, menu syscall.Handle, instance syscall.Handle, param uintptr) (hwnd syscall.Handle, err error) {
r0, _, e1 := syscall.Syscall12(procCreateWindowExW.Addr(), 12, uintptr(exstyle), uintptr(unsafe.Pointer(classname)), uintptr(unsafe.Pointer(windowname)), uintptr(style), uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(wndparent), uintptr(menu), uintptr(instance), uintptr(param)) r0, _, e1 := syscall.Syscall12(procCreateWindowExW.Addr(), 12, uintptr(exstyle), uintptr(unsafe.Pointer(classname)), uintptr(unsafe.Pointer(windowname)), uintptr(style), uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(wndparent), uintptr(menu), uintptr(instance), uintptr(param))
hwnd = syscall.Handle(r0) hwnd = syscall.Handle(r0)
if hwnd == 0 { if hwnd == 0 {
if e1 != 0 { if e1 != 0 {
errno = int(e1) err = error(e1)
} else { } else {
errno = syscall.EINVAL err = syscall.EINVAL
} }
} else {
errno = 0
} }
return return
} }
@ -79,16 +73,14 @@ func DefWindowProc(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintp
return return
} }
func DestroyWindow(hwnd syscall.Handle) (errno int) { func DestroyWindow(hwnd syscall.Handle) (err error) {
r1, _, e1 := syscall.Syscall(procDestroyWindow.Addr(), 1, uintptr(hwnd), 0, 0) r1, _, e1 := syscall.Syscall(procDestroyWindow.Addr(), 1, uintptr(hwnd), 0, 0)
if int(r1) == 0 { if int(r1) == 0 {
if e1 != 0 { if e1 != 0 {
errno = int(e1) err = error(e1)
} else { } else {
errno = syscall.EINVAL err = syscall.EINVAL
} }
} else {
errno = 0
} }
return return
} }
@ -104,31 +96,27 @@ func ShowWindow(hwnd syscall.Handle, cmdshow int32) (wasvisible bool) {
return return
} }
func UpdateWindow(hwnd syscall.Handle) (errno int) { func UpdateWindow(hwnd syscall.Handle) (err error) {
r1, _, e1 := syscall.Syscall(procUpdateWindow.Addr(), 1, uintptr(hwnd), 0, 0) r1, _, e1 := syscall.Syscall(procUpdateWindow.Addr(), 1, uintptr(hwnd), 0, 0)
if int(r1) == 0 { if int(r1) == 0 {
if e1 != 0 { if e1 != 0 {
errno = int(e1) err = error(e1)
} else { } else {
errno = syscall.EINVAL err = syscall.EINVAL
} }
} else {
errno = 0
} }
return return
} }
func GetMessage(msg *Msg, hwnd syscall.Handle, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, errno int) { func GetMessage(msg *Msg, hwnd syscall.Handle, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, err error) {
r0, _, e1 := syscall.Syscall6(procGetMessageW.Addr(), 4, uintptr(unsafe.Pointer(msg)), uintptr(hwnd), uintptr(MsgFilterMin), uintptr(MsgFilterMax), 0, 0) r0, _, e1 := syscall.Syscall6(procGetMessageW.Addr(), 4, uintptr(unsafe.Pointer(msg)), uintptr(hwnd), uintptr(MsgFilterMin), uintptr(MsgFilterMax), 0, 0)
ret = int32(r0) ret = int32(r0)
if ret == -1 { if ret == -1 {
if e1 != 0 { if e1 != 0 {
errno = int(e1) err = error(e1)
} else { } else {
errno = syscall.EINVAL err = syscall.EINVAL
} }
} else {
errno = 0
} }
return return
} }
@ -145,47 +133,41 @@ func DispatchMessage(msg *Msg) (ret int32) {
return return
} }
func LoadIcon(instance syscall.Handle, iconname *uint16) (icon syscall.Handle, errno int) { func LoadIcon(instance syscall.Handle, iconname *uint16) (icon syscall.Handle, err error) {
r0, _, e1 := syscall.Syscall(procLoadIconW.Addr(), 2, uintptr(instance), uintptr(unsafe.Pointer(iconname)), 0) r0, _, e1 := syscall.Syscall(procLoadIconW.Addr(), 2, uintptr(instance), uintptr(unsafe.Pointer(iconname)), 0)
icon = syscall.Handle(r0) icon = syscall.Handle(r0)
if icon == 0 { if icon == 0 {
if e1 != 0 { if e1 != 0 {
errno = int(e1) err = error(e1)
} else { } else {
errno = syscall.EINVAL err = syscall.EINVAL
} }
} else {
errno = 0
} }
return return
} }
func LoadCursor(instance syscall.Handle, cursorname *uint16) (cursor syscall.Handle, errno int) { func LoadCursor(instance syscall.Handle, cursorname *uint16) (cursor syscall.Handle, err error) {
r0, _, e1 := syscall.Syscall(procLoadCursorW.Addr(), 2, uintptr(instance), uintptr(unsafe.Pointer(cursorname)), 0) r0, _, e1 := syscall.Syscall(procLoadCursorW.Addr(), 2, uintptr(instance), uintptr(unsafe.Pointer(cursorname)), 0)
cursor = syscall.Handle(r0) cursor = syscall.Handle(r0)
if cursor == 0 { if cursor == 0 {
if e1 != 0 { if e1 != 0 {
errno = int(e1) err = error(e1)
} else { } else {
errno = syscall.EINVAL err = syscall.EINVAL
} }
} else {
errno = 0
} }
return return
} }
func SetCursor(cursor syscall.Handle) (precursor syscall.Handle, errno int) { func SetCursor(cursor syscall.Handle) (precursor syscall.Handle, err error) {
r0, _, e1 := syscall.Syscall(procSetCursor.Addr(), 1, uintptr(cursor), 0, 0) r0, _, e1 := syscall.Syscall(procSetCursor.Addr(), 1, uintptr(cursor), 0, 0)
precursor = syscall.Handle(r0) precursor = syscall.Handle(r0)
if precursor == 0 { if precursor == 0 {
if e1 != 0 { if e1 != 0 {
errno = int(e1) err = error(e1)
} else { } else {
errno = syscall.EINVAL err = syscall.EINVAL
} }
} else {
errno = 0
} }
return return
} }
@ -196,16 +178,14 @@ func SendMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr
return return
} }
func PostMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (errno int) { func PostMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (err error) {
r1, _, e1 := syscall.Syscall6(procPostMessageW.Addr(), 4, uintptr(hwnd), uintptr(msg), uintptr(wparam), uintptr(lparam), 0, 0) r1, _, e1 := syscall.Syscall6(procPostMessageW.Addr(), 4, uintptr(hwnd), uintptr(msg), uintptr(wparam), uintptr(lparam), 0, 0)
if int(r1) == 0 { if int(r1) == 0 {
if e1 != 0 { if e1 != 0 {
errno = int(e1) err = error(e1)
} else { } else {
errno = syscall.EINVAL err = syscall.EINVAL
} }
} else {
errno = 0
} }
return return
} }

View File

@ -193,7 +193,7 @@ func (f Func) String() string {
var vars map[string]Var = make(map[string]Var) var vars map[string]Var = make(map[string]Var)
var mutex sync.Mutex var mutex sync.Mutex
// Publish declares an named exported variable. This should be called from a // Publish declares a named exported variable. This should be called from a
// package's init function when it creates its Vars. If the name is already // package's init function when it creates its Vars. If the name is already
// registered then this will log.Panic. // registered then this will log.Panic.
func Publish(name string, v Var) { func Publish(name string, v Var) {

View File

@ -813,3 +813,37 @@ func TestPanics(t *testing.T) {
} }
} }
} }
// Test that erroneous String routine doesn't cause fatal recursion.
var recurCount = 0
type Recur struct {
i int
failed *bool
}
func (r Recur) String() string {
if recurCount++; recurCount > 10 {
*r.failed = true
return "FAIL"
}
// This will call badVerb. Before the fix, that would cause us to recur into
// this routine to print %!p(value). Now we don't call the user's method
// during an error.
return Sprintf("recur@%p value: %d", r, r.i)
}
func TestBadVerbRecursion(t *testing.T) {
failed := false
r := Recur{3, &failed}
Sprintf("recur@%p value: %d\n", &r, r.i)
if failed {
t.Error("fail with pointer")
}
failed = false
r = Recur{4, &failed}
Sprintf("recur@%p, value: %d\n", r, r.i)
if failed {
t.Error("fail with value")
}
}

View File

@ -331,9 +331,9 @@ func (f *fmt) fmt_q(s string) {
func (f *fmt) fmt_qc(c int64) { func (f *fmt) fmt_qc(c int64) {
var quoted string var quoted string
if f.plus { if f.plus {
quoted = strconv.QuoteRuneToASCII(int(c)) quoted = strconv.QuoteRuneToASCII(rune(c))
} else { } else {
quoted = strconv.QuoteRune(int(c)) quoted = strconv.QuoteRune(rune(c))
} }
f.padString(quoted) f.padString(quoted)
} }

View File

@ -74,6 +74,7 @@ type GoStringer interface {
type pp struct { type pp struct {
n int n int
panicking bool panicking bool
erroring bool // printing an error condition
buf bytes.Buffer buf bytes.Buffer
// field holds the current item, as an interface{}. // field holds the current item, as an interface{}.
field interface{} field interface{}
@ -124,6 +125,7 @@ var ppFree = newCache(func() interface{} { return new(pp) })
func newPrinter() *pp { func newPrinter() *pp {
p := ppFree.get().(*pp) p := ppFree.get().(*pp)
p.panicking = false p.panicking = false
p.erroring = false
p.fmt.init(&p.buf) p.fmt.init(&p.buf)
return p return p
} }
@ -299,6 +301,7 @@ func (p *pp) unknownType(v interface{}) {
} }
func (p *pp) badVerb(verb rune) { func (p *pp) badVerb(verb rune) {
p.erroring = true
p.add('%') p.add('%')
p.add('!') p.add('!')
p.add(verb) p.add(verb)
@ -316,6 +319,7 @@ func (p *pp) badVerb(verb rune) {
p.buf.Write(nilAngleBytes) p.buf.Write(nilAngleBytes)
} }
p.add(')') p.add(')')
p.erroring = false
} }
func (p *pp) fmtBool(v bool, verb rune) { func (p *pp) fmtBool(v bool, verb rune) {
@ -606,6 +610,9 @@ func (p *pp) catchPanic(field interface{}, verb rune) {
} }
func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString, handled bool) { func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString, handled bool) {
if p.erroring {
return
}
// Is it a Formatter? // Is it a Formatter?
if formatter, ok := p.field.(Formatter); ok { if formatter, ok := p.field.(Formatter); ok {
handled = true handled = true

View File

@ -56,6 +56,7 @@ var (
stringVal string stringVal string
stringVal1 string stringVal1 string
bytesVal []byte bytesVal []byte
runeVal rune
complex64Val complex64 complex64Val complex64
complex128Val complex128 complex128Val complex128
renamedBoolVal renamedBool renamedBoolVal renamedBool
@ -225,9 +226,9 @@ var scanfTests = []ScanfTest{
{"%v", "0377\n", &intVal, 0377}, {"%v", "0377\n", &intVal, 0377},
{"%v", "0x44\n", &intVal, 0x44}, {"%v", "0x44\n", &intVal, 0x44},
{"%d", "72\n", &intVal, 72}, {"%d", "72\n", &intVal, 72},
{"%c", "a\n", &intVal, 'a'}, {"%c", "a\n", &runeVal, 'a'},
{"%c", "\u5072\n", &intVal, 0x5072}, {"%c", "\u5072\n", &runeVal, '\u5072'},
{"%c", "\u1234\n", &intVal, '\u1234'}, {"%c", "\u1234\n", &runeVal, '\u1234'},
{"%d", "73\n", &int8Val, int8(73)}, {"%d", "73\n", &int8Val, int8(73)},
{"%d", "+74\n", &int16Val, int16(74)}, {"%d", "+74\n", &int16Val, int16(74)},
{"%d", "75\n", &int32Val, int32(75)}, {"%d", "75\n", &int32Val, int32(75)},
@ -322,6 +323,7 @@ var s, t string
var c complex128 var c complex128
var x, y Xs var x, y Xs
var z IntString var z IntString
var r1, r2, r3 rune
var multiTests = []ScanfMultiTest{ var multiTests = []ScanfMultiTest{
{"", "", []interface{}{}, []interface{}{}, ""}, {"", "", []interface{}{}, []interface{}{}, ""},
@ -333,7 +335,7 @@ var multiTests = []ScanfMultiTest{
{"%3d22%3d", "33322333", args(&i, &j), args(333, 333), ""}, {"%3d22%3d", "33322333", args(&i, &j), args(333, 333), ""},
{"%6vX=%3fY", "3+2iX=2.5Y", args(&c, &f), args((3 + 2i), 2.5), ""}, {"%6vX=%3fY", "3+2iX=2.5Y", args(&c, &f), args((3 + 2i), 2.5), ""},
{"%d%s", "123abc", args(&i, &s), args(123, "abc"), ""}, {"%d%s", "123abc", args(&i, &s), args(123, "abc"), ""},
{"%c%c%c", "2\u50c2X", args(&i, &j, &k), args('2', '\u50c2', 'X'), ""}, {"%c%c%c", "2\u50c2X", args(&r1, &r2, &r3), args('2', '\u50c2', 'X'), ""},
// Custom scanners. // Custom scanners.
{"%e%f", "eefffff", args(&x, &y), args(Xs("ee"), Xs("fffff")), ""}, {"%e%f", "eefffff", args(&x, &y), args(Xs("ee"), Xs("fffff")), ""},
@ -347,7 +349,7 @@ var multiTests = []ScanfMultiTest{
{"X%d", "10X", args(&intVal), nil, "input does not match format"}, {"X%d", "10X", args(&intVal), nil, "input does not match format"},
// Bad UTF-8: should see every byte. // Bad UTF-8: should see every byte.
{"%c%c%c", "\xc2X\xc2", args(&i, &j, &k), args(utf8.RuneError, 'X', utf8.RuneError), ""}, {"%c%c%c", "\xc2X\xc2", args(&r1, &r2, &r3), args(utf8.RuneError, 'X', utf8.RuneError), ""},
} }
func testScan(name string, t *testing.T, scan func(r io.Reader, a ...interface{}) (int, error)) { func testScan(name string, t *testing.T, scan func(r io.Reader, a ...interface{}) (int, error)) {

View File

@ -466,7 +466,7 @@ func splitQuoted(s string) (r []string, err error) {
arg := make([]rune, len(s)) arg := make([]rune, len(s))
escaped := false escaped := false
quoted := false quoted := false
quote := rune(0) quote := '\x00'
i := 0 i := 0
for _, rune := range s { for _, rune := range s {
switch { switch {
@ -475,9 +475,9 @@ func splitQuoted(s string) (r []string, err error) {
case rune == '\\': case rune == '\\':
escaped = true escaped = true
continue continue
case quote != 0: case quote != '\x00':
if rune == quote { if rune == quote {
quote = 0 quote = '\x00'
continue continue
} }
case rune == '"' || rune == '\'': case rune == '"' || rune == '\'':

View File

@ -281,7 +281,20 @@ func heading(line string) string {
return line return line
} }
// Convert comment text to formatted HTML. type op int
const (
opPara op = iota
opHead
opPre
)
type block struct {
op op
lines []string
}
// ToHTML converts comment text to formatted HTML.
// The comment was prepared by DocReader, // The comment was prepared by DocReader,
// so it is known not to have leading, trailing blank lines // so it is known not to have leading, trailing blank lines
// nor to have trailing spaces at the end of lines. // nor to have trailing spaces at the end of lines.
@ -299,20 +312,43 @@ func heading(line string) string {
// map value is not the empty string, it is considered a URL and the word is converted // map value is not the empty string, it is considered a URL and the word is converted
// into a link. // into a link.
func ToHTML(w io.Writer, text string, words map[string]string) { func ToHTML(w io.Writer, text string, words map[string]string) {
inpara := false for _, b := range blocks(text) {
lastWasBlank := false switch b.op {
lastWasHeading := false case opPara:
w.Write(html_p)
close := func() { for _, line := range b.lines {
if inpara { emphasize(w, line, words, true)
}
w.Write(html_endp) w.Write(html_endp)
inpara = false case opHead:
w.Write(html_h)
for _, line := range b.lines {
commentEscape(w, line, true)
}
w.Write(html_endh)
case opPre:
w.Write(html_pre)
for _, line := range b.lines {
emphasize(w, line, nil, false)
}
w.Write(html_endpre)
} }
} }
open := func() { }
if !inpara {
w.Write(html_p) func blocks(text string) []block {
inpara = true var (
out []block
para []string
lastWasBlank = false
lastWasHeading = false
)
close := func() {
if para != nil {
out = append(out, block{opPara, para})
para = nil
} }
} }
@ -340,17 +376,13 @@ func ToHTML(w io.Writer, text string, words map[string]string) {
for j > i && isBlank(lines[j-1]) { for j > i && isBlank(lines[j-1]) {
j-- j--
} }
block := lines[i:j] pre := lines[i:j]
i = j i = j
unindent(block) unindent(pre)
// put those lines in a pre block // put those lines in a pre block
w.Write(html_pre) out = append(out, block{opPre, pre})
for _, line := range block {
emphasize(w, line, nil, false) // no nice text formatting
}
w.Write(html_endpre)
lastWasHeading = false lastWasHeading = false
continue continue
} }
@ -362,9 +394,7 @@ func ToHTML(w io.Writer, text string, words map[string]string) {
// might be a heading. // might be a heading.
if head := heading(line); head != "" { if head := heading(line); head != "" {
close() close()
w.Write(html_h) out = append(out, block{opHead, []string{head}})
commentEscape(w, head, true) // nice text formatting
w.Write(html_endh)
i += 2 i += 2
lastWasHeading = true lastWasHeading = true
continue continue
@ -372,11 +402,95 @@ func ToHTML(w io.Writer, text string, words map[string]string) {
} }
// open paragraph // open paragraph
open()
lastWasBlank = false lastWasBlank = false
lastWasHeading = false lastWasHeading = false
emphasize(w, lines[i], words, true) // nice text formatting para = append(para, lines[i])
i++ i++
} }
close() close()
return out
}
// ToText prepares comment text for presentation in textual output.
// It wraps paragraphs of text to width or fewer Unicode code points
// and then prefixes each line with the indent. In preformatted sections
// (such as program text), it prefixes each non-blank line with preIndent.
func ToText(w io.Writer, text string, indent, preIndent string, width int) {
l := lineWrapper{
out: w,
width: width,
indent: indent,
}
for i, b := range blocks(text) {
switch b.op {
case opPara:
if i > 0 {
w.Write(nl)
}
for _, line := range b.lines {
l.write(line)
}
l.flush()
case opHead:
w.Write(nl)
for _, line := range b.lines {
l.write(line + "\n")
}
l.flush()
case opPre:
w.Write(nl)
for _, line := range b.lines {
if !isBlank(line) {
w.Write([]byte(preIndent))
w.Write([]byte(line))
}
}
}
}
}
type lineWrapper struct {
out io.Writer
printed bool
width int
indent string
n int
pendSpace int
}
var nl = []byte("\n")
var space = []byte(" ")
func (l *lineWrapper) write(text string) {
if l.n == 0 && l.printed {
l.out.Write(nl) // blank line before new paragraph
}
l.printed = true
for _, f := range strings.Fields(text) {
w := utf8.RuneCountInString(f)
// wrap if line is too long
if l.n > 0 && l.n+l.pendSpace+w > l.width {
l.out.Write(nl)
l.n = 0
l.pendSpace = 0
}
if l.n == 0 {
l.out.Write([]byte(l.indent))
}
l.out.Write(space[:l.pendSpace])
l.out.Write([]byte(f))
l.n += l.pendSpace + w
l.pendSpace = 1
}
}
func (l *lineWrapper) flush() {
if l.n == 0 {
return
}
l.out.Write(nl)
l.pendSpace = 0
l.n = 0
} }

View File

@ -5,6 +5,7 @@
package doc package doc
import ( import (
"reflect"
"testing" "testing"
) )
@ -38,3 +39,45 @@ func TestIsHeading(t *testing.T) {
} }
} }
} }
var blocksTests = []struct {
in string
out []block
}{
{
in: `Para 1.
Para 1 line 2.
Para 2.
Section
Para 3.
pre
pre1
Para 4.
pre
pre2
`,
out: []block{
{opPara, []string{"Para 1.\n", "Para 1 line 2.\n"}},
{opPara, []string{"Para 2.\n"}},
{opHead, []string{"Section"}},
{opPara, []string{"Para 3.\n"}},
{opPre, []string{"pre\n", "pre1\n"}},
{opPara, []string{"Para 4.\n"}},
{opPre, []string{"pre\n", "pre2\n"}},
},
},
}
func TestBlocks(t *testing.T) {
for i, tt := range blocksTests {
b := blocks(tt.in)
if !reflect.DeepEqual(b, tt.out) {
t.Errorf("#%d: mismatch\nhave: %v\nwant: %v", i, b, tt.out)
}
}
}

View File

@ -8,15 +8,16 @@ package doc
import ( import (
"go/ast" "go/ast"
"go/printer"
"strings" "strings"
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
) )
type Example struct { type Example struct {
Name string // name of the item being demonstrated Name string // name of the item being demonstrated
Body *ast.BlockStmt // code Body *printer.CommentedNode // code
Output string // expected output Output string // expected output
} }
func Examples(pkg *ast.Package) []*Example { func Examples(pkg *ast.Package) []*Example {
@ -33,7 +34,7 @@ func Examples(pkg *ast.Package) []*Example {
} }
examples = append(examples, &Example{ examples = append(examples, &Example{
Name: name[len("Example"):], Name: name[len("Example"):],
Body: f.Body, Body: &printer.CommentedNode{f.Body, src.Comments},
Output: CommentText(f.Doc), Output: CommentText(f.Doc),
}) })
} }

View File

@ -807,13 +807,75 @@ func (p *printer) flush(next token.Position, tok token.Token) (droppedFF bool) {
return return
} }
// getNode returns the ast.CommentGroup associated with n, if any.
func getDoc(n ast.Node) *ast.CommentGroup {
switch n := n.(type) {
// *ast.Fields cannot be printed separately - ignore for now
case *ast.ImportSpec:
return n.Doc
case *ast.ValueSpec:
return n.Doc
case *ast.TypeSpec:
return n.Doc
case *ast.GenDecl:
return n.Doc
case *ast.FuncDecl:
return n.Doc
case *ast.File:
return n.Doc
}
return nil
}
func (p *printer) printNode(node interface{}) error { func (p *printer) printNode(node interface{}) error {
// unpack *CommentedNode, if any
var comments []*ast.CommentGroup
if cnode, ok := node.(*CommentedNode); ok {
node = cnode.Node
comments = cnode.Comments
}
if comments != nil {
// commented node - restrict comment list to relevant range
n, ok := node.(ast.Node)
if !ok {
goto unsupported
}
beg := n.Pos()
end := n.End()
// if the node has associated documentation,
// include that commentgroup in the range
// (the comment list is sorted in the order
// of the comment appearance in the source code)
if doc := getDoc(n); doc != nil {
beg = doc.Pos()
}
// token.Pos values are global offsets, we can
// compare them directly
i := 0
for i < len(comments) && comments[i].End() < beg {
i++
}
j := i
for j < len(comments) && comments[j].Pos() < end {
j++
}
if i < j {
p.comments = comments[i:j]
}
} else if n, ok := node.(*ast.File); ok {
// use ast.File comments, if any
p.comments = n.Comments
}
// if there are no comments, use node comments
p.useNodeComments = p.comments == nil
// format node
switch n := node.(type) { switch n := node.(type) {
case ast.Expr: case ast.Expr:
p.useNodeComments = true
p.expr(n, ignoreMultiLine) p.expr(n, ignoreMultiLine)
case ast.Stmt: case ast.Stmt:
p.useNodeComments = true
// A labeled statement will un-indent to position the // A labeled statement will un-indent to position the
// label. Set indent to 1 so we don't get indent "underflow". // label. Set indent to 1 so we don't get indent "underflow".
if _, labeledStmt := n.(*ast.LabeledStmt); labeledStmt { if _, labeledStmt := n.(*ast.LabeledStmt); labeledStmt {
@ -821,19 +883,19 @@ func (p *printer) printNode(node interface{}) error {
} }
p.stmt(n, false, ignoreMultiLine) p.stmt(n, false, ignoreMultiLine)
case ast.Decl: case ast.Decl:
p.useNodeComments = true
p.decl(n, ignoreMultiLine) p.decl(n, ignoreMultiLine)
case ast.Spec: case ast.Spec:
p.useNodeComments = true
p.spec(n, 1, false, ignoreMultiLine) p.spec(n, 1, false, ignoreMultiLine)
case *ast.File: case *ast.File:
p.comments = n.Comments
p.useNodeComments = n.Comments == nil
p.file(n) p.file(n)
default: default:
return fmt.Errorf("go/printer: unsupported node type %T", n) goto unsupported
} }
return nil return nil
unsupported:
return fmt.Errorf("go/printer: unsupported node type %T", node)
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -1001,10 +1063,18 @@ func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node interface{
return return
} }
// A CommentedNode bundles an AST node and corresponding comments.
// It may be provided as argument to any of the FPrint functions.
//
type CommentedNode struct {
Node interface{} // *ast.File, or ast.Expr, ast.Decl, ast.Spec, or ast.Stmt
Comments []*ast.CommentGroup
}
// Fprint "pretty-prints" an AST node to output for a given configuration cfg. // Fprint "pretty-prints" an AST node to output for a given configuration cfg.
// Position information is interpreted relative to the file set fset. // Position information is interpreted relative to the file set fset.
// The node type must be *ast.File, or assignment-compatible to ast.Expr, // The node type must be *ast.File, *CommentedNode, or assignment-compatible
// ast.Decl, ast.Spec, or ast.Stmt. // to ast.Expr, ast.Decl, ast.Spec, or ast.Stmt.
// //
func (cfg *Config) Fprint(output io.Writer, fset *token.FileSet, node interface{}) error { func (cfg *Config) Fprint(output io.Writer, fset *token.FileSet, node interface{}) error {
return cfg.fprint(output, fset, node, make(map[ast.Node]int)) return cfg.fprint(output, fset, node, make(map[ast.Node]int))

View File

@ -107,7 +107,7 @@ func check(t *testing.T, source, golden string, mode checkMode) {
// start a timer to produce a time-out signal // start a timer to produce a time-out signal
tc := make(chan int) tc := make(chan int)
go func() { go func() {
time.Sleep(10e9) // plenty of a safety margin, even for very slow machines time.Sleep(10 * time.Second) // plenty of a safety margin, even for very slow machines
tc <- 0 tc <- 0
}() }()

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build 386 arm
package crc32 package crc32
// The file contains the generic version of updateCastagnoli which just calls // The file contains the generic version of updateCastagnoli which just calls

View File

@ -4,7 +4,7 @@
package html package html
// Section 11.2.3.2 of the HTML5 specification says "The following elements // Section 12.2.3.2 of the HTML5 specification says "The following elements
// have varying levels of special parsing rules". // have varying levels of special parsing rules".
// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#the-stack-of-open-elements // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#the-stack-of-open-elements
var isSpecialElement = map[string]bool{ var isSpecialElement = map[string]bool{

View File

@ -78,7 +78,7 @@ func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) {
i++ i++
} }
x := rune(0) x := '\x00'
for i < len(s) { for i < len(s) {
c = s[i] c = s[i]
i++ i++

56
libgo/go/html/foreign.go Normal file
View File

@ -0,0 +1,56 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package html
// Section 12.2.5.5.
var breakout = map[string]bool{
"b": true,
"big": true,
"blockquote": true,
"body": true,
"br": true,
"center": true,
"code": true,
"dd": true,
"div": true,
"dl": true,
"dt": true,
"em": true,
"embed": true,
"font": true,
"h1": true,
"h2": true,
"h3": true,
"h4": true,
"h5": true,
"h6": true,
"head": true,
"hr": true,
"i": true,
"img": true,
"li": true,
"listing": true,
"menu": true,
"meta": true,
"nobr": true,
"ol": true,
"p": true,
"pre": true,
"ruby": true,
"s": true,
"small": true,
"span": true,
"strong": true,
"strike": true,
"sub": true,
"sup": true,
"table": true,
"tt": true,
"u": true,
"ul": true,
"var": true,
}
// TODO: add look-up tables for MathML and SVG adjustments.

View File

@ -17,21 +17,22 @@ const (
scopeMarkerNode scopeMarkerNode
) )
// Section 11.2.3.3 says "scope markers are inserted when entering applet // Section 12.2.3.3 says "scope markers are inserted when entering applet
// elements, buttons, object elements, marquees, table cells, and table // elements, buttons, object elements, marquees, table cells, and table
// captions, and are used to prevent formatting from 'leaking'". // captions, and are used to prevent formatting from 'leaking'".
var scopeMarker = Node{Type: scopeMarkerNode} var scopeMarker = Node{Type: scopeMarkerNode}
// A Node consists of a NodeType and some Data (tag name for element nodes, // A Node consists of a NodeType and some Data (tag name for element nodes,
// content for text) and are part of a tree of Nodes. Element nodes may also // content for text) and are part of a tree of Nodes. Element nodes may also
// contain a slice of Attributes. Data is unescaped, so that it looks like // have a Namespace and contain a slice of Attributes. Data is unescaped, so
// "a<b" rather than "a&lt;b". // that it looks like "a<b" rather than "a&lt;b".
type Node struct { type Node struct {
Parent *Node Parent *Node
Child []*Node Child []*Node
Type NodeType Type NodeType
Data string Data string
Attr []Attribute Namespace string
Attr []Attribute
} }
// Add adds a node as a child of n. // Add adds a node as a child of n.

View File

@ -22,12 +22,12 @@ type parser struct {
hasSelfClosingToken bool hasSelfClosingToken bool
// doc is the document root element. // doc is the document root element.
doc *Node doc *Node
// The stack of open elements (section 11.2.3.2) and active formatting // The stack of open elements (section 12.2.3.2) and active formatting
// elements (section 11.2.3.3). // elements (section 12.2.3.3).
oe, afe nodeStack oe, afe nodeStack
// Element pointers (section 11.2.3.4). // Element pointers (section 12.2.3.4).
head, form *Node head, form *Node
// Other parsing state flags (section 11.2.3.5). // Other parsing state flags (section 12.2.3.5).
scripting, framesetOK bool scripting, framesetOK bool
// im is the current insertion mode. // im is the current insertion mode.
im insertionMode im insertionMode
@ -35,12 +35,12 @@ type parser struct {
// or inTableText insertion mode. // or inTableText insertion mode.
originalIM insertionMode originalIM insertionMode
// fosterParenting is whether new elements should be inserted according to // fosterParenting is whether new elements should be inserted according to
// the foster parenting rules (section 11.2.5.3). // the foster parenting rules (section 12.2.5.3).
fosterParenting bool fosterParenting bool
// quirks is whether the parser is operating in "quirks mode." // quirks is whether the parser is operating in "quirks mode."
quirks bool quirks bool
// context is the context element when parsing an HTML fragment // context is the context element when parsing an HTML fragment
// (section 11.4). // (section 12.4).
context *Node context *Node
} }
@ -51,7 +51,7 @@ func (p *parser) top() *Node {
return p.doc return p.doc
} }
// stopTags for use in popUntil. These come from section 11.2.3.2. // stopTags for use in popUntil. These come from section 12.2.3.2.
var ( var (
defaultScopeStopTags = []string{"applet", "caption", "html", "table", "td", "th", "marquee", "object"} defaultScopeStopTags = []string{"applet", "caption", "html", "table", "td", "th", "marquee", "object"}
listItemScopeStopTags = []string{"applet", "caption", "html", "table", "td", "th", "marquee", "object", "ol", "ul"} listItemScopeStopTags = []string{"applet", "caption", "html", "table", "td", "th", "marquee", "object", "ol", "ul"}
@ -130,7 +130,7 @@ func (p *parser) addChild(n *Node) {
} }
// fosterParent adds a child node according to the foster parenting rules. // fosterParent adds a child node according to the foster parenting rules.
// Section 11.2.5.3, "foster parenting". // Section 12.2.5.3, "foster parenting".
func (p *parser) fosterParent(n *Node) { func (p *parser) fosterParent(n *Node) {
p.fosterParenting = false p.fosterParenting = false
var table, parent *Node var table, parent *Node
@ -192,20 +192,21 @@ func (p *parser) addText(text string) {
// addElement calls addChild with an element node. // addElement calls addChild with an element node.
func (p *parser) addElement(tag string, attr []Attribute) { func (p *parser) addElement(tag string, attr []Attribute) {
p.addChild(&Node{ p.addChild(&Node{
Type: ElementNode, Type: ElementNode,
Data: tag, Data: tag,
Attr: attr, Namespace: p.top().Namespace,
Attr: attr,
}) })
} }
// Section 11.2.3.3. // Section 12.2.3.3.
func (p *parser) addFormattingElement(tag string, attr []Attribute) { func (p *parser) addFormattingElement(tag string, attr []Attribute) {
p.addElement(tag, attr) p.addElement(tag, attr)
p.afe = append(p.afe, p.top()) p.afe = append(p.afe, p.top())
// TODO. // TODO.
} }
// Section 11.2.3.3. // Section 12.2.3.3.
func (p *parser) clearActiveFormattingElements() { func (p *parser) clearActiveFormattingElements() {
for { for {
n := p.afe.pop() n := p.afe.pop()
@ -215,7 +216,7 @@ func (p *parser) clearActiveFormattingElements() {
} }
} }
// Section 11.2.3.3. // Section 12.2.3.3.
func (p *parser) reconstructActiveFormattingElements() { func (p *parser) reconstructActiveFormattingElements() {
n := p.afe.top() n := p.afe.top()
if n == nil { if n == nil {
@ -265,12 +266,12 @@ func (p *parser) read() error {
return nil return nil
} }
// Section 11.2.4. // Section 12.2.4.
func (p *parser) acknowledgeSelfClosingTag() { func (p *parser) acknowledgeSelfClosingTag() {
p.hasSelfClosingToken = false p.hasSelfClosingToken = false
} }
// An insertion mode (section 11.2.3.1) is the state transition function from // An insertion mode (section 12.2.3.1) is the state transition function from
// a particular state in the HTML5 parser's state machine. It updates the // a particular state in the HTML5 parser's state machine. It updates the
// parser's fields depending on parser.tok (where ErrorToken means EOF). // parser's fields depending on parser.tok (where ErrorToken means EOF).
// It returns whether the token was consumed. // It returns whether the token was consumed.
@ -278,7 +279,7 @@ type insertionMode func(*parser) bool
// setOriginalIM sets the insertion mode to return to after completing a text or // setOriginalIM sets the insertion mode to return to after completing a text or
// inTableText insertion mode. // inTableText insertion mode.
// Section 11.2.3.1, "using the rules for". // Section 12.2.3.1, "using the rules for".
func (p *parser) setOriginalIM() { func (p *parser) setOriginalIM() {
if p.originalIM != nil { if p.originalIM != nil {
panic("html: bad parser state: originalIM was set twice") panic("html: bad parser state: originalIM was set twice")
@ -286,7 +287,7 @@ func (p *parser) setOriginalIM() {
p.originalIM = p.im p.originalIM = p.im
} }
// Section 11.2.3.1, "reset the insertion mode". // Section 12.2.3.1, "reset the insertion mode".
func (p *parser) resetInsertionMode() { func (p *parser) resetInsertionMode() {
for i := len(p.oe) - 1; i >= 0; i-- { for i := len(p.oe) - 1; i >= 0; i-- {
n := p.oe[i] n := p.oe[i]
@ -318,7 +319,10 @@ func (p *parser) resetInsertionMode() {
case "html": case "html":
p.im = beforeHeadIM p.im = beforeHeadIM
default: default:
continue if p.top().Namespace == "" {
continue
}
p.im = inForeignContentIM
} }
return return
} }
@ -327,7 +331,7 @@ func (p *parser) resetInsertionMode() {
const whitespace = " \t\r\n\f" const whitespace = " \t\r\n\f"
// Section 11.2.5.4.1. // Section 12.2.5.4.1.
func initialIM(p *parser) bool { func initialIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case TextToken: case TextToken:
@ -354,7 +358,7 @@ func initialIM(p *parser) bool {
return false return false
} }
// Section 11.2.5.4.2. // Section 12.2.5.4.2.
func beforeHTMLIM(p *parser) bool { func beforeHTMLIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case TextToken: case TextToken:
@ -390,7 +394,7 @@ func beforeHTMLIM(p *parser) bool {
return false return false
} }
// Section 11.2.5.4.3. // Section 12.2.5.4.3.
func beforeHeadIM(p *parser) bool { func beforeHeadIM(p *parser) bool {
var ( var (
add bool add bool
@ -439,7 +443,7 @@ func beforeHeadIM(p *parser) bool {
return !implied return !implied
} }
// Section 11.2.5.4.4. // Section 12.2.5.4.4.
func inHeadIM(p *parser) bool { func inHeadIM(p *parser) bool {
var ( var (
pop bool pop bool
@ -506,7 +510,7 @@ func inHeadIM(p *parser) bool {
return true return true
} }
// Section 11.2.5.4.6. // Section 12.2.5.4.6.
func afterHeadIM(p *parser) bool { func afterHeadIM(p *parser) bool {
var ( var (
add bool add bool
@ -594,7 +598,7 @@ func copyAttributes(dst *Node, src Token) {
} }
} }
// Section 11.2.5.4.7. // Section 12.2.5.4.7.
func inBodyIM(p *parser) bool { func inBodyIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case TextToken: case TextToken:
@ -730,6 +734,11 @@ func inBodyIM(p *parser) bool {
case "plaintext": case "plaintext":
p.popUntil(buttonScopeStopTags, "p") p.popUntil(buttonScopeStopTags, "p")
p.addElement(p.tok.Data, p.tok.Attr) p.addElement(p.tok.Data, p.tok.Attr)
case "button":
p.popUntil(defaultScopeStopTags, "button")
p.reconstructActiveFormattingElements()
p.addElement(p.tok.Data, p.tok.Attr)
p.framesetOK = false
case "optgroup", "option": case "optgroup", "option":
if p.top().Data == "option" { if p.top().Data == "option" {
p.oe.pop() p.oe.pop()
@ -792,6 +801,21 @@ func inBodyIM(p *parser) bool {
p.reconstructActiveFormattingElements() p.reconstructActiveFormattingElements()
p.framesetOK = false p.framesetOK = false
p.addElement(p.tok.Data, p.tok.Attr) p.addElement(p.tok.Data, p.tok.Attr)
case "math", "svg":
p.reconstructActiveFormattingElements()
namespace := ""
if p.tok.Data == "math" {
// TODO: adjust MathML attributes.
namespace = "mathml"
} else {
// TODO: adjust SVG attributes.
namespace = "svg"
}
// TODO: adjust foreign attributes.
p.addElement(p.tok.Data, p.tok.Attr)
p.top().Namespace = namespace
p.im = inForeignContentIM
return true
case "caption", "col", "colgroup", "frame", "head", "tbody", "td", "tfoot", "th", "thead", "tr": case "caption", "col", "colgroup", "frame", "head", "tbody", "td", "tfoot", "th", "thead", "tr":
// Ignore the token. // Ignore the token.
default: default:
@ -970,7 +994,7 @@ func (p *parser) inBodyEndTagOther(tag string) {
} }
} }
// Section 11.2.5.4.8. // Section 12.2.5.4.8.
func textIM(p *parser) bool { func textIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case ErrorToken: case ErrorToken:
@ -986,7 +1010,7 @@ func textIM(p *parser) bool {
return p.tok.Type == EndTagToken return p.tok.Type == EndTagToken
} }
// Section 11.2.5.4.9. // Section 12.2.5.4.9.
func inTableIM(p *parser) bool { func inTableIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case ErrorToken: case ErrorToken:
@ -1075,7 +1099,7 @@ func (p *parser) clearStackToContext(stopTags []string) {
} }
} }
// Section 11.2.5.4.11. // Section 12.2.5.4.11.
func inCaptionIM(p *parser) bool { func inCaptionIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case StartTagToken: case StartTagToken:
@ -1115,7 +1139,7 @@ func inCaptionIM(p *parser) bool {
return inBodyIM(p) return inBodyIM(p)
} }
// Section 11.2.5.4.12. // Section 12.2.5.4.12.
func inColumnGroupIM(p *parser) bool { func inColumnGroupIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case CommentToken: case CommentToken:
@ -1142,8 +1166,8 @@ func inColumnGroupIM(p *parser) bool {
case "colgroup": case "colgroup":
if p.oe.top().Data != "html" { if p.oe.top().Data != "html" {
p.oe.pop() p.oe.pop()
p.im = inTableIM
} }
p.im = inTableIM
return true return true
case "col": case "col":
// Ignore the token. // Ignore the token.
@ -1152,12 +1176,13 @@ func inColumnGroupIM(p *parser) bool {
} }
if p.oe.top().Data != "html" { if p.oe.top().Data != "html" {
p.oe.pop() p.oe.pop()
p.im = inTableIM
return false
} }
p.im = inTableIM return true
return false
} }
// Section 11.2.5.4.13. // Section 12.2.5.4.13.
func inTableBodyIM(p *parser) bool { func inTableBodyIM(p *parser) bool {
var ( var (
add bool add bool
@ -1213,7 +1238,7 @@ func inTableBodyIM(p *parser) bool {
return inTableIM(p) return inTableIM(p)
} }
// Section 11.2.5.4.14. // Section 12.2.5.4.14.
func inRowIM(p *parser) bool { func inRowIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case ErrorToken: case ErrorToken:
@ -1272,7 +1297,7 @@ func inRowIM(p *parser) bool {
return inTableIM(p) return inTableIM(p)
} }
// Section 11.2.5.4.15. // Section 12.2.5.4.15.
func inCellIM(p *parser) bool { func inCellIM(p *parser) bool {
var ( var (
closeTheCellAndReprocess bool closeTheCellAndReprocess bool
@ -1317,7 +1342,7 @@ func inCellIM(p *parser) bool {
return inBodyIM(p) return inBodyIM(p)
} }
// Section 11.2.5.4.16. // Section 12.2.5.4.16.
func inSelectIM(p *parser) bool { func inSelectIM(p *parser) bool {
endSelect := false endSelect := false
switch p.tok.Type { switch p.tok.Type {
@ -1394,7 +1419,7 @@ func inSelectIM(p *parser) bool {
return true return true
} }
// Section 11.2.5.4.18. // Section 12.2.5.4.18.
func afterBodyIM(p *parser) bool { func afterBodyIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case ErrorToken: case ErrorToken:
@ -1424,7 +1449,7 @@ func afterBodyIM(p *parser) bool {
return false return false
} }
// Section 11.2.5.4.19. // Section 12.2.5.4.19.
func inFramesetIM(p *parser) bool { func inFramesetIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case CommentToken: case CommentToken:
@ -1432,6 +1457,18 @@ func inFramesetIM(p *parser) bool {
Type: CommentNode, Type: CommentNode,
Data: p.tok.Data, Data: p.tok.Data,
}) })
case TextToken:
// Ignore all text but whitespace.
s := strings.Map(func(c rune) rune {
switch c {
case ' ', '\t', '\n', '\f', '\r':
return c
}
return -1
}, p.tok.Data)
if s != "" {
p.addText(s)
}
case StartTagToken: case StartTagToken:
switch p.tok.Data { switch p.tok.Data {
case "html": case "html":
@ -1462,7 +1499,7 @@ func inFramesetIM(p *parser) bool {
return true return true
} }
// Section 11.2.5.4.20. // Section 12.2.5.4.20.
func afterFramesetIM(p *parser) bool { func afterFramesetIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case CommentToken: case CommentToken:
@ -1470,6 +1507,18 @@ func afterFramesetIM(p *parser) bool {
Type: CommentNode, Type: CommentNode,
Data: p.tok.Data, Data: p.tok.Data,
}) })
case TextToken:
// Ignore all text but whitespace.
s := strings.Map(func(c rune) rune {
switch c {
case ' ', '\t', '\n', '\f', '\r':
return c
}
return -1
}, p.tok.Data)
if s != "" {
p.addText(s)
}
case StartTagToken: case StartTagToken:
switch p.tok.Data { switch p.tok.Data {
case "html": case "html":
@ -1489,7 +1538,7 @@ func afterFramesetIM(p *parser) bool {
return true return true
} }
// Section 11.2.5.4.21. // Section 12.2.5.4.21.
func afterAfterBodyIM(p *parser) bool { func afterAfterBodyIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case ErrorToken: case ErrorToken:
@ -1512,7 +1561,7 @@ func afterAfterBodyIM(p *parser) bool {
return false return false
} }
// Section 11.2.5.4.22. // Section 12.2.5.4.22.
func afterAfterFramesetIM(p *parser) bool { func afterAfterFramesetIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case CommentToken: case CommentToken:
@ -1533,6 +1582,37 @@ func afterAfterFramesetIM(p *parser) bool {
return true return true
} }
// Section 12.2.5.5.
func inForeignContentIM(p *parser) bool {
switch p.tok.Type {
case CommentToken:
p.addChild(&Node{
Type: CommentNode,
Data: p.tok.Data,
})
case StartTagToken:
if breakout[p.tok.Data] {
// TODO.
}
switch p.top().Namespace {
case "mathml":
// TODO: adjust MathML attributes.
case "svg":
// TODO: adjust SVG tag names.
// TODO: adjust SVG attributes.
default:
panic("html: bad parser state: unexpected namespace")
}
// TODO: adjust foreign attributes.
p.addElement(p.tok.Data, p.tok.Attr)
case EndTagToken:
// TODO.
default:
// Ignore the token.
}
return true
}
func (p *parser) parse() error { func (p *parser) parse() error {
// Iterate until EOF. Any other error will cause an early return. // Iterate until EOF. Any other error will cause an early return.
consumed := true consumed := true

View File

@ -98,7 +98,11 @@ func dumpLevel(w io.Writer, n *Node, level int) error {
case DocumentNode: case DocumentNode:
return errors.New("unexpected DocumentNode") return errors.New("unexpected DocumentNode")
case ElementNode: case ElementNode:
fmt.Fprintf(w, "<%s>", n.Data) if n.Namespace != "" {
fmt.Fprintf(w, "<%s %s>", n.Namespace, n.Data)
} else {
fmt.Fprintf(w, "<%s>", n.Data)
}
for _, a := range n.Attr { for _, a := range n.Attr {
io.WriteString(w, "\n") io.WriteString(w, "\n")
dumpIndent(w, level+1) dumpIndent(w, level+1)
@ -161,13 +165,14 @@ func TestParser(t *testing.T) {
n int n int
}{ }{
// TODO(nigeltao): Process all the test cases from all the .dat files. // TODO(nigeltao): Process all the test cases from all the .dat files.
{"adoption01.dat", -1},
{"doctype01.dat", -1}, {"doctype01.dat", -1},
{"tests1.dat", -1}, {"tests1.dat", -1},
{"tests2.dat", -1}, {"tests2.dat", -1},
{"tests3.dat", -1}, {"tests3.dat", -1},
{"tests4.dat", -1}, {"tests4.dat", -1},
{"tests5.dat", -1}, {"tests5.dat", -1},
{"tests6.dat", 7}, {"tests6.dat", 36},
} }
for _, tf := range testFiles { for _, tf := range testFiles {
f, err := os.Open("testdata/webkit/" + tf.filename) f, err := os.Open("testdata/webkit/" + tf.filename)

View File

@ -247,7 +247,7 @@ func writeQuoted(w writer, s string) error {
return nil return nil
} }
// Section 13.1.2, "Elements", gives this list of void elements. Void elements // Section 12.1.2, "Elements", gives this list of void elements. Void elements
// are those that can't have any contents. // are those that can't have any contents.
var voidElements = map[string]bool{ var voidElements = map[string]bool{
"area": true, "area": true,

View File

@ -106,7 +106,7 @@ func isHex(c byte) bool {
// hexDecode decodes a short hex digit sequence: "10" -> 16. // hexDecode decodes a short hex digit sequence: "10" -> 16.
func hexDecode(s []byte) rune { func hexDecode(s []byte) rune {
n := rune(0) n := '\x00'
for _, c := range s { for _, c := range s {
n <<= 4 n <<= 4
switch { switch {

View File

@ -654,7 +654,7 @@ func TestEscape(t *testing.T) {
for _, test := range tests { for _, test := range tests {
tmpl := New(test.name) tmpl := New(test.name)
// TODO: Move noescape into template/func.go // TODO: Move noescape into template/func.go
tmpl.Funcs(template.FuncMap{ tmpl.Funcs(FuncMap{
"noescape": func(a ...interface{}) string { "noescape": func(a ...interface{}) string {
return fmt.Sprint(a...) return fmt.Sprint(a...)
}, },
@ -792,7 +792,7 @@ func TestEscapeSet(t *testing.T) {
// pred is a template function that returns the predecessor of a // pred is a template function that returns the predecessor of a
// natural number for testing recursive templates. // natural number for testing recursive templates.
fns := template.FuncMap{"pred": func(a ...interface{}) (interface{}, error) { fns := FuncMap{"pred": func(a ...interface{}) (interface{}, error) {
if len(a) == 1 { if len(a) == 1 {
if i, _ := a[0].(int); i > 0 { if i, _ := a[0].(int); i > 0 {
return i - 1, nil return i - 1, nil

View File

@ -49,20 +49,28 @@ func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
// ExecuteTemplate applies the template associated with t that has the given // ExecuteTemplate applies the template associated with t that has the given
// name to the specified data object and writes the output to wr. // name to the specified data object and writes the output to wr.
func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) (err error) { func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
tmpl, err := t.lookupAndEscapeTemplate(wr, name)
if err != nil {
return err
}
return tmpl.text.Execute(wr, data)
}
// lookupAndEscapeTemplate guarantees that the template with the given name
// is escaped, or returns an error if it cannot be. It returns the named
// template.
func (t *Template) lookupAndEscapeTemplate(wr io.Writer, name string) (tmpl *Template, err error) {
t.nameSpace.mu.Lock() t.nameSpace.mu.Lock()
tmpl := t.set[name] defer t.nameSpace.mu.Unlock()
tmpl = t.set[name]
if (tmpl == nil) != (t.text.Lookup(name) == nil) { if (tmpl == nil) != (t.text.Lookup(name) == nil) {
panic("html/template internal error: template escaping out of sync") panic("html/template internal error: template escaping out of sync")
} }
if tmpl != nil && !tmpl.escaped { if tmpl != nil && !tmpl.escaped {
err = escapeTemplates(tmpl, name) err = escapeTemplates(tmpl, name)
} }
t.nameSpace.mu.Unlock() return tmpl, err
if err != nil {
return
}
return t.text.ExecuteTemplate(wr, name, data)
} }
// Parse parses a string into a template. Nested template definitions // Parse parses a string into a template. Nested template definitions
@ -146,12 +154,20 @@ func (t *Template) Name() string {
return t.text.Name() return t.text.Name()
} }
// FuncMap is the type of the map defining the mapping from names to
// functions. Each function must have either a single return value, or two
// return values of which the second has type error. In that case, if the
// second (error) argument evaluates to non-nil during execution, execution
// terminates and Execute returns that error. FuncMap has the same base type
// as template.FuncMap, copied here so clients need not import "text/template".
type FuncMap map[string]interface{}
// Funcs adds the elements of the argument map to the template's function map. // Funcs adds the elements of the argument map to the template's function map.
// It panics if a value in the map is not a function with appropriate return // It panics if a value in the map is not a function with appropriate return
// type. However, it is legal to overwrite elements of the map. The return // type. However, it is legal to overwrite elements of the map. The return
// value is the template, so calls can be chained. // value is the template, so calls can be chained.
func (t *Template) Funcs(funcMap template.FuncMap) *Template { func (t *Template) Funcs(funcMap FuncMap) *Template {
t.text.Funcs(funcMap) t.text.Funcs(template.FuncMap(funcMap))
return t return t
} }
@ -175,7 +191,9 @@ func (t *Template) Lookup(name string) *Template {
// Must panics if err is non-nil in the same way as template.Must. // Must panics if err is non-nil in the same way as template.Must.
func Must(t *Template, err error) *Template { func Must(t *Template, err error) *Template {
t.text = template.Must(t.text, err) if err != nil {
panic(err)
}
return t return t
} }

View File

@ -165,7 +165,7 @@ var pipeTests = []pipeTest{
} }
func delayClose(t *testing.T, cl closer, ch chan int, tt pipeTest) { func delayClose(t *testing.T, cl closer, ch chan int, tt pipeTest) {
time.Sleep(1e6) // 1 ms time.Sleep(1 * time.Millisecond)
var err error var err error
if tt.closeWithError { if tt.closeWithError {
err = cl.CloseWithError(tt.err) err = cl.CloseWithError(tt.err)

View File

@ -9,7 +9,12 @@ package math
// Special cases are: // Special cases are:
// Abs(±Inf) = +Inf // Abs(±Inf) = +Inf
// Abs(NaN) = NaN // Abs(NaN) = NaN
func libc_fabs(float64) float64 __asm__("fabs")
func Abs(x float64) float64 { func Abs(x float64) float64 {
return libc_fabs(x)
}
func abs(x float64) float64 {
switch { switch {
case x < 0: case x < 0:
return -x return -x

View File

@ -1,7 +0,0 @@
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package math
func Abs(x float64) float64

View File

@ -36,6 +36,7 @@ package math
// Acosh(x) calculates the inverse hyperbolic cosine of x. // Acosh(x) calculates the inverse hyperbolic cosine of x.
// //
// Special cases are: // Special cases are:
// Acosh(+Inf) = +Inf
// Acosh(x) = NaN if x < 1 // Acosh(x) = NaN if x < 1
// Acosh(NaN) = NaN // Acosh(NaN) = NaN
func Acosh(x float64) float64 { func Acosh(x float64) float64 {

View File

@ -958,6 +958,75 @@ var fabsSC = []float64{
NaN(), NaN(),
} }
var vffdimSC = [][2]float64{
{Inf(-1), Inf(-1)},
{Inf(-1), Inf(1)},
{Inf(-1), NaN()},
{Copysign(0, -1), Copysign(0, -1)},
{Copysign(0, -1), 0},
{0, Copysign(0, -1)},
{0, 0},
{Inf(1), Inf(-1)},
{Inf(1), Inf(1)},
{Inf(1), NaN()},
{NaN(), Inf(-1)},
{NaN(), Copysign(0, -1)},
{NaN(), 0},
{NaN(), Inf(1)},
{NaN(), NaN()},
}
var fdimSC = []float64{
NaN(),
0,
NaN(),
0,
0,
0,
0,
Inf(1),
NaN(),
NaN(),
NaN(),
NaN(),
NaN(),
NaN(),
NaN(),
}
var fmaxSC = []float64{
Inf(-1),
Inf(1),
NaN(),
Copysign(0, -1),
0,
0,
0,
Inf(1),
Inf(1),
Inf(1),
NaN(),
NaN(),
NaN(),
Inf(1),
NaN(),
}
var fminSC = []float64{
Inf(-1),
Inf(-1),
Inf(-1),
Copysign(0, -1),
Copysign(0, -1),
Copysign(0, -1),
0,
Inf(-1),
Inf(1),
NaN(),
Inf(-1),
NaN(),
NaN(),
NaN(),
NaN(),
}
var vffmodSC = [][2]float64{ var vffmodSC = [][2]float64{
{Inf(-1), Inf(-1)}, {Inf(-1), Inf(-1)},
{Inf(-1), -Pi}, {Inf(-1), -Pi},
@ -1259,12 +1328,26 @@ var modfSC = [][2]float64{
} }
var vfnextafterSC = [][2]float64{ var vfnextafterSC = [][2]float64{
{0, 0},
{0, Copysign(0, -1)},
{0, -1},
{0, NaN()}, {0, NaN()},
{Copysign(0, -1), 1},
{Copysign(0, -1), 0},
{Copysign(0, -1), Copysign(0, -1)},
{Copysign(0, -1), -1},
{NaN(), 0}, {NaN(), 0},
{NaN(), NaN()}, {NaN(), NaN()},
} }
var nextafterSC = []float64{ var nextafterSC = []float64{
0,
0,
-4.9406564584124654418e-324, // Float64frombits(0x8000000000000001)
NaN(), NaN(),
4.9406564584124654418e-324, // Float64frombits(0x0000000000000001)
Copysign(0, -1),
Copysign(0, -1),
-4.9406564584124654418e-324, // Float64frombits(0x8000000000000001)
NaN(), NaN(),
NaN(), NaN(),
} }
@ -1875,6 +1958,11 @@ func TestDim(t *testing.T) {
t.Errorf("Dim(%g, %g) = %g, want %g", vf[i], 0.0, f, fdim[i]) t.Errorf("Dim(%g, %g) = %g, want %g", vf[i], 0.0, f, fdim[i])
} }
} }
for i := 0; i < len(vffdimSC); i++ {
if f := Dim(vffdimSC[i][0], vffdimSC[i][1]); !alike(fdimSC[i], f) {
t.Errorf("Dim(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fdimSC[i])
}
}
} }
func TestFloor(t *testing.T) { func TestFloor(t *testing.T) {
@ -1896,6 +1984,11 @@ func TestMax(t *testing.T) {
t.Errorf("Max(%g, %g) = %g, want %g", vf[i], ceil[i], f, ceil[i]) t.Errorf("Max(%g, %g) = %g, want %g", vf[i], ceil[i], f, ceil[i])
} }
} }
for i := 0; i < len(vffdimSC); i++ {
if f := Max(vffdimSC[i][0], vffdimSC[i][1]); !alike(fmaxSC[i], f) {
t.Errorf("Max(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fmaxSC[i])
}
}
} }
func TestMin(t *testing.T) { func TestMin(t *testing.T) {
@ -1904,6 +1997,11 @@ func TestMin(t *testing.T) {
t.Errorf("Min(%g, %g) = %g, want %g", vf[i], floor[i], f, floor[i]) t.Errorf("Min(%g, %g) = %g, want %g", vf[i], floor[i], f, floor[i])
} }
} }
for i := 0; i < len(vffdimSC); i++ {
if f := Min(vffdimSC[i][0], vffdimSC[i][1]); !alike(fminSC[i], f) {
t.Errorf("Min(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fminSC[i])
}
}
} }
func TestMod(t *testing.T) { func TestMod(t *testing.T) {
@ -1964,6 +2062,20 @@ func TestHypot(t *testing.T) {
} }
} }
func TestHypotGo(t *testing.T) {
for i := 0; i < len(vf); i++ {
a := Abs(1e200 * tanh[i] * Sqrt(2))
if f := HypotGo(1e200*tanh[i], 1e200*tanh[i]); !veryclose(a, f) {
t.Errorf("HypotGo(%g, %g) = %g, want %g", 1e200*tanh[i], 1e200*tanh[i], f, a)
}
}
for i := 0; i < len(vfhypotSC); i++ {
if f := HypotGo(vfhypotSC[i][0], vfhypotSC[i][1]); !alike(hypotSC[i], f) {
t.Errorf("HypotGo(%g, %g) = %g, want %g", vfhypotSC[i][0], vfhypotSC[i][1], f, hypotSC[i])
}
}
}
func TestIlogb(t *testing.T) { func TestIlogb(t *testing.T) {
for i := 0; i < len(vf); i++ { for i := 0; i < len(vf); i++ {
a := frexp[i].i - 1 // adjust because fr in the interval [½, 1) a := frexp[i].i - 1 // adjust because fr in the interval [½, 1)
@ -2175,7 +2287,7 @@ func TestNextafter(t *testing.T) {
t.Errorf("Nextafter(%g, %g) = %g want %g", vf[i], 10.0, f, nextafter[i]) t.Errorf("Nextafter(%g, %g) = %g want %g", vf[i], 10.0, f, nextafter[i])
} }
} }
for i := 0; i < len(vfmodfSC); i++ { for i := 0; i < len(vfnextafterSC); i++ {
if f := Nextafter(vfnextafterSC[i][0], vfnextafterSC[i][1]); !alike(nextafterSC[i], f) { if f := Nextafter(vfnextafterSC[i][0], vfnextafterSC[i][1]); !alike(nextafterSC[i], f) {
t.Errorf("Nextafter(%g, %g) = %g want %g", vfnextafterSC[i][0], vfnextafterSC[i][1], f, nextafterSC[i]) t.Errorf("Nextafter(%g, %g) = %g want %g", vfnextafterSC[i][0], vfnextafterSC[i][1], f, nextafterSC[i])
} }

View File

@ -16,7 +16,12 @@ package math
// Special cases are: // Special cases are:
// Asin(±0) = ±0 // Asin(±0) = ±0
// Asin(x) = NaN if x < -1 or x > 1 // Asin(x) = NaN if x < -1 or x > 1
func libc_asin(float64) float64 __asm__("asin")
func Asin(x float64) float64 { func Asin(x float64) float64 {
return libc_asin(x)
}
func asin(x float64) float64 {
if x == 0 { if x == 0 {
return x // special case return x // special case
} }
@ -46,4 +51,11 @@ func Asin(x float64) float64 {
// //
// Special case is: // Special case is:
// Acos(x) = NaN if x < -1 or x > 1 // Acos(x) = NaN if x < -1 or x > 1
func Acos(x float64) float64 { return Pi/2 - Asin(x) } func libc_acos(float64) float64 __asm__("acos")
func Acos(x float64) float64 {
return libc_acos(x)
}
func acos(x float64) float64 {
return Pi/2 - Asin(x)
}

View File

@ -33,6 +33,7 @@ package math
// Asinh(x) calculates the inverse hyperbolic sine of x. // Asinh(x) calculates the inverse hyperbolic sine of x.
// //
// Special cases are: // Special cases are:
// Asinh(±0) = ±0
// Asinh(±Inf) = ±Inf // Asinh(±Inf) = ±Inf
// Asinh(NaN) = NaN // Asinh(NaN) = NaN
func Asinh(x float64) float64 { func Asinh(x float64) float64 {

View File

@ -51,7 +51,12 @@ func satan(arg float64) float64 {
// Special cases are: // Special cases are:
// Atan(±0) = ±0 // Atan(±0) = ±0
// Atan(±Inf) = ±Pi/2 // Atan(±Inf) = ±Pi/2
func libc_atan(float64) float64 __asm__("atan")
func Atan(x float64) float64 { func Atan(x float64) float64 {
return libc_atan(x)
}
func atan(x float64) float64 {
if x == 0 { if x == 0 {
return x return x
} }

View File

@ -26,7 +26,12 @@ package math
// Atan2(y<0, -Inf) = -Pi // Atan2(y<0, -Inf) = -Pi
// Atan2(+Inf, x) = +Pi/2 // Atan2(+Inf, x) = +Pi/2
// Atan2(-Inf, x) = -Pi/2 // Atan2(-Inf, x) = -Pi/2
func libc_atan2(float64, float64) float64 __asm__("atan2")
func Atan2(y, x float64) float64 { func Atan2(y, x float64) float64 {
return libc_atan2(y, x)
}
func atan2(y, x float64) float64 {
// TODO(rsc): Remove manual inlining of IsNaN, IsInf // TODO(rsc): Remove manual inlining of IsNaN, IsInf
// when compiler does it for us // when compiler does it for us
// special cases // special cases

View File

@ -39,9 +39,10 @@ package math
// Atanh(x) calculates the inverse hyperbolic tangent of x. // Atanh(x) calculates the inverse hyperbolic tangent of x.
// //
// Special cases are: // Special cases are:
// Atanh(x) = NaN if x < -1 or x > 1
// Atanh(1) = +Inf // Atanh(1) = +Inf
// Atanh(±0) = ±0
// Atanh(-1) = -Inf // Atanh(-1) = -Inf
// Atanh(x) = NaN if x < -1 or x > 1
// Atanh(NaN) = NaN // Atanh(NaN) = NaN
func Atanh(x float64) float64 { func Atanh(x float64) float64 {
const NearZero = 1.0 / (1 << 28) // 2**-28 const NearZero = 1.0 / (1 << 28) // 2**-28

View File

@ -592,7 +592,7 @@ func (x nat) bitLen() int {
const MaxBase = 'z' - 'a' + 10 + 1 // = hexValue('z') + 1 const MaxBase = 'z' - 'a' + 10 + 1 // = hexValue('z') + 1
func hexValue(ch rune) Word { func hexValue(ch rune) Word {
d := MaxBase + 1 // illegal base d := int(MaxBase + 1) // illegal base
switch { switch {
case '0' <= ch && ch <= '9': case '0' <= ch && ch <= '9':
d = int(ch - '0') d = int(ch - '0')

View File

@ -49,5 +49,3 @@ const (
MaxUint32 = 1<<32 - 1 MaxUint32 = 1<<32 - 1
MaxUint64 = 1<<64 - 1 MaxUint64 = 1<<64 - 1
) )
// BUG(rsc): The manual should define the special cases for all of these functions.

View File

@ -5,15 +5,45 @@
package math package math
// Dim returns the maximum of x-y or 0. // Dim returns the maximum of x-y or 0.
//
// Special cases are:
// Dim(+Inf, +Inf) = NaN
// Dim(-Inf, -Inf) = NaN
// Dim(x, NaN) = Dim(NaN, x) = NaN
func Dim(x, y float64) float64 { func Dim(x, y float64) float64 {
if x > y { return dim(x, y)
return x - y }
}
return 0 func dim(x, y float64) float64 {
return max(x-y, 0)
} }
// Max returns the larger of x or y. // Max returns the larger of x or y.
//
// Special cases are:
// Max(x, +Inf) = Max(+Inf, x) = +Inf
// Max(x, NaN) = Max(NaN, x) = NaN
// Max(+0, ±0) = Max(±0, +0) = +0
// Max(-0, -0) = -0
func Max(x, y float64) float64 { func Max(x, y float64) float64 {
return max(x, y)
}
func max(x, y float64) float64 {
// TODO(rsc): Remove manual inlining of IsNaN, IsInf
// when compiler does it for us
// special cases
switch {
case x > MaxFloat64 || y > MaxFloat64: // IsInf(x, 1) || IsInf(y, 1):
return Inf(1)
case x != x || y != y: // IsNaN(x) || IsNaN(y):
return NaN()
case x == 0 && x == y:
if Signbit(x) {
return y
}
return x
}
if x > y { if x > y {
return x return x
} }
@ -21,7 +51,30 @@ func Max(x, y float64) float64 {
} }
// Min returns the smaller of x or y. // Min returns the smaller of x or y.
//
// Special cases are:
// Min(x, -Inf) = Min(-Inf, x) = -Inf
// Min(x, NaN) = Min(NaN, x) = NaN
// Min(-0, ±0) = Min(±0, -0) = -0
func Min(x, y float64) float64 { func Min(x, y float64) float64 {
return min(x, y)
}
func min(x, y float64) float64 {
// TODO(rsc): Remove manual inlining of IsNaN, IsInf
// when compiler does it for us
// special cases
switch {
case x < -MaxFloat64 || y < -MaxFloat64: // IsInf(x, -1) || IsInf(y, -1):
return Inf(-1)
case x != x || y != y: // IsNaN(x) || IsNaN(y):
return NaN()
case x == 0 && x == y:
if Signbit(x) {
return x
}
return y
}
if x < y { if x < y {
return x return x
} }

View File

@ -1,9 +0,0 @@
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package math
func Dim(x, y float64) float64
func Max(x, y float64) float64
func Min(x, y float64) float64

View File

@ -11,4 +11,190 @@ package math
// Exp(NaN) = NaN // Exp(NaN) = NaN
// Very large values overflow to 0 or +Inf. // Very large values overflow to 0 or +Inf.
// Very small values underflow to 1. // Very small values underflow to 1.
func Exp(x float64) float64 { return expGo(x) } func libc_exp(float64) float64 __asm__("exp")
func Exp(x float64) float64 {
return libc_exp(x)
}
// The original C code, the long comment, and the constants
// below are from FreeBSD's /usr/src/lib/msun/src/e_exp.c
// and came with this notice. The go code is a simplified
// version of the original C.
//
// ====================================================
// Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
//
// Permission to use, copy, modify, and distribute this
// software is freely granted, provided that this notice
// is preserved.
// ====================================================
//
//
// exp(x)
// Returns the exponential of x.
//
// Method
// 1. Argument reduction:
// Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
// Given x, find r and integer k such that
//
// x = k*ln2 + r, |r| <= 0.5*ln2.
//
// Here r will be represented as r = hi-lo for better
// accuracy.
//
// 2. Approximation of exp(r) by a special rational function on
// the interval [0,0.34658]:
// Write
// R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
// We use a special Remes algorithm on [0,0.34658] to generate
// a polynomial of degree 5 to approximate R. The maximum error
// of this polynomial approximation is bounded by 2**-59. In
// other words,
// R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
// (where z=r*r, and the values of P1 to P5 are listed below)
// and
// | 5 | -59
// | 2.0+P1*z+...+P5*z - R(z) | <= 2
// | |
// The computation of exp(r) thus becomes
// 2*r
// exp(r) = 1 + -------
// R - r
// r*R1(r)
// = 1 + r + ----------- (for better accuracy)
// 2 - R1(r)
// where
// 2 4 10
// R1(r) = r - (P1*r + P2*r + ... + P5*r ).
//
// 3. Scale back to obtain exp(x):
// From step 1, we have
// exp(x) = 2**k * exp(r)
//
// Special cases:
// exp(INF) is INF, exp(NaN) is NaN;
// exp(-INF) is 0, and
// for finite argument, only exp(0)=1 is exact.
//
// Accuracy:
// according to an error analysis, the error is always less than
// 1 ulp (unit in the last place).
//
// Misc. info.
// For IEEE double
// if x > 7.09782712893383973096e+02 then exp(x) overflow
// if x < -7.45133219101941108420e+02 then exp(x) underflow
//
// Constants:
// The hexadecimal values are the intended ones for the following
// constants. The decimal values may be used, provided that the
// compiler will convert from decimal to binary accurately enough
// to produce the hexadecimal values shown.
func exp(x float64) float64 {
const (
Ln2Hi = 6.93147180369123816490e-01
Ln2Lo = 1.90821492927058770002e-10
Log2e = 1.44269504088896338700e+00
Overflow = 7.09782712893383973096e+02
Underflow = -7.45133219101941108420e+02
NearZero = 1.0 / (1 << 28) // 2**-28
)
// TODO(rsc): Remove manual inlining of IsNaN, IsInf
// when compiler does it for us
// special cases
switch {
case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1):
return x
case x < -MaxFloat64: // IsInf(x, -1):
return 0
case x > Overflow:
return Inf(1)
case x < Underflow:
return 0
case -NearZero < x && x < NearZero:
return 1 + x
}
// reduce; computed as r = hi - lo for extra precision.
var k int
switch {
case x < 0:
k = int(Log2e*x - 0.5)
case x > 0:
k = int(Log2e*x + 0.5)
}
hi := x - float64(k)*Ln2Hi
lo := float64(k) * Ln2Lo
// compute
return expmulti(hi, lo, k)
}
// Exp2 returns 2**x, the base-2 exponential of x.
//
// Special cases are the same as Exp.
func Exp2(x float64) float64 {
return exp2(x)
}
func exp2(x float64) float64 {
const (
Ln2Hi = 6.93147180369123816490e-01
Ln2Lo = 1.90821492927058770002e-10
Overflow = 1.0239999999999999e+03
Underflow = -1.0740e+03
)
// TODO: remove manual inlining of IsNaN and IsInf
// when compiler does it for us
// special cases
switch {
case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1):
return x
case x < -MaxFloat64: // IsInf(x, -1):
return 0
case x > Overflow:
return Inf(1)
case x < Underflow:
return 0
}
// argument reduction; x = r×lg(e) + k with |r| ≤ ln(2)/2.
// computed as r = hi - lo for extra precision.
var k int
switch {
case x > 0:
k = int(x + 0.5)
case x < 0:
k = int(x - 0.5)
}
t := x - float64(k)
hi := t * Ln2Hi
lo := -t * Ln2Lo
// compute
return expmulti(hi, lo, k)
}
// exp1 returns e**r × 2**k where r = hi - lo and |r| ≤ ln(2)/2.
func expmulti(hi, lo float64, k int) float64 {
const (
P1 = 1.66666666666666019037e-01 /* 0x3FC55555; 0x5555553E */
P2 = -2.77777777770155933842e-03 /* 0xBF66C16C; 0x16BEBD93 */
P3 = 6.61375632143793436117e-05 /* 0x3F11566A; 0xAF25DE2C */
P4 = -1.65339022054652515390e-06 /* 0xBEBBBD41; 0xC5D26BF1 */
P5 = 4.13813679705723846039e-08 /* 0x3E663769; 0x72BEA4D0 */
)
r := hi - lo
t := r * r
c := r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))))
y := 1 - ((lo - (r*c)/(2-c)) - hi)
// TODO(rsc): make sure Ldexp can handle boundary k
return Ldexp(y, k)
}

View File

@ -1,10 +0,0 @@
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package math
// Exp2 returns 2**x, the base-2 exponential of x.
//
// Special cases are the same as Exp.
func Exp2(x float64) float64 { return exp2Go(x) }

View File

@ -1,191 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package math
// The original C code, the long comment, and the constants
// below are from FreeBSD's /usr/src/lib/msun/src/e_exp.c
// and came with this notice. The go code is a simplified
// version of the original C.
//
// ====================================================
// Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
//
// Permission to use, copy, modify, and distribute this
// software is freely granted, provided that this notice
// is preserved.
// ====================================================
//
//
// exp(x)
// Returns the exponential of x.
//
// Method
// 1. Argument reduction:
// Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
// Given x, find r and integer k such that
//
// x = k*ln2 + r, |r| <= 0.5*ln2.
//
// Here r will be represented as r = hi-lo for better
// accuracy.
//
// 2. Approximation of exp(r) by a special rational function on
// the interval [0,0.34658]:
// Write
// R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
// We use a special Remes algorithm on [0,0.34658] to generate
// a polynomial of degree 5 to approximate R. The maximum error
// of this polynomial approximation is bounded by 2**-59. In
// other words,
// R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
// (where z=r*r, and the values of P1 to P5 are listed below)
// and
// | 5 | -59
// | 2.0+P1*z+...+P5*z - R(z) | <= 2
// | |
// The computation of exp(r) thus becomes
// 2*r
// exp(r) = 1 + -------
// R - r
// r*R1(r)
// = 1 + r + ----------- (for better accuracy)
// 2 - R1(r)
// where
// 2 4 10
// R1(r) = r - (P1*r + P2*r + ... + P5*r ).
//
// 3. Scale back to obtain exp(x):
// From step 1, we have
// exp(x) = 2**k * exp(r)
//
// Special cases:
// exp(INF) is INF, exp(NaN) is NaN;
// exp(-INF) is 0, and
// for finite argument, only exp(0)=1 is exact.
//
// Accuracy:
// according to an error analysis, the error is always less than
// 1 ulp (unit in the last place).
//
// Misc. info.
// For IEEE double
// if x > 7.09782712893383973096e+02 then exp(x) overflow
// if x < -7.45133219101941108420e+02 then exp(x) underflow
//
// Constants:
// The hexadecimal values are the intended ones for the following
// constants. The decimal values may be used, provided that the
// compiler will convert from decimal to binary accurately enough
// to produce the hexadecimal values shown.
// Exp returns e**x, the base-e exponential of x.
//
// Special cases are:
// Exp(+Inf) = +Inf
// Exp(NaN) = NaN
// Very large values overflow to 0 or +Inf.
// Very small values underflow to 1.
func expGo(x float64) float64 {
const (
Ln2Hi = 6.93147180369123816490e-01
Ln2Lo = 1.90821492927058770002e-10
Log2e = 1.44269504088896338700e+00
Overflow = 7.09782712893383973096e+02
Underflow = -7.45133219101941108420e+02
NearZero = 1.0 / (1 << 28) // 2**-28
)
// TODO(rsc): Remove manual inlining of IsNaN, IsInf
// when compiler does it for us
// special cases
switch {
case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1):
return x
case x < -MaxFloat64: // IsInf(x, -1):
return 0
case x > Overflow:
return Inf(1)
case x < Underflow:
return 0
case -NearZero < x && x < NearZero:
return 1 + x
}
// reduce; computed as r = hi - lo for extra precision.
var k int
switch {
case x < 0:
k = int(Log2e*x - 0.5)
case x > 0:
k = int(Log2e*x + 0.5)
}
hi := x - float64(k)*Ln2Hi
lo := float64(k) * Ln2Lo
// compute
return exp(hi, lo, k)
}
// Exp2 returns 2**x, the base-2 exponential of x.
//
// Special cases are the same as Exp.
func exp2Go(x float64) float64 {
const (
Ln2Hi = 6.93147180369123816490e-01
Ln2Lo = 1.90821492927058770002e-10
Overflow = 1.0239999999999999e+03
Underflow = -1.0740e+03
)
// TODO: remove manual inlining of IsNaN and IsInf
// when compiler does it for us
// special cases
switch {
case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1):
return x
case x < -MaxFloat64: // IsInf(x, -1):
return 0
case x > Overflow:
return Inf(1)
case x < Underflow:
return 0
}
// argument reduction; x = r×lg(e) + k with |r| ≤ ln(2)/2.
// computed as r = hi - lo for extra precision.
var k int
switch {
case x > 0:
k = int(x + 0.5)
case x < 0:
k = int(x - 0.5)
}
t := x - float64(k)
hi := t * Ln2Hi
lo := -t * Ln2Lo
// compute
return exp(hi, lo, k)
}
// exp returns e**r × 2**k where r = hi - lo and |r| ≤ ln(2)/2.
func exp(hi, lo float64, k int) float64 {
const (
P1 = 1.66666666666666019037e-01 /* 0x3FC55555; 0x5555553E */
P2 = -2.77777777770155933842e-03 /* 0xBF66C16C; 0x16BEBD93 */
P3 = 6.61375632143793436117e-05 /* 0x3F11566A; 0xAF25DE2C */
P4 = -1.65339022054652515390e-06 /* 0xBEBBBD41; 0xC5D26BF1 */
P5 = 4.13813679705723846039e-08 /* 0x3E663769; 0x72BEA4D0 */
)
r := hi - lo
t := r * r
c := r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))))
y := 1 - ((lo - (r*c)/(2-c)) - hi)
// TODO(rsc): make sure Ldexp can handle boundary k
return Ldexp(y, k)
}

View File

@ -1,10 +0,0 @@
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package math
// Make expGo and exp2Go available for testing.
func ExpGo(x float64) float64 { return expGo(x) }
func Exp2Go(x float64) float64 { return exp2Go(x) }

View File

@ -121,7 +121,12 @@ package math
// Expm1(-Inf) = -1 // Expm1(-Inf) = -1
// Expm1(NaN) = NaN // Expm1(NaN) = NaN
// Very large values overflow to -1 or +Inf. // Very large values overflow to -1 or +Inf.
func libc_expm1(float64) float64 __asm__("expm1")
func Expm1(x float64) float64 { func Expm1(x float64) float64 {
return libc_expm1(x)
}
func expm1(x float64) float64 {
const ( const (
Othreshold = 7.09782712893383973096e+02 // 0x40862E42FEFA39EF Othreshold = 7.09782712893383973096e+02 // 0x40862E42FEFA39EF
Ln2X56 = 3.88162421113569373274e+01 // 0x4043687a9f1af2b1 Ln2X56 = 3.88162421113569373274e+01 // 0x4043687a9f1af2b1

View File

@ -0,0 +1,11 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package math
// Export internal functions for testing.
var ExpGo = exp
var Exp2Go = exp2
var HypotGo = hypot
var SqrtGo = sqrt

View File

@ -7,9 +7,15 @@ package math
// Floor returns the greatest integer value less than or equal to x. // Floor returns the greatest integer value less than or equal to x.
// //
// Special cases are: // Special cases are:
// Floor(±0) = ±0
// Floor(±Inf) = ±Inf // Floor(±Inf) = ±Inf
// Floor(NaN) = NaN // Floor(NaN) = NaN
func libc_floor(float64) float64 __asm__("floor")
func Floor(x float64) float64 { func Floor(x float64) float64 {
return libc_floor(x)
}
func floor(x float64) float64 {
// TODO(rsc): Remove manual inlining of IsNaN, IsInf // TODO(rsc): Remove manual inlining of IsNaN, IsInf
// when compiler does it for us // when compiler does it for us
if x == 0 || x != x || x > MaxFloat64 || x < -MaxFloat64 { // x == 0 || IsNaN(x) || IsInf(x, 0) if x == 0 || x != x || x > MaxFloat64 || x < -MaxFloat64 { // x == 0 || IsNaN(x) || IsInf(x, 0)
@ -29,16 +35,30 @@ func Floor(x float64) float64 {
// Ceil returns the least integer value greater than or equal to x. // Ceil returns the least integer value greater than or equal to x.
// //
// Special cases are: // Special cases are:
// Ceil(±0) = ±0
// Ceil(±Inf) = ±Inf // Ceil(±Inf) = ±Inf
// Ceil(NaN) = NaN // Ceil(NaN) = NaN
func Ceil(x float64) float64 { return -Floor(-x) } func libc_ceil(float64) float64 __asm__("ceil")
func Ceil(x float64) float64 {
return libc_ceil(x)
}
func ceil(x float64) float64 {
return -Floor(-x)
}
// Trunc returns the integer value of x. // Trunc returns the integer value of x.
// //
// Special cases are: // Special cases are:
// Trunc(±0) = ±0
// Trunc(±Inf) = ±Inf // Trunc(±Inf) = ±Inf
// Trunc(NaN) = NaN // Trunc(NaN) = NaN
func libc_trunc(float64) float64 __asm__("trunc")
func Trunc(x float64) float64 { func Trunc(x float64) float64 {
return libc_trunc(x)
}
func trunc(x float64) float64 {
// TODO(rsc): Remove manual inlining of IsNaN, IsInf // TODO(rsc): Remove manual inlining of IsNaN, IsInf
// when compiler does it for us // when compiler does it for us
if x == 0 || x != x || x > MaxFloat64 || x < -MaxFloat64 { // x == 0 || IsNaN(x) || IsInf(x, 0) if x == 0 || x != x || x > MaxFloat64 || x < -MaxFloat64 { // x == 0 || IsNaN(x) || IsInf(x, 0)

View File

@ -14,6 +14,10 @@ package math
// Frexp(±Inf) = ±Inf, 0 // Frexp(±Inf) = ±Inf, 0
// Frexp(NaN) = NaN, 0 // Frexp(NaN) = NaN, 0
func Frexp(f float64) (frac float64, exp int) { func Frexp(f float64) (frac float64, exp int) {
return frexp(f)
}
func frexp(f float64) (frac float64, exp int) {
// TODO(rsc): Remove manual inlining of IsNaN, IsInf // TODO(rsc): Remove manual inlining of IsNaN, IsInf
// when compiler does it for us // when compiler does it for us
// special cases // special cases

View File

@ -15,6 +15,10 @@ package math
// Hypot(p, q) = +Inf if p or q is infinite // Hypot(p, q) = +Inf if p or q is infinite
// Hypot(p, q) = NaN if p or q is NaN // Hypot(p, q) = NaN if p or q is NaN
func Hypot(p, q float64) float64 { func Hypot(p, q float64) float64 {
return hypot(p, q)
}
func hypot(p, q float64) float64 {
// TODO(rsc): Remove manual inlining of IsNaN, IsInf // TODO(rsc): Remove manual inlining of IsNaN, IsInf
// when compiler does it for us // when compiler does it for us
// special cases // special cases

View File

@ -1,63 +0,0 @@
// Copyright 2009-2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package math
/*
Hypot -- sqrt(p*p + q*q), but overflows only if the result does.
See:
Cleve Moler and Donald Morrison,
Replacing Square Roots by Pythagorean Sums
IBM Journal of Research and Development,
Vol. 27, Number 6, pp. 577-581, Nov. 1983
*/
// Hypot computes Sqrt(p*p + q*q), taking care to avoid
// unnecessary overflow and underflow.
//
// Special cases are:
// Hypot(p, q) = +Inf if p or q is infinite
// Hypot(p, q) = NaN if p or q is NaN
func hypotGo(p, q float64) float64 {
// TODO(rsc): Remove manual inlining of IsNaN, IsInf
// when compiler does it for us
// special cases
switch {
case p < -MaxFloat64 || p > MaxFloat64 || q < -MaxFloat64 || q > MaxFloat64: // IsInf(p, 0) || IsInf(q, 0):
return Inf(1)
case p != p || q != q: // IsNaN(p) || IsNaN(q):
return NaN()
}
if p < 0 {
p = -p
}
if q < 0 {
q = -q
}
if p < q {
p, q = q, p
}
if p == 0 {
return 0
}
pfac := p
q = q / p
r := q
p = 1
for {
r = r * r
s := r + 4
if s == 4 {
return p * pfac
}
r = r / s
p = p + 2*r*p
q = q * r
r = q / p
}
panic("unreachable")
}

View File

@ -1,9 +0,0 @@
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package math
// Make hypotGo available for testing.
func HypotGo(x, y float64) float64 { return hypotGo(x, y) }

View File

@ -11,7 +11,12 @@ package math
// Ldexp(±0, exp) = ±0 // Ldexp(±0, exp) = ±0
// Ldexp(±Inf, exp) = ±Inf // Ldexp(±Inf, exp) = ±Inf
// Ldexp(NaN, exp) = NaN // Ldexp(NaN, exp) = NaN
func libc_ldexp(float64, int) float64 __asm__("ldexp")
func Ldexp(frac float64, exp int) float64 { func Ldexp(frac float64, exp int) float64 {
return libc_ldexp(frac, exp)
}
func ldexp(frac float64, exp int) float64 {
// TODO(rsc): Remove manual inlining of IsNaN, IsInf // TODO(rsc): Remove manual inlining of IsNaN, IsInf
// when compiler does it for us // when compiler does it for us
// special cases // special cases

View File

@ -77,7 +77,12 @@ package math
// Log(0) = -Inf // Log(0) = -Inf
// Log(x < 0) = NaN // Log(x < 0) = NaN
// Log(NaN) = NaN // Log(NaN) = NaN
func libc_log(float64) float64 __asm__("log")
func Log(x float64) float64 { func Log(x float64) float64 {
return libc_log(x)
}
func log(x float64) float64 {
const ( const (
Ln2Hi = 6.93147180369123816490e-01 /* 3fe62e42 fee00000 */ Ln2Hi = 6.93147180369123816490e-01 /* 3fe62e42 fee00000 */
Ln2Lo = 1.90821492927058770002e-10 /* 3dea39ef 35793c76 */ Ln2Lo = 1.90821492927058770002e-10 /* 3dea39ef 35793c76 */

View File

@ -6,8 +6,22 @@ package math
// Log10 returns the decimal logarithm of x. // Log10 returns the decimal logarithm of x.
// The special cases are the same as for Log. // The special cases are the same as for Log.
func Log10(x float64) float64 { return Log(x) * (1 / Ln10) } func libc_log10(float64) float64 __asm__("log10")
func Log10(x float64) float64 {
return libc_log10(x)
}
func log10(x float64) float64 {
return Log(x) * (1 / Ln10)
}
// Log2 returns the binary logarithm of x. // Log2 returns the binary logarithm of x.
// The special cases are the same as for Log. // The special cases are the same as for Log.
func Log2(x float64) float64 { return Log(x) * (1 / Ln2) } func libc_log2(float64) float64 __asm__("log2")
func Log2(x float64) float64 {
return libc_log2(x)
}
func log2(x float64) float64 {
return Log(x) * (1 / Ln2)
}

Some files were not shown because too many files have changed in this diff Show More