mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
remove semis after statements in one-statement statement lists
R=rsc, r http://go/go-review/1025029
This commit is contained in:
parent
18ccbc69f8
commit
40621d5c0d
408 changed files with 7859 additions and 7859 deletions
|
|
@ -22,7 +22,7 @@ func fibber(c chan *big.Int, out chan string, n int64) {
|
||||||
|
|
||||||
i := big.NewInt(n);
|
i := big.NewInt(n);
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
c <- i;
|
c <- i
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
j := <-c;
|
j := <-c;
|
||||||
|
|
@ -38,6 +38,6 @@ func main() {
|
||||||
go fibber(c, out, 0);
|
go fibber(c, out, 0);
|
||||||
go fibber(c, out, 1);
|
go fibber(c, out, 1);
|
||||||
for i := 0; i < 200; i++ {
|
for i := 0; i < 200; i++ {
|
||||||
println(<-out);
|
println(<-out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ func NewInt(x int64) *Int { return new(Int).SetInt64(x) }
|
||||||
// making zero values useful and gmp's decision not to.
|
// making zero values useful and gmp's decision not to.
|
||||||
func (z *Int) doinit() {
|
func (z *Int) doinit() {
|
||||||
if z.init {
|
if z.init {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
z.init = true;
|
z.init = true;
|
||||||
C.mpz_init(&z.i[0]);
|
C.mpz_init(&z.i[0]);
|
||||||
|
|
@ -162,9 +162,9 @@ func (z *Int) Set(x *Int) *Int {
|
||||||
func (z *Int) SetBytes(b []byte) *Int {
|
func (z *Int) SetBytes(b []byte) *Int {
|
||||||
z.doinit();
|
z.doinit();
|
||||||
if len(b) == 0 {
|
if len(b) == 0 {
|
||||||
z.SetInt64(0);
|
z.SetInt64(0)
|
||||||
} else {
|
} else {
|
||||||
C.mpz_import(&z.i[0], C.size_t(len(b)), 1, 1, 1, 0, unsafe.Pointer(&b[0]));
|
C.mpz_import(&z.i[0], C.size_t(len(b)), 1, 1, 1, 0, unsafe.Pointer(&b[0]))
|
||||||
}
|
}
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
@ -183,12 +183,12 @@ func (z *Int) SetInt64(x int64) *Int {
|
||||||
func (z *Int) SetString(s string, base int) os.Error {
|
func (z *Int) SetString(s string, base int) os.Error {
|
||||||
z.doinit();
|
z.doinit();
|
||||||
if base < 2 || base > 36 {
|
if base < 2 || base > 36 {
|
||||||
return os.EINVAL;
|
return os.EINVAL
|
||||||
}
|
}
|
||||||
p := C.CString(s);
|
p := C.CString(s);
|
||||||
defer C.free(unsafe.Pointer(p));
|
defer C.free(unsafe.Pointer(p));
|
||||||
if C.mpz_set_str(&z.i[0], p, C.int(base)) < 0 {
|
if C.mpz_set_str(&z.i[0], p, C.int(base)) < 0 {
|
||||||
return os.EINVAL;
|
return os.EINVAL
|
||||||
}
|
}
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
@ -196,7 +196,7 @@ func (z *Int) SetString(s string, base int) os.Error {
|
||||||
// String returns the decimal representation of z.
|
// String returns the decimal representation of z.
|
||||||
func (z *Int) String() string {
|
func (z *Int) String() string {
|
||||||
if z == nil {
|
if z == nil {
|
||||||
return "nil";
|
return "nil"
|
||||||
}
|
}
|
||||||
z.doinit();
|
z.doinit();
|
||||||
p := C.mpz_get_str(nil, 10, &z.i[0]);
|
p := C.mpz_get_str(nil, 10, &z.i[0]);
|
||||||
|
|
@ -207,7 +207,7 @@ func (z *Int) String() string {
|
||||||
|
|
||||||
func (z *Int) destroy() {
|
func (z *Int) destroy() {
|
||||||
if z.init {
|
if z.init {
|
||||||
C.mpz_clear(&z.i[0]);
|
C.mpz_clear(&z.i[0])
|
||||||
}
|
}
|
||||||
z.init = false;
|
z.init = false;
|
||||||
}
|
}
|
||||||
|
|
@ -287,16 +287,16 @@ func (z *Int) Exp(x, y, m *Int) *Int {
|
||||||
y.doinit();
|
y.doinit();
|
||||||
z.doinit();
|
z.doinit();
|
||||||
if m == nil {
|
if m == nil {
|
||||||
C.mpz_pow_ui(&z.i[0], &x.i[0], C.mpz_get_ui(&y.i[0]));
|
C.mpz_pow_ui(&z.i[0], &x.i[0], C.mpz_get_ui(&y.i[0]))
|
||||||
} else {
|
} else {
|
||||||
C.mpz_powm(&z.i[0], &x.i[0], &y.i[0], &m.i[0]);
|
C.mpz_powm(&z.i[0], &x.i[0], &y.i[0], &m.i[0])
|
||||||
}
|
}
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
func (z *Int) Int64() int64 {
|
func (z *Int) Int64() int64 {
|
||||||
if !z.init {
|
if !z.init {
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
return int64(C.mpz_get_si(&z.i[0]));
|
return int64(C.mpz_get_si(&z.i[0]));
|
||||||
}
|
}
|
||||||
|
|
@ -334,9 +334,9 @@ func CmpInt(x, y *Int) int {
|
||||||
y.doinit();
|
y.doinit();
|
||||||
switch cmp := C.mpz_cmp(&x.i[0], &y.i[0]); {
|
switch cmp := C.mpz_cmp(&x.i[0], &y.i[0]); {
|
||||||
case cmp < 0:
|
case cmp < 0:
|
||||||
return -1;
|
return -1
|
||||||
case cmp == 0:
|
case cmp == 0:
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
return +1;
|
return +1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,13 +54,13 @@ var (
|
||||||
|
|
||||||
func extractDigit() int64 {
|
func extractDigit() int64 {
|
||||||
if big.CmpInt(numer, accum) > 0 {
|
if big.CmpInt(numer, accum) > 0 {
|
||||||
return -1;
|
return -1
|
||||||
}
|
}
|
||||||
tmp1.Lsh(numer, 1).Add(tmp1, numer).Add(tmp1, accum);
|
tmp1.Lsh(numer, 1).Add(tmp1, numer).Add(tmp1, accum);
|
||||||
big.DivModInt(tmp1, tmp2, tmp1, denom);
|
big.DivModInt(tmp1, tmp2, tmp1, denom);
|
||||||
tmp2.Add(tmp2, numer);
|
tmp2.Add(tmp2, numer);
|
||||||
if big.CmpInt(tmp2, denom) >= 0 {
|
if big.CmpInt(tmp2, denom) >= 0 {
|
||||||
return -1;
|
return -1
|
||||||
}
|
}
|
||||||
return tmp1.Int64();
|
return tmp1.Int64();
|
||||||
}
|
}
|
||||||
|
|
@ -95,7 +95,7 @@ func main() {
|
||||||
if i++; i%50 == 0 {
|
if i++; i%50 == 0 {
|
||||||
fmt.Printf("\n");
|
fmt.Printf("\n");
|
||||||
if i >= 1000 {
|
if i >= 1000 {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ func fibber(c, out chan int64, i int64) {
|
||||||
runtime.LockOSThread();
|
runtime.LockOSThread();
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
c <- i;
|
c <- i
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
j := <-c;
|
j := <-c;
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,5 @@ import "stdio"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// stdio.Stdout.WriteString("hello, world\n");
|
// stdio.Stdout.WriteString("hello, world\n");
|
||||||
stdio.Puts("hello, world");
|
stdio.Puts("hello, world")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ func openProg(name string) *Prog {
|
||||||
// Instead, turn it into a new Error that will return
|
// Instead, turn it into a new Error that will return
|
||||||
// details for all the errors.
|
// details for all the errors.
|
||||||
for _, e := range list {
|
for _, e := range list {
|
||||||
fmt.Fprintln(os.Stderr, e);
|
fmt.Fprintln(os.Stderr, e)
|
||||||
}
|
}
|
||||||
os.Exit(2);
|
os.Exit(2);
|
||||||
}
|
}
|
||||||
|
|
@ -94,16 +94,16 @@ func openProg(name string) *Prog {
|
||||||
}
|
}
|
||||||
sawC = true;
|
sawC = true;
|
||||||
if s.Name != nil {
|
if s.Name != nil {
|
||||||
error(s.Path[0].Pos(), `cannot rename import "C"`);
|
error(s.Path[0].Pos(), `cannot rename import "C"`)
|
||||||
}
|
}
|
||||||
if s.Doc != nil {
|
if s.Doc != nil {
|
||||||
p.Preamble += doc.CommentText(s.Doc) + "\n";
|
p.Preamble += doc.CommentText(s.Doc) + "\n"
|
||||||
} else if len(d.Specs) == 1 && d.Doc != nil {
|
} else if len(d.Specs) == 1 && d.Doc != nil {
|
||||||
p.Preamble += doc.CommentText(d.Doc) + "\n";
|
p.Preamble += doc.CommentText(d.Doc) + "\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ws == 0 {
|
if ws == 0 {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
d.Specs = d.Specs[0:ws];
|
d.Specs = d.Specs[0:ws];
|
||||||
p.AST.Decls[w] = d;
|
p.AST.Decls[w] = d;
|
||||||
|
|
@ -112,7 +112,7 @@ func openProg(name string) *Prog {
|
||||||
p.AST.Decls = p.AST.Decls[0:w];
|
p.AST.Decls = p.AST.Decls[0:w];
|
||||||
|
|
||||||
if !sawC {
|
if !sawC {
|
||||||
error(noPos, `cannot find import "C"`);
|
error(noPos, `cannot find import "C"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accumulate pointers to uses of C.x.
|
// Accumulate pointers to uses of C.x.
|
||||||
|
|
@ -135,7 +135,7 @@ func walk(x interface{}, p *Prog, context string) {
|
||||||
if i >= cap(p.Crefs) {
|
if i >= cap(p.Crefs) {
|
||||||
new := make([]*Cref, 2*i);
|
new := make([]*Cref, 2*i);
|
||||||
for j, v := range p.Crefs {
|
for j, v := range p.Crefs {
|
||||||
new[j] = v;
|
new[j] = v
|
||||||
}
|
}
|
||||||
p.Crefs = new;
|
p.Crefs = new;
|
||||||
}
|
}
|
||||||
|
|
@ -159,7 +159,7 @@ func walk(x interface{}, p *Prog, context string) {
|
||||||
|
|
||||||
// These are ordered and grouped to match ../../pkg/go/ast/ast.go
|
// These are ordered and grouped to match ../../pkg/go/ast/ast.go
|
||||||
case *ast.Field:
|
case *ast.Field:
|
||||||
walk(&n.Type, p, "type");
|
walk(&n.Type, p, "type")
|
||||||
case *ast.BadExpr:
|
case *ast.BadExpr:
|
||||||
case *ast.Ident:
|
case *ast.Ident:
|
||||||
case *ast.Ellipsis:
|
case *ast.Ellipsis:
|
||||||
|
|
@ -172,14 +172,14 @@ func walk(x interface{}, p *Prog, context string) {
|
||||||
walk(&n.Type, p, "type");
|
walk(&n.Type, p, "type");
|
||||||
walk(n.Elts, p, "expr");
|
walk(n.Elts, p, "expr");
|
||||||
case *ast.ParenExpr:
|
case *ast.ParenExpr:
|
||||||
walk(&n.X, p, context);
|
walk(&n.X, p, context)
|
||||||
case *ast.SelectorExpr:
|
case *ast.SelectorExpr:
|
||||||
walk(&n.X, p, "selector");
|
walk(&n.X, p, "selector")
|
||||||
case *ast.IndexExpr:
|
case *ast.IndexExpr:
|
||||||
walk(&n.X, p, "expr");
|
walk(&n.X, p, "expr");
|
||||||
walk(&n.Index, p, "expr");
|
walk(&n.Index, p, "expr");
|
||||||
if n.End != nil {
|
if n.End != nil {
|
||||||
walk(&n.End, p, "expr");
|
walk(&n.End, p, "expr")
|
||||||
}
|
}
|
||||||
case *ast.TypeAssertExpr:
|
case *ast.TypeAssertExpr:
|
||||||
walk(&n.X, p, "expr");
|
walk(&n.X, p, "expr");
|
||||||
|
|
@ -188,9 +188,9 @@ func walk(x interface{}, p *Prog, context string) {
|
||||||
walk(&n.Fun, p, "call");
|
walk(&n.Fun, p, "call");
|
||||||
walk(n.Args, p, "expr");
|
walk(n.Args, p, "expr");
|
||||||
case *ast.StarExpr:
|
case *ast.StarExpr:
|
||||||
walk(&n.X, p, context);
|
walk(&n.X, p, context)
|
||||||
case *ast.UnaryExpr:
|
case *ast.UnaryExpr:
|
||||||
walk(&n.X, p, "expr");
|
walk(&n.X, p, "expr")
|
||||||
case *ast.BinaryExpr:
|
case *ast.BinaryExpr:
|
||||||
walk(&n.X, p, "expr");
|
walk(&n.X, p, "expr");
|
||||||
walk(&n.Y, p, "expr");
|
walk(&n.Y, p, "expr");
|
||||||
|
|
@ -202,40 +202,40 @@ func walk(x interface{}, p *Prog, context string) {
|
||||||
walk(&n.Len, p, "expr");
|
walk(&n.Len, p, "expr");
|
||||||
walk(&n.Elt, p, "type");
|
walk(&n.Elt, p, "type");
|
||||||
case *ast.StructType:
|
case *ast.StructType:
|
||||||
walk(n.Fields, p, "field");
|
walk(n.Fields, p, "field")
|
||||||
case *ast.FuncType:
|
case *ast.FuncType:
|
||||||
walk(n.Params, p, "field");
|
walk(n.Params, p, "field");
|
||||||
walk(n.Results, p, "field");
|
walk(n.Results, p, "field");
|
||||||
case *ast.InterfaceType:
|
case *ast.InterfaceType:
|
||||||
walk(n.Methods, p, "field");
|
walk(n.Methods, p, "field")
|
||||||
case *ast.MapType:
|
case *ast.MapType:
|
||||||
walk(&n.Key, p, "type");
|
walk(&n.Key, p, "type");
|
||||||
walk(&n.Value, p, "type");
|
walk(&n.Value, p, "type");
|
||||||
case *ast.ChanType:
|
case *ast.ChanType:
|
||||||
walk(&n.Value, p, "type");
|
walk(&n.Value, p, "type")
|
||||||
|
|
||||||
case *ast.BadStmt:
|
case *ast.BadStmt:
|
||||||
case *ast.DeclStmt:
|
case *ast.DeclStmt:
|
||||||
walk(n.Decl, p, "decl");
|
walk(n.Decl, p, "decl")
|
||||||
case *ast.EmptyStmt:
|
case *ast.EmptyStmt:
|
||||||
case *ast.LabeledStmt:
|
case *ast.LabeledStmt:
|
||||||
walk(n.Stmt, p, "stmt");
|
walk(n.Stmt, p, "stmt")
|
||||||
case *ast.ExprStmt:
|
case *ast.ExprStmt:
|
||||||
walk(&n.X, p, "expr");
|
walk(&n.X, p, "expr")
|
||||||
case *ast.IncDecStmt:
|
case *ast.IncDecStmt:
|
||||||
walk(&n.X, p, "expr");
|
walk(&n.X, p, "expr")
|
||||||
case *ast.AssignStmt:
|
case *ast.AssignStmt:
|
||||||
walk(n.Lhs, p, "expr");
|
walk(n.Lhs, p, "expr");
|
||||||
walk(n.Rhs, p, "expr");
|
walk(n.Rhs, p, "expr");
|
||||||
case *ast.GoStmt:
|
case *ast.GoStmt:
|
||||||
walk(n.Call, p, "expr");
|
walk(n.Call, p, "expr")
|
||||||
case *ast.DeferStmt:
|
case *ast.DeferStmt:
|
||||||
walk(n.Call, p, "expr");
|
walk(n.Call, p, "expr")
|
||||||
case *ast.ReturnStmt:
|
case *ast.ReturnStmt:
|
||||||
walk(n.Results, p, "expr");
|
walk(n.Results, p, "expr")
|
||||||
case *ast.BranchStmt:
|
case *ast.BranchStmt:
|
||||||
case *ast.BlockStmt:
|
case *ast.BlockStmt:
|
||||||
walk(n.List, p, "stmt");
|
walk(n.List, p, "stmt")
|
||||||
case *ast.IfStmt:
|
case *ast.IfStmt:
|
||||||
walk(n.Init, p, "stmt");
|
walk(n.Init, p, "stmt");
|
||||||
walk(&n.Cond, p, "expr");
|
walk(&n.Cond, p, "expr");
|
||||||
|
|
@ -260,7 +260,7 @@ func walk(x interface{}, p *Prog, context string) {
|
||||||
walk(n.Rhs, p, "expr");
|
walk(n.Rhs, p, "expr");
|
||||||
walk(n.Body, p, "stmt");
|
walk(n.Body, p, "stmt");
|
||||||
case *ast.SelectStmt:
|
case *ast.SelectStmt:
|
||||||
walk(n.Body, p, "stmt");
|
walk(n.Body, p, "stmt")
|
||||||
case *ast.ForStmt:
|
case *ast.ForStmt:
|
||||||
walk(n.Init, p, "stmt");
|
walk(n.Init, p, "stmt");
|
||||||
walk(&n.Cond, p, "expr");
|
walk(&n.Cond, p, "expr");
|
||||||
|
|
@ -277,47 +277,47 @@ func walk(x interface{}, p *Prog, context string) {
|
||||||
walk(&n.Type, p, "type");
|
walk(&n.Type, p, "type");
|
||||||
walk(n.Values, p, "expr");
|
walk(n.Values, p, "expr");
|
||||||
case *ast.TypeSpec:
|
case *ast.TypeSpec:
|
||||||
walk(&n.Type, p, "type");
|
walk(&n.Type, p, "type")
|
||||||
|
|
||||||
case *ast.BadDecl:
|
case *ast.BadDecl:
|
||||||
case *ast.GenDecl:
|
case *ast.GenDecl:
|
||||||
walk(n.Specs, p, "spec");
|
walk(n.Specs, p, "spec")
|
||||||
case *ast.FuncDecl:
|
case *ast.FuncDecl:
|
||||||
if n.Recv != nil {
|
if n.Recv != nil {
|
||||||
walk(n.Recv, p, "field");
|
walk(n.Recv, p, "field")
|
||||||
}
|
}
|
||||||
walk(n.Type, p, "type");
|
walk(n.Type, p, "type");
|
||||||
if n.Body != nil {
|
if n.Body != nil {
|
||||||
walk(n.Body, p, "stmt");
|
walk(n.Body, p, "stmt")
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.File:
|
case *ast.File:
|
||||||
walk(n.Decls, p, "decl");
|
walk(n.Decls, p, "decl")
|
||||||
|
|
||||||
case *ast.Package:
|
case *ast.Package:
|
||||||
for _, f := range n.Files {
|
for _, f := range n.Files {
|
||||||
walk(f, p, "file");
|
walk(f, p, "file")
|
||||||
}
|
}
|
||||||
|
|
||||||
case []ast.Decl:
|
case []ast.Decl:
|
||||||
for _, d := range n {
|
for _, d := range n {
|
||||||
walk(d, p, context);
|
walk(d, p, context)
|
||||||
}
|
}
|
||||||
case []ast.Expr:
|
case []ast.Expr:
|
||||||
for i := range n {
|
for i := range n {
|
||||||
walk(&n[i], p, context);
|
walk(&n[i], p, context)
|
||||||
}
|
}
|
||||||
case []*ast.Field:
|
case []*ast.Field:
|
||||||
for _, f := range n {
|
for _, f := range n {
|
||||||
walk(f, p, context);
|
walk(f, p, context)
|
||||||
}
|
}
|
||||||
case []ast.Stmt:
|
case []ast.Stmt:
|
||||||
for _, s := range n {
|
for _, s := range n {
|
||||||
walk(s, p, context);
|
walk(s, p, context)
|
||||||
}
|
}
|
||||||
case []ast.Spec:
|
case []ast.Spec:
|
||||||
for _, s := range n {
|
for _, s := range n {
|
||||||
walk(s, p, context);
|
walk(s, p, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ func (p *Prog) loadDebugInfo() {
|
||||||
// Construct a slice of unique names from p.Crefs.
|
// Construct a slice of unique names from p.Crefs.
|
||||||
m := make(map[string]int);
|
m := make(map[string]int);
|
||||||
for _, c := range p.Crefs {
|
for _, c := range p.Crefs {
|
||||||
m[c.Name] = -1;
|
m[c.Name] = -1
|
||||||
}
|
}
|
||||||
names := make([]string, 0, len(m));
|
names := make([]string, 0, len(m));
|
||||||
for name, _ := range m {
|
for name, _ := range m {
|
||||||
|
|
@ -59,40 +59,40 @@ func (p *Prog) loadDebugInfo() {
|
||||||
kind := make(map[string]string);
|
kind := make(map[string]string);
|
||||||
_, stderr := p.gccDebug(b.Bytes());
|
_, stderr := p.gccDebug(b.Bytes());
|
||||||
if stderr == "" {
|
if stderr == "" {
|
||||||
fatal("gcc produced no output");
|
fatal("gcc produced no output")
|
||||||
}
|
}
|
||||||
for _, line := range strings.Split(stderr, "\n", 0) {
|
for _, line := range strings.Split(stderr, "\n", 0) {
|
||||||
if len(line) < 9 || line[0:9] != "cgo-test:" {
|
if len(line) < 9 || line[0:9] != "cgo-test:" {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
line = line[9:len(line)];
|
line = line[9:len(line)];
|
||||||
colon := strings.Index(line, ":");
|
colon := strings.Index(line, ":");
|
||||||
if colon < 0 {
|
if colon < 0 {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
i, err := strconv.Atoi(line[0:colon]);
|
i, err := strconv.Atoi(line[0:colon]);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
what := "";
|
what := "";
|
||||||
switch {
|
switch {
|
||||||
default:
|
default:
|
||||||
continue;
|
continue
|
||||||
case strings.Index(line, ": useless type name in empty declaration") >= 0:
|
case strings.Index(line, ": useless type name in empty declaration") >= 0:
|
||||||
what = "type";
|
what = "type"
|
||||||
case strings.Index(line, ": statement with no effect") >= 0:
|
case strings.Index(line, ": statement with no effect") >= 0:
|
||||||
what = "value";
|
what = "value"
|
||||||
case strings.Index(line, "undeclared") >= 0:
|
case strings.Index(line, "undeclared") >= 0:
|
||||||
what = "error";
|
what = "error"
|
||||||
}
|
}
|
||||||
if old, ok := kind[names[i]]; ok && old != what {
|
if old, ok := kind[names[i]]; ok && old != what {
|
||||||
error(noPos, "inconsistent gcc output about C.%s", names[i]);
|
error(noPos, "inconsistent gcc output about C.%s", names[i])
|
||||||
}
|
}
|
||||||
kind[names[i]] = what;
|
kind[names[i]] = what;
|
||||||
}
|
}
|
||||||
for _, n := range names {
|
for _, n := range names {
|
||||||
if _, ok := kind[n]; !ok {
|
if _, ok := kind[n]; !ok {
|
||||||
error(noPos, "could not determine kind of name for C.%s", n);
|
error(noPos, "could not determine kind of name for C.%s", n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,11 +107,11 @@ func (p *Prog) loadDebugInfo() {
|
||||||
b.Reset();
|
b.Reset();
|
||||||
b.WriteString(p.Preamble);
|
b.WriteString(p.Preamble);
|
||||||
for i, n := range names {
|
for i, n := range names {
|
||||||
fmt.Fprintf(&b, "typeof(%s) *__cgo__%d;\n", n, i);
|
fmt.Fprintf(&b, "typeof(%s) *__cgo__%d;\n", n, i)
|
||||||
}
|
}
|
||||||
d, stderr := p.gccDebug(b.Bytes());
|
d, stderr := p.gccDebug(b.Bytes());
|
||||||
if d == nil {
|
if d == nil {
|
||||||
fatal("gcc failed:\n%s\non input:\n%s", stderr, b.Bytes());
|
fatal("gcc failed:\n%s\non input:\n%s", stderr, b.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
|
// Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
|
||||||
|
|
@ -120,39 +120,39 @@ func (p *Prog) loadDebugInfo() {
|
||||||
for {
|
for {
|
||||||
e, err := r.Next();
|
e, err := r.Next();
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal("reading DWARF entry: %s", err);
|
fatal("reading DWARF entry: %s", err)
|
||||||
}
|
}
|
||||||
if e == nil {
|
if e == nil {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
if e.Tag != dwarf.TagVariable {
|
if e.Tag != dwarf.TagVariable {
|
||||||
goto Continue;
|
goto Continue
|
||||||
}
|
}
|
||||||
name, _ := e.Val(dwarf.AttrName).(string);
|
name, _ := e.Val(dwarf.AttrName).(string);
|
||||||
typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset);
|
typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset);
|
||||||
if name == "" || typOff == 0 {
|
if name == "" || typOff == 0 {
|
||||||
fatal("malformed DWARF TagVariable entry");
|
fatal("malformed DWARF TagVariable entry")
|
||||||
}
|
}
|
||||||
if !strings.HasPrefix(name, "__cgo__") {
|
if !strings.HasPrefix(name, "__cgo__") {
|
||||||
goto Continue;
|
goto Continue
|
||||||
}
|
}
|
||||||
typ, err := d.Type(typOff);
|
typ, err := d.Type(typOff);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal("loading DWARF type: %s", err);
|
fatal("loading DWARF type: %s", err)
|
||||||
}
|
}
|
||||||
t, ok := typ.(*dwarf.PtrType);
|
t, ok := typ.(*dwarf.PtrType);
|
||||||
if !ok || t == nil {
|
if !ok || t == nil {
|
||||||
fatal("internal error: %s has non-pointer type", name);
|
fatal("internal error: %s has non-pointer type", name)
|
||||||
}
|
}
|
||||||
i, err := strconv.Atoi(name[7:len(name)]);
|
i, err := strconv.Atoi(name[7:len(name)]);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal("malformed __cgo__ name: %s", name);
|
fatal("malformed __cgo__ name: %s", name)
|
||||||
}
|
}
|
||||||
types[i] = t.Type;
|
types[i] = t.Type;
|
||||||
|
|
||||||
Continue:
|
Continue:
|
||||||
if e.Tag != dwarf.TagCompileUnit {
|
if e.Tag != dwarf.TagCompileUnit {
|
||||||
r.SkipChildren();
|
r.SkipChildren()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -164,9 +164,9 @@ func (p *Prog) loadDebugInfo() {
|
||||||
c.TypeName = kind[c.Name] == "type";
|
c.TypeName = kind[c.Name] == "type";
|
||||||
f, fok := types[i].(*dwarf.FuncType);
|
f, fok := types[i].(*dwarf.FuncType);
|
||||||
if c.Context == "call" && !c.TypeName && fok {
|
if c.Context == "call" && !c.TypeName && fok {
|
||||||
c.FuncType = conv.FuncType(f);
|
c.FuncType = conv.FuncType(f)
|
||||||
} else {
|
} else {
|
||||||
c.Type = conv.Type(types[i]);
|
c.Type = conv.Type(types[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.Typedef = conv.typedef;
|
p.Typedef = conv.typedef;
|
||||||
|
|
@ -175,10 +175,10 @@ func (p *Prog) loadDebugInfo() {
|
||||||
func concat(a, b []string) []string {
|
func concat(a, b []string) []string {
|
||||||
c := make([]string, len(a)+len(b));
|
c := make([]string, len(a)+len(b));
|
||||||
for i, s := range a {
|
for i, s := range a {
|
||||||
c[i] = s;
|
c[i] = s
|
||||||
}
|
}
|
||||||
for i, s := range b {
|
for i, s := range b {
|
||||||
c[i+len(a)] = s;
|
c[i+len(a)] = s
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
@ -189,7 +189,7 @@ func concat(a, b []string) []string {
|
||||||
func (p *Prog) gccDebug(stdin []byte) (*dwarf.Data, string) {
|
func (p *Prog) gccDebug(stdin []byte) (*dwarf.Data, string) {
|
||||||
machine := "-m32";
|
machine := "-m32";
|
||||||
if p.PtrSize == 8 {
|
if p.PtrSize == 8 {
|
||||||
machine = "-m64";
|
machine = "-m64"
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp := "_cgo_.o";
|
tmp := "_cgo_.o";
|
||||||
|
|
@ -206,7 +206,7 @@ func (p *Prog) gccDebug(stdin []byte) (*dwarf.Data, string) {
|
||||||
};
|
};
|
||||||
_, stderr, ok := run(stdin, concat(base, p.GccOptions));
|
_, stderr, ok := run(stdin, concat(base, p.GccOptions));
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, string(stderr);
|
return nil, string(stderr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to parse f as ELF and Mach-O and hope one works.
|
// Try to parse f as ELF and Mach-O and hope one works.
|
||||||
|
|
@ -216,13 +216,13 @@ func (p *Prog) gccDebug(stdin []byte) (*dwarf.Data, string) {
|
||||||
var err os.Error;
|
var err os.Error;
|
||||||
if f, err = elf.Open(tmp); err != nil {
|
if f, err = elf.Open(tmp); err != nil {
|
||||||
if f, err = macho.Open(tmp); err != nil {
|
if f, err = macho.Open(tmp); err != nil {
|
||||||
fatal("cannot parse gcc output %s as ELF or Mach-O object", tmp);
|
fatal("cannot parse gcc output %s as ELF or Mach-O object", tmp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
d, err := f.DWARF();
|
d, err := f.DWARF();
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal("cannot load DWARF debug information from %s: %s", tmp, err);
|
fatal("cannot load DWARF debug information from %s: %s", tmp, err)
|
||||||
}
|
}
|
||||||
return d, "";
|
return d, "";
|
||||||
}
|
}
|
||||||
|
|
@ -302,7 +302,7 @@ var cnameMap = map[string]string{
|
||||||
func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
||||||
if t, ok := c.m[dtype]; ok {
|
if t, ok := c.m[dtype]; ok {
|
||||||
if t.Go == nil {
|
if t.Go == nil {
|
||||||
fatal("type conversion loop at %s", dtype);
|
fatal("type conversion loop at %s", dtype)
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
@ -312,17 +312,17 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
||||||
t.Align = -1;
|
t.Align = -1;
|
||||||
t.C = dtype.Common().Name;
|
t.C = dtype.Common().Name;
|
||||||
if t.Size < 0 {
|
if t.Size < 0 {
|
||||||
fatal("dwarf.Type %s reports unknown size", dtype);
|
fatal("dwarf.Type %s reports unknown size", dtype)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.m[dtype] = t;
|
c.m[dtype] = t;
|
||||||
switch dt := dtype.(type) {
|
switch dt := dtype.(type) {
|
||||||
default:
|
default:
|
||||||
fatal("unexpected type: %s", dtype);
|
fatal("unexpected type: %s", dtype)
|
||||||
|
|
||||||
case *dwarf.AddrType:
|
case *dwarf.AddrType:
|
||||||
if t.Size != c.ptrSize {
|
if t.Size != c.ptrSize {
|
||||||
fatal("unexpected: %d-byte address type - %s", t.Size, dtype);
|
fatal("unexpected: %d-byte address type - %s", t.Size, dtype)
|
||||||
}
|
}
|
||||||
t.Go = c.uintptr;
|
t.Go = c.uintptr;
|
||||||
t.Align = t.Size;
|
t.Align = t.Size;
|
||||||
|
|
@ -344,7 +344,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
||||||
|
|
||||||
case *dwarf.CharType:
|
case *dwarf.CharType:
|
||||||
if t.Size != 1 {
|
if t.Size != 1 {
|
||||||
fatal("unexpected: %d-byte char type - %s", t.Size, dtype);
|
fatal("unexpected: %d-byte char type - %s", t.Size, dtype)
|
||||||
}
|
}
|
||||||
t.Go = c.int8;
|
t.Go = c.int8;
|
||||||
t.Align = 1;
|
t.Align = 1;
|
||||||
|
|
@ -352,32 +352,32 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
||||||
case *dwarf.EnumType:
|
case *dwarf.EnumType:
|
||||||
switch t.Size {
|
switch t.Size {
|
||||||
default:
|
default:
|
||||||
fatal("unexpected: %d-byte enum type - %s", t.Size, dtype);
|
fatal("unexpected: %d-byte enum type - %s", t.Size, dtype)
|
||||||
case 1:
|
case 1:
|
||||||
t.Go = c.uint8;
|
t.Go = c.uint8
|
||||||
case 2:
|
case 2:
|
||||||
t.Go = c.uint16;
|
t.Go = c.uint16
|
||||||
case 4:
|
case 4:
|
||||||
t.Go = c.uint32;
|
t.Go = c.uint32
|
||||||
case 8:
|
case 8:
|
||||||
t.Go = c.uint64;
|
t.Go = c.uint64
|
||||||
}
|
}
|
||||||
if t.Align = t.Size; t.Align >= c.ptrSize {
|
if t.Align = t.Size; t.Align >= c.ptrSize {
|
||||||
t.Align = c.ptrSize;
|
t.Align = c.ptrSize
|
||||||
}
|
}
|
||||||
t.C = "enum " + dt.EnumName;
|
t.C = "enum " + dt.EnumName;
|
||||||
|
|
||||||
case *dwarf.FloatType:
|
case *dwarf.FloatType:
|
||||||
switch t.Size {
|
switch t.Size {
|
||||||
default:
|
default:
|
||||||
fatal("unexpected: %d-byte float type - %s", t.Size, dtype);
|
fatal("unexpected: %d-byte float type - %s", t.Size, dtype)
|
||||||
case 4:
|
case 4:
|
||||||
t.Go = c.float32;
|
t.Go = c.float32
|
||||||
case 8:
|
case 8:
|
||||||
t.Go = c.float64;
|
t.Go = c.float64
|
||||||
}
|
}
|
||||||
if t.Align = t.Size; t.Align >= c.ptrSize {
|
if t.Align = t.Size; t.Align >= c.ptrSize {
|
||||||
t.Align = c.ptrSize;
|
t.Align = c.ptrSize
|
||||||
}
|
}
|
||||||
|
|
||||||
case *dwarf.FuncType:
|
case *dwarf.FuncType:
|
||||||
|
|
@ -388,22 +388,22 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
||||||
|
|
||||||
case *dwarf.IntType:
|
case *dwarf.IntType:
|
||||||
if dt.BitSize > 0 {
|
if dt.BitSize > 0 {
|
||||||
fatal("unexpected: %d-bit int type - %s", dt.BitSize, dtype);
|
fatal("unexpected: %d-bit int type - %s", dt.BitSize, dtype)
|
||||||
}
|
}
|
||||||
switch t.Size {
|
switch t.Size {
|
||||||
default:
|
default:
|
||||||
fatal("unexpected: %d-byte int type - %s", t.Size, dtype);
|
fatal("unexpected: %d-byte int type - %s", t.Size, dtype)
|
||||||
case 1:
|
case 1:
|
||||||
t.Go = c.int8;
|
t.Go = c.int8
|
||||||
case 2:
|
case 2:
|
||||||
t.Go = c.int16;
|
t.Go = c.int16
|
||||||
case 4:
|
case 4:
|
||||||
t.Go = c.int32;
|
t.Go = c.int32
|
||||||
case 8:
|
case 8:
|
||||||
t.Go = c.int64;
|
t.Go = c.int64
|
||||||
}
|
}
|
||||||
if t.Align = t.Size; t.Align >= c.ptrSize {
|
if t.Align = t.Size; t.Align >= c.ptrSize {
|
||||||
t.Align = c.ptrSize;
|
t.Align = c.ptrSize
|
||||||
}
|
}
|
||||||
|
|
||||||
case *dwarf.PtrType:
|
case *dwarf.PtrType:
|
||||||
|
|
@ -436,7 +436,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
||||||
tag = "__" + strconv.Itoa(c.tagGen);
|
tag = "__" + strconv.Itoa(c.tagGen);
|
||||||
c.tagGen++;
|
c.tagGen++;
|
||||||
} else if t.C == "" {
|
} else if t.C == "" {
|
||||||
t.C = dt.Kind + " " + tag;
|
t.C = dt.Kind + " " + tag
|
||||||
}
|
}
|
||||||
name := c.Ident("_C" + dt.Kind + "_" + tag);
|
name := c.Ident("_C" + dt.Kind + "_" + tag);
|
||||||
t.Go = name; // publish before recursive calls
|
t.Go = name; // publish before recursive calls
|
||||||
|
|
@ -444,12 +444,12 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
||||||
case "union", "class":
|
case "union", "class":
|
||||||
c.typedef[name.Value] = c.Opaque(t.Size);
|
c.typedef[name.Value] = c.Opaque(t.Size);
|
||||||
if t.C == "" {
|
if t.C == "" {
|
||||||
t.C = fmt.Sprintf("typeof(unsigned char[%d])", t.Size);
|
t.C = fmt.Sprintf("typeof(unsigned char[%d])", t.Size)
|
||||||
}
|
}
|
||||||
case "struct":
|
case "struct":
|
||||||
g, csyntax, align := c.Struct(dt);
|
g, csyntax, align := c.Struct(dt);
|
||||||
if t.C == "" {
|
if t.C == "" {
|
||||||
t.C = csyntax;
|
t.C = csyntax
|
||||||
}
|
}
|
||||||
t.Align = align;
|
t.Align = align;
|
||||||
c.typedef[name.Value] = g;
|
c.typedef[name.Value] = g;
|
||||||
|
|
@ -472,34 +472,34 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
||||||
t.Size = sub.Size;
|
t.Size = sub.Size;
|
||||||
t.Align = sub.Align;
|
t.Align = sub.Align;
|
||||||
if _, ok := c.typedef[name.Value]; !ok {
|
if _, ok := c.typedef[name.Value]; !ok {
|
||||||
c.typedef[name.Value] = sub.Go;
|
c.typedef[name.Value] = sub.Go
|
||||||
}
|
}
|
||||||
|
|
||||||
case *dwarf.UcharType:
|
case *dwarf.UcharType:
|
||||||
if t.Size != 1 {
|
if t.Size != 1 {
|
||||||
fatal("unexpected: %d-byte uchar type - %s", t.Size, dtype);
|
fatal("unexpected: %d-byte uchar type - %s", t.Size, dtype)
|
||||||
}
|
}
|
||||||
t.Go = c.uint8;
|
t.Go = c.uint8;
|
||||||
t.Align = 1;
|
t.Align = 1;
|
||||||
|
|
||||||
case *dwarf.UintType:
|
case *dwarf.UintType:
|
||||||
if dt.BitSize > 0 {
|
if dt.BitSize > 0 {
|
||||||
fatal("unexpected: %d-bit uint type - %s", dt.BitSize, dtype);
|
fatal("unexpected: %d-bit uint type - %s", dt.BitSize, dtype)
|
||||||
}
|
}
|
||||||
switch t.Size {
|
switch t.Size {
|
||||||
default:
|
default:
|
||||||
fatal("unexpected: %d-byte uint type - %s", t.Size, dtype);
|
fatal("unexpected: %d-byte uint type - %s", t.Size, dtype)
|
||||||
case 1:
|
case 1:
|
||||||
t.Go = c.uint8;
|
t.Go = c.uint8
|
||||||
case 2:
|
case 2:
|
||||||
t.Go = c.uint16;
|
t.Go = c.uint16
|
||||||
case 4:
|
case 4:
|
||||||
t.Go = c.uint32;
|
t.Go = c.uint32
|
||||||
case 8:
|
case 8:
|
||||||
t.Go = c.uint64;
|
t.Go = c.uint64
|
||||||
}
|
}
|
||||||
if t.Align = t.Size; t.Align >= c.ptrSize {
|
if t.Align = t.Size; t.Align >= c.ptrSize {
|
||||||
t.Align = c.ptrSize;
|
t.Align = c.ptrSize
|
||||||
}
|
}
|
||||||
|
|
||||||
case *dwarf.VoidType:
|
case *dwarf.VoidType:
|
||||||
|
|
@ -512,7 +512,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
||||||
s := dtype.Common().Name;
|
s := dtype.Common().Name;
|
||||||
if s != "" {
|
if s != "" {
|
||||||
if ss, ok := cnameMap[s]; ok {
|
if ss, ok := cnameMap[s]; ok {
|
||||||
s = ss;
|
s = ss
|
||||||
}
|
}
|
||||||
s = strings.Join(strings.Split(s, " ", 0), ""); // strip spaces
|
s = strings.Join(strings.Split(s, " ", 0), ""); // strip spaces
|
||||||
name := c.Ident("_C_"+s);
|
name := c.Ident("_C_"+s);
|
||||||
|
|
@ -522,7 +522,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.C == "" {
|
if t.C == "" {
|
||||||
fatal("internal error: did not create C name for %s", dtype);
|
fatal("internal error: did not create C name for %s", dtype)
|
||||||
}
|
}
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
|
|
@ -541,14 +541,14 @@ func (c *typeConv) FuncArg(dtype dwarf.Type) *Type {
|
||||||
Align: c.ptrSize,
|
Align: c.ptrSize,
|
||||||
Go: &ast.StarExpr{X: t.Go},
|
Go: &ast.StarExpr{X: t.Go},
|
||||||
C: t.C + "*",
|
C: t.C + "*",
|
||||||
};
|
}
|
||||||
case *dwarf.TypedefType:
|
case *dwarf.TypedefType:
|
||||||
// C has much more relaxed rules than Go for
|
// C has much more relaxed rules than Go for
|
||||||
// implicit type conversions. When the parameter
|
// implicit type conversions. When the parameter
|
||||||
// is type T defined as *X, simulate a little of the
|
// is type T defined as *X, simulate a little of the
|
||||||
// laxness of C by making the argument *X instead of T.
|
// laxness of C by making the argument *X instead of T.
|
||||||
if ptr, ok := base(dt.Type).(*dwarf.PtrType); ok {
|
if ptr, ok := base(dt.Type).(*dwarf.PtrType); ok {
|
||||||
return c.Type(ptr);
|
return c.Type(ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
|
|
@ -587,7 +587,7 @@ func (c *typeConv) Opaque(n int64) ast.Expr {
|
||||||
return &ast.ArrayType{
|
return &ast.ArrayType{
|
||||||
Len: c.intExpr(n),
|
Len: c.intExpr(n),
|
||||||
Elt: c.byte,
|
Elt: c.byte,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expr for integer n.
|
// Expr for integer n.
|
||||||
|
|
@ -595,7 +595,7 @@ func (c *typeConv) intExpr(n int64) ast.Expr {
|
||||||
return &ast.BasicLit{
|
return &ast.BasicLit{
|
||||||
Kind: token.INT,
|
Kind: token.INT,
|
||||||
Value: strings.Bytes(strconv.Itoa64(n)),
|
Value: strings.Bytes(strconv.Itoa64(n)),
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add padding of given size to fld.
|
// Add padding of given size to fld.
|
||||||
|
|
@ -623,7 +623,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType) (expr *ast.StructType, csyntax s
|
||||||
off += t.Size;
|
off += t.Size;
|
||||||
csyntax += t.C + " " + f.Name + "; ";
|
csyntax += t.C + " " + f.Name + "; ";
|
||||||
if t.Align > align {
|
if t.Align > align {
|
||||||
align = t.Align;
|
align = t.Align
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if off < dt.ByteSize {
|
if off < dt.ByteSize {
|
||||||
|
|
@ -631,7 +631,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType) (expr *ast.StructType, csyntax s
|
||||||
off = dt.ByteSize;
|
off = dt.ByteSize;
|
||||||
}
|
}
|
||||||
if off != dt.ByteSize {
|
if off != dt.ByteSize {
|
||||||
fatal("struct size calculation error");
|
fatal("struct size calculation error")
|
||||||
}
|
}
|
||||||
csyntax += "}";
|
csyntax += "}";
|
||||||
expr = &ast.StructType{Fields: fld};
|
expr = &ast.StructType{Fields: fld};
|
||||||
|
|
|
||||||
|
|
@ -45,18 +45,18 @@ func main() {
|
||||||
|
|
||||||
arch := os.Getenv("GOARCH");
|
arch := os.Getenv("GOARCH");
|
||||||
if arch == "" {
|
if arch == "" {
|
||||||
fatal("$GOARCH is not set");
|
fatal("$GOARCH is not set")
|
||||||
}
|
}
|
||||||
ptrSize, ok := ptrSizeMap[arch];
|
ptrSize, ok := ptrSizeMap[arch];
|
||||||
if !ok {
|
if !ok {
|
||||||
fatal("unknown architecture %s", arch);
|
fatal("unknown architecture %s", arch)
|
||||||
}
|
}
|
||||||
|
|
||||||
p := openProg(input);
|
p := openProg(input);
|
||||||
for _, cref := range p.Crefs {
|
for _, cref := range p.Crefs {
|
||||||
// Convert C.ulong to C.unsigned long, etc.
|
// Convert C.ulong to C.unsigned long, etc.
|
||||||
if expand, ok := expandName[cref.Name]; ok {
|
if expand, ok := expandName[cref.Name]; ok {
|
||||||
cref.Name = expand;
|
cref.Name = expand
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,7 +79,7 @@ func main() {
|
||||||
*cref.Expr = cref.Type.Go;
|
*cref.Expr = cref.Type.Go;
|
||||||
case "expr":
|
case "expr":
|
||||||
if cref.TypeName {
|
if cref.TypeName {
|
||||||
error((*cref.Expr).Pos(), "type C.%s used as expression", cref.Name);
|
error((*cref.Expr).Pos(), "type C.%s used as expression", cref.Name)
|
||||||
}
|
}
|
||||||
// Reference to C variable.
|
// Reference to C variable.
|
||||||
// We declare a pointer and arrange to have it filled in.
|
// We declare a pointer and arrange to have it filled in.
|
||||||
|
|
@ -87,13 +87,13 @@ func main() {
|
||||||
p.Vardef[cref.Name] = cref.Type;
|
p.Vardef[cref.Name] = cref.Type;
|
||||||
case "type":
|
case "type":
|
||||||
if !cref.TypeName {
|
if !cref.TypeName {
|
||||||
error((*cref.Expr).Pos(), "expression C.%s used as type", cref.Name);
|
error((*cref.Expr).Pos(), "expression C.%s used as type", cref.Name)
|
||||||
}
|
}
|
||||||
*cref.Expr = cref.Type.Go;
|
*cref.Expr = cref.Type.Go;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if nerrors > 0 {
|
if nerrors > 0 {
|
||||||
os.Exit(2);
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
p.PackagePath = p.Package;
|
p.PackagePath = p.Package;
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import (
|
||||||
func creat(name string) *os.File {
|
func creat(name string) *os.File {
|
||||||
f, err := os.Open(name, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0666);
|
f, err := os.Open(name, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0666);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal("%s", err);
|
fatal("%s", err)
|
||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
@ -27,7 +27,7 @@ func (p *Prog) writeOutput(srcfile string) {
|
||||||
|
|
||||||
base := srcfile;
|
base := srcfile;
|
||||||
if strings.HasSuffix(base, ".go") {
|
if strings.HasSuffix(base, ".go") {
|
||||||
base = base[0 : len(base)-3];
|
base = base[0 : len(base)-3]
|
||||||
}
|
}
|
||||||
fgo1 := creat(base + ".cgo1.go");
|
fgo1 := creat(base + ".cgo1.go");
|
||||||
fgo2 := creat(base + ".cgo2.go");
|
fgo2 := creat(base + ".cgo2.go");
|
||||||
|
|
@ -80,7 +80,7 @@ func (p *Prog) writeOutput(srcfile string) {
|
||||||
|
|
||||||
if name == "CString" || name == "GoString" {
|
if name == "CString" || name == "GoString" {
|
||||||
// The builtins are already defined in the C prolog.
|
// The builtins are already defined in the C prolog.
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct a gcc struct matching the 6c argument frame.
|
// Construct a gcc struct matching the 6c argument frame.
|
||||||
|
|
@ -150,12 +150,12 @@ func (p *Prog) writeOutput(srcfile string) {
|
||||||
fmt.Fprintf(fgcc, "\t%s *a = v;\n", structType);
|
fmt.Fprintf(fgcc, "\t%s *a = v;\n", structType);
|
||||||
fmt.Fprintf(fgcc, "\t");
|
fmt.Fprintf(fgcc, "\t");
|
||||||
if def.Result != nil {
|
if def.Result != nil {
|
||||||
fmt.Fprintf(fgcc, "a->r = ");
|
fmt.Fprintf(fgcc, "a->r = ")
|
||||||
}
|
}
|
||||||
fmt.Fprintf(fgcc, "%s(", name);
|
fmt.Fprintf(fgcc, "%s(", name);
|
||||||
for i := range def.Params {
|
for i := range def.Params {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
fmt.Fprintf(fgcc, ", ");
|
fmt.Fprintf(fgcc, ", ")
|
||||||
}
|
}
|
||||||
fmt.Fprintf(fgcc, "a->p%d", i);
|
fmt.Fprintf(fgcc, "a->p%d", i);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ type ByteReaderAt []byte
|
||||||
|
|
||||||
func (r ByteReaderAt) ReadAt(p []byte, off int64) (n int, err os.Error) {
|
func (r ByteReaderAt) ReadAt(p []byte, off int64) (n int, err os.Error) {
|
||||||
if off >= int64(len(r)) || off < 0 {
|
if off >= int64(len(r)) || off < 0 {
|
||||||
return 0, os.EOF;
|
return 0, os.EOF
|
||||||
}
|
}
|
||||||
return bytes.Copy(p, r[off:len(r)]), nil;
|
return bytes.Copy(p, r[off:len(r)]), nil;
|
||||||
}
|
}
|
||||||
|
|
@ -29,23 +29,23 @@ func (r ByteReaderAt) ReadAt(p []byte, off int64) (n int, err os.Error) {
|
||||||
func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
|
func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
|
||||||
cmd, err := exec.LookPath(argv[0]);
|
cmd, err := exec.LookPath(argv[0]);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal("exec %s: %s", argv[0], err);
|
fatal("exec %s: %s", argv[0], err)
|
||||||
}
|
}
|
||||||
r0, w0, err := os.Pipe();
|
r0, w0, err := os.Pipe();
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal("%s", err);
|
fatal("%s", err)
|
||||||
}
|
}
|
||||||
r1, w1, err := os.Pipe();
|
r1, w1, err := os.Pipe();
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal("%s", err);
|
fatal("%s", err)
|
||||||
}
|
}
|
||||||
r2, w2, err := os.Pipe();
|
r2, w2, err := os.Pipe();
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal("%s", err);
|
fatal("%s", err)
|
||||||
}
|
}
|
||||||
pid, err := os.ForkExec(cmd, argv, os.Environ(), "", []*os.File{r0, w1, w2});
|
pid, err := os.ForkExec(cmd, argv, os.Environ(), "", []*os.File{r0, w1, w2});
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal("%s", err);
|
fatal("%s", err)
|
||||||
}
|
}
|
||||||
r0.Close();
|
r0.Close();
|
||||||
w1.Close();
|
w1.Close();
|
||||||
|
|
@ -70,7 +70,7 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
|
||||||
|
|
||||||
w, err := os.Wait(pid, 0);
|
w, err := os.Wait(pid, 0);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal("%s", err);
|
fatal("%s", err)
|
||||||
}
|
}
|
||||||
ok = w.Exited() && w.ExitStatus() == 0;
|
ok = w.Exited() && w.ExitStatus() == 0;
|
||||||
return;
|
return;
|
||||||
|
|
@ -88,7 +88,7 @@ var noPos token.Position
|
||||||
func error(pos token.Position, msg string, args ...) {
|
func error(pos token.Position, msg string, args ...) {
|
||||||
nerrors++;
|
nerrors++;
|
||||||
if pos.IsValid() {
|
if pos.IsValid() {
|
||||||
fmt.Fprintf(os.Stderr, "%s: ", pos);
|
fmt.Fprintf(os.Stderr, "%s: ", pos)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stderr, msg, args);
|
fmt.Fprintf(os.Stderr, msg, args);
|
||||||
fmt.Fprintf(os.Stderr, "\n");
|
fmt.Fprintf(os.Stderr, "\n");
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ func extractEBNF(src []byte) []byte {
|
||||||
// i = beginning of EBNF text
|
// i = beginning of EBNF text
|
||||||
i := bytes.Index(src, open);
|
i := bytes.Index(src, open);
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
break; // no EBNF found - we are done
|
break // no EBNF found - we are done
|
||||||
}
|
}
|
||||||
i += len(open);
|
i += len(open);
|
||||||
|
|
||||||
|
|
@ -49,14 +49,14 @@ func extractEBNF(src []byte) []byte {
|
||||||
// to maintain correct line numbers in error messages
|
// to maintain correct line numbers in error messages
|
||||||
for _, ch := range src[0:i] {
|
for _, ch := range src[0:i] {
|
||||||
if ch == '\n' {
|
if ch == '\n' {
|
||||||
buf.WriteByte('\n');
|
buf.WriteByte('\n')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// j = end of EBNF text (or end of source)
|
// j = end of EBNF text (or end of source)
|
||||||
j := bytes.Index(src[i:len(src)], close); // close marker
|
j := bytes.Index(src[i:len(src)], close); // close marker
|
||||||
if j < 0 {
|
if j < 0 {
|
||||||
j = len(src)-i;
|
j = len(src)-i
|
||||||
}
|
}
|
||||||
j += i;
|
j += i;
|
||||||
|
|
||||||
|
|
@ -77,28 +77,28 @@ func main() {
|
||||||
var filename string;
|
var filename string;
|
||||||
switch flag.NArg() {
|
switch flag.NArg() {
|
||||||
case 0:
|
case 0:
|
||||||
filename = "/dev/stdin";
|
filename = "/dev/stdin"
|
||||||
case 1:
|
case 1:
|
||||||
filename = flag.Arg(0);
|
filename = flag.Arg(0)
|
||||||
default:
|
default:
|
||||||
usage();
|
usage()
|
||||||
}
|
}
|
||||||
|
|
||||||
src, err := io.ReadFile(filename);
|
src, err := io.ReadFile(filename);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
scanner.PrintError(os.Stderr, err);
|
scanner.PrintError(os.Stderr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if path.Ext(filename) == ".html" {
|
if path.Ext(filename) == ".html" {
|
||||||
src = extractEBNF(src);
|
src = extractEBNF(src)
|
||||||
}
|
}
|
||||||
|
|
||||||
grammar, err := ebnf.Parse(filename, src);
|
grammar, err := ebnf.Parse(filename, src);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
scanner.PrintError(os.Stderr, err);
|
scanner.PrintError(os.Stderr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = ebnf.Verify(grammar, *start); err != nil {
|
if err = ebnf.Verify(grammar, *start); err != nil {
|
||||||
scanner.PrintError(os.Stderr, err);
|
scanner.PrintError(os.Stderr, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ func (dt *delayTime) backoff(max int) {
|
||||||
dt.mutex.Lock();
|
dt.mutex.Lock();
|
||||||
v := dt.value.(int) * 2;
|
v := dt.value.(int) * 2;
|
||||||
if v > max {
|
if v > max {
|
||||||
v = max;
|
v = max
|
||||||
}
|
}
|
||||||
dt.value = v;
|
dt.value = v;
|
||||||
dt.mutex.Unlock();
|
dt.mutex.Unlock();
|
||||||
|
|
@ -94,7 +94,7 @@ var fsTree RWValue // *Directory tree of packages, updated with each sync
|
||||||
func init() {
|
func init() {
|
||||||
goroot = os.Getenv("GOROOT");
|
goroot = os.Getenv("GOROOT");
|
||||||
if goroot == "" {
|
if goroot == "" {
|
||||||
goroot = pathutil.Join(os.Getenv("HOME"), "go");
|
goroot = pathutil.Join(os.Getenv("HOME"), "go")
|
||||||
}
|
}
|
||||||
flag.StringVar(&goroot, "goroot", goroot, "Go root directory");
|
flag.StringVar(&goroot, "goroot", goroot, "Go root directory");
|
||||||
}
|
}
|
||||||
|
|
@ -106,25 +106,25 @@ func init() {
|
||||||
func isGoFile(dir *os.Dir) bool {
|
func isGoFile(dir *os.Dir) bool {
|
||||||
return dir.IsRegular() &&
|
return dir.IsRegular() &&
|
||||||
!strings.HasPrefix(dir.Name, ".") && // ignore .files
|
!strings.HasPrefix(dir.Name, ".") && // ignore .files
|
||||||
pathutil.Ext(dir.Name) == ".go";
|
pathutil.Ext(dir.Name) == ".go"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func isPkgFile(dir *os.Dir) bool {
|
func isPkgFile(dir *os.Dir) bool {
|
||||||
return isGoFile(dir) &&
|
return isGoFile(dir) &&
|
||||||
!strings.HasSuffix(dir.Name, "_test.go"); // ignore test files
|
!strings.HasSuffix(dir.Name, "_test.go") // ignore test files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func isPkgDir(dir *os.Dir) bool {
|
func isPkgDir(dir *os.Dir) bool {
|
||||||
return dir.IsDirectory() && len(dir.Name) > 0 && dir.Name[0] != '_';
|
return dir.IsDirectory() && len(dir.Name) > 0 && dir.Name[0] != '_'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func pkgName(filename string) string {
|
func pkgName(filename string) string {
|
||||||
file, err := parse(filename, parser.PackageClauseOnly);
|
file, err := parse(filename, parser.PackageClauseOnly);
|
||||||
if err != nil || file == nil {
|
if err != nil || file == nil {
|
||||||
return "";
|
return ""
|
||||||
}
|
}
|
||||||
return file.Name.Value;
|
return file.Name.Value;
|
||||||
}
|
}
|
||||||
|
|
@ -145,11 +145,11 @@ func firstSentence(s string) string {
|
||||||
k1 := k+1;
|
k1 := k+1;
|
||||||
if ch == '.' {
|
if ch == '.' {
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
i = k1; // first period
|
i = k1 // first period
|
||||||
}
|
}
|
||||||
if k1 < len(s) && s[k1] <= ' ' {
|
if k1 < len(s) && s[k1] <= ' ' {
|
||||||
if j < 0 {
|
if j < 0 {
|
||||||
j = k1; // first period followed by white space
|
j = k1 // first period followed by white space
|
||||||
}
|
}
|
||||||
if !unicode.IsUpper(prev) {
|
if !unicode.IsUpper(prev) {
|
||||||
j = k1;
|
j = k1;
|
||||||
|
|
@ -165,7 +165,7 @@ func firstSentence(s string) string {
|
||||||
j = i;
|
j = i;
|
||||||
if j < 0 {
|
if j < 0 {
|
||||||
// no period at all, use the entire string
|
// no period at all, use the entire string
|
||||||
j = len(s);
|
j = len(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -190,7 +190,7 @@ func newDirTree(path, name string, depth, maxDepth int) *Directory {
|
||||||
// return a dummy directory so that the parent directory
|
// return a dummy directory so that the parent directory
|
||||||
// doesn't get discarded just because we reached the max
|
// doesn't get discarded just because we reached the max
|
||||||
// directory depth
|
// directory depth
|
||||||
return &Directory{depth, path, name, "", nil};
|
return &Directory{depth, path, name, "", nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
list, _ := io.ReadDir(path); // ignore errors
|
list, _ := io.ReadDir(path); // ignore errors
|
||||||
|
|
@ -202,7 +202,7 @@ func newDirTree(path, name string, depth, maxDepth int) *Directory {
|
||||||
for _, d := range list {
|
for _, d := range list {
|
||||||
switch {
|
switch {
|
||||||
case isPkgDir(d):
|
case isPkgDir(d):
|
||||||
ndirs++;
|
ndirs++
|
||||||
case isPkgFile(d):
|
case isPkgFile(d):
|
||||||
nfiles++;
|
nfiles++;
|
||||||
if text == "" {
|
if text == "" {
|
||||||
|
|
@ -218,7 +218,7 @@ func newDirTree(path, name string, depth, maxDepth int) *Directory {
|
||||||
(file.Name.Value == name || file.Name.Value == fakePkgName) &&
|
(file.Name.Value == name || file.Name.Value == fakePkgName) &&
|
||||||
file.Doc != nil {
|
file.Doc != nil {
|
||||||
// found documentation; extract a synopsys
|
// found documentation; extract a synopsys
|
||||||
text = firstSentence(doc.CommentText(file.Doc));
|
text = firstSentence(doc.CommentText(file.Doc))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -244,7 +244,7 @@ func newDirTree(path, name string, depth, maxDepth int) *Directory {
|
||||||
// if there are no package files and no subdirectories
|
// if there are no package files and no subdirectories
|
||||||
// (with package files), ignore the directory
|
// (with package files), ignore the directory
|
||||||
if nfiles == 0 && len(dirs) == 0 {
|
if nfiles == 0 && len(dirs) == 0 {
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Directory{depth, path, name, text, dirs};
|
return &Directory{depth, path, name, text, dirs};
|
||||||
|
|
@ -259,7 +259,7 @@ func newDirTree(path, name string, depth, maxDepth int) *Directory {
|
||||||
func newDirectory(root string, maxDepth int) *Directory {
|
func newDirectory(root string, maxDepth int) *Directory {
|
||||||
d, err := os.Lstat(root);
|
d, err := os.Lstat(root);
|
||||||
if err != nil || !isPkgDir(d) {
|
if err != nil || !isPkgDir(d) {
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
return newDirTree(root, d.Name, 0, maxDepth);
|
return newDirTree(root, d.Name, 0, maxDepth);
|
||||||
}
|
}
|
||||||
|
|
@ -268,10 +268,10 @@ func newDirectory(root string, maxDepth int) *Directory {
|
||||||
func (dir *Directory) walk(c chan<- *Directory, skipRoot bool) {
|
func (dir *Directory) walk(c chan<- *Directory, skipRoot bool) {
|
||||||
if dir != nil {
|
if dir != nil {
|
||||||
if !skipRoot {
|
if !skipRoot {
|
||||||
c <- dir;
|
c <- dir
|
||||||
}
|
}
|
||||||
for _, d := range dir.Dirs {
|
for _, d := range dir.Dirs {
|
||||||
d.walk(c, false);
|
d.walk(c, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -292,7 +292,7 @@ func (dir *Directory) lookup(path string) *Directory {
|
||||||
path = pathutil.Clean(path); // no trailing '/'
|
path = pathutil.Clean(path); // no trailing '/'
|
||||||
|
|
||||||
if dir == nil || path == "" || path == "." {
|
if dir == nil || path == "" || path == "." {
|
||||||
return dir;
|
return dir
|
||||||
}
|
}
|
||||||
|
|
||||||
dpath, dname := pathutil.Split(path);
|
dpath, dname := pathutil.Split(path);
|
||||||
|
|
@ -300,7 +300,7 @@ func (dir *Directory) lookup(path string) *Directory {
|
||||||
// directory-local name
|
// directory-local name
|
||||||
for _, d := range dir.Dirs {
|
for _, d := range dir.Dirs {
|
||||||
if dname == d.Name {
|
if dname == d.Name {
|
||||||
return d;
|
return d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
|
|
@ -333,7 +333,7 @@ type DirList struct {
|
||||||
//
|
//
|
||||||
func (root *Directory) listing(skipRoot bool) *DirList {
|
func (root *Directory) listing(skipRoot bool) *DirList {
|
||||||
if root == nil {
|
if root == nil {
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine number of entries n and maximum height
|
// determine number of entries n and maximum height
|
||||||
|
|
@ -343,16 +343,16 @@ func (root *Directory) listing(skipRoot bool) *DirList {
|
||||||
for d := range root.iter(skipRoot) {
|
for d := range root.iter(skipRoot) {
|
||||||
n++;
|
n++;
|
||||||
if minDepth > d.Depth {
|
if minDepth > d.Depth {
|
||||||
minDepth = d.Depth;
|
minDepth = d.Depth
|
||||||
}
|
}
|
||||||
if maxDepth < d.Depth {
|
if maxDepth < d.Depth {
|
||||||
maxDepth = d.Depth;
|
maxDepth = d.Depth
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maxHeight := maxDepth-minDepth+1;
|
maxHeight := maxDepth-minDepth+1;
|
||||||
|
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// create list
|
// create list
|
||||||
|
|
@ -367,11 +367,11 @@ func (root *Directory) listing(skipRoot bool) *DirList {
|
||||||
// crashes and check)
|
// crashes and check)
|
||||||
path := d.Path;
|
path := d.Path;
|
||||||
if strings.HasPrefix(d.Path, root.Path) {
|
if strings.HasPrefix(d.Path, root.Path) {
|
||||||
path = d.Path[len(root.Path):len(d.Path)];
|
path = d.Path[len(root.Path):len(d.Path)]
|
||||||
}
|
}
|
||||||
// remove trailing '/' if any - path must be relative
|
// remove trailing '/' if any - path must be relative
|
||||||
if len(path) > 0 && path[0] == '/' {
|
if len(path) > 0 && path[0] == '/' {
|
||||||
path = path[1:len(path)];
|
path = path[1:len(path)]
|
||||||
}
|
}
|
||||||
p.Path = path;
|
p.Path = path;
|
||||||
p.Name = d.Name;
|
p.Name = d.Name;
|
||||||
|
|
@ -502,7 +502,7 @@ func (s *Styler) BasicLit(x *ast.BasicLit) (text []byte, tag printer.HTMLTag) {
|
||||||
func (s *Styler) Ident(id *ast.Ident) (text []byte, tag printer.HTMLTag) {
|
func (s *Styler) Ident(id *ast.Ident) (text []byte, tag printer.HTMLTag) {
|
||||||
text = strings.Bytes(id.Value);
|
text = strings.Bytes(id.Value);
|
||||||
if s.highlight == id.Value {
|
if s.highlight == id.Value {
|
||||||
tag = printer.HTMLTag{"<span class=highlight>", "</span>"};
|
tag = printer.HTMLTag{"<span class=highlight>", "</span>"}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -521,7 +521,7 @@ func (s *Styler) Token(tok token.Token) (text []byte, tag printer.HTMLTag) {
|
||||||
func writeNode(w io.Writer, node interface{}, html bool, styler printer.Styler) {
|
func writeNode(w io.Writer, node interface{}, html bool, styler printer.Styler) {
|
||||||
mode := printer.UseSpaces;
|
mode := printer.UseSpaces;
|
||||||
if html {
|
if html {
|
||||||
mode |= printer.GenHTML;
|
mode |= printer.GenHTML
|
||||||
}
|
}
|
||||||
(&printer.Config{mode, *tabwidth, styler}).Fprint(w, node);
|
(&printer.Config{mode, *tabwidth, styler}).Fprint(w, node);
|
||||||
}
|
}
|
||||||
|
|
@ -541,20 +541,20 @@ func writeText(w io.Writer, text []byte, html bool) {
|
||||||
func writeAny(w io.Writer, x interface{}, html bool) {
|
func writeAny(w io.Writer, x interface{}, html bool) {
|
||||||
switch v := x.(type) {
|
switch v := x.(type) {
|
||||||
case []byte:
|
case []byte:
|
||||||
writeText(w, v, html);
|
writeText(w, v, html)
|
||||||
case string:
|
case string:
|
||||||
writeText(w, strings.Bytes(v), html);
|
writeText(w, strings.Bytes(v), html)
|
||||||
case ast.Decl:
|
case ast.Decl:
|
||||||
writeNode(w, v, html, &defaultStyler);
|
writeNode(w, v, html, &defaultStyler)
|
||||||
case ast.Expr:
|
case ast.Expr:
|
||||||
writeNode(w, v, html, &defaultStyler);
|
writeNode(w, v, html, &defaultStyler)
|
||||||
default:
|
default:
|
||||||
if html {
|
if html {
|
||||||
var buf bytes.Buffer;
|
var buf bytes.Buffer;
|
||||||
fmt.Fprint(&buf, x);
|
fmt.Fprint(&buf, x);
|
||||||
writeText(w, buf.Bytes(), true);
|
writeText(w, buf.Bytes(), true);
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprint(w, x);
|
fmt.Fprint(w, x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -562,7 +562,7 @@ func writeAny(w io.Writer, x interface{}, html bool) {
|
||||||
|
|
||||||
// Template formatter for "html" format.
|
// Template formatter for "html" format.
|
||||||
func htmlFmt(w io.Writer, x interface{}, format string) {
|
func htmlFmt(w io.Writer, x interface{}, format string) {
|
||||||
writeAny(w, x, true);
|
writeAny(w, x, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -576,13 +576,13 @@ func htmlCommentFmt(w io.Writer, x interface{}, format string) {
|
||||||
|
|
||||||
// Template formatter for "" (default) format.
|
// Template formatter for "" (default) format.
|
||||||
func textFmt(w io.Writer, x interface{}, format string) {
|
func textFmt(w io.Writer, x interface{}, format string) {
|
||||||
writeAny(w, x, false);
|
writeAny(w, x, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func removePrefix(s, prefix string) string {
|
func removePrefix(s, prefix string) string {
|
||||||
if strings.HasPrefix(s, prefix) {
|
if strings.HasPrefix(s, prefix) {
|
||||||
return s[len(prefix):len(s)];
|
return s[len(prefix):len(s)]
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
@ -593,7 +593,7 @@ func pathFmt(w io.Writer, x interface{}, format string) {
|
||||||
// TODO(gri): Need to find a better solution for this.
|
// TODO(gri): Need to find a better solution for this.
|
||||||
// This will not work correctly if *cmdroot
|
// This will not work correctly if *cmdroot
|
||||||
// or *pkgroot change.
|
// or *pkgroot change.
|
||||||
writeAny(w, removePrefix(x.(string), "src"), true);
|
writeAny(w, removePrefix(x.(string), "src"), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -607,7 +607,7 @@ func linkFmt(w io.Writer, x interface{}, format string) {
|
||||||
if pos.IsValid() {
|
if pos.IsValid() {
|
||||||
// line id's in html-printed source are of the
|
// line id's in html-printed source are of the
|
||||||
// form "L%d" where %d stands for the line number
|
// form "L%d" where %d stands for the line number
|
||||||
fmt.Fprintf(w, "/%s#L%d", htmlEscape(pos.Filename), pos.Line);
|
fmt.Fprintf(w, "/%s#L%d", htmlEscape(pos.Filename), pos.Line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -628,7 +628,7 @@ var infoKinds = [nKinds]string{
|
||||||
|
|
||||||
// Template formatter for "infoKind" format.
|
// Template formatter for "infoKind" format.
|
||||||
func infoKindFmt(w io.Writer, x interface{}, format string) {
|
func infoKindFmt(w io.Writer, x interface{}, format string) {
|
||||||
fmt.Fprintf(w, infoKinds[x.(SpotKind)]); // infoKind entries are html-escaped
|
fmt.Fprintf(w, infoKinds[x.(SpotKind)]) // infoKind entries are html-escaped
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -661,7 +661,7 @@ func infoSnippetFmt(w io.Writer, x interface{}, format string) {
|
||||||
// Template formatter for "padding" format.
|
// Template formatter for "padding" format.
|
||||||
func paddingFmt(w io.Writer, x interface{}, format string) {
|
func paddingFmt(w io.Writer, x interface{}, format string) {
|
||||||
for i := x.(int); i > 0; i-- {
|
for i := x.(int); i > 0; i-- {
|
||||||
fmt.Fprint(w, `<td width="25"></td>`);
|
fmt.Fprint(w, `<td width="25"></td>`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -669,7 +669,7 @@ func paddingFmt(w io.Writer, x interface{}, format string) {
|
||||||
// Template formatter for "time" format.
|
// Template formatter for "time" format.
|
||||||
func timeFmt(w io.Writer, x interface{}, format string) {
|
func timeFmt(w io.Writer, x interface{}, format string) {
|
||||||
// note: os.Dir.Mtime_ns is in uint64 in ns!
|
// note: os.Dir.Mtime_ns is in uint64 in ns!
|
||||||
template.HTMLEscape(w, strings.Bytes(time.SecondsToLocalTime(int64(x.(uint64) / 1e9)).String()));
|
template.HTMLEscape(w, strings.Bytes(time.SecondsToLocalTime(int64(x.(uint64) / 1e9)).String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -691,11 +691,11 @@ func readTemplate(name string) *template.Template {
|
||||||
path := pathutil.Join(*tmplroot, name);
|
path := pathutil.Join(*tmplroot, name);
|
||||||
data, err := io.ReadFile(path);
|
data, err := io.ReadFile(path);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Exitf("ReadFile %s: %v", path, err);
|
log.Exitf("ReadFile %s: %v", path, err)
|
||||||
}
|
}
|
||||||
t, err := template.Parse(string(data), fmap);
|
t, err := template.Parse(string(data), fmap);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Exitf("%s: %v", name, err);
|
log.Exitf("%s: %v", name, err)
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
@ -744,7 +744,7 @@ func servePage(c *http.Conn, title, query string, content []byte) {
|
||||||
};
|
};
|
||||||
|
|
||||||
if err := godocHTML.Execute(&d, c); err != nil {
|
if err := godocHTML.Execute(&d, c); err != nil {
|
||||||
log.Stderrf("godocHTML.Execute: %s", err);
|
log.Stderrf("godocHTML.Execute: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -768,7 +768,7 @@ func commentText(src []byte) (text string) {
|
||||||
i := bytes.Index(src, tagBegin);
|
i := bytes.Index(src, tagBegin);
|
||||||
j := bytes.Index(src, tagEnd);
|
j := bytes.Index(src, tagEnd);
|
||||||
if i >= 0 && j >= i+len(tagBegin) {
|
if i >= 0 && j >= i+len(tagBegin) {
|
||||||
text = string(bytes.TrimSpace(src[i+len(tagBegin) : j]));
|
text = string(bytes.TrimSpace(src[i+len(tagBegin) : j]))
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -799,7 +799,7 @@ func serveParseErrors(c *http.Conn, errors *parseErrors) {
|
||||||
// format errors
|
// format errors
|
||||||
var buf bytes.Buffer;
|
var buf bytes.Buffer;
|
||||||
if err := parseerrorHTML.Execute(errors, &buf); err != nil {
|
if err := parseerrorHTML.Execute(errors, &buf); err != nil {
|
||||||
log.Stderrf("parseerrorHTML.Execute: %s", err);
|
log.Stderrf("parseerrorHTML.Execute: %s", err)
|
||||||
}
|
}
|
||||||
servePage(c, "Parse errors in source file " + errors.filename, "", buf.Bytes());
|
servePage(c, "Parse errors in source file " + errors.filename, "", buf.Bytes());
|
||||||
}
|
}
|
||||||
|
|
@ -842,7 +842,7 @@ var textExt = map[string]bool{
|
||||||
func isTextFile(path string) bool {
|
func isTextFile(path string) bool {
|
||||||
// if the extension is known, use it for decision making
|
// if the extension is known, use it for decision making
|
||||||
if isText, found := textExt[pathutil.Ext(path)]; found {
|
if isText, found := textExt[pathutil.Ext(path)]; found {
|
||||||
return isText;
|
return isText
|
||||||
}
|
}
|
||||||
|
|
||||||
// the extension is not known; read an initial chunk of
|
// the extension is not known; read an initial chunk of
|
||||||
|
|
@ -850,24 +850,24 @@ func isTextFile(path string) bool {
|
||||||
// does, it's probably a text file
|
// does, it's probably a text file
|
||||||
f, err := os.Open(path, os.O_RDONLY, 0);
|
f, err := os.Open(path, os.O_RDONLY, 0);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf [1024]byte;
|
var buf [1024]byte;
|
||||||
n, err := f.Read(&buf);
|
n, err := f.Read(&buf);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
s := string(buf[0:n]);
|
s := string(buf[0:n]);
|
||||||
n -= utf8.UTFMax; // make sure there's enough bytes for a complete unicode char
|
n -= utf8.UTFMax; // make sure there's enough bytes for a complete unicode char
|
||||||
for i, c := range s {
|
for i, c := range s {
|
||||||
if i > n {
|
if i > n {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
if c == 0xFFFD || c < ' ' && c != '\n' && c != '\t' {
|
if c == 0xFFFD || c < ' ' && c != '\n' && c != '\t' {
|
||||||
// decoding error or control character - not a text file
|
// decoding error or control character - not a text file
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -879,7 +879,7 @@ func isTextFile(path string) bool {
|
||||||
func serveTextFile(c *http.Conn, r *http.Request, path string) {
|
func serveTextFile(c *http.Conn, r *http.Request, path string) {
|
||||||
src, err := io.ReadFile(path);
|
src, err := io.ReadFile(path);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Stderrf("serveTextFile: %s", err);
|
log.Stderrf("serveTextFile: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer;
|
var buf bytes.Buffer;
|
||||||
|
|
@ -893,7 +893,7 @@ func serveTextFile(c *http.Conn, r *http.Request, path string) {
|
||||||
|
|
||||||
func serveDirectory(c *http.Conn, r *http.Request, path string) {
|
func serveDirectory(c *http.Conn, r *http.Request, path string) {
|
||||||
if redirect(c, r) {
|
if redirect(c, r) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
list, err := io.ReadDir(path);
|
list, err := io.ReadDir(path);
|
||||||
|
|
@ -904,7 +904,7 @@ func serveDirectory(c *http.Conn, r *http.Request, path string) {
|
||||||
|
|
||||||
var buf bytes.Buffer;
|
var buf bytes.Buffer;
|
||||||
if err := dirlistHTML.Execute(list, &buf); err != nil {
|
if err := dirlistHTML.Execute(list, &buf); err != nil {
|
||||||
log.Stderrf("dirlistHTML.Execute: %s", err);
|
log.Stderrf("dirlistHTML.Execute: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
servePage(c, "Directory " + path, "", buf.Bytes());
|
servePage(c, "Directory " + path, "", buf.Bytes());
|
||||||
|
|
@ -1009,7 +1009,7 @@ func (h *httpHandler) getPageInfo(path string) PageInfo {
|
||||||
pkg, err := parser.ParsePackage(dirname, filter, parser.ParseComments);
|
pkg, err := parser.ParsePackage(dirname, filter, parser.ParseComments);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: parse errors should be shown instead of an empty directory
|
// TODO: parse errors should be shown instead of an empty directory
|
||||||
log.Stderrf("parser.parsePackage: %s", err);
|
log.Stderrf("parser.parsePackage: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute package documentation
|
// compute package documentation
|
||||||
|
|
@ -1025,11 +1025,11 @@ func (h *httpHandler) getPageInfo(path string) PageInfo {
|
||||||
// directory tree is present; lookup respective directory
|
// directory tree is present; lookup respective directory
|
||||||
// (may still fail if the file system was updated and the
|
// (may still fail if the file system was updated and the
|
||||||
// new directory tree has not yet beet computed)
|
// new directory tree has not yet beet computed)
|
||||||
dir = tree.(*Directory).lookup(dirname);
|
dir = tree.(*Directory).lookup(dirname)
|
||||||
} else {
|
} else {
|
||||||
// no directory tree present (either early after startup
|
// no directory tree present (either early after startup
|
||||||
// or command-line mode); compute one level for this page
|
// or command-line mode); compute one level for this page
|
||||||
dir = newDirectory(dirname, 1);
|
dir = newDirectory(dirname, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return PageInfo{pdoc, dir.listing(true), h.isPkg};
|
return PageInfo{pdoc, dir.listing(true), h.isPkg};
|
||||||
|
|
@ -1038,7 +1038,7 @@ func (h *httpHandler) getPageInfo(path string) PageInfo {
|
||||||
|
|
||||||
func (h *httpHandler) ServeHTTP(c *http.Conn, r *http.Request) {
|
func (h *httpHandler) ServeHTTP(c *http.Conn, r *http.Request) {
|
||||||
if redirect(c, r) {
|
if redirect(c, r) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
path := r.URL.Path;
|
path := r.URL.Path;
|
||||||
|
|
@ -1048,30 +1048,30 @@ func (h *httpHandler) ServeHTTP(c *http.Conn, r *http.Request) {
|
||||||
var buf bytes.Buffer;
|
var buf bytes.Buffer;
|
||||||
if r.FormValue("f") == "text" {
|
if r.FormValue("f") == "text" {
|
||||||
if err := packageText.Execute(info, &buf); err != nil {
|
if err := packageText.Execute(info, &buf); err != nil {
|
||||||
log.Stderrf("packageText.Execute: %s", err);
|
log.Stderrf("packageText.Execute: %s", err)
|
||||||
}
|
}
|
||||||
serveText(c, buf.Bytes());
|
serveText(c, buf.Bytes());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := packageHTML.Execute(info, &buf); err != nil {
|
if err := packageHTML.Execute(info, &buf); err != nil {
|
||||||
log.Stderrf("packageHTML.Execute: %s", err);
|
log.Stderrf("packageHTML.Execute: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if path == "" {
|
if path == "" {
|
||||||
path = "."; // don't display an empty path
|
path = "." // don't display an empty path
|
||||||
}
|
}
|
||||||
title := "Directory " + path;
|
title := "Directory " + path;
|
||||||
if info.PDoc != nil {
|
if info.PDoc != nil {
|
||||||
switch {
|
switch {
|
||||||
case h.isPkg:
|
case h.isPkg:
|
||||||
title = "Package " + info.PDoc.PackageName;
|
title = "Package " + info.PDoc.PackageName
|
||||||
case info.PDoc.PackageName == fakePkgName:
|
case info.PDoc.PackageName == fakePkgName:
|
||||||
// assume that the directory name is the command name
|
// assume that the directory name is the command name
|
||||||
_, pkgname := pathutil.Split(pathutil.Clean(path));
|
_, pkgname := pathutil.Split(pathutil.Clean(path));
|
||||||
title = "Command " + pkgname;
|
title = "Command " + pkgname;
|
||||||
default:
|
default:
|
||||||
title = "Command " + info.PDoc.PackageName;
|
title = "Command " + info.PDoc.PackageName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1105,14 +1105,14 @@ func search(c *http.Conn, r *http.Request) {
|
||||||
|
|
||||||
var buf bytes.Buffer;
|
var buf bytes.Buffer;
|
||||||
if err := searchHTML.Execute(result, &buf); err != nil {
|
if err := searchHTML.Execute(result, &buf); err != nil {
|
||||||
log.Stderrf("searchHTML.Execute: %s", err);
|
log.Stderrf("searchHTML.Execute: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var title string;
|
var title string;
|
||||||
if result.Hit != nil {
|
if result.Hit != nil {
|
||||||
title = fmt.Sprintf(`Results for query %q`, query);
|
title = fmt.Sprintf(`Results for query %q`, query)
|
||||||
} else {
|
} else {
|
||||||
title = fmt.Sprintf(`No results found for query %q`, query);
|
title = fmt.Sprintf(`No results found for query %q`, query)
|
||||||
}
|
}
|
||||||
|
|
||||||
servePage(c, title, query, buf.Bytes());
|
servePage(c, title, query, buf.Bytes());
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ func (h *RunList) reduce(less func(x, y interface{}) bool, newRun func(h *RunLis
|
||||||
}
|
}
|
||||||
// add final run, if any
|
// add final run, if any
|
||||||
if i < h.Len() {
|
if i < h.Len() {
|
||||||
hh.Push(newRun(h, i, h.Len()));
|
hh.Push(newRun(h, i, h.Len()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return &hh;
|
return &hh;
|
||||||
|
|
@ -119,7 +119,7 @@ func init() {
|
||||||
// sanity check: if nKinds is too large, the SpotInfo
|
// sanity check: if nKinds is too large, the SpotInfo
|
||||||
// accessor functions may need to be updated
|
// accessor functions may need to be updated
|
||||||
if nKinds > 8 {
|
if nKinds > 8 {
|
||||||
panic();
|
panic()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,13 +132,13 @@ func makeSpotInfo(kind SpotKind, lori int, isIndex bool) SpotInfo {
|
||||||
// lori value doesn't fit - since snippet indices are
|
// lori value doesn't fit - since snippet indices are
|
||||||
// most certainly always smaller then 1<<28, this can
|
// most certainly always smaller then 1<<28, this can
|
||||||
// only happen for line numbers; give it no line number (= 0)
|
// only happen for line numbers; give it no line number (= 0)
|
||||||
x = 0;
|
x = 0
|
||||||
}
|
}
|
||||||
// encode kind: bits [1..4)
|
// encode kind: bits [1..4)
|
||||||
x |= SpotInfo(kind)<<1;
|
x |= SpotInfo(kind)<<1;
|
||||||
// encode isIndex: bit 0
|
// encode isIndex: bit 0
|
||||||
if isIndex {
|
if isIndex {
|
||||||
x |= 1;
|
x |= 1
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
@ -220,7 +220,7 @@ type Pak struct {
|
||||||
|
|
||||||
// Paks are sorted by name (primary key) and by import path (secondary key).
|
// Paks are sorted by name (primary key) and by import path (secondary key).
|
||||||
func (p *Pak) less(q *Pak) bool {
|
func (p *Pak) less(q *Pak) bool {
|
||||||
return p.Name < q.Name || p.Name == q.Name && p.Path < q.Path;
|
return p.Name < q.Name || p.Name == q.Name && p.Path < q.Path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -266,7 +266,7 @@ func newFileRun(h0 *RunList, i, j int) interface{} {
|
||||||
// create the FileRun
|
// create the FileRun
|
||||||
groups := make([]*KindRun, h2.Len());
|
groups := make([]*KindRun, h2.Len());
|
||||||
for i := 0; i < h2.Len(); i++ {
|
for i := 0; i < h2.Len(); i++ {
|
||||||
groups[i] = h2.At(i).(*KindRun);
|
groups[i] = h2.At(i).(*KindRun)
|
||||||
}
|
}
|
||||||
return &FileRun{file, groups};
|
return &FileRun{file, groups};
|
||||||
}
|
}
|
||||||
|
|
@ -289,7 +289,7 @@ func (p *PakRun) Swap(i, j int) { p.Files[i], p.Files[j] = p.Files[j], p.Files[
|
||||||
|
|
||||||
// FileRuns are sorted by package for the reduction into PakRuns.
|
// FileRuns are sorted by package for the reduction into PakRuns.
|
||||||
func lessFileRun(x, y interface{}) bool {
|
func lessFileRun(x, y interface{}) bool {
|
||||||
return x.(*FileRun).File.Pak.less(&y.(*FileRun).File.Pak);
|
return x.(*FileRun).File.Pak.less(&y.(*FileRun).File.Pak)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -329,7 +329,7 @@ func reduce(h0 *RunList) HitList {
|
||||||
// create a HitList
|
// create a HitList
|
||||||
h := make(HitList, h2.Len());
|
h := make(HitList, h2.Len());
|
||||||
for i := 0; i < h2.Len(); i++ {
|
for i := 0; i < h2.Len(); i++ {
|
||||||
h[i] = h2.At(i).(*PakRun);
|
h[i] = h2.At(i).(*PakRun)
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
@ -340,7 +340,7 @@ func (h HitList) filter(pakname string) HitList {
|
||||||
n := 0;
|
n := 0;
|
||||||
for _, p := range h {
|
for _, p := range h {
|
||||||
if p.Pak.Name == pakname {
|
if p.Pak.Name == pakname {
|
||||||
n++;
|
n++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// create filtered HitList
|
// create filtered HitList
|
||||||
|
|
@ -393,7 +393,7 @@ func newAltWords(h *RunList, i, j int) interface{} {
|
||||||
func (a *AltWords) filter(s string) *AltWords {
|
func (a *AltWords) filter(s string) *AltWords {
|
||||||
if len(a.Alts) == 1 && a.Alts[0] == s {
|
if len(a.Alts) == 1 && a.Alts[0] == s {
|
||||||
// there are no different alternatives
|
// there are no different alternatives
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// make a new AltWords with the current spelling removed
|
// make a new AltWords with the current spelling removed
|
||||||
|
|
@ -445,7 +445,7 @@ func (x *Indexer) addSnippet(s *Snippet) int {
|
||||||
|
|
||||||
func (x *Indexer) visitComment(c *ast.CommentGroup) {
|
func (x *Indexer) visitComment(c *ast.CommentGroup) {
|
||||||
if c != nil {
|
if c != nil {
|
||||||
ast.Walk(x, c);
|
ast.Walk(x, c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -480,7 +480,7 @@ func (x *Indexer) visitSpec(spec ast.Spec, isVarDecl bool) {
|
||||||
x.visitComment(n.Doc);
|
x.visitComment(n.Doc);
|
||||||
x.visitIdent(ImportDecl, n.Name);
|
x.visitIdent(ImportDecl, n.Name);
|
||||||
for _, s := range n.Path {
|
for _, s := range n.Path {
|
||||||
ast.Walk(x, s);
|
ast.Walk(x, s)
|
||||||
}
|
}
|
||||||
x.visitComment(n.Comment);
|
x.visitComment(n.Comment);
|
||||||
|
|
||||||
|
|
@ -488,14 +488,14 @@ func (x *Indexer) visitSpec(spec ast.Spec, isVarDecl bool) {
|
||||||
x.visitComment(n.Doc);
|
x.visitComment(n.Doc);
|
||||||
kind := ConstDecl;
|
kind := ConstDecl;
|
||||||
if isVarDecl {
|
if isVarDecl {
|
||||||
kind = VarDecl;
|
kind = VarDecl
|
||||||
}
|
}
|
||||||
for _, n := range n.Names {
|
for _, n := range n.Names {
|
||||||
x.visitIdent(kind, n);
|
x.visitIdent(kind, n)
|
||||||
}
|
}
|
||||||
ast.Walk(x, n.Type);
|
ast.Walk(x, n.Type);
|
||||||
for _, v := range n.Values {
|
for _, v := range n.Values {
|
||||||
ast.Walk(x, v);
|
ast.Walk(x, v)
|
||||||
}
|
}
|
||||||
x.visitComment(n.Comment);
|
x.visitComment(n.Comment);
|
||||||
|
|
||||||
|
|
@ -512,17 +512,17 @@ func (x *Indexer) Visit(node interface{}) bool {
|
||||||
// TODO(gri): methods in interface types are categorized as VarDecl
|
// TODO(gri): methods in interface types are categorized as VarDecl
|
||||||
switch n := node.(type) {
|
switch n := node.(type) {
|
||||||
case *ast.Ident:
|
case *ast.Ident:
|
||||||
x.visitIdent(Use, n);
|
x.visitIdent(Use, n)
|
||||||
|
|
||||||
case *ast.Field:
|
case *ast.Field:
|
||||||
x.decl = nil; // no snippets for fields
|
x.decl = nil; // no snippets for fields
|
||||||
x.visitComment(n.Doc);
|
x.visitComment(n.Doc);
|
||||||
for _, m := range n.Names {
|
for _, m := range n.Names {
|
||||||
x.visitIdent(VarDecl, m);
|
x.visitIdent(VarDecl, m)
|
||||||
}
|
}
|
||||||
ast.Walk(x, n.Type);
|
ast.Walk(x, n.Type);
|
||||||
for _, s := range n.Tag {
|
for _, s := range n.Tag {
|
||||||
ast.Walk(x, s);
|
ast.Walk(x, s)
|
||||||
}
|
}
|
||||||
x.visitComment(n.Comment);
|
x.visitComment(n.Comment);
|
||||||
|
|
||||||
|
|
@ -532,18 +532,18 @@ func (x *Indexer) Visit(node interface{}) bool {
|
||||||
x.decl = nil; // no snippets for local declarations
|
x.decl = nil; // no snippets for local declarations
|
||||||
x.visitComment(decl.Doc);
|
x.visitComment(decl.Doc);
|
||||||
for _, s := range decl.Specs {
|
for _, s := range decl.Specs {
|
||||||
x.visitSpec(s, decl.Tok == token.VAR);
|
x.visitSpec(s, decl.Tok == token.VAR)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// handle error case gracefully
|
// handle error case gracefully
|
||||||
ast.Walk(x, n.Decl);
|
ast.Walk(x, n.Decl)
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.GenDecl:
|
case *ast.GenDecl:
|
||||||
x.decl = n;
|
x.decl = n;
|
||||||
x.visitComment(n.Doc);
|
x.visitComment(n.Doc);
|
||||||
for _, s := range n.Specs {
|
for _, s := range n.Specs {
|
||||||
x.visitSpec(s, n.Tok == token.VAR);
|
x.visitSpec(s, n.Tok == token.VAR)
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.FuncDecl:
|
case *ast.FuncDecl:
|
||||||
|
|
@ -557,7 +557,7 @@ func (x *Indexer) Visit(node interface{}) bool {
|
||||||
x.visitIdent(kind, n.Name);
|
x.visitIdent(kind, n.Name);
|
||||||
ast.Walk(x, n.Type);
|
ast.Walk(x, n.Type);
|
||||||
if n.Body != nil {
|
if n.Body != nil {
|
||||||
ast.Walk(x, n.Type);
|
ast.Walk(x, n.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.File:
|
case *ast.File:
|
||||||
|
|
@ -565,14 +565,14 @@ func (x *Indexer) Visit(node interface{}) bool {
|
||||||
x.decl = nil;
|
x.decl = nil;
|
||||||
x.visitIdent(PackageClause, n.Name);
|
x.visitIdent(PackageClause, n.Name);
|
||||||
for _, d := range n.Decls {
|
for _, d := range n.Decls {
|
||||||
ast.Walk(x, d);
|
ast.Walk(x, d)
|
||||||
}
|
}
|
||||||
// don't visit package level comments for now
|
// don't visit package level comments for now
|
||||||
// to avoid duplicate visiting from individual
|
// to avoid duplicate visiting from individual
|
||||||
// nodes
|
// nodes
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -580,26 +580,26 @@ func (x *Indexer) Visit(node interface{}) bool {
|
||||||
|
|
||||||
|
|
||||||
func (x *Indexer) VisitDir(path string, d *os.Dir) bool {
|
func (x *Indexer) VisitDir(path string, d *os.Dir) bool {
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (x *Indexer) VisitFile(path string, d *os.Dir) {
|
func (x *Indexer) VisitFile(path string, d *os.Dir) {
|
||||||
if !isGoFile(d) {
|
if !isGoFile(d) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if excludeTestFiles && (!isPkgFile(d) || strings.HasPrefix(path, "test/")) {
|
if excludeTestFiles && (!isPkgFile(d) || strings.HasPrefix(path, "test/")) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if excludeMainPackages && pkgName(path) == "main" {
|
if excludeMainPackages && pkgName(path) == "main" {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := parser.ParseFile(path, nil, parser.ParseComments);
|
file, err := parser.ParseFile(path, nil, parser.ParseComments);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return; // ignore files with (parse) errors
|
return // ignore files with (parse) errors
|
||||||
}
|
}
|
||||||
|
|
||||||
dir, _ := pathutil.Split(path);
|
dir, _ := pathutil.Split(path);
|
||||||
|
|
@ -668,7 +668,7 @@ func NewIndex(root string) *Index {
|
||||||
// convert snippet vector into a list
|
// convert snippet vector into a list
|
||||||
snippets := make([]*Snippet, x.snippets.Len());
|
snippets := make([]*Snippet, x.snippets.Len());
|
||||||
for i := 0; i < x.snippets.Len(); i++ {
|
for i := 0; i < x.snippets.Len(); i++ {
|
||||||
snippets[i] = x.snippets.At(i).(*Snippet);
|
snippets[i] = x.snippets.At(i).(*Snippet)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Index{words, alts, snippets, x.nspots};
|
return &Index{words, alts, snippets, x.nspots};
|
||||||
|
|
@ -678,7 +678,7 @@ func NewIndex(root string) *Index {
|
||||||
// Size returns the number of different words and
|
// Size returns the number of different words and
|
||||||
// spots indexed as a measure for the index size.
|
// spots indexed as a measure for the index size.
|
||||||
func (x *Index) Size() (nwords int, nspots int) {
|
func (x *Index) Size() (nwords int, nspots int) {
|
||||||
return len(x.words), x.nspots;
|
return len(x.words), x.nspots
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -689,7 +689,7 @@ func (x *Index) LookupWord(w string) (match *LookupResult, alt *AltWords) {
|
||||||
// (if there is no match, the alternatives do
|
// (if there is no match, the alternatives do
|
||||||
// not contain the current spelling)
|
// not contain the current spelling)
|
||||||
if match != nil && alt != nil {
|
if match != nil && alt != nil {
|
||||||
alt = alt.filter(w);
|
alt = alt.filter(w)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -722,7 +722,7 @@ func (x *Index) Lookup(query string) (match *LookupResult, alt *AltWords, illega
|
||||||
|
|
||||||
switch len(ss) {
|
switch len(ss) {
|
||||||
case 1:
|
case 1:
|
||||||
match, alt = x.LookupWord(ss[0]);
|
match, alt = x.LookupWord(ss[0])
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
pakname := ss[0];
|
pakname := ss[0];
|
||||||
|
|
@ -735,7 +735,7 @@ func (x *Index) Lookup(query string) (match *LookupResult, alt *AltWords, illega
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
illegal = true;
|
illegal = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -745,7 +745,7 @@ func (x *Index) Lookup(query string) (match *LookupResult, alt *AltWords, illega
|
||||||
func (x *Index) Snippet(i int) *Snippet {
|
func (x *Index) Snippet(i int) *Snippet {
|
||||||
// handle illegal snippet indices gracefully
|
// handle illegal snippet indices gracefully
|
||||||
if 0 <= i && i < len(x.snippets) {
|
if 0 <= i && i < len(x.snippets) {
|
||||||
return x.snippets[i];
|
return x.snippets[i]
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ func exec(c *http.Conn, args []string) (status int) {
|
||||||
bin := args[0];
|
bin := args[0];
|
||||||
fds := []*os.File{nil, w, w};
|
fds := []*os.File{nil, w, w};
|
||||||
if *verbose {
|
if *verbose {
|
||||||
log.Stderrf("executing %v", args);
|
log.Stderrf("executing %v", args)
|
||||||
}
|
}
|
||||||
pid, err := os.ForkExec(bin, args, os.Environ(), goroot, fds);
|
pid, err := os.ForkExec(bin, args, os.Environ(), goroot, fds);
|
||||||
defer r.Close();
|
defer r.Close();
|
||||||
|
|
@ -86,7 +86,7 @@ func exec(c *http.Conn, args []string) (status int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if *verbose {
|
if *verbose {
|
||||||
os.Stderr.Write(buf.Bytes());
|
os.Stderr.Write(buf.Bytes())
|
||||||
}
|
}
|
||||||
if c != nil {
|
if c != nil {
|
||||||
c.SetHeader("content-type", "text/plain; charset=utf-8");
|
c.SetHeader("content-type", "text/plain; charset=utf-8");
|
||||||
|
|
@ -114,10 +114,10 @@ func dosync(c *http.Conn, r *http.Request) {
|
||||||
case 1:
|
case 1:
|
||||||
// sync failed because no files changed;
|
// sync failed because no files changed;
|
||||||
// don't change the package tree
|
// don't change the package tree
|
||||||
syncDelay.set(*syncMin); // revert to regular sync schedule
|
syncDelay.set(*syncMin) // revert to regular sync schedule
|
||||||
default:
|
default:
|
||||||
// sync failed because of an error - back off exponentially, but try at least once a day
|
// sync failed because of an error - back off exponentially, but try at least once a day
|
||||||
syncDelay.backoff(24*60);
|
syncDelay.backoff(24*60)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,7 +135,7 @@ func loggingHandler(h http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(c *http.Conn, req *http.Request) {
|
return http.HandlerFunc(func(c *http.Conn, req *http.Request) {
|
||||||
log.Stderrf("%s\t%s", c.RemoteAddr, req.URL);
|
log.Stderrf("%s\t%s", c.RemoteAddr, req.URL);
|
||||||
h.ServeHTTP(c, req);
|
h.ServeHTTP(c, req);
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -145,15 +145,15 @@ func main() {
|
||||||
|
|
||||||
// Check usage: either server and no args, or command line and args
|
// Check usage: either server and no args, or command line and args
|
||||||
if (*httpaddr != "") != (flag.NArg() == 0) {
|
if (*httpaddr != "") != (flag.NArg() == 0) {
|
||||||
usage();
|
usage()
|
||||||
}
|
}
|
||||||
|
|
||||||
if *tabwidth < 0 {
|
if *tabwidth < 0 {
|
||||||
log.Exitf("negative tabwidth %d", *tabwidth);
|
log.Exitf("negative tabwidth %d", *tabwidth)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.Chdir(goroot); err != nil {
|
if err := os.Chdir(goroot); err != nil {
|
||||||
log.Exitf("chdir %s: %v", goroot, err);
|
log.Exitf("chdir %s: %v", goroot, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
readTemplates();
|
readTemplates();
|
||||||
|
|
@ -174,7 +174,7 @@ func main() {
|
||||||
|
|
||||||
registerPublicHandlers(http.DefaultServeMux);
|
registerPublicHandlers(http.DefaultServeMux);
|
||||||
if *syncCmd != "" {
|
if *syncCmd != "" {
|
||||||
http.Handle("/debug/sync", http.HandlerFunc(dosync));
|
http.Handle("/debug/sync", http.HandlerFunc(dosync))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize directory tree with corresponding timestamp.
|
// Initialize directory tree with corresponding timestamp.
|
||||||
|
|
@ -192,7 +192,7 @@ func main() {
|
||||||
dosync(nil, nil);
|
dosync(nil, nil);
|
||||||
delay, _ := syncDelay.get();
|
delay, _ := syncDelay.get();
|
||||||
if *verbose {
|
if *verbose {
|
||||||
log.Stderrf("next sync in %dmin", delay.(int));
|
log.Stderrf("next sync in %dmin", delay.(int))
|
||||||
}
|
}
|
||||||
time.Sleep(int64(delay.(int))*60e9);
|
time.Sleep(int64(delay.(int))*60e9);
|
||||||
}
|
}
|
||||||
|
|
@ -210,7 +210,7 @@ func main() {
|
||||||
|
|
||||||
// Start http server.
|
// Start http server.
|
||||||
if err := http.ListenAndServe(*httpaddr, handler); err != nil {
|
if err := http.ListenAndServe(*httpaddr, handler); err != nil {
|
||||||
log.Exitf("ListenAndServe %s: %v", *httpaddr, err);
|
log.Exitf("ListenAndServe %s: %v", *httpaddr, err)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -225,7 +225,7 @@ func main() {
|
||||||
|
|
||||||
if info.PDoc == nil && info.Dirs == nil {
|
if info.PDoc == nil && info.Dirs == nil {
|
||||||
// try again, this time assume it's a command
|
// try again, this time assume it's a command
|
||||||
info = cmdHandler.getPageInfo(flag.Arg(0));
|
info = cmdHandler.getPageInfo(flag.Arg(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
if info.PDoc != nil && flag.NArg() > 1 {
|
if info.PDoc != nil && flag.NArg() > 1 {
|
||||||
|
|
@ -234,6 +234,6 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := packageText.Execute(info, os.Stdout); err != nil {
|
if err := packageText.Execute(info, os.Stdout); err != nil {
|
||||||
log.Stderrf("packageText.Execute: %s", err);
|
log.Stderrf("packageText.Execute: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,14 +31,14 @@ type snippetStyler struct {
|
||||||
|
|
||||||
|
|
||||||
func (s *snippetStyler) LineTag(line int) (text []uint8, tag printer.HTMLTag) {
|
func (s *snippetStyler) LineTag(line int) (text []uint8, tag printer.HTMLTag) {
|
||||||
return; // no LineTag for snippets
|
return // no LineTag for snippets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (s *snippetStyler) Ident(id *ast.Ident) (text []byte, tag printer.HTMLTag) {
|
func (s *snippetStyler) Ident(id *ast.Ident) (text []byte, tag printer.HTMLTag) {
|
||||||
text = strings.Bytes(id.Value);
|
text = strings.Bytes(id.Value);
|
||||||
if s.highlight == id {
|
if s.highlight == id {
|
||||||
tag = printer.HTMLTag{"<span class=highlight>", "</span>"};
|
tag = printer.HTMLTag{"<span class=highlight>", "</span>"}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -56,17 +56,17 @@ func findSpec(list []ast.Spec, id *ast.Ident) ast.Spec {
|
||||||
switch s := spec.(type) {
|
switch s := spec.(type) {
|
||||||
case *ast.ImportSpec:
|
case *ast.ImportSpec:
|
||||||
if s.Name == id {
|
if s.Name == id {
|
||||||
return s;
|
return s
|
||||||
}
|
}
|
||||||
case *ast.ValueSpec:
|
case *ast.ValueSpec:
|
||||||
for _, n := range s.Names {
|
for _, n := range s.Names {
|
||||||
if n == id {
|
if n == id {
|
||||||
return s;
|
return s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *ast.TypeSpec:
|
case *ast.TypeSpec:
|
||||||
if s.Name == id {
|
if s.Name == id {
|
||||||
return s;
|
return s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -77,7 +77,7 @@ func findSpec(list []ast.Spec, id *ast.Ident) ast.Spec {
|
||||||
func genSnippet(d *ast.GenDecl, id *ast.Ident) *Snippet {
|
func genSnippet(d *ast.GenDecl, id *ast.Ident) *Snippet {
|
||||||
s := findSpec(d.Specs, id);
|
s := findSpec(d.Specs, id);
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return nil; // declaration doesn't contain id - exit gracefully
|
return nil // declaration doesn't contain id - exit gracefully
|
||||||
}
|
}
|
||||||
|
|
||||||
// only use the spec containing the id for the snippet
|
// only use the spec containing the id for the snippet
|
||||||
|
|
@ -89,7 +89,7 @@ func genSnippet(d *ast.GenDecl, id *ast.Ident) *Snippet {
|
||||||
|
|
||||||
func funcSnippet(d *ast.FuncDecl, id *ast.Ident) *Snippet {
|
func funcSnippet(d *ast.FuncDecl, id *ast.Ident) *Snippet {
|
||||||
if d.Name != id {
|
if d.Name != id {
|
||||||
return nil; // declaration doesn't contain id - exit gracefully
|
return nil // declaration doesn't contain id - exit gracefully
|
||||||
}
|
}
|
||||||
|
|
||||||
// only use the function signature for the snippet
|
// only use the function signature for the snippet
|
||||||
|
|
@ -106,9 +106,9 @@ func funcSnippet(d *ast.FuncDecl, id *ast.Ident) *Snippet {
|
||||||
func NewSnippet(decl ast.Decl, id *ast.Ident) (s *Snippet) {
|
func NewSnippet(decl ast.Decl, id *ast.Ident) (s *Snippet) {
|
||||||
switch d := decl.(type) {
|
switch d := decl.(type) {
|
||||||
case *ast.GenDecl:
|
case *ast.GenDecl:
|
||||||
s = genSnippet(d, id);
|
s = genSnippet(d, id)
|
||||||
case *ast.FuncDecl:
|
case *ast.FuncDecl:
|
||||||
s = funcSnippet(d, id);
|
s = funcSnippet(d, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle failure gracefully
|
// handle failure gracefully
|
||||||
|
|
@ -116,7 +116,7 @@ func NewSnippet(decl ast.Decl, id *ast.Ident) (s *Snippet) {
|
||||||
s = &Snippet{
|
s = &Snippet{
|
||||||
id.Pos().Line,
|
id.Pos().Line,
|
||||||
fmt.Sprintf(`could not generate a snippet for <span class="highlight">%s</span>`, id.Value),
|
fmt.Sprintf(`could not generate a snippet for <span class="highlight">%s</span>`, id.Value),
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,13 +43,13 @@ func (p *ebnfParser) next() {
|
||||||
if p.tok.IsKeyword() {
|
if p.tok.IsKeyword() {
|
||||||
// TODO Should keyword mapping always happen outside scanner?
|
// TODO Should keyword mapping always happen outside scanner?
|
||||||
// Or should there be a flag to scanner to enable keyword mapping?
|
// Or should there be a flag to scanner to enable keyword mapping?
|
||||||
p.tok = token.IDENT;
|
p.tok = token.IDENT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (p *ebnfParser) Error(pos token.Position, msg string) {
|
func (p *ebnfParser) Error(pos token.Position, msg string) {
|
||||||
fmt.Fprintf(p.out, `<span class="alert">error: %s</span>`, msg);
|
fmt.Fprintf(p.out, `<span class="alert">error: %s</span>`, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -60,7 +60,7 @@ func (p *ebnfParser) errorExpected(pos token.Position, msg string) {
|
||||||
// make the error message more specific
|
// make the error message more specific
|
||||||
msg += ", found '" + p.tok.String() + "'";
|
msg += ", found '" + p.tok.String() + "'";
|
||||||
if p.tok.IsLiteral() {
|
if p.tok.IsLiteral() {
|
||||||
msg += " "+string(p.lit);
|
msg += " "+string(p.lit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.Error(pos, msg);
|
p.Error(pos, msg);
|
||||||
|
|
@ -70,7 +70,7 @@ func (p *ebnfParser) errorExpected(pos token.Position, msg string) {
|
||||||
func (p *ebnfParser) expect(tok token.Token) token.Position {
|
func (p *ebnfParser) expect(tok token.Token) token.Position {
|
||||||
pos := p.pos;
|
pos := p.pos;
|
||||||
if p.tok != tok {
|
if p.tok != tok {
|
||||||
p.errorExpected(pos, "'" + tok.String() + "'");
|
p.errorExpected(pos, "'" + tok.String() + "'")
|
||||||
}
|
}
|
||||||
p.next(); // make progress in any case
|
p.next(); // make progress in any case
|
||||||
return pos;
|
return pos;
|
||||||
|
|
@ -81,9 +81,9 @@ func (p *ebnfParser) parseIdentifier(def bool) {
|
||||||
name := string(p.lit);
|
name := string(p.lit);
|
||||||
p.expect(token.IDENT);
|
p.expect(token.IDENT);
|
||||||
if def {
|
if def {
|
||||||
fmt.Fprintf(p.out, `<a id="%s">%s</a>`, name, name);
|
fmt.Fprintf(p.out, `<a id="%s">%s</a>`, name, name)
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(p.out, `<a href="#%s" class="noline">%s</a>`, name, name);
|
fmt.Fprintf(p.out, `<a href="#%s" class="noline">%s</a>`, name, name)
|
||||||
}
|
}
|
||||||
p.prev += len(name); // skip identifier when calling flush
|
p.prev += len(name); // skip identifier when calling flush
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +92,7 @@ func (p *ebnfParser) parseIdentifier(def bool) {
|
||||||
func (p *ebnfParser) parseTerm() bool {
|
func (p *ebnfParser) parseTerm() bool {
|
||||||
switch p.tok {
|
switch p.tok {
|
||||||
case token.IDENT:
|
case token.IDENT:
|
||||||
p.parseIdentifier(false);
|
p.parseIdentifier(false)
|
||||||
|
|
||||||
case token.STRING:
|
case token.STRING:
|
||||||
p.next();
|
p.next();
|
||||||
|
|
@ -117,7 +117,7 @@ func (p *ebnfParser) parseTerm() bool {
|
||||||
p.expect(token.RBRACE);
|
p.expect(token.RBRACE);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -134,7 +134,7 @@ func (p *ebnfParser) parseExpression() {
|
||||||
for {
|
for {
|
||||||
p.parseSequence();
|
p.parseSequence();
|
||||||
if p.tok != token.OR {
|
if p.tok != token.OR {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
p.next();
|
p.next();
|
||||||
}
|
}
|
||||||
|
|
@ -158,7 +158,7 @@ func (p *ebnfParser) parse(out io.Writer, src []byte) {
|
||||||
|
|
||||||
// process source
|
// process source
|
||||||
for p.tok != token.EOF {
|
for p.tok != token.EOF {
|
||||||
p.parseProduction();
|
p.parseProduction()
|
||||||
}
|
}
|
||||||
p.flush();
|
p.flush();
|
||||||
}
|
}
|
||||||
|
|
@ -178,14 +178,14 @@ func linkify(out io.Writer, src []byte) {
|
||||||
// i: beginning of EBNF text (or end of source)
|
// i: beginning of EBNF text (or end of source)
|
||||||
i := bytes.Index(src, openTag);
|
i := bytes.Index(src, openTag);
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
i = n-len(openTag);
|
i = n-len(openTag)
|
||||||
}
|
}
|
||||||
i += len(openTag);
|
i += len(openTag);
|
||||||
|
|
||||||
// j: end of EBNF text (or end of source)
|
// j: end of EBNF text (or end of source)
|
||||||
j := bytes.Index(src[i:n], closeTag); // close marker
|
j := bytes.Index(src[i:n], closeTag); // close marker
|
||||||
if j < 0 {
|
if j < 0 {
|
||||||
j = n-i;
|
j = n-i
|
||||||
}
|
}
|
||||||
j += i;
|
j += i;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,10 +52,10 @@ func usage() {
|
||||||
func parserMode() uint {
|
func parserMode() uint {
|
||||||
mode := uint(0);
|
mode := uint(0);
|
||||||
if *comments {
|
if *comments {
|
||||||
mode |= parser.ParseComments;
|
mode |= parser.ParseComments
|
||||||
}
|
}
|
||||||
if *trace {
|
if *trace {
|
||||||
mode |= parser.Trace;
|
mode |= parser.Trace
|
||||||
}
|
}
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
@ -64,10 +64,10 @@ func parserMode() uint {
|
||||||
func printerMode() uint {
|
func printerMode() uint {
|
||||||
mode := uint(0);
|
mode := uint(0);
|
||||||
if !*align {
|
if !*align {
|
||||||
mode |= printer.RawFormat;
|
mode |= printer.RawFormat
|
||||||
}
|
}
|
||||||
if *usespaces {
|
if *usespaces {
|
||||||
mode |= printer.UseSpaces;
|
mode |= printer.UseSpaces
|
||||||
}
|
}
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
@ -75,42 +75,42 @@ func printerMode() uint {
|
||||||
|
|
||||||
func isGoFile(d *os.Dir) bool {
|
func isGoFile(d *os.Dir) bool {
|
||||||
// ignore non-Go files
|
// ignore non-Go files
|
||||||
return d.IsRegular() && !strings.HasPrefix(d.Name, ".") && strings.HasSuffix(d.Name, ".go");
|
return d.IsRegular() && !strings.HasPrefix(d.Name, ".") && strings.HasSuffix(d.Name, ".go")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func processFile(filename string) os.Error {
|
func processFile(filename string) os.Error {
|
||||||
src, err := io.ReadFile(filename);
|
src, err := io.ReadFile(filename);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := parser.ParseFile(filename, src, parserMode());
|
file, err := parser.ParseFile(filename, src, parserMode());
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var res bytes.Buffer;
|
var res bytes.Buffer;
|
||||||
_, err = (&printer.Config{printerMode(), *tabwidth, nil}).Fprint(&res, file);
|
_, err = (&printer.Config{printerMode(), *tabwidth, nil}).Fprint(&res, file);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if bytes.Compare(src, res.Bytes()) != 0 {
|
if bytes.Compare(src, res.Bytes()) != 0 {
|
||||||
// formatting has changed
|
// formatting has changed
|
||||||
if *list {
|
if *list {
|
||||||
fmt.Fprintln(os.Stdout, filename);
|
fmt.Fprintln(os.Stdout, filename)
|
||||||
}
|
}
|
||||||
if *write {
|
if *write {
|
||||||
err = io.WriteFile(filename, res.Bytes(), 0);
|
err = io.WriteFile(filename, res.Bytes(), 0);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !*list && !*write {
|
if !*list && !*write {
|
||||||
_, err = os.Stdout.Write(res.Bytes());
|
_, err = os.Stdout.Write(res.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
@ -120,7 +120,7 @@ func processFile(filename string) os.Error {
|
||||||
type fileVisitor chan os.Error
|
type fileVisitor chan os.Error
|
||||||
|
|
||||||
func (v fileVisitor) VisitDir(path string, d *os.Dir) bool {
|
func (v fileVisitor) VisitDir(path string, d *os.Dir) bool {
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -128,7 +128,7 @@ func (v fileVisitor) VisitFile(path string, d *os.Dir) {
|
||||||
if isGoFile(d) {
|
if isGoFile(d) {
|
||||||
v <- nil; // synchronize error handler
|
v <- nil; // synchronize error handler
|
||||||
if err := processFile(path); err != nil {
|
if err := processFile(path); err != nil {
|
||||||
v <- err;
|
v <- err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -140,7 +140,7 @@ func walkDir(path string) {
|
||||||
go func() {
|
go func() {
|
||||||
for err := range v {
|
for err := range v {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
report(err);
|
report(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
@ -160,7 +160,7 @@ func main() {
|
||||||
|
|
||||||
if flag.NArg() == 0 {
|
if flag.NArg() == 0 {
|
||||||
if err := processFile("/dev/stdin"); err != nil {
|
if err := processFile("/dev/stdin"); err != nil {
|
||||||
report(err);
|
report(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,13 +168,13 @@ func main() {
|
||||||
path := flag.Arg(i);
|
path := flag.Arg(i);
|
||||||
switch dir, err := os.Stat(path); {
|
switch dir, err := os.Stat(path); {
|
||||||
case err != nil:
|
case err != nil:
|
||||||
report(err);
|
report(err)
|
||||||
case dir.IsRegular():
|
case dir.IsRegular():
|
||||||
if err := processFile(path); err != nil {
|
if err := processFile(path); err != nil {
|
||||||
report(err);
|
report(err)
|
||||||
}
|
}
|
||||||
case dir.IsDirectory():
|
case dir.IsDirectory():
|
||||||
walkDir(path);
|
walkDir(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -35,11 +35,11 @@ func main() {
|
||||||
var err os.Error;
|
var err os.Error;
|
||||||
switch len(args) {
|
switch len(args) {
|
||||||
case 0:
|
case 0:
|
||||||
data, err = io.ReadAll(os.Stdin);
|
data, err = io.ReadAll(os.Stdin)
|
||||||
case 1:
|
case 1:
|
||||||
data, err = io.ReadFile(args[0]);
|
data, err = io.ReadFile(args[0])
|
||||||
default:
|
default:
|
||||||
usage();
|
usage()
|
||||||
}
|
}
|
||||||
chk(err);
|
chk(err);
|
||||||
|
|
||||||
|
|
@ -63,25 +63,25 @@ func main() {
|
||||||
chk(err);
|
chk(err);
|
||||||
dirty := make(map[string]int);
|
dirty := make(map[string]int);
|
||||||
for _, f := range dirtylist {
|
for _, f := range dirtylist {
|
||||||
dirty[f] = 1;
|
dirty[f] = 1
|
||||||
}
|
}
|
||||||
conflict := make(map[string]int);
|
conflict := make(map[string]int);
|
||||||
for _, f := range pset.File {
|
for _, f := range pset.File {
|
||||||
if f.Verb == patch.Delete || f.Verb == patch.Rename {
|
if f.Verb == patch.Delete || f.Verb == patch.Rename {
|
||||||
if _, ok := dirty[f.Src]; ok {
|
if _, ok := dirty[f.Src]; ok {
|
||||||
conflict[f.Src] = 1;
|
conflict[f.Src] = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if f.Verb != patch.Delete {
|
if f.Verb != patch.Delete {
|
||||||
if _, ok := dirty[f.Dst]; ok {
|
if _, ok := dirty[f.Dst]; ok {
|
||||||
conflict[f.Dst] = 1;
|
conflict[f.Dst] = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(conflict) > 0 {
|
if len(conflict) > 0 {
|
||||||
fmt.Fprintf(os.Stderr, "cannot apply patch to locally modified files:\n");
|
fmt.Fprintf(os.Stderr, "cannot apply patch to locally modified files:\n");
|
||||||
for name := range conflict {
|
for name := range conflict {
|
||||||
fmt.Fprintf(os.Stderr, "\t%s\n", name);
|
fmt.Fprintf(os.Stderr, "\t%s\n", name)
|
||||||
}
|
}
|
||||||
os.Exit(2);
|
os.Exit(2);
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +136,7 @@ func main() {
|
||||||
for i := range op {
|
for i := range op {
|
||||||
o := &op[i];
|
o := &op[i];
|
||||||
if o.Verb == patch.Delete {
|
if o.Verb == patch.Delete {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if o.Verb == patch.Add {
|
if o.Verb == patch.Add {
|
||||||
makeParent(o.Dst);
|
makeParent(o.Dst);
|
||||||
|
|
@ -145,9 +145,9 @@ func main() {
|
||||||
if o.Data != nil {
|
if o.Data != nil {
|
||||||
chk(io.WriteFile(o.Dst, o.Data, 0644));
|
chk(io.WriteFile(o.Dst, o.Data, 0644));
|
||||||
if o.Verb == patch.Add {
|
if o.Verb == patch.Add {
|
||||||
undoRm(o.Dst);
|
undoRm(o.Dst)
|
||||||
} else {
|
} else {
|
||||||
undoRevert(o.Dst);
|
undoRevert(o.Dst)
|
||||||
}
|
}
|
||||||
changed[o.Dst] = 1;
|
changed[o.Dst] = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -178,7 +178,7 @@ func main() {
|
||||||
}
|
}
|
||||||
sort.SortStrings(list);
|
sort.SortStrings(list);
|
||||||
for _, f := range list {
|
for _, f := range list {
|
||||||
fmt.Printf("%s\n", f);
|
fmt.Printf("%s\n", f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,25 +195,25 @@ func mkdirAll(path string, perm int) os.Error {
|
||||||
dir, err := os.Lstat(path);
|
dir, err := os.Lstat(path);
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if dir.IsDirectory() {
|
if dir.IsDirectory() {
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
return &os.PathError{"mkdir", path, os.ENOTDIR};
|
return &os.PathError{"mkdir", path, os.ENOTDIR};
|
||||||
}
|
}
|
||||||
|
|
||||||
i := len(path);
|
i := len(path);
|
||||||
for i > 0 && path[i-1] == '/' { // Skip trailing slashes.
|
for i > 0 && path[i-1] == '/' { // Skip trailing slashes.
|
||||||
i--;
|
i--
|
||||||
}
|
}
|
||||||
|
|
||||||
j := i;
|
j := i;
|
||||||
for j > 0 && path[j-1] != '/' { // Scan backward over element.
|
for j > 0 && path[j-1] != '/' { // Scan backward over element.
|
||||||
j--;
|
j--
|
||||||
}
|
}
|
||||||
|
|
||||||
if j > 0 {
|
if j > 0 {
|
||||||
err = mkdirAll(path[0 : j-1], perm);
|
err = mkdirAll(path[0 : j-1], perm);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,7 +223,7 @@ func mkdirAll(path string, perm int) os.Error {
|
||||||
// double-checking that directory doesn't exist.
|
// double-checking that directory doesn't exist.
|
||||||
dir, err1 := os.Lstat(path);
|
dir, err1 := os.Lstat(path);
|
||||||
if err1 == nil && dir.IsDirectory() {
|
if err1 == nil && dir.IsDirectory() {
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
@ -253,7 +253,7 @@ func undoRm(name string) { undoLog.Push(undo(func() os.Error { return os.Remove(
|
||||||
func runUndo() {
|
func runUndo() {
|
||||||
for i := undoLog.Len() - 1; i >= 0; i-- {
|
for i := undoLog.Len() - 1; i >= 0; i-- {
|
||||||
if err := undoLog.At(i).(undo)(); err != nil {
|
if err := undoLog.At(i).(undo)(); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", err);
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -263,7 +263,7 @@ func runUndo() {
|
||||||
func hgRoot() (string, os.Error) {
|
func hgRoot() (string, os.Error) {
|
||||||
out, err := run([]string{"hg", "root"}, nil);
|
out, err := run([]string{"hg", "root"}, nil);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err;
|
return "", err
|
||||||
}
|
}
|
||||||
return strings.TrimSpace(out), nil;
|
return strings.TrimSpace(out), nil;
|
||||||
}
|
}
|
||||||
|
|
@ -280,7 +280,7 @@ func hgIncoming() bool {
|
||||||
func hgModified() ([]string, os.Error) {
|
func hgModified() ([]string, os.Error) {
|
||||||
out, err := run([]string{"hg", "status", "-n"}, nil);
|
out, err := run([]string{"hg", "status", "-n"}, nil);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err;
|
return nil, err
|
||||||
}
|
}
|
||||||
return strings.Split(strings.TrimSpace(out), "\n", 0), nil;
|
return strings.Split(strings.TrimSpace(out), "\n", 0), nil;
|
||||||
}
|
}
|
||||||
|
|
@ -320,7 +320,7 @@ func hgRename(dst, src string) os.Error {
|
||||||
func copy(a []string) []string {
|
func copy(a []string) []string {
|
||||||
b := make([]string, len(a));
|
b := make([]string, len(a));
|
||||||
for i, s := range a {
|
for i, s := range a {
|
||||||
b[i] = s;
|
b[i] = s
|
||||||
}
|
}
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
@ -338,7 +338,7 @@ func run(argv []string, input []byte) (out string, err os.Error) {
|
||||||
if !ok {
|
if !ok {
|
||||||
prog, err = exec.LookPath(argv[0]);
|
prog, err = exec.LookPath(argv[0]);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
lookPathCache[argv[0]] = prog;
|
lookPathCache[argv[0]] = prog;
|
||||||
}
|
}
|
||||||
|
|
@ -347,12 +347,12 @@ func run(argv []string, input []byte) (out string, err os.Error) {
|
||||||
if len(input) == 0 {
|
if len(input) == 0 {
|
||||||
cmd, err = exec.Run(prog, argv, os.Environ(), exec.DevNull, exec.Pipe, exec.MergeWithStdout);
|
cmd, err = exec.Run(prog, argv, os.Environ(), exec.DevNull, exec.Pipe, exec.MergeWithStdout);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cmd, err = exec.Run(prog, argv, os.Environ(), exec.Pipe, exec.Pipe, exec.MergeWithStdout);
|
cmd, err = exec.Run(prog, argv, os.Environ(), exec.Pipe, exec.Pipe, exec.MergeWithStdout);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
cmd.Stdin.Write(input);
|
cmd.Stdin.Write(input);
|
||||||
|
|
@ -369,7 +369,7 @@ func run(argv []string, input []byte) (out string, err os.Error) {
|
||||||
}
|
}
|
||||||
w, err := cmd.Wait(0);
|
w, err := cmd.Wait(0);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
if !w.Exited() || w.ExitStatus() != 0 {
|
if !w.Exited() || w.ExitStatus() != 0 {
|
||||||
err = w;
|
err = w;
|
||||||
|
|
|
||||||
|
|
@ -50,10 +50,10 @@ func NewReader(r io.Reader) *Reader { return &Reader{r: r} }
|
||||||
func (tr *Reader) Next() (*Header, os.Error) {
|
func (tr *Reader) Next() (*Header, os.Error) {
|
||||||
var hdr *Header;
|
var hdr *Header;
|
||||||
if tr.err == nil {
|
if tr.err == nil {
|
||||||
tr.skipUnread();
|
tr.skipUnread()
|
||||||
}
|
}
|
||||||
if tr.err == nil {
|
if tr.err == nil {
|
||||||
hdr = tr.readHeader();
|
hdr = tr.readHeader()
|
||||||
}
|
}
|
||||||
return hdr, tr.err;
|
return hdr, tr.err;
|
||||||
}
|
}
|
||||||
|
|
@ -63,7 +63,7 @@ func (tr *Reader) Next() (*Header, os.Error) {
|
||||||
func cString(b []byte) string {
|
func cString(b []byte) string {
|
||||||
n := 0;
|
n := 0;
|
||||||
for n < len(b) && b[n] != 0 {
|
for n < len(b) && b[n] != 0 {
|
||||||
n++;
|
n++
|
||||||
}
|
}
|
||||||
return string(b[0:n]);
|
return string(b[0:n]);
|
||||||
}
|
}
|
||||||
|
|
@ -71,15 +71,15 @@ func cString(b []byte) string {
|
||||||
func (tr *Reader) octal(b []byte) int64 {
|
func (tr *Reader) octal(b []byte) int64 {
|
||||||
// Removing leading spaces.
|
// Removing leading spaces.
|
||||||
for len(b) > 0 && b[0] == ' ' {
|
for len(b) > 0 && b[0] == ' ' {
|
||||||
b = b[1:len(b)];
|
b = b[1:len(b)]
|
||||||
}
|
}
|
||||||
// Removing trailing NULs and spaces.
|
// Removing trailing NULs and spaces.
|
||||||
for len(b) > 0 && (b[len(b)-1] == ' ' || b[len(b)-1] == '\x00') {
|
for len(b) > 0 && (b[len(b)-1] == ' ' || b[len(b)-1] == '\x00') {
|
||||||
b = b[0 : len(b)-1];
|
b = b[0 : len(b)-1]
|
||||||
}
|
}
|
||||||
x, err := strconv.Btoui64(cString(b), 8);
|
x, err := strconv.Btoui64(cString(b), 8);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tr.err = err;
|
tr.err = err
|
||||||
}
|
}
|
||||||
return int64(x);
|
return int64(x);
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +87,7 @@ func (tr *Reader) octal(b []byte) int64 {
|
||||||
type ignoreWriter struct{}
|
type ignoreWriter struct{}
|
||||||
|
|
||||||
func (ignoreWriter) Write(b []byte) (n int, err os.Error) {
|
func (ignoreWriter) Write(b []byte) (n int, err os.Error) {
|
||||||
return len(b), nil;
|
return len(b), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip any unread bytes in the existing file entry, as well as any alignment padding.
|
// Skip any unread bytes in the existing file entry, as well as any alignment padding.
|
||||||
|
|
@ -95,16 +95,16 @@ func (tr *Reader) skipUnread() {
|
||||||
nr := tr.nb + tr.pad; // number of bytes to skip
|
nr := tr.nb + tr.pad; // number of bytes to skip
|
||||||
|
|
||||||
if sr, ok := tr.r.(io.Seeker); ok {
|
if sr, ok := tr.r.(io.Seeker); ok {
|
||||||
_, tr.err = sr.Seek(nr, 1);
|
_, tr.err = sr.Seek(nr, 1)
|
||||||
} else {
|
} else {
|
||||||
_, tr.err = io.Copyn(ignoreWriter{}, tr.r, nr);
|
_, tr.err = io.Copyn(ignoreWriter{}, tr.r, nr)
|
||||||
}
|
}
|
||||||
tr.nb, tr.pad = 0, 0;
|
tr.nb, tr.pad = 0, 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *Reader) verifyChecksum(header []byte) bool {
|
func (tr *Reader) verifyChecksum(header []byte) bool {
|
||||||
if tr.err != nil {
|
if tr.err != nil {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
given := tr.octal(header[148:156]);
|
given := tr.octal(header[148:156]);
|
||||||
|
|
@ -115,16 +115,16 @@ func (tr *Reader) verifyChecksum(header []byte) bool {
|
||||||
func (tr *Reader) readHeader() *Header {
|
func (tr *Reader) readHeader() *Header {
|
||||||
header := make([]byte, blockSize);
|
header := make([]byte, blockSize);
|
||||||
if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
|
if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Two blocks of zero bytes marks the end of the archive.
|
// Two blocks of zero bytes marks the end of the archive.
|
||||||
if bytes.Equal(header, zeroBlock[0 : blockSize]) {
|
if bytes.Equal(header, zeroBlock[0 : blockSize]) {
|
||||||
if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
|
if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
if !bytes.Equal(header, zeroBlock[0 : blockSize]) {
|
if !bytes.Equal(header, zeroBlock[0 : blockSize]) {
|
||||||
tr.err = HeaderError;
|
tr.err = HeaderError
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
@ -156,12 +156,12 @@ func (tr *Reader) readHeader() *Header {
|
||||||
switch magic {
|
switch magic {
|
||||||
case "ustar\x0000": // POSIX tar (1003.1-1988)
|
case "ustar\x0000": // POSIX tar (1003.1-1988)
|
||||||
if string(header[508:512]) == "tar\x00" {
|
if string(header[508:512]) == "tar\x00" {
|
||||||
format = "star";
|
format = "star"
|
||||||
} else {
|
} else {
|
||||||
format = "posix";
|
format = "posix"
|
||||||
}
|
}
|
||||||
case "ustar \x00": // old GNU tar
|
case "ustar \x00": // old GNU tar
|
||||||
format = "gnu";
|
format = "gnu"
|
||||||
}
|
}
|
||||||
|
|
||||||
switch format {
|
switch format {
|
||||||
|
|
@ -177,14 +177,14 @@ func (tr *Reader) readHeader() *Header {
|
||||||
var prefix string;
|
var prefix string;
|
||||||
switch format {
|
switch format {
|
||||||
case "posix", "gnu":
|
case "posix", "gnu":
|
||||||
prefix = cString(s.next(155));
|
prefix = cString(s.next(155))
|
||||||
case "star":
|
case "star":
|
||||||
prefix = cString(s.next(131));
|
prefix = cString(s.next(131));
|
||||||
hdr.Atime = tr.octal(s.next(12));
|
hdr.Atime = tr.octal(s.next(12));
|
||||||
hdr.Ctime = tr.octal(s.next(12));
|
hdr.Ctime = tr.octal(s.next(12));
|
||||||
}
|
}
|
||||||
if len(prefix) > 0 {
|
if len(prefix) > 0 {
|
||||||
hdr.Name = prefix + "/" + hdr.Name;
|
hdr.Name = prefix + "/" + hdr.Name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -206,7 +206,7 @@ func (tr *Reader) readHeader() *Header {
|
||||||
// until Next is called to advance to the next entry.
|
// until Next is called to advance to the next entry.
|
||||||
func (tr *Reader) Read(b []uint8) (n int, err os.Error) {
|
func (tr *Reader) Read(b []uint8) (n int, err os.Error) {
|
||||||
if int64(len(b)) > tr.nb {
|
if int64(len(b)) > tr.nb {
|
||||||
b = b[0 : tr.nb];
|
b = b[0 : tr.nb]
|
||||||
}
|
}
|
||||||
n, err = tr.r.Read(b);
|
n, err = tr.r.Read(b);
|
||||||
tr.nb -= int64(n);
|
tr.nb -= int64(n);
|
||||||
|
|
|
||||||
|
|
@ -120,12 +120,12 @@ testLoop:
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(hdr, header) {
|
if !reflect.DeepEqual(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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hdr, err := tr.Next();
|
hdr, err := tr.Next();
|
||||||
if hdr != nil || err != nil {
|
if hdr != nil || err != nil {
|
||||||
t.Errorf("test %d: Unexpected entry or error: hdr=%v err=%v", i, err);
|
t.Errorf("test %d: Unexpected entry or error: hdr=%v err=%v", i, err)
|
||||||
}
|
}
|
||||||
f.Close();
|
f.Close();
|
||||||
}
|
}
|
||||||
|
|
@ -134,7 +134,7 @@ testLoop:
|
||||||
func TestPartialRead(t *testing.T) {
|
func TestPartialRead(t *testing.T) {
|
||||||
f, err := os.Open("testdata/gnu.tar", os.O_RDONLY, 0444);
|
f, err := os.Open("testdata/gnu.tar", os.O_RDONLY, 0444);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err);
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
defer f.Close();
|
defer f.Close();
|
||||||
|
|
||||||
|
|
@ -143,26 +143,26 @@ func TestPartialRead(t *testing.T) {
|
||||||
// Read the first four bytes; Next() should skip the last byte.
|
// Read the first four bytes; Next() should skip the last byte.
|
||||||
hdr, err := tr.Next();
|
hdr, err := tr.Next();
|
||||||
if err != nil || hdr == nil {
|
if err != nil || hdr == nil {
|
||||||
t.Fatalf("Didn't get first file: %v", err);
|
t.Fatalf("Didn't get first file: %v", err)
|
||||||
}
|
}
|
||||||
buf := make([]byte, 4);
|
buf := make([]byte, 4);
|
||||||
if _, err := io.ReadFull(tr, buf); err != nil {
|
if _, err := io.ReadFull(tr, buf); err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err);
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
if expected := strings.Bytes("Kilt"); !bytes.Equal(buf, expected) {
|
if expected := strings.Bytes("Kilt"); !bytes.Equal(buf, expected) {
|
||||||
t.Errorf("Contents = %v, want %v", buf, expected);
|
t.Errorf("Contents = %v, want %v", buf, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second file
|
// Second file
|
||||||
hdr, err = tr.Next();
|
hdr, err = tr.Next();
|
||||||
if err != nil || hdr == nil {
|
if err != nil || hdr == nil {
|
||||||
t.Fatalf("Didn't get second file: %v", err);
|
t.Fatalf("Didn't get second file: %v", err)
|
||||||
}
|
}
|
||||||
buf = make([]byte, 6);
|
buf = make([]byte, 6);
|
||||||
if _, err := io.ReadFull(tr, buf); err != nil {
|
if _, err := io.ReadFull(tr, buf); err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err);
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
if expected := strings.Bytes("Google"); !bytes.Equal(buf, expected) {
|
if expected := strings.Bytes("Google"); !bytes.Equal(buf, expected) {
|
||||||
t.Errorf("Contents = %v, want %v", buf, expected);
|
t.Errorf("Contents = %v, want %v", buf, expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ func (tw *Writer) Flush() os.Error {
|
||||||
for n > 0 && tw.err == nil {
|
for n > 0 && tw.err == nil {
|
||||||
nr := n;
|
nr := n;
|
||||||
if nr > blockSize {
|
if nr > blockSize {
|
||||||
nr = blockSize;
|
nr = blockSize
|
||||||
}
|
}
|
||||||
var nw int;
|
var nw int;
|
||||||
nw, tw.err = tw.w.Write(zeroBlock[0:nr]);
|
nw, tw.err = tw.w.Write(zeroBlock[0:nr]);
|
||||||
|
|
@ -68,15 +68,15 @@ func (tw *Writer) Flush() os.Error {
|
||||||
func (tw *Writer) cString(b []byte, s string) {
|
func (tw *Writer) cString(b []byte, s string) {
|
||||||
if len(s) > len(b) {
|
if len(s) > len(b) {
|
||||||
if tw.err == nil {
|
if tw.err == nil {
|
||||||
tw.err = ErrFieldTooLong;
|
tw.err = ErrFieldTooLong
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for i, ch := range strings.Bytes(s) {
|
for i, ch := range strings.Bytes(s) {
|
||||||
b[i] = ch;
|
b[i] = ch
|
||||||
}
|
}
|
||||||
if len(s) < len(b) {
|
if len(s) < len(b) {
|
||||||
b[len(s)] = 0;
|
b[len(s)] = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,7 +85,7 @@ func (tw *Writer) octal(b []byte, x int64) {
|
||||||
s := strconv.Itob64(x, 8);
|
s := strconv.Itob64(x, 8);
|
||||||
// leading zeros, but leave room for a NUL.
|
// leading zeros, but leave room for a NUL.
|
||||||
for len(s)+1 < len(b) {
|
for len(s)+1 < len(b) {
|
||||||
s = "0"+s;
|
s = "0"+s
|
||||||
}
|
}
|
||||||
tw.cString(b, s);
|
tw.cString(b, s);
|
||||||
}
|
}
|
||||||
|
|
@ -111,10 +111,10 @@ func (tw *Writer) numeric(b []byte, x int64) {
|
||||||
// WriteHeader calls Flush if it is not the first header.
|
// WriteHeader calls Flush if it is not the first header.
|
||||||
func (tw *Writer) WriteHeader(hdr *Header) os.Error {
|
func (tw *Writer) WriteHeader(hdr *Header) os.Error {
|
||||||
if tw.err == nil {
|
if tw.err == nil {
|
||||||
tw.Flush();
|
tw.Flush()
|
||||||
}
|
}
|
||||||
if tw.err != nil {
|
if tw.err != nil {
|
||||||
return tw.err;
|
return tw.err
|
||||||
}
|
}
|
||||||
|
|
||||||
tw.nb = int64(hdr.Size);
|
tw.nb = int64(hdr.Size);
|
||||||
|
|
@ -142,7 +142,7 @@ func (tw *Writer) WriteHeader(hdr *Header) os.Error {
|
||||||
|
|
||||||
// Use the GNU magic instead of POSIX magic if we used any GNU extensions.
|
// Use the GNU magic instead of POSIX magic if we used any GNU extensions.
|
||||||
if tw.usedBinary {
|
if tw.usedBinary {
|
||||||
bytes.Copy(header[257:265], strings.Bytes("ustar \x00"));
|
bytes.Copy(header[257:265], strings.Bytes("ustar \x00"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// The chksum field is terminated by a NUL and a space.
|
// The chksum field is terminated by a NUL and a space.
|
||||||
|
|
@ -153,7 +153,7 @@ func (tw *Writer) WriteHeader(hdr *Header) os.Error {
|
||||||
|
|
||||||
if tw.err != nil {
|
if tw.err != nil {
|
||||||
// problem with header; probably integer too big for a field.
|
// problem with header; probably integer too big for a field.
|
||||||
return tw.err;
|
return tw.err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, tw.err = tw.w.Write(header);
|
_, tw.err = tw.w.Write(header);
|
||||||
|
|
@ -173,7 +173,7 @@ func (tw *Writer) Write(b []uint8) (n int, err os.Error) {
|
||||||
n, err = tw.w.Write(b);
|
n, err = tw.w.Write(b);
|
||||||
tw.nb -= int64(n);
|
tw.nb -= int64(n);
|
||||||
if err == nil && overwrite {
|
if err == nil && overwrite {
|
||||||
err = ErrWriteTooLong;
|
err = ErrWriteTooLong
|
||||||
}
|
}
|
||||||
tw.err = err;
|
tw.err = err;
|
||||||
return;
|
return;
|
||||||
|
|
@ -181,7 +181,7 @@ func (tw *Writer) Write(b []uint8) (n int, err os.Error) {
|
||||||
|
|
||||||
func (tw *Writer) Close() os.Error {
|
func (tw *Writer) Close() os.Error {
|
||||||
if tw.err != nil || tw.closed {
|
if tw.err != nil || tw.closed {
|
||||||
return tw.err;
|
return tw.err
|
||||||
}
|
}
|
||||||
tw.Flush();
|
tw.Flush();
|
||||||
tw.closed = true;
|
tw.closed = true;
|
||||||
|
|
@ -190,7 +190,7 @@ func (tw *Writer) Close() os.Error {
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
_, tw.err = tw.w.Write(zeroBlock);
|
_, tw.err = tw.w.Write(zeroBlock);
|
||||||
if tw.err != nil {
|
if tw.err != nil {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tw.err;
|
return tw.err;
|
||||||
|
|
|
||||||
|
|
@ -87,9 +87,9 @@ func bytestr(offset int, b []byte) string {
|
||||||
for _, ch := range b {
|
for _, ch := range b {
|
||||||
switch {
|
switch {
|
||||||
case '0' <= ch && ch <= '9', 'A' <= ch && ch <= 'Z', 'a' <= ch && ch <= 'z':
|
case '0' <= ch && ch <= '9', 'A' <= ch && ch <= 'Z', 'a' <= ch && ch <= 'z':
|
||||||
s += fmt.Sprintf(" %c", ch);
|
s += fmt.Sprintf(" %c", ch)
|
||||||
default:
|
default:
|
||||||
s += fmt.Sprintf(" %02x", ch);
|
s += fmt.Sprintf(" %02x", ch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
|
@ -102,15 +102,15 @@ func bytediff(a []byte, b []byte) string {
|
||||||
for offset := 0; len(a)+len(b) > 0; offset += rowLen {
|
for offset := 0; len(a)+len(b) > 0; offset += rowLen {
|
||||||
na, nb := rowLen, rowLen;
|
na, nb := rowLen, rowLen;
|
||||||
if na > len(a) {
|
if na > len(a) {
|
||||||
na = len(a);
|
na = len(a)
|
||||||
}
|
}
|
||||||
if nb > len(b) {
|
if nb > len(b) {
|
||||||
nb = len(b);
|
nb = len(b)
|
||||||
}
|
}
|
||||||
sa := bytestr(offset, a[0:na]);
|
sa := bytestr(offset, a[0:na]);
|
||||||
sb := bytestr(offset, b[0:nb]);
|
sb := bytestr(offset, b[0:nb]);
|
||||||
if sa != sb {
|
if sa != sb {
|
||||||
s += fmt.Sprintf("-%v\n+%v\n", sa, sb);
|
s += fmt.Sprintf("-%v\n+%v\n", sa, sb)
|
||||||
}
|
}
|
||||||
a = a[na:len(a)];
|
a = a[na:len(a)];
|
||||||
b = b[nb:len(b)];
|
b = b[nb:len(b)];
|
||||||
|
|
@ -147,7 +147,7 @@ testLoop:
|
||||||
actual := buf.Bytes();
|
actual := buf.Bytes();
|
||||||
if !bytes.Equal(expected, actual) {
|
if !bytes.Equal(expected, actual) {
|
||||||
t.Errorf("test %d: Incorrect result: (-=expected, +=actual)\n%v",
|
t.Errorf("test %d: Incorrect result: (-=expected, +=actual)\n%v",
|
||||||
i, bytediff(expected, actual));
|
i, bytediff(expected, actual))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,10 +82,10 @@ func parseInt64(bytes []byte) (ret int64, err os.Error) {
|
||||||
func parseInt(bytes []byte) (int, os.Error) {
|
func parseInt(bytes []byte) (int, os.Error) {
|
||||||
ret64, err := parseInt64(bytes);
|
ret64, err := parseInt64(bytes);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err;
|
return 0, err
|
||||||
}
|
}
|
||||||
if ret64 != int64(int(ret64)) {
|
if ret64 != int64(int(ret64)) {
|
||||||
return 0, StructuralError{"integer too large"};
|
return 0, StructuralError{"integer too large"}
|
||||||
}
|
}
|
||||||
return int(ret64), nil;
|
return int(ret64), nil;
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +104,7 @@ type BitString struct {
|
||||||
// returns false.
|
// returns false.
|
||||||
func (b BitString) At(i int) int {
|
func (b BitString) At(i int) int {
|
||||||
if i < 0 || i >= b.BitLength {
|
if i < 0 || i >= b.BitLength {
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
x := i/8;
|
x := i/8;
|
||||||
y := 7-uint(i%8);
|
y := 7-uint(i%8);
|
||||||
|
|
@ -155,7 +155,7 @@ func parseObjectIdentifier(bytes []byte) (s []int, err os.Error) {
|
||||||
var v int;
|
var v int;
|
||||||
v, offset, err = parseBase128Int(bytes, offset);
|
v, offset, err = parseBase128Int(bytes, offset);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
s[i] = v;
|
s[i] = v;
|
||||||
}
|
}
|
||||||
|
|
@ -177,7 +177,7 @@ func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err os.Erro
|
||||||
ret |= int(b&0x7f);
|
ret |= int(b&0x7f);
|
||||||
offset++;
|
offset++;
|
||||||
if b&0x80 == 0 {
|
if b&0x80 == 0 {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = SyntaxError{"truncated base 128 integer"};
|
err = SyntaxError{"truncated base 128 integer"};
|
||||||
|
|
@ -192,12 +192,12 @@ func isDigit(b byte) bool { return '0' <= b && b <= '9' }
|
||||||
func twoDigits(bytes []byte, max int) (int, bool) {
|
func twoDigits(bytes []byte, max int) (int, bool) {
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
if !isDigit(bytes[i]) {
|
if !isDigit(bytes[i]) {
|
||||||
return 0, false;
|
return 0, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
value := (int(bytes[0])-'0')*10 + int(bytes[1]-'0');
|
value := (int(bytes[0])-'0')*10 + int(bytes[1]-'0');
|
||||||
if value > max {
|
if value > max {
|
||||||
return 0, false;
|
return 0, false
|
||||||
}
|
}
|
||||||
return value, true;
|
return value, true;
|
||||||
}
|
}
|
||||||
|
|
@ -225,54 +225,54 @@ func parseUTCTime(bytes []byte) (ret time.Time, err os.Error) {
|
||||||
// RFC 5280, section 5.1.2.4 says that years 2050 or later use another date
|
// RFC 5280, section 5.1.2.4 says that years 2050 or later use another date
|
||||||
// scheme.
|
// scheme.
|
||||||
if year > 50 {
|
if year > 50 {
|
||||||
ret.Year = 1900+int64(year);
|
ret.Year = 1900+int64(year)
|
||||||
} else {
|
} else {
|
||||||
ret.Year = 2000+int64(year);
|
ret.Year = 2000+int64(year)
|
||||||
}
|
}
|
||||||
ret.Month, ok2 = twoDigits(bytes[2:4], 12);
|
ret.Month, ok2 = twoDigits(bytes[2:4], 12);
|
||||||
ret.Day, ok3 = twoDigits(bytes[4:6], 31);
|
ret.Day, ok3 = twoDigits(bytes[4:6], 31);
|
||||||
ret.Hour, ok4 = twoDigits(bytes[6:8], 23);
|
ret.Hour, ok4 = twoDigits(bytes[6:8], 23);
|
||||||
ret.Minute, ok5 = twoDigits(bytes[8:10], 59);
|
ret.Minute, ok5 = twoDigits(bytes[8:10], 59);
|
||||||
if !ok1 || !ok2 || !ok3 || !ok4 || !ok5 {
|
if !ok1 || !ok2 || !ok3 || !ok4 || !ok5 {
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
bytes = bytes[10:len(bytes)];
|
bytes = bytes[10:len(bytes)];
|
||||||
switch bytes[0] {
|
switch bytes[0] {
|
||||||
case '0', '1', '2', '3', '4', '5', '6':
|
case '0', '1', '2', '3', '4', '5', '6':
|
||||||
if len(bytes) < 3 {
|
if len(bytes) < 3 {
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
ret.Second, ok1 = twoDigits(bytes[0:2], 60); // 60, not 59, because of leap seconds.
|
ret.Second, ok1 = twoDigits(bytes[0:2], 60); // 60, not 59, because of leap seconds.
|
||||||
if !ok1 {
|
if !ok1 {
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
bytes = bytes[2:len(bytes)];
|
bytes = bytes[2:len(bytes)];
|
||||||
}
|
}
|
||||||
if len(bytes) == 0 {
|
if len(bytes) == 0 {
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
switch bytes[0] {
|
switch bytes[0] {
|
||||||
case 'Z':
|
case 'Z':
|
||||||
if len(bytes) != 1 {
|
if len(bytes) != 1 {
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case '-', '+':
|
case '-', '+':
|
||||||
if len(bytes) != 5 {
|
if len(bytes) != 5 {
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
hours, ok1 := twoDigits(bytes[1:3], 12);
|
hours, ok1 := twoDigits(bytes[1:3], 12);
|
||||||
minutes, ok2 := twoDigits(bytes[3:5], 59);
|
minutes, ok2 := twoDigits(bytes[3:5], 59);
|
||||||
if !ok1 || !ok2 {
|
if !ok1 || !ok2 {
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
sign := 1;
|
sign := 1;
|
||||||
if bytes[0] == '-' {
|
if bytes[0] == '-' {
|
||||||
sign = -1;
|
sign = -1
|
||||||
}
|
}
|
||||||
ret.ZoneOffset = sign*(60*(hours*60 + minutes));
|
ret.ZoneOffset = sign*(60*(hours*60 + minutes));
|
||||||
default:
|
default:
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -306,7 +306,7 @@ func isPrintable(b byte) bool {
|
||||||
b == ' ' ||
|
b == ' ' ||
|
||||||
b == ':' ||
|
b == ':' ||
|
||||||
b == '=' ||
|
b == '=' ||
|
||||||
b == '?';
|
b == '?'
|
||||||
}
|
}
|
||||||
|
|
||||||
// IA5String
|
// IA5String
|
||||||
|
|
@ -383,7 +383,7 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i
|
||||||
if ret.tag == 0x1f {
|
if ret.tag == 0x1f {
|
||||||
ret.tag, offset, err = parseBase128Int(bytes, offset);
|
ret.tag, offset, err = parseBase128Int(bytes, offset);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if offset >= len(bytes) {
|
if offset >= len(bytes) {
|
||||||
|
|
@ -394,7 +394,7 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i
|
||||||
offset++;
|
offset++;
|
||||||
if b&0x80 == 0 {
|
if b&0x80 == 0 {
|
||||||
// The length is encoded in the bottom 7 bits.
|
// The length is encoded in the bottom 7 bits.
|
||||||
ret.length = int(b&0x7f);
|
ret.length = int(b&0x7f)
|
||||||
} else {
|
} else {
|
||||||
// Bottom 7 bits give the number of length bytes to follow.
|
// Bottom 7 bits give the number of length bytes to follow.
|
||||||
numBytes := int(b&0x7f);
|
numBytes := int(b&0x7f);
|
||||||
|
|
@ -423,7 +423,7 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i
|
||||||
// We magically map SET and SET OF to SEQUENCE and SEQUENCE OF
|
// We magically map SET and SET OF to SEQUENCE and SEQUENCE OF
|
||||||
// because we treat everything as ordered.
|
// because we treat everything as ordered.
|
||||||
if ret.tag == tagSet {
|
if ret.tag == tagSet {
|
||||||
ret.tag = tagSequence;
|
ret.tag = tagSequence
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -464,7 +464,7 @@ func parseFieldParameters(str string) (ret fieldParameters) {
|
||||||
for _, part := range strings.Split(str, ",", 0) {
|
for _, part := range strings.Split(str, ",", 0) {
|
||||||
switch {
|
switch {
|
||||||
case part == "optional":
|
case part == "optional":
|
||||||
ret.optional = true;
|
ret.optional = true
|
||||||
case part == "explicit":
|
case part == "explicit":
|
||||||
ret.explicit = true;
|
ret.explicit = true;
|
||||||
if ret.tag == nil {
|
if ret.tag == nil {
|
||||||
|
|
@ -493,28 +493,28 @@ func parseFieldParameters(str string) (ret fieldParameters) {
|
||||||
func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) {
|
func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) {
|
||||||
switch t {
|
switch t {
|
||||||
case objectIdentifierType:
|
case objectIdentifierType:
|
||||||
return tagOID, false, true;
|
return tagOID, false, true
|
||||||
case bitStringType:
|
case bitStringType:
|
||||||
return tagBitString, false, true;
|
return tagBitString, false, true
|
||||||
case timeType:
|
case timeType:
|
||||||
return tagUTCTime, false, true;
|
return tagUTCTime, false, true
|
||||||
}
|
}
|
||||||
switch i := t.(type) {
|
switch i := t.(type) {
|
||||||
case *reflect.BoolType:
|
case *reflect.BoolType:
|
||||||
return tagBoolean, false, true;
|
return tagBoolean, false, true
|
||||||
case *reflect.IntType:
|
case *reflect.IntType:
|
||||||
return tagInteger, false, true;
|
return tagInteger, false, true
|
||||||
case *reflect.Int64Type:
|
case *reflect.Int64Type:
|
||||||
return tagInteger, false, true;
|
return tagInteger, false, true
|
||||||
case *reflect.StructType:
|
case *reflect.StructType:
|
||||||
return tagSequence, true, true;
|
return tagSequence, true, true
|
||||||
case *reflect.SliceType:
|
case *reflect.SliceType:
|
||||||
if _, ok := t.(*reflect.SliceType).Elem().(*reflect.Uint8Type); ok {
|
if _, ok := t.(*reflect.SliceType).Elem().(*reflect.Uint8Type); ok {
|
||||||
return tagOctetString, false, true;
|
return tagOctetString, false, true
|
||||||
}
|
}
|
||||||
return tagSequence, true, true;
|
return tagSequence, true, true;
|
||||||
case *reflect.StringType:
|
case *reflect.StringType:
|
||||||
return tagPrintableString, false, true;
|
return tagPrintableString, false, true
|
||||||
}
|
}
|
||||||
return 0, false, false;
|
return 0, false, false;
|
||||||
}
|
}
|
||||||
|
|
@ -536,7 +536,7 @@ func parseSequenceOf(bytes []byte, sliceType *reflect.SliceType, elemType reflec
|
||||||
var t tagAndLength;
|
var t tagAndLength;
|
||||||
t, offset, err = parseTagAndLength(bytes, offset);
|
t, offset, err = parseTagAndLength(bytes, offset);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if t.class != classUniversal || t.isCompound != compoundType || t.tag != expectedTag {
|
if t.class != classUniversal || t.isCompound != compoundType || t.tag != expectedTag {
|
||||||
err = StructuralError{"sequence tag mismatch"};
|
err = StructuralError{"sequence tag mismatch"};
|
||||||
|
|
@ -555,7 +555,7 @@ func parseSequenceOf(bytes []byte, sliceType *reflect.SliceType, elemType reflec
|
||||||
for i := 0; i < numElements; i++ {
|
for i := 0; i < numElements; i++ {
|
||||||
offset, err = parseField(ret.Elem(i), bytes, offset, params);
|
offset, err = parseField(ret.Elem(i), bytes, offset, params);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -571,7 +571,7 @@ var (
|
||||||
// invalidLength returns true iff offset + length > sliceLength, or if the
|
// invalidLength returns true iff offset + length > sliceLength, or if the
|
||||||
// addition would overflow.
|
// addition would overflow.
|
||||||
func invalidLength(offset, length, sliceLength int) bool {
|
func invalidLength(offset, length, sliceLength int) bool {
|
||||||
return offset+length < offset || offset+length > sliceLength;
|
return offset+length < offset || offset+length > sliceLength
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseField is the main parsing function. Given a byte array and an offset
|
// parseField is the main parsing function. Given a byte array and an offset
|
||||||
|
|
@ -584,7 +584,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
// If we have run out of data, it may be that there are optional elements at the end.
|
// If we have run out of data, it may be that there are optional elements at the end.
|
||||||
if offset == len(bytes) {
|
if offset == len(bytes) {
|
||||||
if !setDefaultValue(v, params) {
|
if !setDefaultValue(v, params) {
|
||||||
err = SyntaxError{"sequence truncated"};
|
err = SyntaxError{"sequence truncated"}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -594,7 +594,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
var t tagAndLength;
|
var t tagAndLength;
|
||||||
t, offset, err = parseTagAndLength(bytes, offset);
|
t, offset, err = parseTagAndLength(bytes, offset);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if invalidLength(offset, t.length, len(bytes)) {
|
if invalidLength(offset, t.length, len(bytes)) {
|
||||||
err = SyntaxError{"data truncated"};
|
err = SyntaxError{"data truncated"};
|
||||||
|
|
@ -612,7 +612,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
var t tagAndLength;
|
var t tagAndLength;
|
||||||
t, offset, err = parseTagAndLength(bytes, offset);
|
t, offset, err = parseTagAndLength(bytes, offset);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if invalidLength(offset, t.length, len(bytes)) {
|
if invalidLength(offset, t.length, len(bytes)) {
|
||||||
err = SyntaxError{"data truncated"};
|
err = SyntaxError{"data truncated"};
|
||||||
|
|
@ -623,29 +623,29 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
innerBytes := bytes[offset : offset + t.length];
|
innerBytes := bytes[offset : offset + t.length];
|
||||||
switch t.tag {
|
switch t.tag {
|
||||||
case tagPrintableString:
|
case tagPrintableString:
|
||||||
result, err = parsePrintableString(innerBytes);
|
result, err = parsePrintableString(innerBytes)
|
||||||
case tagIA5String:
|
case tagIA5String:
|
||||||
result, err = parseIA5String(innerBytes);
|
result, err = parseIA5String(innerBytes)
|
||||||
case tagInteger:
|
case tagInteger:
|
||||||
result, err = parseInt64(innerBytes);
|
result, err = parseInt64(innerBytes)
|
||||||
case tagBitString:
|
case tagBitString:
|
||||||
result, err = parseBitString(innerBytes);
|
result, err = parseBitString(innerBytes)
|
||||||
case tagOID:
|
case tagOID:
|
||||||
result, err = parseObjectIdentifier(innerBytes);
|
result, err = parseObjectIdentifier(innerBytes)
|
||||||
case tagUTCTime:
|
case tagUTCTime:
|
||||||
result, err = parseUTCTime(innerBytes);
|
result, err = parseUTCTime(innerBytes)
|
||||||
case tagOctetString:
|
case tagOctetString:
|
||||||
result = innerBytes;
|
result = innerBytes
|
||||||
default:
|
default:
|
||||||
// If we don't know how to handle the type, we just leave Value as nil.
|
// If we don't know how to handle the type, we just leave Value as nil.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
offset += t.length;
|
offset += t.length;
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if result != nil {
|
if result != nil {
|
||||||
ifaceValue.Set(reflect.NewValue(result));
|
ifaceValue.Set(reflect.NewValue(result))
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -657,21 +657,21 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
|
|
||||||
t, offset, err := parseTagAndLength(bytes, offset);
|
t, offset, err := parseTagAndLength(bytes, offset);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if params.explicit {
|
if params.explicit {
|
||||||
if t.class == classContextSpecific && t.tag == *params.tag && t.isCompound {
|
if t.class == classContextSpecific && t.tag == *params.tag && t.isCompound {
|
||||||
t, offset, err = parseTagAndLength(bytes, offset);
|
t, offset, err = parseTagAndLength(bytes, offset);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The tags didn't match, it might be an optional element.
|
// The tags didn't match, it might be an optional element.
|
||||||
ok := setDefaultValue(v, params);
|
ok := setDefaultValue(v, params);
|
||||||
if ok {
|
if ok {
|
||||||
offset = initOffset;
|
offset = initOffset
|
||||||
} else {
|
} else {
|
||||||
err = StructuralError{"explicitly tagged member didn't match"};
|
err = StructuralError{"explicitly tagged member didn't match"}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -682,7 +682,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
// PrintableString when it sees a string so, if we see an IA5String on
|
// PrintableString when it sees a string so, if we see an IA5String on
|
||||||
// the wire, we change the universal type to match.
|
// the wire, we change the universal type to match.
|
||||||
if universalTag == tagPrintableString && t.tag == tagIA5String {
|
if universalTag == tagPrintableString && t.tag == tagIA5String {
|
||||||
universalTag = tagIA5String;
|
universalTag = tagIA5String
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedClass := classUniversal;
|
expectedClass := classUniversal;
|
||||||
|
|
@ -698,9 +698,9 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
// Tags don't match. Again, it could be an optional element.
|
// Tags don't match. Again, it could be an optional element.
|
||||||
ok := setDefaultValue(v, params);
|
ok := setDefaultValue(v, params);
|
||||||
if ok {
|
if ok {
|
||||||
offset = initOffset;
|
offset = initOffset
|
||||||
} else {
|
} else {
|
||||||
err = StructuralError{fmt.Sprintf("tags don't match (%d vs %+v) %+v %s %#v", expectedTag, t, params, fieldType.Name(), bytes[offset:len(bytes)])};
|
err = StructuralError{fmt.Sprintf("tags don't match (%d vs %+v) %+v %s %#v", expectedTag, t, params, fieldType.Name(), bytes[offset:len(bytes)])}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -717,7 +717,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
sliceValue := v.(*reflect.SliceValue);
|
sliceValue := v.(*reflect.SliceValue);
|
||||||
sliceValue.Set(reflect.MakeSlice(sliceValue.Type().(*reflect.SliceType), len(newSlice), len(newSlice)));
|
sliceValue.Set(reflect.MakeSlice(sliceValue.Type().(*reflect.SliceType), len(newSlice), len(newSlice)));
|
||||||
if err1 == nil {
|
if err1 == nil {
|
||||||
reflect.ArrayCopy(sliceValue, reflect.NewValue(newSlice).(reflect.ArrayOrSliceValue));
|
reflect.ArrayCopy(sliceValue, reflect.NewValue(newSlice).(reflect.ArrayOrSliceValue))
|
||||||
}
|
}
|
||||||
offset += t.length;
|
offset += t.length;
|
||||||
err = err1;
|
err = err1;
|
||||||
|
|
@ -727,7 +727,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
bs, err1 := parseBitString(innerBytes);
|
bs, err1 := parseBitString(innerBytes);
|
||||||
offset += t.length;
|
offset += t.length;
|
||||||
if err1 == nil {
|
if err1 == nil {
|
||||||
structValue.Set(reflect.NewValue(bs).(*reflect.StructValue));
|
structValue.Set(reflect.NewValue(bs).(*reflect.StructValue))
|
||||||
}
|
}
|
||||||
err = err1;
|
err = err1;
|
||||||
return;
|
return;
|
||||||
|
|
@ -736,7 +736,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
time, err1 := parseUTCTime(innerBytes);
|
time, err1 := parseUTCTime(innerBytes);
|
||||||
offset += t.length;
|
offset += t.length;
|
||||||
if err1 == nil {
|
if err1 == nil {
|
||||||
structValue.Set(reflect.NewValue(time).(*reflect.StructValue));
|
structValue.Set(reflect.NewValue(time).(*reflect.StructValue))
|
||||||
}
|
}
|
||||||
err = err1;
|
err = err1;
|
||||||
return;
|
return;
|
||||||
|
|
@ -746,7 +746,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
parsedBool, err1 := parseBool(innerBytes);
|
parsedBool, err1 := parseBool(innerBytes);
|
||||||
offset += t.length;
|
offset += t.length;
|
||||||
if err1 == nil {
|
if err1 == nil {
|
||||||
val.Set(parsedBool);
|
val.Set(parsedBool)
|
||||||
}
|
}
|
||||||
err = err1;
|
err = err1;
|
||||||
return;
|
return;
|
||||||
|
|
@ -754,7 +754,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
parsedInt, err1 := parseInt(innerBytes);
|
parsedInt, err1 := parseInt(innerBytes);
|
||||||
offset += t.length;
|
offset += t.length;
|
||||||
if err1 == nil {
|
if err1 == nil {
|
||||||
val.Set(parsedInt);
|
val.Set(parsedInt)
|
||||||
}
|
}
|
||||||
err = err1;
|
err = err1;
|
||||||
return;
|
return;
|
||||||
|
|
@ -762,7 +762,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
parsedInt, err1 := parseInt64(innerBytes);
|
parsedInt, err1 := parseInt64(innerBytes);
|
||||||
offset += t.length;
|
offset += t.length;
|
||||||
if err1 == nil {
|
if err1 == nil {
|
||||||
val.Set(parsedInt);
|
val.Set(parsedInt)
|
||||||
}
|
}
|
||||||
err = err1;
|
err = err1;
|
||||||
return;
|
return;
|
||||||
|
|
@ -773,7 +773,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
field := structType.Field(i);
|
field := structType.Field(i);
|
||||||
innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag));
|
innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag));
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
offset += t.length;
|
offset += t.length;
|
||||||
|
|
@ -791,7 +791,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem());
|
newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem());
|
||||||
offset += t.length;
|
offset += t.length;
|
||||||
if err1 == nil {
|
if err1 == nil {
|
||||||
val.Set(newSlice);
|
val.Set(newSlice)
|
||||||
}
|
}
|
||||||
err = err1;
|
err = err1;
|
||||||
return;
|
return;
|
||||||
|
|
@ -799,14 +799,14 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
var v string;
|
var v string;
|
||||||
switch universalTag {
|
switch universalTag {
|
||||||
case tagPrintableString:
|
case tagPrintableString:
|
||||||
v, err = parsePrintableString(innerBytes);
|
v, err = parsePrintableString(innerBytes)
|
||||||
case tagIA5String:
|
case tagIA5String:
|
||||||
v, err = parseIA5String(innerBytes);
|
v, err = parseIA5String(innerBytes)
|
||||||
default:
|
default:
|
||||||
err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)};
|
err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)}
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
val.Set(v);
|
val.Set(v)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -819,17 +819,17 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||||
// wasn't provided or it failed to install it into the Value.
|
// wasn't provided or it failed to install it into the Value.
|
||||||
func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
|
func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
|
||||||
if !params.optional {
|
if !params.optional {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
ok = true;
|
ok = true;
|
||||||
if params.defaultValue == nil {
|
if params.defaultValue == nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
switch val := v.(type) {
|
switch val := v.(type) {
|
||||||
case *reflect.IntValue:
|
case *reflect.IntValue:
|
||||||
val.Set(int(*params.defaultValue));
|
val.Set(int(*params.defaultValue))
|
||||||
case *reflect.Int64Value:
|
case *reflect.Int64Value:
|
||||||
val.Set(int64(*params.defaultValue));
|
val.Set(int64(*params.defaultValue))
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,10 +35,10 @@ func TestParseInt64(t *testing.T) {
|
||||||
for i, test := range int64TestData {
|
for i, test := range int64TestData {
|
||||||
ret, err := parseInt64(test.in);
|
ret, err := parseInt64(test.in);
|
||||||
if (err == nil) != test.ok {
|
if (err == nil) != test.ok {
|
||||||
t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok);
|
t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
|
||||||
}
|
}
|
||||||
if test.ok && ret != test.out {
|
if test.ok && ret != test.out {
|
||||||
t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out);
|
t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -63,11 +63,11 @@ func TestBitString(t *testing.T) {
|
||||||
for i, test := range bitStringTestData {
|
for i, test := range bitStringTestData {
|
||||||
ret, err := parseBitString(test.in);
|
ret, err := parseBitString(test.in);
|
||||||
if (err == nil) != test.ok {
|
if (err == nil) != test.ok {
|
||||||
t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok);
|
t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if test.bitLength != ret.BitLength || bytes.Compare(ret.Bytes, test.out) != 0 {
|
if test.bitLength != ret.BitLength || bytes.Compare(ret.Bytes, test.out) != 0 {
|
||||||
t.Errorf("#%d: Bad result: %v (expected %v %v)", i, ret, test.out, test.bitLength);
|
t.Errorf("#%d: Bad result: %v (expected %v %v)", i, ret, test.out, test.bitLength)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -76,16 +76,16 @@ func TestBitString(t *testing.T) {
|
||||||
func TestBitStringAt(t *testing.T) {
|
func TestBitStringAt(t *testing.T) {
|
||||||
bs := BitString{[]byte{0x82, 0x40}, 16};
|
bs := BitString{[]byte{0x82, 0x40}, 16};
|
||||||
if bs.At(0) != 1 {
|
if bs.At(0) != 1 {
|
||||||
t.Error("#1: Failed");
|
t.Error("#1: Failed")
|
||||||
}
|
}
|
||||||
if bs.At(1) != 0 {
|
if bs.At(1) != 0 {
|
||||||
t.Error("#2: Failed");
|
t.Error("#2: Failed")
|
||||||
}
|
}
|
||||||
if bs.At(6) != 1 {
|
if bs.At(6) != 1 {
|
||||||
t.Error("#3: Failed");
|
t.Error("#3: Failed")
|
||||||
}
|
}
|
||||||
if bs.At(9) != 1 {
|
if bs.At(9) != 1 {
|
||||||
t.Error("#4: Failed");
|
t.Error("#4: Failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,11 +107,11 @@ func TestObjectIdentifier(t *testing.T) {
|
||||||
for i, test := range objectIdentifierTestData {
|
for i, test := range objectIdentifierTestData {
|
||||||
ret, err := parseObjectIdentifier(test.in);
|
ret, err := parseObjectIdentifier(test.in);
|
||||||
if (err == nil) != test.ok {
|
if (err == nil) != test.ok {
|
||||||
t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok);
|
t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if !reflect.DeepEqual(test.out, ret) {
|
if !reflect.DeepEqual(test.out, ret) {
|
||||||
t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out);
|
t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -142,11 +142,11 @@ func TestTime(t *testing.T) {
|
||||||
for i, test := range timeTestData {
|
for i, test := range timeTestData {
|
||||||
ret, err := parseUTCTime(strings.Bytes(test.in));
|
ret, err := parseUTCTime(strings.Bytes(test.in));
|
||||||
if (err == nil) != test.ok {
|
if (err == nil) != test.ok {
|
||||||
t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok);
|
t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if !reflect.DeepEqual(test.out, ret) {
|
if !reflect.DeepEqual(test.out, ret) {
|
||||||
t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out);
|
t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -177,10 +177,10 @@ func TestParseTagAndLength(t *testing.T) {
|
||||||
for i, test := range tagAndLengthData {
|
for i, test := range tagAndLengthData {
|
||||||
tagAndLength, _, err := parseTagAndLength(test.in, 0);
|
tagAndLength, _, err := parseTagAndLength(test.in, 0);
|
||||||
if (err == nil) != test.ok {
|
if (err == nil) != test.ok {
|
||||||
t.Errorf("#%d: Incorrect error result (did pass? %v, expected: %v)", i, err == nil, test.ok);
|
t.Errorf("#%d: Incorrect error result (did pass? %v, expected: %v)", i, err == nil, test.ok)
|
||||||
}
|
}
|
||||||
if err == nil && !reflect.DeepEqual(test.out, tagAndLength) {
|
if err == nil && !reflect.DeepEqual(test.out, tagAndLength) {
|
||||||
t.Errorf("#%d: Bad result: %v (expected %v)", i, tagAndLength, test.out);
|
t.Errorf("#%d: Bad result: %v (expected %v)", i, tagAndLength, test.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -213,7 +213,7 @@ func TestParseFieldParameters(t *testing.T) {
|
||||||
for i, test := range parseFieldParametersTestData {
|
for i, test := range parseFieldParametersTestData {
|
||||||
f := parseFieldParameters(test.in);
|
f := parseFieldParameters(test.in);
|
||||||
if !reflect.DeepEqual(f, test.out) {
|
if !reflect.DeepEqual(f, test.out) {
|
||||||
t.Errorf("#%d: Bad result: %v (expected %v)", i, f, test.out);
|
t.Errorf("#%d: Bad result: %v (expected %v)", i, f, test.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -260,10 +260,10 @@ func TestUnmarshal(t *testing.T) {
|
||||||
val := pv.Interface();
|
val := pv.Interface();
|
||||||
err := Unmarshal(val, test.in);
|
err := Unmarshal(val, test.in);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unmarshal failed at index %d %v", i, err);
|
t.Errorf("Unmarshal failed at index %d %v", i, err)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(val, test.out) {
|
if !reflect.DeepEqual(val, test.out) {
|
||||||
t.Errorf("#%d:\nhave %#v\nwant %#v", i, val, test.out);
|
t.Errorf("#%d:\nhave %#v\nwant %#v", i, val, test.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -310,10 +310,10 @@ func TestCertificate(t *testing.T) {
|
||||||
// This is a minimal, self-signed certificate that should parse correctly.
|
// This is a minimal, self-signed certificate that should parse correctly.
|
||||||
var cert Certificate;
|
var cert Certificate;
|
||||||
if err := Unmarshal(&cert, derEncodedSelfSignedCertBytes); err != nil {
|
if err := Unmarshal(&cert, derEncodedSelfSignedCertBytes); err != nil {
|
||||||
t.Errorf("Unmarshal failed: %v", err);
|
t.Errorf("Unmarshal failed: %v", err)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(cert, derEncodedSelfSignedCert) {
|
if !reflect.DeepEqual(cert, derEncodedSelfSignedCert) {
|
||||||
t.Errorf("Bad result:\ngot: %+v\nwant: %+v\n", cert, derEncodedSelfSignedCert);
|
t.Errorf("Bad result:\ngot: %+v\nwant: %+v\n", cert, derEncodedSelfSignedCert)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -323,7 +323,7 @@ func TestCertificateWithNUL(t *testing.T) {
|
||||||
|
|
||||||
var cert Certificate;
|
var cert Certificate;
|
||||||
if err := Unmarshal(&cert, derEncodedPaypalNULCertBytes); err == nil {
|
if err := Unmarshal(&cert, derEncodedPaypalNULCertBytes); err == nil {
|
||||||
t.Error("Unmarshal succeeded, should not have");
|
t.Error("Unmarshal succeeded, should not have")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ func addWW_g(x, y, c Word) (z1, z0 Word) {
|
||||||
yc := y+c;
|
yc := y+c;
|
||||||
z0 = x+yc;
|
z0 = x+yc;
|
||||||
if z0 < x || yc < y {
|
if z0 < x || yc < y {
|
||||||
z1 = 1;
|
z1 = 1
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -44,7 +44,7 @@ func subWW_g(x, y, c Word) (z1, z0 Word) {
|
||||||
yc := y+c;
|
yc := y+c;
|
||||||
z0 = x-yc;
|
z0 = x-yc;
|
||||||
if z0 > x || yc < y {
|
if z0 > x || yc < y {
|
||||||
z1 = 1;
|
z1 = 1
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -57,7 +57,7 @@ func mulWW_g(x, y Word) (z1, z0 Word) {
|
||||||
// and return the product as 2 Words.
|
// and return the product as 2 Words.
|
||||||
|
|
||||||
if x < y {
|
if x < y {
|
||||||
x, y = y, x;
|
x, y = y, x
|
||||||
}
|
}
|
||||||
|
|
||||||
if x < _B2 {
|
if x < _B2 {
|
||||||
|
|
@ -100,7 +100,7 @@ func mulWW_g(x, y Word) (z1, z0 Word) {
|
||||||
t1a := t1;
|
t1a := t1;
|
||||||
t1 += x0*y1;
|
t1 += x0*y1;
|
||||||
if t1 < t1a {
|
if t1 < t1a {
|
||||||
c++;
|
c++
|
||||||
}
|
}
|
||||||
t2 := x1*y1 + c*_B2;
|
t2 := x1*y1 + c*_B2;
|
||||||
|
|
||||||
|
|
@ -114,7 +114,7 @@ func mulWW_g(x, y Word) (z1, z0 Word) {
|
||||||
var c3 Word;
|
var c3 Word;
|
||||||
z1 = t1 + t0>>_W2;
|
z1 = t1 + t0>>_W2;
|
||||||
if z1 < t1 {
|
if z1 < t1 {
|
||||||
c3++;
|
c3++
|
||||||
}
|
}
|
||||||
z1 >>= _W2;
|
z1 >>= _W2;
|
||||||
z1 += c3*_B2;
|
z1 += c3*_B2;
|
||||||
|
|
@ -149,7 +149,7 @@ func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
|
||||||
t1a := t1;
|
t1a := t1;
|
||||||
t1 += x0*y1;
|
t1 += x0*y1;
|
||||||
if t1 < t1a { // If the number got smaller then we overflowed.
|
if t1 < t1a { // If the number got smaller then we overflowed.
|
||||||
c2++;
|
c2++
|
||||||
}
|
}
|
||||||
|
|
||||||
t2 := x1*y1 + c2*_B2;
|
t2 := x1*y1 + c2*_B2;
|
||||||
|
|
@ -164,7 +164,7 @@ func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
|
||||||
var c3 Word;
|
var c3 Word;
|
||||||
z1 = t1 + t0>>_W2;
|
z1 = t1 + t0>>_W2;
|
||||||
if z1 < t1 {
|
if z1 < t1 {
|
||||||
c3++;
|
c3++
|
||||||
}
|
}
|
||||||
z1 >>= _W2;
|
z1 >>= _W2;
|
||||||
z1 += t2 + c3*_B2;
|
z1 += t2 + c3*_B2;
|
||||||
|
|
@ -213,7 +213,7 @@ func divStep(x1, x0, y Word) (q, r Word) {
|
||||||
// Number of leading zeros in x.
|
// Number of leading zeros in x.
|
||||||
func leadingZeros(x Word) (n uint) {
|
func leadingZeros(x Word) (n uint) {
|
||||||
if x == 0 {
|
if x == 0 {
|
||||||
return uint(_W);
|
return uint(_W)
|
||||||
}
|
}
|
||||||
for x&(1<<(_W-1)) == 0 {
|
for x&(1<<(_W-1)) == 0 {
|
||||||
n++;
|
n++;
|
||||||
|
|
@ -259,7 +259,7 @@ func divWW_g(x1, x0, y Word) (q, r Word) {
|
||||||
r = x0>>z;
|
r = x0>>z;
|
||||||
|
|
||||||
if q1 != 0 {
|
if q1 != 0 {
|
||||||
panic("div out of range");
|
panic("div out of range")
|
||||||
}
|
}
|
||||||
|
|
||||||
return q0, r;
|
return q0, r;
|
||||||
|
|
@ -315,14 +315,14 @@ func init() {
|
||||||
|
|
||||||
|
|
||||||
func (p *Word) at(i int) *Word {
|
func (p *Word) at(i int) *Word {
|
||||||
return (*Word)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + uintptr(i)*_S));
|
return (*Word)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + uintptr(i)*_S))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func addVV_s(z, x, y *Word, n int) (c Word)
|
func addVV_s(z, x, y *Word, n int) (c Word)
|
||||||
func addVV_g(z, x, y *Word, n int) (c Word) {
|
func addVV_g(z, x, y *Word, n int) (c Word) {
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
c, *z.at(i) = addWW_g(*x.at(i), *y.at(i), c);
|
c, *z.at(i) = addWW_g(*x.at(i), *y.at(i), c)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -331,7 +331,7 @@ func addVV_g(z, x, y *Word, n int) (c Word) {
|
||||||
func subVV_s(z, x, y *Word, n int) (c Word)
|
func subVV_s(z, x, y *Word, n int) (c Word)
|
||||||
func subVV_g(z, x, y *Word, n int) (c Word) {
|
func subVV_g(z, x, y *Word, n int) (c Word) {
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
c, *z.at(i) = subWW_g(*x.at(i), *y.at(i), c);
|
c, *z.at(i) = subWW_g(*x.at(i), *y.at(i), c)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -341,7 +341,7 @@ func addVW_s(z, x *Word, y Word, n int) (c Word)
|
||||||
func addVW_g(z, x *Word, y Word, n int) (c Word) {
|
func addVW_g(z, x *Word, y Word, n int) (c Word) {
|
||||||
c = y;
|
c = y;
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
c, *z.at(i) = addWW_g(*x.at(i), c, 0);
|
c, *z.at(i) = addWW_g(*x.at(i), c, 0)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -351,7 +351,7 @@ func subVW_s(z, x *Word, y Word, n int) (c Word)
|
||||||
func subVW_g(z, x *Word, y Word, n int) (c Word) {
|
func subVW_g(z, x *Word, y Word, n int) (c Word) {
|
||||||
c = y;
|
c = y;
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
c, *z.at(i) = subWW_g(*x.at(i), c, 0);
|
c, *z.at(i) = subWW_g(*x.at(i), c, 0)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -361,7 +361,7 @@ func mulAddVWW_s(z, x *Word, y, r Word, n int) (c Word)
|
||||||
func mulAddVWW_g(z, x *Word, y, r Word, n int) (c Word) {
|
func mulAddVWW_g(z, x *Word, y, r Word, n int) (c Word) {
|
||||||
c = r;
|
c = r;
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
c, *z.at(i) = mulAddWWW_g(*x.at(i), y, c);
|
c, *z.at(i) = mulAddWWW_g(*x.at(i), y, c)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -382,7 +382,7 @@ func divWVW_s(z *Word, xn Word, x *Word, y Word, n int) (r Word)
|
||||||
func divWVW_g(z *Word, xn Word, x *Word, y Word, n int) (r Word) {
|
func divWVW_g(z *Word, xn Word, x *Word, y Word, n int) (r Word) {
|
||||||
r = xn;
|
r = xn;
|
||||||
for i := n-1; i >= 0; i-- {
|
for i := n-1; i >= 0; i-- {
|
||||||
*z.at(i), r = divWW_g(r, *x.at(i), y);
|
*z.at(i), r = divWW_g(r, *x.at(i), y)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ var sumWW = []argWW{
|
||||||
func testFunWW(t *testing.T, msg string, f funWW, a argWW) {
|
func testFunWW(t *testing.T, msg string, f funWW, a argWW) {
|
||||||
z1, z0 := f(a.x, a.y, a.c);
|
z1, z0 := f(a.x, a.y, a.c);
|
||||||
if z1 != a.z1 || z0 != a.z0 {
|
if z1 != a.z1 || z0 != a.z0 {
|
||||||
t.Errorf("%s%+v\n\tgot z1:z0 = %#x:%#x; want %#x:%#x", msg, a, z1, z0, a.z1, a.z0);
|
t.Errorf("%s%+v\n\tgot z1:z0 = %#x:%#x; want %#x:%#x", msg, a, z1, z0, a.z1, a.z0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ func TestFunWW(t *testing.T) {
|
||||||
|
|
||||||
func addr(x []Word) *Word {
|
func addr(x []Word) *Word {
|
||||||
if len(x) == 0 {
|
if len(x) == 0 {
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
return &x[0];
|
return &x[0];
|
||||||
}
|
}
|
||||||
|
|
@ -90,7 +90,7 @@ func testFunVV(t *testing.T, msg string, f funVV, a argVV) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if c != a.c {
|
if c != a.c {
|
||||||
t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c);
|
t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,7 +159,7 @@ func testFunVW(t *testing.T, msg string, f funVW, a argVW) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if c != a.c {
|
if c != a.c {
|
||||||
t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c);
|
t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -222,7 +222,7 @@ func testFunVWW(t *testing.T, msg string, f funVWW, a argVWW) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if c != a.c {
|
if c != a.c {
|
||||||
t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c);
|
t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,7 +250,7 @@ func testFunWVW(t *testing.T, msg string, f funWVW, a argWVW) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if r != a.r {
|
if r != a.r {
|
||||||
t.Errorf("%s%+v\n\tgot r = %#x; want %#x", msg, a, r, a.r);
|
t.Errorf("%s%+v\n\tgot r = %#x; want %#x", msg, a, r, a.r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -286,7 +286,7 @@ func TestMulWW(t *testing.T) {
|
||||||
for i, test := range mulWWTests {
|
for i, test := range mulWWTests {
|
||||||
q, r := mulWW_g(test.x, test.y);
|
q, r := mulWW_g(test.x, test.y);
|
||||||
if q != test.q || r != test.r {
|
if q != test.q || r != test.r {
|
||||||
t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r);
|
t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -311,7 +311,7 @@ func TestMulAddWWW(t *testing.T) {
|
||||||
for i, test := range mulAddWWWTests {
|
for i, test := range mulAddWWWTests {
|
||||||
q, r := mulAddWWW_g(test.x, test.y, test.c);
|
q, r := mulAddWWW_g(test.x, test.y, test.c);
|
||||||
if q != test.q || r != test.r {
|
if q != test.q || r != test.r {
|
||||||
t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r);
|
t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ func (z *Int) Add(x, y *Int) *Int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(z.abs) == 0 {
|
if len(z.abs) == 0 {
|
||||||
z.neg = false; // 0 has no sign
|
z.neg = false // 0 has no sign
|
||||||
}
|
}
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +82,7 @@ func (z *Int) Sub(x, y *Int) *Int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(z.abs) == 0 {
|
if len(z.abs) == 0 {
|
||||||
z.neg = false; // 0 has no sign
|
z.neg = false // 0 has no sign
|
||||||
}
|
}
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
@ -120,7 +120,7 @@ func (z *Int) Mod(x, y *Int) (r *Int) {
|
||||||
|
|
||||||
func div(q, r, x, y *Int) {
|
func div(q, r, x, y *Int) {
|
||||||
if len(y.abs) == 0 {
|
if len(y.abs) == 0 {
|
||||||
panic("Divide by zero undefined");
|
panic("Divide by zero undefined")
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmpNN(x.abs, y.abs) < 0 {
|
if cmpNN(x.abs, y.abs) < 0 {
|
||||||
|
|
@ -131,12 +131,12 @@ func div(q, r, x, y *Int) {
|
||||||
src := x.abs;
|
src := x.abs;
|
||||||
dst := x.abs;
|
dst := x.abs;
|
||||||
if r == x {
|
if r == x {
|
||||||
dst = nil;
|
dst = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
r.abs = makeN(dst, len(src), false);
|
r.abs = makeN(dst, len(src), false);
|
||||||
for i, v := range src {
|
for i, v := range src {
|
||||||
r.abs[i] = v;
|
r.abs[i] = v
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -185,12 +185,12 @@ func CmpInt(x, y *Int) (r int) {
|
||||||
case x.neg == y.neg:
|
case x.neg == y.neg:
|
||||||
r = cmpNN(x.abs, y.abs);
|
r = cmpNN(x.abs, y.abs);
|
||||||
if x.neg {
|
if x.neg {
|
||||||
r = -r;
|
r = -r
|
||||||
}
|
}
|
||||||
case x.neg:
|
case x.neg:
|
||||||
r = -1;
|
r = -1
|
||||||
default:
|
default:
|
||||||
r = 1;
|
r = 1
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -199,7 +199,7 @@ func CmpInt(x, y *Int) (r int) {
|
||||||
func (z *Int) String() string {
|
func (z *Int) String() string {
|
||||||
s := "";
|
s := "";
|
||||||
if z.neg {
|
if z.neg {
|
||||||
s = "-";
|
s = "-"
|
||||||
}
|
}
|
||||||
return s + stringN(z.abs, 10);
|
return s + stringN(z.abs, 10);
|
||||||
}
|
}
|
||||||
|
|
@ -212,23 +212,23 @@ func (z *Int) SetString(s string, base int) (*Int, bool) {
|
||||||
var scanned int;
|
var scanned int;
|
||||||
|
|
||||||
if base == 1 || base > 16 {
|
if base == 1 || base > 16 {
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
|
|
||||||
if s[0] == '-' {
|
if s[0] == '-' {
|
||||||
z.neg = true;
|
z.neg = true;
|
||||||
s = s[1:len(s)];
|
s = s[1:len(s)];
|
||||||
} else {
|
} else {
|
||||||
z.neg = false;
|
z.neg = false
|
||||||
}
|
}
|
||||||
|
|
||||||
z.abs, _, scanned = scanN(z.abs, s, base);
|
z.abs, _, scanned = scanN(z.abs, s, base);
|
||||||
if scanned != len(s) {
|
if scanned != len(s) {
|
||||||
goto Error;
|
goto Error
|
||||||
}
|
}
|
||||||
|
|
||||||
return z, true;
|
return z, true;
|
||||||
|
|
@ -293,7 +293,7 @@ func (z *Int) Bytes() []byte {
|
||||||
|
|
||||||
i := 0;
|
i := 0;
|
||||||
for i < len(b) && b[i] == 0 {
|
for i < len(b) && b[i] == 0 {
|
||||||
i++;
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
return b[i:len(b)];
|
return b[i:len(b)];
|
||||||
|
|
@ -304,7 +304,7 @@ func (z *Int) Bytes() []byte {
|
||||||
// considered to have a length of one.
|
// considered to have a length of one.
|
||||||
func (z *Int) Len() int {
|
func (z *Int) Len() int {
|
||||||
if len(z.abs) == 0 {
|
if len(z.abs) == 0 {
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return len(z.abs)*int(_W) - int(leadingZeros(z.abs[len(z.abs)-1]));
|
return len(z.abs)*int(_W) - int(leadingZeros(z.abs[len(z.abs)-1]));
|
||||||
|
|
@ -338,11 +338,11 @@ func (z *Int) Exp(x, y, m *Int) *Int {
|
||||||
z.Mul(z, z);
|
z.Mul(z, z);
|
||||||
|
|
||||||
if v&mask != 0 {
|
if v&mask != 0 {
|
||||||
z.Mul(z, x);
|
z.Mul(z, x)
|
||||||
}
|
}
|
||||||
|
|
||||||
if m != nil {
|
if m != nil {
|
||||||
z.Mod(z, m);
|
z.Mod(z, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
v <<= 1;
|
v <<= 1;
|
||||||
|
|
@ -355,11 +355,11 @@ func (z *Int) Exp(x, y, m *Int) *Int {
|
||||||
z.Mul(z, z);
|
z.Mul(z, z);
|
||||||
|
|
||||||
if v&mask != 0 {
|
if v&mask != 0 {
|
||||||
z.Mul(z, x);
|
z.Mul(z, x)
|
||||||
}
|
}
|
||||||
|
|
||||||
if m != nil {
|
if m != nil {
|
||||||
z.Mod(z, m);
|
z.Mod(z, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
v <<= 1;
|
v <<= 1;
|
||||||
|
|
@ -379,10 +379,10 @@ func GcdInt(d, x, y, a, b *Int) {
|
||||||
if a.neg || b.neg {
|
if a.neg || b.neg {
|
||||||
d.New(0);
|
d.New(0);
|
||||||
if x != nil {
|
if x != nil {
|
||||||
x.New(0);
|
x.New(0)
|
||||||
}
|
}
|
||||||
if y != nil {
|
if y != nil {
|
||||||
y.New(0);
|
y.New(0)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -418,11 +418,11 @@ func GcdInt(d, x, y, a, b *Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if x != nil {
|
if x != nil {
|
||||||
*x = *lastX;
|
*x = *lastX
|
||||||
}
|
}
|
||||||
|
|
||||||
if y != nil {
|
if y != nil {
|
||||||
*y = *lastY;
|
*y = *lastY
|
||||||
}
|
}
|
||||||
|
|
||||||
*d = *A;
|
*d = *A;
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ func TestSetZ(t *testing.T) {
|
||||||
var z Int;
|
var z Int;
|
||||||
z.Set(a.z);
|
z.Set(a.z);
|
||||||
if CmpInt(&z, a.z) != 0 {
|
if CmpInt(&z, a.z) != 0 {
|
||||||
t.Errorf("got z = %v; want %v", z, a.z);
|
t.Errorf("got z = %v; want %v", z, a.z)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -57,7 +57,7 @@ func testFunZZ(t *testing.T, msg string, f funZZ, a argZZ) {
|
||||||
var z Int;
|
var z Int;
|
||||||
f(&z, a.x, a.y);
|
f(&z, a.x, a.y);
|
||||||
if CmpInt(&z, a.z) != 0 {
|
if CmpInt(&z, a.z) != 0 {
|
||||||
t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, &z, a.z);
|
t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, &z, a.z)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,7 +121,7 @@ func TestFact(t *testing.T) {
|
||||||
for n, s := range facts {
|
for n, s := range facts {
|
||||||
f := fact(n).String();
|
f := fact(n).String();
|
||||||
if f != s {
|
if f != s {
|
||||||
t.Errorf("%d! = %s; want %s", n, f, s);
|
t.Errorf("%d! = %s; want %s", n, f, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -162,11 +162,11 @@ func TestSetString(t *testing.T) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if CmpInt(n, new(Int).New(test.out)) != 0 {
|
if CmpInt(n, new(Int).New(test.out)) != 0 {
|
||||||
t.Errorf("#%d (input '%s') got: %s want: %d\n", i, test.in, n, test.out);
|
t.Errorf("#%d (input '%s') got: %s want: %d\n", i, test.in, n, test.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -197,7 +197,7 @@ func TestDivSigns(t *testing.T) {
|
||||||
expectedR := new(Int).New(test.r);
|
expectedR := new(Int).New(test.r);
|
||||||
|
|
||||||
if CmpInt(q, expectedQ) != 0 || CmpInt(r, expectedR) != 0 {
|
if CmpInt(q, expectedQ) != 0 || CmpInt(r, expectedR) != 0 {
|
||||||
t.Errorf("#%d: got (%s, %s) want (%s, %s)", i, q, r, expectedQ, expectedR);
|
t.Errorf("#%d: got (%s, %s) want (%s, %s)", i, q, r, expectedQ, expectedR)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -208,11 +208,11 @@ func checkSetBytes(b []byte) bool {
|
||||||
hex2 := hex.EncodeToString(b);
|
hex2 := hex.EncodeToString(b);
|
||||||
|
|
||||||
for len(hex1) < len(hex2) {
|
for len(hex1) < len(hex2) {
|
||||||
hex1 = "0"+hex1;
|
hex1 = "0"+hex1
|
||||||
}
|
}
|
||||||
|
|
||||||
for len(hex1) > len(hex2) {
|
for len(hex1) > len(hex2) {
|
||||||
hex2 = "0"+hex2;
|
hex2 = "0"+hex2
|
||||||
}
|
}
|
||||||
|
|
||||||
return hex1 == hex2;
|
return hex1 == hex2;
|
||||||
|
|
@ -222,7 +222,7 @@ func checkSetBytes(b []byte) bool {
|
||||||
func TestSetBytes(t *testing.T) {
|
func TestSetBytes(t *testing.T) {
|
||||||
err := quick.Check(checkSetBytes, nil);
|
err := quick.Check(checkSetBytes, nil);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err);
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,7 +236,7 @@ func checkBytes(b []byte) bool {
|
||||||
func TestBytes(t *testing.T) {
|
func TestBytes(t *testing.T) {
|
||||||
err := quick.Check(checkSetBytes, nil);
|
err := quick.Check(checkSetBytes, nil);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err);
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -246,13 +246,13 @@ func checkDiv(x, y []byte) bool {
|
||||||
v := new(Int).SetBytes(y);
|
v := new(Int).SetBytes(y);
|
||||||
|
|
||||||
if len(v.abs) == 0 {
|
if len(v.abs) == 0 {
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
q, r := new(Int).Div(u, v);
|
q, r := new(Int).Div(u, v);
|
||||||
|
|
||||||
if CmpInt(r, v) >= 0 {
|
if CmpInt(r, v) >= 0 {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
uprime := new(Int).Set(q);
|
uprime := new(Int).Set(q);
|
||||||
|
|
@ -282,7 +282,7 @@ var divTests = []divTest{
|
||||||
func TestDiv(t *testing.T) {
|
func TestDiv(t *testing.T) {
|
||||||
err := quick.Check(checkDiv, nil);
|
err := quick.Check(checkDiv, nil);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err);
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, test := range divTests {
|
for i, test := range divTests {
|
||||||
|
|
@ -294,7 +294,7 @@ func TestDiv(t *testing.T) {
|
||||||
q, r := new(Int).Div(x, y);
|
q, r := new(Int).Div(x, y);
|
||||||
|
|
||||||
if CmpInt(q, expectedQ) != 0 || CmpInt(r, expectedR) != 0 {
|
if CmpInt(q, expectedQ) != 0 || CmpInt(r, expectedR) != 0 {
|
||||||
t.Errorf("#%d got (%s, %s) want (%s, %s)", i, q, r, expectedQ, expectedR);
|
t.Errorf("#%d got (%s, %s) want (%s, %s)", i, q, r, expectedQ, expectedR)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -314,7 +314,7 @@ func TestDivStepD6(t *testing.T) {
|
||||||
const expectedR32 = "39614081266355540837921718287";
|
const expectedR32 = "39614081266355540837921718287";
|
||||||
if q.String() != expectedQ64 && q.String() != expectedQ32 ||
|
if q.String() != expectedQ64 && q.String() != expectedQ32 ||
|
||||||
r.String() != expectedR64 && r.String() != expectedR32 {
|
r.String() != expectedR64 && r.String() != expectedR32 {
|
||||||
t.Errorf("got (%s, %s) want (%s, %s) or (%s, %s)", q, r, expectedQ64, expectedR64, expectedQ32, expectedR32);
|
t.Errorf("got (%s, %s) want (%s, %s) or (%s, %s)", q, r, expectedQ64, expectedR64, expectedQ32, expectedR32)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -347,7 +347,7 @@ func TestLen(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Len() != test.out {
|
if n.Len() != test.out {
|
||||||
t.Errorf("#%d got %d want %d\n", i, n.Len(), test.out);
|
t.Errorf("#%d got %d want %d\n", i, n.Len(), test.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -390,9 +390,9 @@ func TestExp(t *testing.T) {
|
||||||
var m *Int;
|
var m *Int;
|
||||||
|
|
||||||
if len(test.m) == 0 {
|
if len(test.m) == 0 {
|
||||||
m, ok4 = nil, true;
|
m, ok4 = nil, true
|
||||||
} else {
|
} else {
|
||||||
m, ok4 = new(Int).SetString(test.m, 0);
|
m, ok4 = new(Int).SetString(test.m, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ok1 || !ok2 || !ok3 || !ok4 {
|
if !ok1 || !ok2 || !ok3 || !ok4 {
|
||||||
|
|
@ -402,7 +402,7 @@ func TestExp(t *testing.T) {
|
||||||
|
|
||||||
z := new(Int).Exp(x, y, m);
|
z := new(Int).Exp(x, y, m);
|
||||||
if CmpInt(z, out) != 0 {
|
if CmpInt(z, out) != 0 {
|
||||||
t.Errorf("#%d got %s want %s", i, z, out);
|
t.Errorf("#%d got %s want %s", i, z, out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -454,7 +454,7 @@ func TestGcd(t *testing.T) {
|
||||||
if CmpInt(expectedX, x) != 0 ||
|
if CmpInt(expectedX, x) != 0 ||
|
||||||
CmpInt(expectedY, y) != 0 ||
|
CmpInt(expectedY, y) != 0 ||
|
||||||
CmpInt(expectedD, d) != 0 {
|
CmpInt(expectedD, d) != 0 {
|
||||||
t.Errorf("#%d got (%s %s %s) want (%s %s %s)", i, x, y, d, expectedX, expectedY, expectedD);
|
t.Errorf("#%d got (%s %s %s) want (%s %s %s)", i, x, y, d, expectedX, expectedY, expectedD)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ package big
|
||||||
func normN(z []Word) []Word {
|
func normN(z []Word) []Word {
|
||||||
i := len(z);
|
i := len(z);
|
||||||
for i > 0 && z[i-1] == 0 {
|
for i > 0 && z[i-1] == 0 {
|
||||||
i--;
|
i--
|
||||||
}
|
}
|
||||||
z = z[0:i];
|
z = z[0:i];
|
||||||
return z;
|
return z;
|
||||||
|
|
@ -49,7 +49,7 @@ func makeN(z []Word, m int, clear bool) []Word {
|
||||||
z = z[0:m]; // reuse z - has at least one extra word for a carry, if any
|
z = z[0:m]; // reuse z - has at least one extra word for a carry, if any
|
||||||
if clear {
|
if clear {
|
||||||
for i := range z {
|
for i := range z {
|
||||||
z[i] = 0;
|
z[i] = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return z;
|
return z;
|
||||||
|
|
@ -57,7 +57,7 @@ func makeN(z []Word, m int, clear bool) []Word {
|
||||||
|
|
||||||
c := 4; // minimum capacity
|
c := 4; // minimum capacity
|
||||||
if m > c {
|
if m > c {
|
||||||
c = m;
|
c = m
|
||||||
}
|
}
|
||||||
return make([]Word, m, c+1); // +1: extra word for a carry, if any
|
return make([]Word, m, c+1); // +1: extra word for a carry, if any
|
||||||
}
|
}
|
||||||
|
|
@ -65,7 +65,7 @@ func makeN(z []Word, m int, clear bool) []Word {
|
||||||
|
|
||||||
func newN(z []Word, x uint64) []Word {
|
func newN(z []Word, x uint64) []Word {
|
||||||
if x == 0 {
|
if x == 0 {
|
||||||
return makeN(z, 0, false);
|
return makeN(z, 0, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// single-digit values
|
// single-digit values
|
||||||
|
|
@ -78,7 +78,7 @@ func newN(z []Word, x uint64) []Word {
|
||||||
// compute number of words n required to represent x
|
// compute number of words n required to represent x
|
||||||
n := 0;
|
n := 0;
|
||||||
for t := x; t > 0; t >>= _W {
|
for t := x; t > 0; t >>= _W {
|
||||||
n++;
|
n++
|
||||||
}
|
}
|
||||||
|
|
||||||
// split x into n words
|
// split x into n words
|
||||||
|
|
@ -95,7 +95,7 @@ func newN(z []Word, x uint64) []Word {
|
||||||
func setN(z, x []Word) []Word {
|
func setN(z, x []Word) []Word {
|
||||||
z = makeN(z, len(x), false);
|
z = makeN(z, len(x), false);
|
||||||
for i, d := range x {
|
for i, d := range x {
|
||||||
z[i] = d;
|
z[i] = d
|
||||||
}
|
}
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
@ -107,20 +107,20 @@ func addNN(z, x, y []Word) []Word {
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case m < n:
|
case m < n:
|
||||||
return addNN(z, y, x);
|
return addNN(z, y, x)
|
||||||
case m == 0:
|
case m == 0:
|
||||||
// n == 0 because m >= n; result is 0
|
// n == 0 because m >= n; result is 0
|
||||||
return makeN(z, 0, false);
|
return makeN(z, 0, false)
|
||||||
case n == 0:
|
case n == 0:
|
||||||
// result is x
|
// result is x
|
||||||
return setN(z, x);
|
return setN(z, x)
|
||||||
}
|
}
|
||||||
// m > 0
|
// m > 0
|
||||||
|
|
||||||
z = makeN(z, m, false);
|
z = makeN(z, m, false);
|
||||||
c := addVV(&z[0], &x[0], &y[0], n);
|
c := addVV(&z[0], &x[0], &y[0], n);
|
||||||
if m > n {
|
if m > n {
|
||||||
c = addVW(&z[n], &x[n], c, m-n);
|
c = addVW(&z[n], &x[n], c, m-n)
|
||||||
}
|
}
|
||||||
if c > 0 {
|
if c > 0 {
|
||||||
z = z[0 : m+1];
|
z = z[0 : m+1];
|
||||||
|
|
@ -137,23 +137,23 @@ func subNN(z, x, y []Word) []Word {
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case m < n:
|
case m < n:
|
||||||
panic("underflow");
|
panic("underflow")
|
||||||
case m == 0:
|
case m == 0:
|
||||||
// n == 0 because m >= n; result is 0
|
// n == 0 because m >= n; result is 0
|
||||||
return makeN(z, 0, false);
|
return makeN(z, 0, false)
|
||||||
case n == 0:
|
case n == 0:
|
||||||
// result is x
|
// result is x
|
||||||
return setN(z, x);
|
return setN(z, x)
|
||||||
}
|
}
|
||||||
// m > 0
|
// m > 0
|
||||||
|
|
||||||
z = makeN(z, m, false);
|
z = makeN(z, m, false);
|
||||||
c := subVV(&z[0], &x[0], &y[0], n);
|
c := subVV(&z[0], &x[0], &y[0], n);
|
||||||
if m > n {
|
if m > n {
|
||||||
c = subVW(&z[n], &x[n], c, m-n);
|
c = subVW(&z[n], &x[n], c, m-n)
|
||||||
}
|
}
|
||||||
if c != 0 {
|
if c != 0 {
|
||||||
panic("underflow");
|
panic("underflow")
|
||||||
}
|
}
|
||||||
z = normN(z);
|
z = normN(z);
|
||||||
|
|
||||||
|
|
@ -167,23 +167,23 @@ func cmpNN(x, y []Word) (r int) {
|
||||||
if m != n || m == 0 {
|
if m != n || m == 0 {
|
||||||
switch {
|
switch {
|
||||||
case m < n:
|
case m < n:
|
||||||
r = -1;
|
r = -1
|
||||||
case m > n:
|
case m > n:
|
||||||
r = 1;
|
r = 1
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
i := m-1;
|
i := m-1;
|
||||||
for i > 0 && x[i] == y[i] {
|
for i > 0 && x[i] == y[i] {
|
||||||
i--;
|
i--
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case x[i] < y[i]:
|
case x[i] < y[i]:
|
||||||
r = -1;
|
r = -1
|
||||||
case x[i] > y[i]:
|
case x[i] > y[i]:
|
||||||
r = 1;
|
r = 1
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -192,7 +192,7 @@ func cmpNN(x, y []Word) (r int) {
|
||||||
func mulAddNWW(z, x []Word, y, r Word) []Word {
|
func mulAddNWW(z, x []Word, y, r Word) []Word {
|
||||||
m := len(x);
|
m := len(x);
|
||||||
if m == 0 || y == 0 {
|
if m == 0 || y == 0 {
|
||||||
return newN(z, uint64(r)); // result is r
|
return newN(z, uint64(r)) // result is r
|
||||||
}
|
}
|
||||||
// m > 0
|
// m > 0
|
||||||
|
|
||||||
|
|
@ -213,21 +213,21 @@ func mulNN(z, x, y []Word) []Word {
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case m < n:
|
case m < n:
|
||||||
return mulNN(z, y, x);
|
return mulNN(z, y, x)
|
||||||
case m == 0 || n == 0:
|
case m == 0 || n == 0:
|
||||||
return makeN(z, 0, false);
|
return makeN(z, 0, false)
|
||||||
case n == 1:
|
case n == 1:
|
||||||
return mulAddNWW(z, x, y[0], 0);
|
return mulAddNWW(z, x, y[0], 0)
|
||||||
}
|
}
|
||||||
// m >= n && m > 1 && n > 1
|
// m >= n && m > 1 && n > 1
|
||||||
|
|
||||||
z = makeN(z, m+n, true);
|
z = makeN(z, m+n, true);
|
||||||
if &z[0] == &x[0] || &z[0] == &y[0] {
|
if &z[0] == &x[0] || &z[0] == &y[0] {
|
||||||
z = makeN(nil, m+n, true); // z is an alias for x or y - cannot reuse
|
z = makeN(nil, m+n, true) // z is an alias for x or y - cannot reuse
|
||||||
}
|
}
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
if f := y[i]; f != 0 {
|
if f := y[i]; f != 0 {
|
||||||
z[m+i] = addMulVVW(&z[i], &x[0], f, m);
|
z[m+i] = addMulVVW(&z[i], &x[0], f, m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
z = normN(z);
|
z = normN(z);
|
||||||
|
|
@ -241,7 +241,7 @@ func divNW(z, x []Word, y Word) (q []Word, r Word) {
|
||||||
m := len(x);
|
m := len(x);
|
||||||
switch {
|
switch {
|
||||||
case y == 0:
|
case y == 0:
|
||||||
panic("division by zero");
|
panic("division by zero")
|
||||||
case y == 1:
|
case y == 1:
|
||||||
q = setN(z, x); // result is x
|
q = setN(z, x); // result is x
|
||||||
return;
|
return;
|
||||||
|
|
@ -290,7 +290,7 @@ func divNN(z, z2, uIn, v []Word) (q, r []Word) {
|
||||||
rhat += v[n-1];
|
rhat += v[n-1];
|
||||||
// v[n-1] >= 0, so this tests for overflow.
|
// v[n-1] >= 0, so this tests for overflow.
|
||||||
if rhat < prevRhat {
|
if rhat < prevRhat {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
x1, x2 = mulWW_g(qhat, v[n-2]);
|
x1, x2 = mulWW_g(qhat, v[n-2]);
|
||||||
}
|
}
|
||||||
|
|
@ -323,7 +323,7 @@ func divNN(z, z2, uIn, v []Word) (q, r []Word) {
|
||||||
func log2(x Word) int {
|
func log2(x Word) int {
|
||||||
n := 0;
|
n := 0;
|
||||||
for ; x > 0; x >>= 1 {
|
for ; x > 0; x >>= 1 {
|
||||||
n++;
|
n++
|
||||||
}
|
}
|
||||||
return n-1;
|
return n-1;
|
||||||
}
|
}
|
||||||
|
|
@ -335,7 +335,7 @@ func log2(x Word) int {
|
||||||
func log2N(x []Word) int {
|
func log2N(x []Word) int {
|
||||||
m := len(x);
|
m := len(x);
|
||||||
if m > 0 {
|
if m > 0 {
|
||||||
return (m-1)*int(_W) + log2(x[m-1]);
|
return (m-1)*int(_W) + log2(x[m-1])
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -345,13 +345,13 @@ func hexValue(ch byte) int {
|
||||||
var d byte;
|
var d byte;
|
||||||
switch {
|
switch {
|
||||||
case '0' <= ch && ch <= '9':
|
case '0' <= ch && ch <= '9':
|
||||||
d = ch-'0';
|
d = ch-'0'
|
||||||
case 'a' <= ch && ch <= 'f':
|
case 'a' <= ch && ch <= 'f':
|
||||||
d = ch-'a'+10;
|
d = ch-'a'+10
|
||||||
case 'A' <= ch && ch <= 'F':
|
case 'A' <= ch && ch <= 'F':
|
||||||
d = ch-'A'+10;
|
d = ch-'A'+10
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1
|
||||||
}
|
}
|
||||||
return int(d);
|
return int(d);
|
||||||
}
|
}
|
||||||
|
|
@ -376,16 +376,16 @@ func scanN(z []Word, s string, base int) ([]Word, int, int) {
|
||||||
if n > 1 && (s[1] == 'x' || s[1] == 'X') {
|
if n > 1 && (s[1] == 'x' || s[1] == 'X') {
|
||||||
if n == 2 {
|
if n == 2 {
|
||||||
// Reject a string which is just '0x' as nonsense.
|
// Reject a string which is just '0x' as nonsense.
|
||||||
return nil, 0, 0;
|
return nil, 0, 0
|
||||||
}
|
}
|
||||||
base, i = 16, 2;
|
base, i = 16, 2;
|
||||||
} else {
|
} else {
|
||||||
base, i = 8, 1;
|
base, i = 8, 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if base < 2 || 16 < base {
|
if base < 2 || 16 < base {
|
||||||
panic("illegal base");
|
panic("illegal base")
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert string
|
// convert string
|
||||||
|
|
@ -393,9 +393,9 @@ func scanN(z []Word, s string, base int) ([]Word, int, int) {
|
||||||
for ; i < n; i++ {
|
for ; i < n; i++ {
|
||||||
d := hexValue(s[i]);
|
d := hexValue(s[i]);
|
||||||
if 0 <= d && d < base {
|
if 0 <= d && d < base {
|
||||||
z = mulAddNWW(z, z, Word(base), Word(d));
|
z = mulAddNWW(z, z, Word(base), Word(d))
|
||||||
} else {
|
} else {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -408,11 +408,11 @@ func scanN(z []Word, s string, base int) ([]Word, int, int) {
|
||||||
// a []byte buffer and return it
|
// a []byte buffer and return it
|
||||||
func stringN(x []Word, base int) string {
|
func stringN(x []Word, base int) string {
|
||||||
if base < 2 || 16 < base {
|
if base < 2 || 16 < base {
|
||||||
panic("illegal base");
|
panic("illegal base")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(x) == 0 {
|
if len(x) == 0 {
|
||||||
return "0";
|
return "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate buffer for conversion
|
// allocate buffer for conversion
|
||||||
|
|
@ -444,7 +444,7 @@ func leadingZeroBits(x Word) int {
|
||||||
|
|
||||||
for i := 0; x != 0; i++ {
|
for i := 0; x != 0; i++ {
|
||||||
if x&(1<<(_W-1)) != 0 {
|
if x&(1<<(_W-1)) != 0 {
|
||||||
return i+c;
|
return i+c
|
||||||
}
|
}
|
||||||
x <<= 1;
|
x <<= 1;
|
||||||
}
|
}
|
||||||
|
|
@ -455,7 +455,7 @@ func leadingZeroBits(x Word) int {
|
||||||
|
|
||||||
func shiftLeft(dst, src []Word, n int) {
|
func shiftLeft(dst, src []Word, n int) {
|
||||||
if len(src) == 0 {
|
if len(src) == 0 {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ñ := uint(_W)-uint(n);
|
ñ := uint(_W)-uint(n);
|
||||||
|
|
@ -469,7 +469,7 @@ func shiftLeft(dst, src []Word, n int) {
|
||||||
|
|
||||||
func shiftRight(dst, src []Word, n int) {
|
func shiftRight(dst, src []Word, n int) {
|
||||||
if len(src) == 0 {
|
if len(src) == 0 {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ñ := uint(_W)-uint(n);
|
ñ := uint(_W)-uint(n);
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ func TestSetN(t *testing.T) {
|
||||||
for _, a := range sumNN {
|
for _, a := range sumNN {
|
||||||
z := setN(nil, a.z);
|
z := setN(nil, a.z);
|
||||||
if cmpNN(z, a.z) != 0 {
|
if cmpNN(z, a.z) != 0 {
|
||||||
t.Errorf("got z = %v; want %v", z, a.z);
|
t.Errorf("got z = %v; want %v", z, a.z)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -52,7 +52,7 @@ func TestSetN(t *testing.T) {
|
||||||
func testFunNN(t *testing.T, msg string, f funNN, a argNN) {
|
func testFunNN(t *testing.T, msg string, f funNN, a argNN) {
|
||||||
z := f(nil, a.x, a.y);
|
z := f(nil, a.x, a.y);
|
||||||
if cmpNN(z, a.z) != 0 {
|
if cmpNN(z, a.z) != 0 {
|
||||||
t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, z, a.z);
|
t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, z, a.z)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,18 +101,18 @@ func TestStringN(t *testing.T) {
|
||||||
for _, a := range tabN {
|
for _, a := range tabN {
|
||||||
s := stringN(a.x, a.b);
|
s := stringN(a.x, a.b);
|
||||||
if s != a.s {
|
if s != a.s {
|
||||||
t.Errorf("stringN%+v\n\tgot s = %s; want %s", a, s, a.s);
|
t.Errorf("stringN%+v\n\tgot s = %s; want %s", a, s, a.s)
|
||||||
}
|
}
|
||||||
|
|
||||||
x, b, n := scanN(nil, a.s, a.b);
|
x, b, n := scanN(nil, a.s, a.b);
|
||||||
if cmpNN(x, a.x) != 0 {
|
if cmpNN(x, a.x) != 0 {
|
||||||
t.Errorf("scanN%+v\n\tgot z = %v; want %v", a, x, a.x);
|
t.Errorf("scanN%+v\n\tgot z = %v; want %v", a, x, a.x)
|
||||||
}
|
}
|
||||||
if b != a.b {
|
if b != a.b {
|
||||||
t.Errorf("scanN%+v\n\tgot b = %d; want %d", a, b, a.b);
|
t.Errorf("scanN%+v\n\tgot b = %d; want %d", a, b, a.b)
|
||||||
}
|
}
|
||||||
if n != len(a.s) {
|
if n != len(a.s) {
|
||||||
t.Errorf("scanN%+v\n\tgot n = %d; want %d", a, n, len(a.s));
|
t.Errorf("scanN%+v\n\tgot n = %d; want %d", a, n, len(a.s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +122,7 @@ func TestLeadingZeroBits(t *testing.T) {
|
||||||
var x Word = 1<<(_W-1);
|
var x Word = 1<<(_W-1);
|
||||||
for i := 0; i <= int(_W); i++ {
|
for i := 0; i <= int(_W); i++ {
|
||||||
if leadingZeroBits(x) != i {
|
if leadingZeroBits(x) != i {
|
||||||
t.Errorf("failed at %x: got %d want %d", x, leadingZeroBits(x), i);
|
t.Errorf("failed at %x: got %d want %d", x, leadingZeroBits(x), i)
|
||||||
}
|
}
|
||||||
x >>= 1;
|
x >>= 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ func Mul128(x, y uint64) (z1, z0 uint64) {
|
||||||
)
|
)
|
||||||
|
|
||||||
if x < y {
|
if x < y {
|
||||||
x, y = y, x;
|
x, y = y, x
|
||||||
}
|
}
|
||||||
|
|
||||||
if x < B2 {
|
if x < B2 {
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ const (
|
||||||
|
|
||||||
func assert(p bool) {
|
func assert(p bool) {
|
||||||
if !p {
|
if !p {
|
||||||
panic("assert failed");
|
panic("assert failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,14 +115,14 @@ type Natural []digit
|
||||||
//
|
//
|
||||||
func Nat(x uint64) Natural {
|
func Nat(x uint64) Natural {
|
||||||
if x == 0 {
|
if x == 0 {
|
||||||
return nil; // len == 0
|
return nil // len == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// single-digit values
|
// single-digit values
|
||||||
// (note: cannot re-use preallocated values because
|
// (note: cannot re-use preallocated values because
|
||||||
// the in-place operations may overwrite them)
|
// the in-place operations may overwrite them)
|
||||||
if x < _B {
|
if x < _B {
|
||||||
return Natural{digit(x)};
|
return Natural{digit(x)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute number of digits required to represent x
|
// compute number of digits required to represent x
|
||||||
|
|
@ -130,7 +130,7 @@ func Nat(x uint64) Natural {
|
||||||
// for any base)
|
// for any base)
|
||||||
n := 0;
|
n := 0;
|
||||||
for t := x; t > 0; t >>= _W {
|
for t := x; t > 0; t >>= _W {
|
||||||
n++;
|
n++
|
||||||
}
|
}
|
||||||
|
|
||||||
// split x into digits
|
// split x into digits
|
||||||
|
|
@ -151,9 +151,9 @@ func (x Natural) Value() uint64 {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
switch n {
|
switch n {
|
||||||
case 0:
|
case 0:
|
||||||
return 0;
|
return 0
|
||||||
case 1:
|
case 1:
|
||||||
return uint64(x[0]);
|
return uint64(x[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// multi-digit values
|
// multi-digit values
|
||||||
|
|
@ -199,7 +199,7 @@ func (x Natural) IsZero() bool { return len(x) == 0 }
|
||||||
func normalize(x Natural) Natural {
|
func normalize(x Natural) Natural {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
for n > 0 && x[n-1] == 0 {
|
for n > 0 && x[n-1] == 0 {
|
||||||
n--;
|
n--
|
||||||
}
|
}
|
||||||
return x[0:n];
|
return x[0:n];
|
||||||
}
|
}
|
||||||
|
|
@ -212,10 +212,10 @@ func normalize(x Natural) Natural {
|
||||||
func nalloc(z Natural, n int) Natural {
|
func nalloc(z Natural, n int) Natural {
|
||||||
size := n;
|
size := n;
|
||||||
if size <= 0 {
|
if size <= 0 {
|
||||||
size = 4;
|
size = 4
|
||||||
}
|
}
|
||||||
if size <= cap(z) {
|
if size <= cap(z) {
|
||||||
return z[0:n];
|
return z[0:n]
|
||||||
}
|
}
|
||||||
return make(Natural, n, size);
|
return make(Natural, n, size);
|
||||||
}
|
}
|
||||||
|
|
@ -270,7 +270,7 @@ func Nsub(zp *Natural, x, y Natural) {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
m := len(y);
|
m := len(y);
|
||||||
if n < m {
|
if n < m {
|
||||||
panic("underflow");
|
panic("underflow")
|
||||||
}
|
}
|
||||||
|
|
||||||
z := nalloc(*zp, n);
|
z := nalloc(*zp, n);
|
||||||
|
|
@ -287,7 +287,7 @@ func Nsub(zp *Natural, x, y Natural) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if int64(c) < 0 {
|
if int64(c) < 0 {
|
||||||
panic("underflow");
|
panic("underflow")
|
||||||
}
|
}
|
||||||
*zp = normalize(z);
|
*zp = normalize(z);
|
||||||
}
|
}
|
||||||
|
|
@ -313,7 +313,7 @@ func muladd11(x, y, c digit) (digit, digit) {
|
||||||
|
|
||||||
func mul1(z, x Natural, y digit) (c digit) {
|
func mul1(z, x Natural, y digit) (c digit) {
|
||||||
for i := 0; i < len(x); i++ {
|
for i := 0; i < len(x); i++ {
|
||||||
c, z[i] = muladd11(x[i], y, c);
|
c, z[i] = muladd11(x[i], y, c)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -327,7 +327,7 @@ func Nscale(z *Natural, d uint64) {
|
||||||
*z = Nat(0);
|
*z = Nat(0);
|
||||||
return;
|
return;
|
||||||
case d == 1:
|
case d == 1:
|
||||||
return;
|
return
|
||||||
case d >= _B:
|
case d >= _B:
|
||||||
*z = z.Mul1(d);
|
*z = z.Mul1(d);
|
||||||
return;
|
return;
|
||||||
|
|
@ -340,11 +340,11 @@ func Nscale(z *Natural, d uint64) {
|
||||||
if n >= cap(*z) {
|
if n >= cap(*z) {
|
||||||
zz := make(Natural, n+1);
|
zz := make(Natural, n+1);
|
||||||
for i, d := range *z {
|
for i, d := range *z {
|
||||||
zz[i] = d;
|
zz[i] = d
|
||||||
}
|
}
|
||||||
*z = zz;
|
*z = zz;
|
||||||
} else {
|
} else {
|
||||||
*z = (*z)[0 : n+1];
|
*z = (*z)[0 : n+1]
|
||||||
}
|
}
|
||||||
(*z)[n] = c;
|
(*z)[n] = c;
|
||||||
}
|
}
|
||||||
|
|
@ -373,13 +373,13 @@ func muladd1(x Natural, d, c digit) Natural {
|
||||||
func (x Natural) Mul1(d uint64) Natural {
|
func (x Natural) Mul1(d uint64) Natural {
|
||||||
switch {
|
switch {
|
||||||
case d == 0:
|
case d == 0:
|
||||||
return Nat(0);
|
return Nat(0)
|
||||||
case d == 1:
|
case d == 1:
|
||||||
return x;
|
return x
|
||||||
case isSmall(digit(d)):
|
case isSmall(digit(d)):
|
||||||
muladd1(x, digit(d), 0);
|
muladd1(x, digit(d), 0)
|
||||||
case d >= _B:
|
case d >= _B:
|
||||||
return x.Mul(Nat(d));
|
return x.Mul(Nat(d))
|
||||||
}
|
}
|
||||||
|
|
||||||
z := make(Natural, len(x)+1);
|
z := make(Natural, len(x)+1);
|
||||||
|
|
@ -395,15 +395,15 @@ func (x Natural) Mul(y Natural) Natural {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
m := len(y);
|
m := len(y);
|
||||||
if n < m {
|
if n < m {
|
||||||
return y.Mul(x);
|
return y.Mul(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
if m == 0 {
|
if m == 0 {
|
||||||
return Nat(0);
|
return Nat(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if m == 1 && y[0] < _B {
|
if m == 1 && y[0] < _B {
|
||||||
return x.Mul1(uint64(y[0]));
|
return x.Mul1(uint64(y[0]))
|
||||||
}
|
}
|
||||||
|
|
||||||
z := make(Natural, n+m);
|
z := make(Natural, n+m);
|
||||||
|
|
@ -412,7 +412,7 @@ func (x Natural) Mul(y Natural) Natural {
|
||||||
if d != 0 {
|
if d != 0 {
|
||||||
c := digit(0);
|
c := digit(0);
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
c, z[i+j] = muladd11(x[i], d, z[i+j]+c);
|
c, z[i+j] = muladd11(x[i], d, z[i+j]+c)
|
||||||
}
|
}
|
||||||
z[n+j] = c;
|
z[n+j] = c;
|
||||||
}
|
}
|
||||||
|
|
@ -439,7 +439,7 @@ func unpack(x Natural) []digit2 {
|
||||||
// normalize result
|
// normalize result
|
||||||
k := 2*n;
|
k := 2*n;
|
||||||
for k > 0 && z[k-1] == 0 {
|
for k > 0 && z[k-1] == 0 {
|
||||||
k--;
|
k--
|
||||||
}
|
}
|
||||||
return z[0:k]; // trim leading 0's
|
return z[0:k]; // trim leading 0's
|
||||||
}
|
}
|
||||||
|
|
@ -454,7 +454,7 @@ func pack(x []digit2) Natural {
|
||||||
z[n] = digit(x[n*2]);
|
z[n] = digit(x[n*2]);
|
||||||
}
|
}
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
z[i] = digit(x[i*2 + 1])<<_W2 | digit(x[i*2]);
|
z[i] = digit(x[i*2 + 1])<<_W2 | digit(x[i*2])
|
||||||
}
|
}
|
||||||
return normalize(z);
|
return normalize(z);
|
||||||
}
|
}
|
||||||
|
|
@ -506,7 +506,7 @@ func divmod(x, y []digit2) ([]digit2, []digit2) {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
m := len(y);
|
m := len(y);
|
||||||
if m == 0 {
|
if m == 0 {
|
||||||
panic("division by zero");
|
panic("division by zero")
|
||||||
}
|
}
|
||||||
assert(n+1 <= cap(x)); // space for one extra digit
|
assert(n+1 <= cap(x)); // space for one extra digit
|
||||||
x = x[0 : n+1];
|
x = x[0 : n+1];
|
||||||
|
|
@ -515,12 +515,12 @@ func divmod(x, y []digit2) ([]digit2, []digit2) {
|
||||||
if m == 1 {
|
if m == 1 {
|
||||||
// division by single digit
|
// division by single digit
|
||||||
// result is shifted left by 1 in place!
|
// result is shifted left by 1 in place!
|
||||||
x[0] = div21(x[1 : n+1], x[0:n], y[0]);
|
x[0] = div21(x[1 : n+1], x[0:n], y[0])
|
||||||
|
|
||||||
} else if m > n {
|
} else if m > n {
|
||||||
// y > x => quotient = 0, remainder = x
|
// y > x => quotient = 0, remainder = x
|
||||||
// TODO in this case we shouldn't even unpack x and y
|
// TODO in this case we shouldn't even unpack x and y
|
||||||
m = n;
|
m = n
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// general case
|
// general case
|
||||||
|
|
@ -546,12 +546,12 @@ func divmod(x, y []digit2) ([]digit2, []digit2) {
|
||||||
{
|
{
|
||||||
x0, x1, x2 := digit(x[k]), digit(x[k-1]), digit(x[k-2]);
|
x0, x1, x2 := digit(x[k]), digit(x[k-1]), digit(x[k-2]);
|
||||||
if x0 != y1 {
|
if x0 != y1 {
|
||||||
q = (x0<<_W2 + x1)/y1;
|
q = (x0<<_W2 + x1)/y1
|
||||||
} else {
|
} else {
|
||||||
q = _B2-1;
|
q = _B2-1
|
||||||
}
|
}
|
||||||
for y2*q > (x0<<_W2 + x1 - y1*q)<<_W2 + x2 {
|
for y2*q > (x0<<_W2 + x1 - y1*q)<<_W2 + x2 {
|
||||||
q--;
|
q--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -623,7 +623,7 @@ func shl(z, x Natural, s uint) digit {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
c := digit(0);
|
c := digit(0);
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
c, z[i] = x[i]>>(_W-s), x[i]<<s&_M | c;
|
c, z[i] = x[i]>>(_W-s), x[i]<<s&_M | c
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
@ -647,7 +647,7 @@ func shr(z, x Natural, s uint) digit {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
c := digit(0);
|
c := digit(0);
|
||||||
for i := n-1; i >= 0; i-- {
|
for i := n-1; i >= 0; i-- {
|
||||||
c, z[i] = x[i]<<(_W-s)&_M, x[i]>>s | c;
|
c, z[i] = x[i]<<(_W-s)&_M, x[i]>>s | c
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
@ -659,7 +659,7 @@ func (x Natural) Shr(s uint) Natural {
|
||||||
n := uint(len(x));
|
n := uint(len(x));
|
||||||
m := n - s/_W;
|
m := n - s/_W;
|
||||||
if m > n { // check for underflow
|
if m > n { // check for underflow
|
||||||
m = 0;
|
m = 0
|
||||||
}
|
}
|
||||||
z := make(Natural, m);
|
z := make(Natural, m);
|
||||||
|
|
||||||
|
|
@ -675,12 +675,12 @@ func (x Natural) And(y Natural) Natural {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
m := len(y);
|
m := len(y);
|
||||||
if n < m {
|
if n < m {
|
||||||
return y.And(x);
|
return y.And(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
z := make(Natural, m);
|
z := make(Natural, m);
|
||||||
for i := 0; i < m; i++ {
|
for i := 0; i < m; i++ {
|
||||||
z[i] = x[i]&y[i];
|
z[i] = x[i]&y[i]
|
||||||
}
|
}
|
||||||
// upper bits are 0
|
// upper bits are 0
|
||||||
|
|
||||||
|
|
@ -690,7 +690,7 @@ func (x Natural) And(y Natural) Natural {
|
||||||
|
|
||||||
func copy(z, x Natural) {
|
func copy(z, x Natural) {
|
||||||
for i, e := range x {
|
for i, e := range x {
|
||||||
z[i] = e;
|
z[i] = e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -701,12 +701,12 @@ func (x Natural) AndNot(y Natural) Natural {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
m := len(y);
|
m := len(y);
|
||||||
if n < m {
|
if n < m {
|
||||||
m = n;
|
m = n
|
||||||
}
|
}
|
||||||
|
|
||||||
z := make(Natural, n);
|
z := make(Natural, n);
|
||||||
for i := 0; i < m; i++ {
|
for i := 0; i < m; i++ {
|
||||||
z[i] = x[i]&^y[i];
|
z[i] = x[i]&^y[i]
|
||||||
}
|
}
|
||||||
copy(z[m:n], x[m:n]);
|
copy(z[m:n], x[m:n]);
|
||||||
|
|
||||||
|
|
@ -720,12 +720,12 @@ func (x Natural) Or(y Natural) Natural {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
m := len(y);
|
m := len(y);
|
||||||
if n < m {
|
if n < m {
|
||||||
return y.Or(x);
|
return y.Or(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
z := make(Natural, n);
|
z := make(Natural, n);
|
||||||
for i := 0; i < m; i++ {
|
for i := 0; i < m; i++ {
|
||||||
z[i] = x[i]|y[i];
|
z[i] = x[i]|y[i]
|
||||||
}
|
}
|
||||||
copy(z[m:n], x[m:n]);
|
copy(z[m:n], x[m:n]);
|
||||||
|
|
||||||
|
|
@ -739,12 +739,12 @@ func (x Natural) Xor(y Natural) Natural {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
m := len(y);
|
m := len(y);
|
||||||
if n < m {
|
if n < m {
|
||||||
return y.Xor(x);
|
return y.Xor(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
z := make(Natural, n);
|
z := make(Natural, n);
|
||||||
for i := 0; i < m; i++ {
|
for i := 0; i < m; i++ {
|
||||||
z[i] = x[i]^y[i];
|
z[i] = x[i]^y[i]
|
||||||
}
|
}
|
||||||
copy(z[m:n], x[m:n]);
|
copy(z[m:n], x[m:n]);
|
||||||
|
|
||||||
|
|
@ -763,20 +763,20 @@ func (x Natural) Cmp(y Natural) int {
|
||||||
m := len(y);
|
m := len(y);
|
||||||
|
|
||||||
if n != m || n == 0 {
|
if n != m || n == 0 {
|
||||||
return n-m;
|
return n-m
|
||||||
}
|
}
|
||||||
|
|
||||||
i := n-1;
|
i := n-1;
|
||||||
for i > 0 && x[i] == y[i] {
|
for i > 0 && x[i] == y[i] {
|
||||||
i--;
|
i--
|
||||||
}
|
}
|
||||||
|
|
||||||
d := 0;
|
d := 0;
|
||||||
switch {
|
switch {
|
||||||
case x[i] < y[i]:
|
case x[i] < y[i]:
|
||||||
d = -1;
|
d = -1
|
||||||
case x[i] > y[i]:
|
case x[i] > y[i]:
|
||||||
d = 1;
|
d = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
|
|
@ -805,7 +805,7 @@ func log2(x uint64) uint {
|
||||||
func (x Natural) Log2() uint {
|
func (x Natural) Log2() uint {
|
||||||
n := len(x);
|
n := len(x);
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
return (uint(n)-1)*_W + log2(uint64(x[n-1]));
|
return (uint(n)-1)*_W + log2(uint64(x[n-1]))
|
||||||
}
|
}
|
||||||
panic("Log2(0)");
|
panic("Log2(0)");
|
||||||
}
|
}
|
||||||
|
|
@ -831,7 +831,7 @@ func divmod1(x Natural, d digit) (Natural, digit) {
|
||||||
//
|
//
|
||||||
func (x Natural) ToString(base uint) string {
|
func (x Natural) ToString(base uint) string {
|
||||||
if len(x) == 0 {
|
if len(x) == 0 {
|
||||||
return "0";
|
return "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate buffer for conversion
|
// allocate buffer for conversion
|
||||||
|
|
@ -865,11 +865,11 @@ func (x Natural) String() string { return x.ToString(10) }
|
||||||
func fmtbase(c int) uint {
|
func fmtbase(c int) uint {
|
||||||
switch c {
|
switch c {
|
||||||
case 'b':
|
case 'b':
|
||||||
return 2;
|
return 2
|
||||||
case 'o':
|
case 'o':
|
||||||
return 8;
|
return 8
|
||||||
case 'x':
|
case 'x':
|
||||||
return 16;
|
return 16
|
||||||
}
|
}
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
@ -885,11 +885,11 @@ func hexvalue(ch byte) uint {
|
||||||
d := uint(1<<logH);
|
d := uint(1<<logH);
|
||||||
switch {
|
switch {
|
||||||
case '0' <= ch && ch <= '9':
|
case '0' <= ch && ch <= '9':
|
||||||
d = uint(ch-'0');
|
d = uint(ch-'0')
|
||||||
case 'a' <= ch && ch <= 'f':
|
case 'a' <= ch && ch <= 'f':
|
||||||
d = uint(ch-'a')+10;
|
d = uint(ch-'a')+10
|
||||||
case 'A' <= ch && ch <= 'F':
|
case 'A' <= ch && ch <= 'F':
|
||||||
d = uint(ch-'A')+10;
|
d = uint(ch-'A')+10
|
||||||
}
|
}
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
@ -912,9 +912,9 @@ func NatFromString(s string, base uint) (Natural, uint, int) {
|
||||||
base = 10;
|
base = 10;
|
||||||
if n > 0 && s[0] == '0' {
|
if n > 0 && s[0] == '0' {
|
||||||
if n > 1 && (s[1] == 'x' || s[1] == 'X') {
|
if n > 1 && (s[1] == 'x' || s[1] == 'X') {
|
||||||
base, i = 16, 2;
|
base, i = 16, 2
|
||||||
} else {
|
} else {
|
||||||
base, i = 8, 1;
|
base, i = 8, 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -925,9 +925,9 @@ func NatFromString(s string, base uint) (Natural, uint, int) {
|
||||||
for ; i < n; i++ {
|
for ; i < n; i++ {
|
||||||
d := hexvalue(s[i]);
|
d := hexvalue(s[i]);
|
||||||
if d < base {
|
if d < base {
|
||||||
x = muladd1(x, digit(base), digit(d));
|
x = muladd1(x, digit(base), digit(d))
|
||||||
} else {
|
} else {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -952,7 +952,7 @@ func pop1(x digit) uint {
|
||||||
func (x Natural) Pop() uint {
|
func (x Natural) Pop() uint {
|
||||||
n := uint(0);
|
n := uint(0);
|
||||||
for i := len(x)-1; i >= 0; i-- {
|
for i := len(x)-1; i >= 0; i-- {
|
||||||
n += pop1(x[i]);
|
n += pop1(x[i])
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
@ -966,7 +966,7 @@ func (xp Natural) Pow(n uint) Natural {
|
||||||
for n > 0 {
|
for n > 0 {
|
||||||
// z * x^n == x^n0
|
// z * x^n == x^n0
|
||||||
if n&1 == 1 {
|
if n&1 == 1 {
|
||||||
z = z.Mul(x);
|
z = z.Mul(x)
|
||||||
}
|
}
|
||||||
x, n = x.Mul(x), n/2;
|
x, n = x.Mul(x), n/2;
|
||||||
}
|
}
|
||||||
|
|
@ -980,11 +980,11 @@ func (xp Natural) Pow(n uint) Natural {
|
||||||
func MulRange(a, b uint) Natural {
|
func MulRange(a, b uint) Natural {
|
||||||
switch {
|
switch {
|
||||||
case a > b:
|
case a > b:
|
||||||
return Nat(1);
|
return Nat(1)
|
||||||
case a == b:
|
case a == b:
|
||||||
return Nat(uint64(a));
|
return Nat(uint64(a))
|
||||||
case a+1 == b:
|
case a+1 == b:
|
||||||
return Nat(uint64(a)).Mul(Nat(uint64(b)));
|
return Nat(uint64(a)).Mul(Nat(uint64(b)))
|
||||||
}
|
}
|
||||||
m := (a+b)>>1;
|
m := (a+b)>>1;
|
||||||
assert(a <= m && m < b);
|
assert(a <= m && m < b);
|
||||||
|
|
@ -997,7 +997,7 @@ func MulRange(a, b uint) Natural {
|
||||||
func Fact(n uint) Natural {
|
func Fact(n uint) Natural {
|
||||||
// Using MulRange() instead of the basic for-loop
|
// Using MulRange() instead of the basic for-loop
|
||||||
// lead to faster factorial computation.
|
// lead to faster factorial computation.
|
||||||
return MulRange(2, n);
|
return MulRange(2, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1012,7 +1012,7 @@ func (x Natural) Gcd(y Natural) Natural {
|
||||||
// Euclidean algorithm.
|
// Euclidean algorithm.
|
||||||
a, b := x, y;
|
a, b := x, y;
|
||||||
for !b.IsZero() {
|
for !b.IsZero() {
|
||||||
a, b = b, a.Mod(b);
|
a, b = b, a.Mod(b)
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ const (
|
||||||
func natFromString(s string, base uint, slen *int) Natural {
|
func natFromString(s string, base uint, slen *int) Natural {
|
||||||
x, _, len := NatFromString(s, base);
|
x, _, len := NatFromString(s, base);
|
||||||
if slen != nil {
|
if slen != nil {
|
||||||
*slen = len;
|
*slen = len
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
@ -30,7 +30,7 @@ func natFromString(s string, base uint, slen *int) Natural {
|
||||||
func intFromString(s string, base uint, slen *int) *Integer {
|
func intFromString(s string, base uint, slen *int) *Integer {
|
||||||
x, _, len := IntFromString(s, base);
|
x, _, len := IntFromString(s, base);
|
||||||
if slen != nil {
|
if slen != nil {
|
||||||
*slen = len;
|
*slen = len
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
@ -39,7 +39,7 @@ func intFromString(s string, base uint, slen *int) *Integer {
|
||||||
func ratFromString(s string, base uint, slen *int) *Rational {
|
func ratFromString(s string, base uint, slen *int) *Rational {
|
||||||
x, _, len := RatFromString(s, base);
|
x, _, len := RatFromString(s, base);
|
||||||
if slen != nil {
|
if slen != nil {
|
||||||
*slen = len;
|
*slen = len
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
@ -69,28 +69,28 @@ var tester *testing.T
|
||||||
|
|
||||||
func test(n uint, b bool) {
|
func test(n uint, b bool) {
|
||||||
if !b {
|
if !b {
|
||||||
tester.Fatalf("TEST failed: %s (%d)", test_msg, n);
|
tester.Fatalf("TEST failed: %s (%d)", test_msg, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func nat_eq(n uint, x, y Natural) {
|
func nat_eq(n uint, x, y Natural) {
|
||||||
if x.Cmp(y) != 0 {
|
if x.Cmp(y) != 0 {
|
||||||
tester.Fatalf("TEST failed: %s (%d)\nx = %v\ny = %v", test_msg, n, &x, &y);
|
tester.Fatalf("TEST failed: %s (%d)\nx = %v\ny = %v", test_msg, n, &x, &y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func int_eq(n uint, x, y *Integer) {
|
func int_eq(n uint, x, y *Integer) {
|
||||||
if x.Cmp(y) != 0 {
|
if x.Cmp(y) != 0 {
|
||||||
tester.Fatalf("TEST failed: %s (%d)\nx = %v\ny = %v", test_msg, n, x, y);
|
tester.Fatalf("TEST failed: %s (%d)\nx = %v\ny = %v", test_msg, n, x, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func rat_eq(n uint, x, y *Rational) {
|
func rat_eq(n uint, x, y *Rational) {
|
||||||
if x.Cmp(y) != 0 {
|
if x.Cmp(y) != 0 {
|
||||||
tester.Fatalf("TEST failed: %s (%d)\nx = %v\ny = %v", test_msg, n, x, y);
|
tester.Fatalf("TEST failed: %s (%d)\nx = %v\ny = %v", test_msg, n, x, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,7 +116,7 @@ func TestNatConv(t *testing.T) {
|
||||||
|
|
||||||
test_msg = "NatConvB";
|
test_msg = "NatConvB";
|
||||||
for i := uint(0); i < 100; i++ {
|
for i := uint(0); i < 100; i++ {
|
||||||
test(i, Nat(uint64(i)).String() == fmt.Sprintf("%d", i));
|
test(i, Nat(uint64(i)).String() == fmt.Sprintf("%d", i))
|
||||||
}
|
}
|
||||||
|
|
||||||
test_msg = "NatConvC";
|
test_msg = "NatConvC";
|
||||||
|
|
@ -146,7 +146,7 @@ func TestNatConv(t *testing.T) {
|
||||||
test_msg = "NatConvF";
|
test_msg = "NatConvF";
|
||||||
tmp := c.Mul(c);
|
tmp := c.Mul(c);
|
||||||
for base := uint(2); base <= 16; base++ {
|
for base := uint(2); base <= 16; base++ {
|
||||||
nat_eq(base, natFromString(tmp.ToString(base), base, nil), tmp);
|
nat_eq(base, natFromString(tmp.ToString(base), base, nil), tmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
test_msg = "NatConvG";
|
test_msg = "NatConvG";
|
||||||
|
|
@ -158,7 +158,7 @@ func TestNatConv(t *testing.T) {
|
||||||
|
|
||||||
func abs(x int64) uint64 {
|
func abs(x int64) uint64 {
|
||||||
if x < 0 {
|
if x < 0 {
|
||||||
x = -x;
|
x = -x
|
||||||
}
|
}
|
||||||
return uint64(x);
|
return uint64(x);
|
||||||
}
|
}
|
||||||
|
|
@ -235,7 +235,7 @@ func add(x, y Natural) Natural {
|
||||||
z1 := x.Add(y);
|
z1 := x.Add(y);
|
||||||
z2 := y.Add(x);
|
z2 := y.Add(x);
|
||||||
if z1.Cmp(z2) != 0 {
|
if z1.Cmp(z2) != 0 {
|
||||||
tester.Fatalf("addition not symmetric:\n\tx = %v\n\ty = %t", x, y);
|
tester.Fatalf("addition not symmetric:\n\tx = %v\n\ty = %t", x, y)
|
||||||
}
|
}
|
||||||
return z1;
|
return z1;
|
||||||
}
|
}
|
||||||
|
|
@ -244,7 +244,7 @@ func add(x, y Natural) Natural {
|
||||||
func sum(n uint64, scale Natural) Natural {
|
func sum(n uint64, scale Natural) Natural {
|
||||||
s := nat_zero;
|
s := nat_zero;
|
||||||
for ; n > 0; n-- {
|
for ; n > 0; n-- {
|
||||||
s = add(s, Nat(n).Mul(scale));
|
s = add(s, Nat(n).Mul(scale))
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
@ -268,13 +268,13 @@ func mul(x, y Natural) Natural {
|
||||||
z1 := x.Mul(y);
|
z1 := x.Mul(y);
|
||||||
z2 := y.Mul(x);
|
z2 := y.Mul(x);
|
||||||
if z1.Cmp(z2) != 0 {
|
if z1.Cmp(z2) != 0 {
|
||||||
tester.Fatalf("multiplication not symmetric:\n\tx = %v\n\ty = %t", x, y);
|
tester.Fatalf("multiplication not symmetric:\n\tx = %v\n\ty = %t", x, y)
|
||||||
}
|
}
|
||||||
if !x.IsZero() && z1.Div(x).Cmp(y) != 0 {
|
if !x.IsZero() && z1.Div(x).Cmp(y) != 0 {
|
||||||
tester.Fatalf("multiplication/division not inverse (A):\n\tx = %v\n\ty = %t", x, y);
|
tester.Fatalf("multiplication/division not inverse (A):\n\tx = %v\n\ty = %t", x, y)
|
||||||
}
|
}
|
||||||
if !y.IsZero() && z1.Div(y).Cmp(x) != 0 {
|
if !y.IsZero() && z1.Div(y).Cmp(x) != 0 {
|
||||||
tester.Fatalf("multiplication/division not inverse (B):\n\tx = %v\n\ty = %t", x, y);
|
tester.Fatalf("multiplication/division not inverse (B):\n\tx = %v\n\ty = %t", x, y)
|
||||||
}
|
}
|
||||||
return z1;
|
return z1;
|
||||||
}
|
}
|
||||||
|
|
@ -290,7 +290,7 @@ func TestNatSub(t *testing.T) {
|
||||||
for i := uint64(0); i < 100; i++ {
|
for i := uint64(0); i < 100; i++ {
|
||||||
t := sum(i, c);
|
t := sum(i, c);
|
||||||
for j := uint64(0); j <= i; j++ {
|
for j := uint64(0); j <= i; j++ {
|
||||||
t = t.Sub(mul(Nat(j), c));
|
t = t.Sub(mul(Nat(j), c))
|
||||||
}
|
}
|
||||||
nat_eq(uint(i), t, nat_zero);
|
nat_eq(uint(i), t, nat_zero);
|
||||||
}
|
}
|
||||||
|
|
@ -311,7 +311,7 @@ func TestNatMul(t *testing.T) {
|
||||||
const n = 100;
|
const n = 100;
|
||||||
p := b.Mul(c).Shl(n);
|
p := b.Mul(c).Shl(n);
|
||||||
for i := uint(0); i < n; i++ {
|
for i := uint(0); i < n; i++ {
|
||||||
nat_eq(i, mul(b.Shl(i), c.Shl(n-i)), p);
|
nat_eq(i, mul(b.Shl(i), c.Shl(n-i)), p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -329,7 +329,7 @@ func TestNatDiv(t *testing.T) {
|
||||||
const n = 100;
|
const n = 100;
|
||||||
p := Fact(n);
|
p := Fact(n);
|
||||||
for i := uint(0); i < n; i++ {
|
for i := uint(0); i < n; i++ {
|
||||||
nat_eq(100+i, p.Div(MulRange(1, i)), MulRange(i+1, n));
|
nat_eq(100+i, p.Div(MulRange(1, i)), MulRange(i+1, n))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -398,7 +398,7 @@ func TestNatMod(t *testing.T) {
|
||||||
for i := uint(0); ; i++ {
|
for i := uint(0); ; i++ {
|
||||||
d := nat_one.Shl(i);
|
d := nat_one.Shl(i);
|
||||||
if d.Cmp(c) < 0 {
|
if d.Cmp(c) < 0 {
|
||||||
nat_eq(i, c.Add(d).Mod(c), d);
|
nat_eq(i, c.Add(d).Mod(c), d)
|
||||||
} else {
|
} else {
|
||||||
nat_eq(i, c.Add(d).Div(c), nat_two);
|
nat_eq(i, c.Add(d).Div(c), nat_two);
|
||||||
nat_eq(i, c.Add(d).Mod(c), d.Sub(c));
|
nat_eq(i, c.Add(d).Mod(c), d.Sub(c));
|
||||||
|
|
@ -420,7 +420,7 @@ func TestNatShift(t *testing.T) {
|
||||||
|
|
||||||
test_msg = "NatShift2";
|
test_msg = "NatShift2";
|
||||||
for i := uint(0); i < 100; i++ {
|
for i := uint(0); i < 100; i++ {
|
||||||
test(i, c.Shl(i).Shr(i).Cmp(c) == 0);
|
test(i, c.Shl(i).Shr(i).Cmp(c) == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
test_msg = "NatShift3L";
|
test_msg = "NatShift3L";
|
||||||
|
|
@ -457,7 +457,7 @@ func TestIntShift(t *testing.T) {
|
||||||
|
|
||||||
test_msg = "IntShift2";
|
test_msg = "IntShift2";
|
||||||
for i := uint(0); i < 100; i++ {
|
for i := uint(0); i < 100; i++ {
|
||||||
test(i, ip.Shl(i).Shr(i).Cmp(ip) == 0);
|
test(i, ip.Shl(i).Shr(i).Cmp(ip) == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
test_msg = "IntShift3L";
|
test_msg = "IntShift3L";
|
||||||
|
|
@ -499,25 +499,25 @@ func TestNatBitOps(t *testing.T) {
|
||||||
test_msg = "NatAnd";
|
test_msg = "NatAnd";
|
||||||
bz := Nat(x&y);
|
bz := Nat(x&y);
|
||||||
for i := uint(0); i < 100; i++ {
|
for i := uint(0); i < 100; i++ {
|
||||||
nat_eq(i, bx.Shl(i).And(by.Shl(i)), bz.Shl(i));
|
nat_eq(i, bx.Shl(i).And(by.Shl(i)), bz.Shl(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
test_msg = "NatAndNot";
|
test_msg = "NatAndNot";
|
||||||
bz = Nat(x&^y);
|
bz = Nat(x&^y);
|
||||||
for i := uint(0); i < 100; i++ {
|
for i := uint(0); i < 100; i++ {
|
||||||
nat_eq(i, bx.Shl(i).AndNot(by.Shl(i)), bz.Shl(i));
|
nat_eq(i, bx.Shl(i).AndNot(by.Shl(i)), bz.Shl(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
test_msg = "NatOr";
|
test_msg = "NatOr";
|
||||||
bz = Nat(x|y);
|
bz = Nat(x|y);
|
||||||
for i := uint(0); i < 100; i++ {
|
for i := uint(0); i < 100; i++ {
|
||||||
nat_eq(i, bx.Shl(i).Or(by.Shl(i)), bz.Shl(i));
|
nat_eq(i, bx.Shl(i).Or(by.Shl(i)), bz.Shl(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
test_msg = "NatXor";
|
test_msg = "NatXor";
|
||||||
bz = Nat(x^y);
|
bz = Nat(x^y);
|
||||||
for i := uint(0); i < 100; i++ {
|
for i := uint(0); i < 100; i++ {
|
||||||
nat_eq(i, bx.Shl(i).Xor(by.Shl(i)), bz.Shl(i));
|
nat_eq(i, bx.Shl(i).Xor(by.Shl(i)), bz.Shl(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -560,7 +560,7 @@ func TestIntBitOps2(t *testing.T) {
|
||||||
for y := int64(-5); y < 15; y++ {
|
for y := int64(-5); y < 15; y++ {
|
||||||
by := Int(y);
|
by := Int(y);
|
||||||
for i := uint(50); i < 70; i++ { // shift across 64bit boundary
|
for i := uint(50); i < 70; i++ { // shift across 64bit boundary
|
||||||
int_eq(i, bx.Shl(i).And(by.Shl(i)), Int(x&y).Shl(i));
|
int_eq(i, bx.Shl(i).And(by.Shl(i)), Int(x&y).Shl(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -583,7 +583,7 @@ func TestIntBitOps2(t *testing.T) {
|
||||||
for y := int64(-5); y < 15; y++ {
|
for y := int64(-5); y < 15; y++ {
|
||||||
by := Int(y);
|
by := Int(y);
|
||||||
for i := uint(50); i < 70; i++ { // shift across 64bit boundary
|
for i := uint(50); i < 70; i++ { // shift across 64bit boundary
|
||||||
int_eq(i, bx.Shl(i).Or(by.Shl(i)), Int(x|y).Shl(i));
|
int_eq(i, bx.Shl(i).Or(by.Shl(i)), Int(x|y).Shl(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -594,7 +594,7 @@ func TestIntBitOps2(t *testing.T) {
|
||||||
for y := int64(-5); y < 15; y++ {
|
for y := int64(-5); y < 15; y++ {
|
||||||
by := Int(y);
|
by := Int(y);
|
||||||
for i := uint(50); i < 70; i++ { // shift across 64bit boundary
|
for i := uint(50); i < 70; i++ { // shift across 64bit boundary
|
||||||
int_eq(i, bx.Shl(i).Xor(by.Shl(i)), Int(x^y).Shl(i));
|
int_eq(i, bx.Shl(i).Xor(by.Shl(i)), Int(x^y).Shl(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -624,7 +624,7 @@ func TestNatLog2(t *testing.T) {
|
||||||
|
|
||||||
test_msg = "NatLog2B";
|
test_msg = "NatLog2B";
|
||||||
for i := uint(0); i < 100; i++ {
|
for i := uint(0); i < 100; i++ {
|
||||||
test(i, nat_one.Shl(i).Log2() == i);
|
test(i, nat_one.Shl(i).Log2() == i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -644,7 +644,7 @@ func TestNatPow(t *testing.T) {
|
||||||
|
|
||||||
test_msg = "NatPowB";
|
test_msg = "NatPowB";
|
||||||
for i := uint(0); i < 100; i++ {
|
for i := uint(0); i < 100; i++ {
|
||||||
nat_eq(i, nat_two.Pow(i), nat_one.Shl(i));
|
nat_eq(i, nat_two.Pow(i), nat_one.Shl(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -660,6 +660,6 @@ func TestNatPop(t *testing.T) {
|
||||||
|
|
||||||
test_msg = "NatPopB";
|
test_msg = "NatPopB";
|
||||||
for i := uint(0); i < 100; i++ {
|
for i := uint(0); i < 100; i++ {
|
||||||
test(i, nat_one.Shl(i).Sub(nat_one).Pop() == i);
|
test(i, nat_one.Shl(i).Sub(nat_one).Pop() == i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ type Integer struct {
|
||||||
//
|
//
|
||||||
func MakeInt(sign bool, mant Natural) *Integer {
|
func MakeInt(sign bool, mant Natural) *Integer {
|
||||||
if mant.IsZero() {
|
if mant.IsZero() {
|
||||||
sign = false; // normalize
|
sign = false // normalize
|
||||||
}
|
}
|
||||||
return &Integer{sign, mant};
|
return &Integer{sign, mant};
|
||||||
}
|
}
|
||||||
|
|
@ -42,9 +42,9 @@ func Int(x int64) *Integer {
|
||||||
if x < 0 {
|
if x < 0 {
|
||||||
// For the most negative x, -x == x, and
|
// For the most negative x, -x == x, and
|
||||||
// the bit pattern has the correct value.
|
// the bit pattern has the correct value.
|
||||||
ux = uint64(-x);
|
ux = uint64(-x)
|
||||||
} else {
|
} else {
|
||||||
ux = uint64(x);
|
ux = uint64(x)
|
||||||
}
|
}
|
||||||
return MakeInt(x < 0, Nat(ux));
|
return MakeInt(x < 0, Nat(ux));
|
||||||
}
|
}
|
||||||
|
|
@ -56,7 +56,7 @@ func Int(x int64) *Integer {
|
||||||
func (x *Integer) Value() int64 {
|
func (x *Integer) Value() int64 {
|
||||||
z := int64(x.mant.Value());
|
z := int64(x.mant.Value());
|
||||||
if x.sign {
|
if x.sign {
|
||||||
z = -z;
|
z = -z
|
||||||
}
|
}
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
@ -167,7 +167,7 @@ func (x *Integer) Sub(y *Integer) *Integer {
|
||||||
func Iscale(z *Integer, d int64) {
|
func Iscale(z *Integer, d int64) {
|
||||||
f := uint64(d);
|
f := uint64(d);
|
||||||
if d < 0 {
|
if d < 0 {
|
||||||
f = uint64(-d);
|
f = uint64(-d)
|
||||||
}
|
}
|
||||||
z.sign = z.sign != (d < 0);
|
z.sign = z.sign != (d < 0);
|
||||||
Nscale(&z.mant, f);
|
Nscale(&z.mant, f);
|
||||||
|
|
@ -179,7 +179,7 @@ func Iscale(z *Integer, d int64) {
|
||||||
func (x *Integer) Mul1(d int64) *Integer {
|
func (x *Integer) Mul1(d int64) *Integer {
|
||||||
f := uint64(d);
|
f := uint64(d);
|
||||||
if d < 0 {
|
if d < 0 {
|
||||||
f = uint64(-d);
|
f = uint64(-d)
|
||||||
}
|
}
|
||||||
return MakeInt(x.sign != (d < 0), x.mant.Mul1(f));
|
return MakeInt(x.sign != (d < 0), x.mant.Mul1(f));
|
||||||
}
|
}
|
||||||
|
|
@ -192,7 +192,7 @@ func (x *Integer) Mul(y *Integer) *Integer {
|
||||||
// x * (-y) == -(x * y)
|
// x * (-y) == -(x * y)
|
||||||
// (-x) * y == -(x * y)
|
// (-x) * y == -(x * y)
|
||||||
// (-x) * (-y) == x * y
|
// (-x) * (-y) == x * y
|
||||||
return MakeInt(x.sign != y.sign, x.mant.Mul(y.mant));
|
return MakeInt(x.sign != y.sign, x.mant.Mul(y.mant))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -201,7 +201,7 @@ func (x *Integer) Mul(y *Integer) *Integer {
|
||||||
func (x *Integer) MulNat(y Natural) *Integer {
|
func (x *Integer) MulNat(y Natural) *Integer {
|
||||||
// x * y == x * y
|
// x * y == x * y
|
||||||
// (-x) * y == -(x * y)
|
// (-x) * y == -(x * y)
|
||||||
return MakeInt(x.sign, x.mant.Mul(y));
|
return MakeInt(x.sign, x.mant.Mul(y))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -220,7 +220,7 @@ func (x *Integer) Quo(y *Integer) *Integer {
|
||||||
// x / (-y) == -(x / y)
|
// x / (-y) == -(x / y)
|
||||||
// (-x) / y == -(x / y)
|
// (-x) / y == -(x / y)
|
||||||
// (-x) / (-y) == x / y
|
// (-x) / (-y) == x / y
|
||||||
return MakeInt(x.sign != y.sign, x.mant.Div(y.mant));
|
return MakeInt(x.sign != y.sign, x.mant.Div(y.mant))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -234,7 +234,7 @@ func (x *Integer) Rem(y *Integer) *Integer {
|
||||||
// x % (-y) == x % y
|
// x % (-y) == x % y
|
||||||
// (-x) % y == -(x % y)
|
// (-x) % y == -(x % y)
|
||||||
// (-x) % (-y) == -(x % y)
|
// (-x) % (-y) == -(x % y)
|
||||||
return MakeInt(x.sign, x.mant.Mod(y.mant));
|
return MakeInt(x.sign, x.mant.Mod(y.mant))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -264,9 +264,9 @@ func (x *Integer) Div(y *Integer) *Integer {
|
||||||
q, r := x.QuoRem(y);
|
q, r := x.QuoRem(y);
|
||||||
if r.IsNeg() {
|
if r.IsNeg() {
|
||||||
if y.IsPos() {
|
if y.IsPos() {
|
||||||
q = q.Sub(Int(1));
|
q = q.Sub(Int(1))
|
||||||
} else {
|
} else {
|
||||||
q = q.Add(Int(1));
|
q = q.Add(Int(1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return q;
|
return q;
|
||||||
|
|
@ -281,9 +281,9 @@ func (x *Integer) Mod(y *Integer) *Integer {
|
||||||
r := x.Rem(y);
|
r := x.Rem(y);
|
||||||
if r.IsNeg() {
|
if r.IsNeg() {
|
||||||
if y.IsPos() {
|
if y.IsPos() {
|
||||||
r = r.Add(y);
|
r = r.Add(y)
|
||||||
} else {
|
} else {
|
||||||
r = r.Sub(y);
|
r = r.Sub(y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
|
@ -333,7 +333,7 @@ func (x *Integer) Shl(s uint) *Integer { return MakeInt(x.sign, x.mant.Shl(s)) }
|
||||||
func (x *Integer) Shr(s uint) *Integer {
|
func (x *Integer) Shr(s uint) *Integer {
|
||||||
if x.sign {
|
if x.sign {
|
||||||
// (-x) >> s == ^(x-1) >> s == ^((x-1) >> s) == -(((x-1) >> s) + 1)
|
// (-x) >> s == ^(x-1) >> s == ^((x-1) >> s) == -(((x-1) >> s) + 1)
|
||||||
return MakeInt(true, x.mant.Sub(Nat(1)).Shr(s).Add(Nat(1)));
|
return MakeInt(true, x.mant.Sub(Nat(1)).Shr(s).Add(Nat(1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
return MakeInt(false, x.mant.Shr(s));
|
return MakeInt(false, x.mant.Shr(s));
|
||||||
|
|
@ -344,7 +344,7 @@ func (x *Integer) Shr(s uint) *Integer {
|
||||||
func (x *Integer) Not() *Integer {
|
func (x *Integer) Not() *Integer {
|
||||||
if x.sign {
|
if x.sign {
|
||||||
// ^(-x) == ^(^(x-1)) == x-1
|
// ^(-x) == ^(^(x-1)) == x-1
|
||||||
return MakeInt(false, x.mant.Sub(Nat(1)));
|
return MakeInt(false, x.mant.Sub(Nat(1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ^x == -x-1 == -(x+1)
|
// ^x == -x-1 == -(x+1)
|
||||||
|
|
@ -358,7 +358,7 @@ func (x *Integer) And(y *Integer) *Integer {
|
||||||
if x.sign == y.sign {
|
if x.sign == y.sign {
|
||||||
if x.sign {
|
if x.sign {
|
||||||
// (-x) & (-y) == ^(x-1) & ^(y-1) == ^((x-1) | (y-1)) == -(((x-1) | (y-1)) + 1)
|
// (-x) & (-y) == ^(x-1) & ^(y-1) == ^((x-1) | (y-1)) == -(((x-1) | (y-1)) + 1)
|
||||||
return MakeInt(true, x.mant.Sub(Nat(1)).Or(y.mant.Sub(Nat(1))).Add(Nat(1)));
|
return MakeInt(true, x.mant.Sub(Nat(1)).Or(y.mant.Sub(Nat(1))).Add(Nat(1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// x & y == x & y
|
// x & y == x & y
|
||||||
|
|
@ -367,7 +367,7 @@ func (x *Integer) And(y *Integer) *Integer {
|
||||||
|
|
||||||
// x.sign != y.sign
|
// x.sign != y.sign
|
||||||
if x.sign {
|
if x.sign {
|
||||||
x, y = y, x; // & is symmetric
|
x, y = y, x // & is symmetric
|
||||||
}
|
}
|
||||||
|
|
||||||
// x & (-y) == x & ^(y-1) == x &^ (y-1)
|
// x & (-y) == x & ^(y-1) == x &^ (y-1)
|
||||||
|
|
@ -381,7 +381,7 @@ func (x *Integer) AndNot(y *Integer) *Integer {
|
||||||
if x.sign == y.sign {
|
if x.sign == y.sign {
|
||||||
if x.sign {
|
if x.sign {
|
||||||
// (-x) &^ (-y) == ^(x-1) &^ ^(y-1) == ^(x-1) & (y-1) == (y-1) &^ (x-1)
|
// (-x) &^ (-y) == ^(x-1) &^ ^(y-1) == ^(x-1) & (y-1) == (y-1) &^ (x-1)
|
||||||
return MakeInt(false, y.mant.Sub(Nat(1)).AndNot(x.mant.Sub(Nat(1))));
|
return MakeInt(false, y.mant.Sub(Nat(1)).AndNot(x.mant.Sub(Nat(1))))
|
||||||
}
|
}
|
||||||
|
|
||||||
// x &^ y == x &^ y
|
// x &^ y == x &^ y
|
||||||
|
|
@ -390,7 +390,7 @@ func (x *Integer) AndNot(y *Integer) *Integer {
|
||||||
|
|
||||||
if x.sign {
|
if x.sign {
|
||||||
// (-x) &^ y == ^(x-1) &^ y == ^(x-1) & ^y == ^((x-1) | y) == -(((x-1) | y) + 1)
|
// (-x) &^ y == ^(x-1) &^ y == ^(x-1) & ^y == ^((x-1) | y) == -(((x-1) | y) + 1)
|
||||||
return MakeInt(true, x.mant.Sub(Nat(1)).Or(y.mant).Add(Nat(1)));
|
return MakeInt(true, x.mant.Sub(Nat(1)).Or(y.mant).Add(Nat(1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// x &^ (-y) == x &^ ^(y-1) == x & (y-1)
|
// x &^ (-y) == x &^ ^(y-1) == x & (y-1)
|
||||||
|
|
@ -404,7 +404,7 @@ func (x *Integer) Or(y *Integer) *Integer {
|
||||||
if x.sign == y.sign {
|
if x.sign == y.sign {
|
||||||
if x.sign {
|
if x.sign {
|
||||||
// (-x) | (-y) == ^(x-1) | ^(y-1) == ^((x-1) & (y-1)) == -(((x-1) & (y-1)) + 1)
|
// (-x) | (-y) == ^(x-1) | ^(y-1) == ^((x-1) & (y-1)) == -(((x-1) & (y-1)) + 1)
|
||||||
return MakeInt(true, x.mant.Sub(Nat(1)).And(y.mant.Sub(Nat(1))).Add(Nat(1)));
|
return MakeInt(true, x.mant.Sub(Nat(1)).And(y.mant.Sub(Nat(1))).Add(Nat(1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// x | y == x | y
|
// x | y == x | y
|
||||||
|
|
@ -413,7 +413,7 @@ func (x *Integer) Or(y *Integer) *Integer {
|
||||||
|
|
||||||
// x.sign != y.sign
|
// x.sign != y.sign
|
||||||
if x.sign {
|
if x.sign {
|
||||||
x, y = y, x; // | or symmetric
|
x, y = y, x // | or symmetric
|
||||||
}
|
}
|
||||||
|
|
||||||
// x | (-y) == x | ^(y-1) == ^((y-1) &^ x) == -(^((y-1) &^ x) + 1)
|
// x | (-y) == x | ^(y-1) == ^((y-1) &^ x) == -(^((y-1) &^ x) + 1)
|
||||||
|
|
@ -427,7 +427,7 @@ func (x *Integer) Xor(y *Integer) *Integer {
|
||||||
if x.sign == y.sign {
|
if x.sign == y.sign {
|
||||||
if x.sign {
|
if x.sign {
|
||||||
// (-x) ^ (-y) == ^(x-1) ^ ^(y-1) == (x-1) ^ (y-1)
|
// (-x) ^ (-y) == ^(x-1) ^ ^(y-1) == (x-1) ^ (y-1)
|
||||||
return MakeInt(false, x.mant.Sub(Nat(1)).Xor(y.mant.Sub(Nat(1))));
|
return MakeInt(false, x.mant.Sub(Nat(1)).Xor(y.mant.Sub(Nat(1))))
|
||||||
}
|
}
|
||||||
|
|
||||||
// x ^ y == x ^ y
|
// x ^ y == x ^ y
|
||||||
|
|
@ -436,7 +436,7 @@ func (x *Integer) Xor(y *Integer) *Integer {
|
||||||
|
|
||||||
// x.sign != y.sign
|
// x.sign != y.sign
|
||||||
if x.sign {
|
if x.sign {
|
||||||
x, y = y, x; // ^ is symmetric
|
x, y = y, x // ^ is symmetric
|
||||||
}
|
}
|
||||||
|
|
||||||
// x ^ (-y) == x ^ ^(y-1) == ^(x ^ (y-1)) == -((x ^ (y-1)) + 1)
|
// x ^ (-y) == x ^ ^(y-1) == ^(x ^ (y-1)) == -((x ^ (y-1)) + 1)
|
||||||
|
|
@ -460,12 +460,12 @@ func (x *Integer) Cmp(y *Integer) int {
|
||||||
case x.sign == y.sign:
|
case x.sign == y.sign:
|
||||||
r = x.mant.Cmp(y.mant);
|
r = x.mant.Cmp(y.mant);
|
||||||
if x.sign {
|
if x.sign {
|
||||||
r = -r;
|
r = -r
|
||||||
}
|
}
|
||||||
case x.sign:
|
case x.sign:
|
||||||
r = -1;
|
r = -1
|
||||||
case y.sign:
|
case y.sign:
|
||||||
r = 1;
|
r = 1
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
@ -475,11 +475,11 @@ func (x *Integer) Cmp(y *Integer) int {
|
||||||
//
|
//
|
||||||
func (x *Integer) ToString(base uint) string {
|
func (x *Integer) ToString(base uint) string {
|
||||||
if x.mant.IsZero() {
|
if x.mant.IsZero() {
|
||||||
return "0";
|
return "0"
|
||||||
}
|
}
|
||||||
var s string;
|
var s string;
|
||||||
if x.sign {
|
if x.sign {
|
||||||
s = "-";
|
s = "-"
|
||||||
}
|
}
|
||||||
return s + x.mant.ToString(base);
|
return s + x.mant.ToString(base);
|
||||||
}
|
}
|
||||||
|
|
@ -511,7 +511,7 @@ func IntFromString(s string, base uint) (*Integer, uint, int) {
|
||||||
// skip sign, if any
|
// skip sign, if any
|
||||||
i0 := 0;
|
i0 := 0;
|
||||||
if len(s) > 0 && (s[0] == '-' || s[0] == '+') {
|
if len(s) > 0 && (s[0] == '-' || s[0] == '+') {
|
||||||
i0 = 1;
|
i0 = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mant, base, slen := NatFromString(s[i0:len(s)], base);
|
mant, base, slen := NatFromString(s[i0:len(s)], base);
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@ type fpNat struct {
|
||||||
func (x fpNat) sub(y fpNat) fpNat {
|
func (x fpNat) sub(y fpNat) fpNat {
|
||||||
switch d := x.e - y.e; {
|
switch d := x.e - y.e; {
|
||||||
case d < 0:
|
case d < 0:
|
||||||
return fpNat{x.m.Sub(y.m.Shl(uint(-d))), x.e};
|
return fpNat{x.m.Sub(y.m.Shl(uint(-d))), x.e}
|
||||||
case d > 0:
|
case d > 0:
|
||||||
return fpNat{x.m.Shl(uint(d)).Sub(y.m), y.e};
|
return fpNat{x.m.Shl(uint(d)).Sub(y.m), y.e}
|
||||||
}
|
}
|
||||||
return fpNat{x.m.Sub(y.m), x.e};
|
return fpNat{x.m.Sub(y.m), x.e};
|
||||||
}
|
}
|
||||||
|
|
@ -52,9 +52,9 @@ func (x fpNat) mul(y fpNat) fpNat { return fpNat{x.m.Mul(y.m), x.e + y.e} }
|
||||||
func (x fpNat) mant() Natural {
|
func (x fpNat) mant() Natural {
|
||||||
switch {
|
switch {
|
||||||
case x.e > 0:
|
case x.e > 0:
|
||||||
return x.m.Shl(uint(x.e));
|
return x.m.Shl(uint(x.e))
|
||||||
case x.e < 0:
|
case x.e < 0:
|
||||||
return x.m.Shr(uint(-x.e));
|
return x.m.Shr(uint(-x.e))
|
||||||
}
|
}
|
||||||
return x.m;
|
return x.m;
|
||||||
}
|
}
|
||||||
|
|
@ -71,15 +71,15 @@ func nrDivEst(x0, y0 Natural) Natural {
|
||||||
// y0 > 0
|
// y0 > 0
|
||||||
|
|
||||||
if y0.Cmp(Nat(1)) == 0 {
|
if y0.Cmp(Nat(1)) == 0 {
|
||||||
return x0;
|
return x0
|
||||||
}
|
}
|
||||||
// y0 > 1
|
// y0 > 1
|
||||||
|
|
||||||
switch d := x0.Cmp(y0); {
|
switch d := x0.Cmp(y0); {
|
||||||
case d < 0:
|
case d < 0:
|
||||||
return Nat(0);
|
return Nat(0)
|
||||||
case d == 0:
|
case d == 0:
|
||||||
return Nat(1);
|
return Nat(1)
|
||||||
}
|
}
|
||||||
// x0 > y0 > 1
|
// x0 > y0 > 1
|
||||||
|
|
||||||
|
|
@ -119,7 +119,7 @@ func nrDivEst(x0, y0 Natural) Natural {
|
||||||
q.e -= e;
|
q.e -= e;
|
||||||
res := q.mant();
|
res := q.mant();
|
||||||
if res.Cmp(p) == 0 {
|
if res.Cmp(p) == 0 {
|
||||||
return res;
|
return res
|
||||||
}
|
}
|
||||||
p = res;
|
p = res;
|
||||||
|
|
||||||
|
|
@ -131,7 +131,7 @@ func nrDivEst(x0, y0 Natural) Natural {
|
||||||
// computation time massively.
|
// computation time massively.
|
||||||
d := int(r.m.Log2() + 1)-maxLen;
|
d := int(r.m.Log2() + 1)-maxLen;
|
||||||
if d > 0 {
|
if d > 0 {
|
||||||
r = fpNat{r.m.Shr(uint(d)), r.e + d};
|
r = fpNat{r.m.Shr(uint(d)), r.e + d}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,10 +157,10 @@ func div(t *testing.T, x, y Natural) {
|
||||||
q, r := nrdiv(x, y);
|
q, r := nrdiv(x, y);
|
||||||
qx, rx := x.DivMod(y);
|
qx, rx := x.DivMod(y);
|
||||||
if q.Cmp(qx) != 0 {
|
if q.Cmp(qx) != 0 {
|
||||||
t.Errorf("x = %s, y = %s, got q = %s, want q = %s", x, y, q, qx);
|
t.Errorf("x = %s, y = %s, got q = %s, want q = %s", x, y, q, qx)
|
||||||
}
|
}
|
||||||
if r.Cmp(rx) != 0 {
|
if r.Cmp(rx) != 0 {
|
||||||
t.Errorf("x = %s, y = %s, got r = %s, want r = %s", x, y, r, rx);
|
t.Errorf("x = %s, y = %s, got r = %s, want r = %s", x, y, r, rx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ func MakeRat(a *Integer, b Natural) *Rational {
|
||||||
func Rat(a0 int64, b0 int64) *Rational {
|
func Rat(a0 int64, b0 int64) *Rational {
|
||||||
a, b := Int(a0), Int(b0);
|
a, b := Int(a0), Int(b0);
|
||||||
if b.sign {
|
if b.sign {
|
||||||
a = a.Neg();
|
a = a.Neg()
|
||||||
}
|
}
|
||||||
return MakeRat(a, b.mant);
|
return MakeRat(a, b.mant);
|
||||||
}
|
}
|
||||||
|
|
@ -43,7 +43,7 @@ func Rat(a0 int64, b0 int64) *Rational {
|
||||||
// Value returns the numerator and denominator of x.
|
// Value returns the numerator and denominator of x.
|
||||||
//
|
//
|
||||||
func (x *Rational) Value() (numerator *Integer, denominator Natural) {
|
func (x *Rational) Value() (numerator *Integer, denominator Natural) {
|
||||||
return x.a, x.b;
|
return x.a, x.b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -80,14 +80,14 @@ func (x *Rational) Neg() *Rational { return MakeRat(x.a.Neg(), x.b) }
|
||||||
// Add returns the sum x + y.
|
// Add returns the sum x + y.
|
||||||
//
|
//
|
||||||
func (x *Rational) Add(y *Rational) *Rational {
|
func (x *Rational) Add(y *Rational) *Rational {
|
||||||
return MakeRat((x.a.MulNat(y.b)).Add(y.a.MulNat(x.b)), x.b.Mul(y.b));
|
return MakeRat((x.a.MulNat(y.b)).Add(y.a.MulNat(x.b)), x.b.Mul(y.b))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Sub returns the difference x - y.
|
// Sub returns the difference x - y.
|
||||||
//
|
//
|
||||||
func (x *Rational) Sub(y *Rational) *Rational {
|
func (x *Rational) Sub(y *Rational) *Rational {
|
||||||
return MakeRat((x.a.MulNat(y.b)).Sub(y.a.MulNat(x.b)), x.b.Mul(y.b));
|
return MakeRat((x.a.MulNat(y.b)).Sub(y.a.MulNat(x.b)), x.b.Mul(y.b))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -103,7 +103,7 @@ func (x *Rational) Quo(y *Rational) *Rational {
|
||||||
a := x.a.MulNat(y.b);
|
a := x.a.MulNat(y.b);
|
||||||
b := y.a.MulNat(x.b);
|
b := y.a.MulNat(x.b);
|
||||||
if b.IsNeg() {
|
if b.IsNeg() {
|
||||||
a = a.Neg();
|
a = a.Neg()
|
||||||
}
|
}
|
||||||
return MakeRat(a, b.mant);
|
return MakeRat(a, b.mant);
|
||||||
}
|
}
|
||||||
|
|
@ -125,7 +125,7 @@ func (x *Rational) Cmp(y *Rational) int { return (x.a.MulNat(y.b)).Cmp(y.a.MulNa
|
||||||
func (x *Rational) ToString(base uint) string {
|
func (x *Rational) ToString(base uint) string {
|
||||||
s := x.a.ToString(base);
|
s := x.a.ToString(base);
|
||||||
if !x.IsInt() {
|
if !x.IsInt() {
|
||||||
s += "/" + x.b.ToString(base);
|
s += "/" + x.b.ToString(base)
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
@ -194,9 +194,9 @@ func RatFromString(s string, base uint) (*Rational, uint, int) {
|
||||||
rlen += elen;
|
rlen += elen;
|
||||||
m := Nat(10).Pow(uint(e.mant.Value()));
|
m := Nat(10).Pow(uint(e.mant.Value()));
|
||||||
if e.sign {
|
if e.sign {
|
||||||
b = b.Mul(m);
|
b = b.Mul(m)
|
||||||
} else {
|
} else {
|
||||||
a = a.MulNat(m);
|
a = a.MulNat(m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,12 +34,12 @@ var (
|
||||||
type BufSizeError int
|
type BufSizeError int
|
||||||
|
|
||||||
func (b BufSizeError) String() string {
|
func (b BufSizeError) String() string {
|
||||||
return "bufio: bad buffer size " + strconv.Itoa(int(b));
|
return "bufio: bad buffer size " + strconv.Itoa(int(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
func copySlice(dst []byte, src []byte) {
|
func copySlice(dst []byte, src []byte) {
|
||||||
for i := 0; i < len(dst); i++ {
|
for i := 0; i < len(dst); i++ {
|
||||||
dst[i] = src[i];
|
dst[i] = src[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,12 +61,12 @@ type Reader struct {
|
||||||
// It returns the Reader and any error.
|
// It returns the Reader and any error.
|
||||||
func NewReaderSize(rd io.Reader, size int) (*Reader, os.Error) {
|
func NewReaderSize(rd io.Reader, size int) (*Reader, os.Error) {
|
||||||
if size <= 0 {
|
if size <= 0 {
|
||||||
return nil, BufSizeError(size);
|
return nil, BufSizeError(size)
|
||||||
}
|
}
|
||||||
// Is it already a Reader?
|
// Is it already a Reader?
|
||||||
b, ok := rd.(*Reader);
|
b, ok := rd.(*Reader);
|
||||||
if ok && len(b.buf) >= size {
|
if ok && len(b.buf) >= size {
|
||||||
return b, nil;
|
return b, nil
|
||||||
}
|
}
|
||||||
b = new(Reader);
|
b = new(Reader);
|
||||||
b.buf = make([]byte, size);
|
b.buf = make([]byte, size);
|
||||||
|
|
@ -80,7 +80,7 @@ func NewReader(rd io.Reader) *Reader {
|
||||||
b, err := NewReaderSize(rd, defaultBufSize);
|
b, err := NewReaderSize(rd, defaultBufSize);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// cannot happen - defaultBufSize is a valid size
|
// cannot happen - defaultBufSize is a valid size
|
||||||
panic("bufio: NewReader: ", err.String());
|
panic("bufio: NewReader: ", err.String())
|
||||||
}
|
}
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +92,7 @@ func (b *Reader) fill() {
|
||||||
copySlice(b.buf[0 : b.w - b.r], b.buf[b.r : b.w]);
|
copySlice(b.buf[0 : b.w - b.r], b.buf[b.r : b.w]);
|
||||||
b.w -= b.r;
|
b.w -= b.r;
|
||||||
} else {
|
} else {
|
||||||
b.w = 0;
|
b.w = 0
|
||||||
}
|
}
|
||||||
b.r = 0;
|
b.r = 0;
|
||||||
|
|
||||||
|
|
@ -100,7 +100,7 @@ func (b *Reader) fill() {
|
||||||
n, e := b.rd.Read(b.buf[b.w : len(b.buf)]);
|
n, e := b.rd.Read(b.buf[b.w : len(b.buf)]);
|
||||||
b.w += n;
|
b.w += n;
|
||||||
if e != nil {
|
if e != nil {
|
||||||
b.err = e;
|
b.err = e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,14 +115,14 @@ func (b *Reader) Read(p []byte) (nn int, err os.Error) {
|
||||||
n := len(p);
|
n := len(p);
|
||||||
if b.w == b.r {
|
if b.w == b.r {
|
||||||
if b.err != nil {
|
if b.err != nil {
|
||||||
return nn, b.err;
|
return nn, b.err
|
||||||
}
|
}
|
||||||
if len(p) >= len(b.buf) {
|
if len(p) >= len(b.buf) {
|
||||||
// Large read, empty buffer.
|
// Large read, empty buffer.
|
||||||
// Read directly into p to avoid copy.
|
// Read directly into p to avoid copy.
|
||||||
n, b.err = b.rd.Read(p);
|
n, b.err = b.rd.Read(p);
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
b.lastbyte = int(p[n-1]);
|
b.lastbyte = int(p[n-1])
|
||||||
}
|
}
|
||||||
p = p[n:len(p)];
|
p = p[n:len(p)];
|
||||||
nn += n;
|
nn += n;
|
||||||
|
|
@ -132,7 +132,7 @@ func (b *Reader) Read(p []byte) (nn int, err os.Error) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if n > b.w - b.r {
|
if n > b.w - b.r {
|
||||||
n = b.w - b.r;
|
n = b.w - b.r
|
||||||
}
|
}
|
||||||
copySlice(p[0:n], b.buf[b.r : b.r + n]);
|
copySlice(p[0:n], b.buf[b.r : b.r + n]);
|
||||||
p = p[n:len(p)];
|
p = p[n:len(p)];
|
||||||
|
|
@ -148,7 +148,7 @@ func (b *Reader) Read(p []byte) (nn int, err os.Error) {
|
||||||
func (b *Reader) ReadByte() (c byte, err os.Error) {
|
func (b *Reader) ReadByte() (c byte, err os.Error) {
|
||||||
for b.w == b.r {
|
for b.w == b.r {
|
||||||
if b.err != nil {
|
if b.err != nil {
|
||||||
return 0, b.err;
|
return 0, b.err
|
||||||
}
|
}
|
||||||
b.fill();
|
b.fill();
|
||||||
}
|
}
|
||||||
|
|
@ -168,7 +168,7 @@ func (b *Reader) UnreadByte() os.Error {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
if b.r <= 0 {
|
if b.r <= 0 {
|
||||||
return ErrInvalidUnreadByte;
|
return ErrInvalidUnreadByte
|
||||||
}
|
}
|
||||||
b.r--;
|
b.r--;
|
||||||
b.lastbyte = -1;
|
b.lastbyte = -1;
|
||||||
|
|
@ -179,14 +179,14 @@ func (b *Reader) UnreadByte() os.Error {
|
||||||
// rune and its size in bytes.
|
// rune and its size in bytes.
|
||||||
func (b *Reader) ReadRune() (rune int, size int, err os.Error) {
|
func (b *Reader) ReadRune() (rune int, size int, err os.Error) {
|
||||||
for b.r + utf8.UTFMax > b.w && !utf8.FullRune(b.buf[b.r : b.w]) && b.err == nil {
|
for b.r + utf8.UTFMax > b.w && !utf8.FullRune(b.buf[b.r : b.w]) && b.err == nil {
|
||||||
b.fill();
|
b.fill()
|
||||||
}
|
}
|
||||||
if b.r == b.w {
|
if b.r == b.w {
|
||||||
return 0, 0, b.err;
|
return 0, 0, b.err
|
||||||
}
|
}
|
||||||
rune, size = int(b.buf[b.r]), 1;
|
rune, size = int(b.buf[b.r]), 1;
|
||||||
if rune >= 0x80 {
|
if rune >= 0x80 {
|
||||||
rune, size = utf8.DecodeRune(b.buf[b.r : b.w]);
|
rune, size = utf8.DecodeRune(b.buf[b.r : b.w])
|
||||||
}
|
}
|
||||||
b.r += size;
|
b.r += size;
|
||||||
b.lastbyte = int(b.buf[b.r - 1]);
|
b.lastbyte = int(b.buf[b.r - 1]);
|
||||||
|
|
@ -198,7 +198,7 @@ func (b *Reader) ReadRune() (rune int, size int, err os.Error) {
|
||||||
func findByte(p []byte, c byte) int {
|
func findByte(p []byte, c byte) int {
|
||||||
for i := 0; i < len(p); i++ {
|
for i := 0; i < len(p); i++ {
|
||||||
if p[i] == c {
|
if p[i] == c {
|
||||||
return i;
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -245,7 +245,7 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err os.Error) {
|
||||||
|
|
||||||
// Buffer is full?
|
// Buffer is full?
|
||||||
if b.Buffered() >= len(b.buf) {
|
if b.Buffered() >= len(b.buf) {
|
||||||
return nil, ErrBufferFull;
|
return nil, ErrBufferFull
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic("not reached");
|
panic("not reached");
|
||||||
|
|
@ -268,7 +268,7 @@ func (b *Reader) ReadBytes(delim byte) (line []byte, err os.Error) {
|
||||||
var e os.Error;
|
var e os.Error;
|
||||||
frag, e = b.ReadSlice(delim);
|
frag, e = b.ReadSlice(delim);
|
||||||
if e == nil { // got final fragment
|
if e == nil { // got final fragment
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
if e != ErrBufferFull { // unexpected error
|
if e != ErrBufferFull { // unexpected error
|
||||||
err = e;
|
err = e;
|
||||||
|
|
@ -292,11 +292,11 @@ func (b *Reader) ReadBytes(delim byte) (line []byte, err os.Error) {
|
||||||
|
|
||||||
// Grow list if needed.
|
// Grow list if needed.
|
||||||
if full == nil {
|
if full == nil {
|
||||||
full = make([][]byte, 16);
|
full = make([][]byte, 16)
|
||||||
} else if nfull >= len(full) {
|
} else if nfull >= len(full) {
|
||||||
newfull := make([][]byte, len(full)*2);
|
newfull := make([][]byte, len(full)*2);
|
||||||
for i := 0; i < len(full); i++ {
|
for i := 0; i < len(full); i++ {
|
||||||
newfull[i] = full[i];
|
newfull[i] = full[i]
|
||||||
}
|
}
|
||||||
full = newfull;
|
full = newfull;
|
||||||
}
|
}
|
||||||
|
|
@ -309,7 +309,7 @@ func (b *Reader) ReadBytes(delim byte) (line []byte, err os.Error) {
|
||||||
// Allocate new buffer to hold the full pieces and the fragment.
|
// Allocate new buffer to hold the full pieces and the fragment.
|
||||||
n := 0;
|
n := 0;
|
||||||
for i := 0; i < nfull; i++ {
|
for i := 0; i < nfull; i++ {
|
||||||
n += len(full[i]);
|
n += len(full[i])
|
||||||
}
|
}
|
||||||
n += len(frag);
|
n += len(frag);
|
||||||
|
|
||||||
|
|
@ -351,12 +351,12 @@ type Writer struct {
|
||||||
// It returns the Writer and any error.
|
// It returns the Writer and any error.
|
||||||
func NewWriterSize(wr io.Writer, size int) (*Writer, os.Error) {
|
func NewWriterSize(wr io.Writer, size int) (*Writer, os.Error) {
|
||||||
if size <= 0 {
|
if size <= 0 {
|
||||||
return nil, BufSizeError(size);
|
return nil, BufSizeError(size)
|
||||||
}
|
}
|
||||||
// Is it already a Writer?
|
// Is it already a Writer?
|
||||||
b, ok := wr.(*Writer);
|
b, ok := wr.(*Writer);
|
||||||
if ok && len(b.buf) >= size {
|
if ok && len(b.buf) >= size {
|
||||||
return b, nil;
|
return b, nil
|
||||||
}
|
}
|
||||||
b = new(Writer);
|
b = new(Writer);
|
||||||
b.buf = make([]byte, size);
|
b.buf = make([]byte, size);
|
||||||
|
|
@ -369,7 +369,7 @@ func NewWriter(wr io.Writer) *Writer {
|
||||||
b, err := NewWriterSize(wr, defaultBufSize);
|
b, err := NewWriterSize(wr, defaultBufSize);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// cannot happen - defaultBufSize is valid size
|
// cannot happen - defaultBufSize is valid size
|
||||||
panic("bufio: NewWriter: ", err.String());
|
panic("bufio: NewWriter: ", err.String())
|
||||||
}
|
}
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
@ -377,15 +377,15 @@ func NewWriter(wr io.Writer) *Writer {
|
||||||
// Flush writes any buffered data to the underlying io.Writer.
|
// Flush writes any buffered data to the underlying io.Writer.
|
||||||
func (b *Writer) Flush() os.Error {
|
func (b *Writer) Flush() os.Error {
|
||||||
if b.err != nil {
|
if b.err != nil {
|
||||||
return b.err;
|
return b.err
|
||||||
}
|
}
|
||||||
n, e := b.wr.Write(b.buf[0 : b.n]);
|
n, e := b.wr.Write(b.buf[0 : b.n]);
|
||||||
if n < b.n && e == nil {
|
if n < b.n && e == nil {
|
||||||
e = io.ErrShortWrite;
|
e = io.ErrShortWrite
|
||||||
}
|
}
|
||||||
if e != nil {
|
if e != nil {
|
||||||
if n > 0 && n < b.n {
|
if n > 0 && n < b.n {
|
||||||
copySlice(b.buf[0 : b.n - n], b.buf[n : b.n]);
|
copySlice(b.buf[0 : b.n - n], b.buf[n : b.n])
|
||||||
}
|
}
|
||||||
b.n -= n;
|
b.n -= n;
|
||||||
b.err = e;
|
b.err = e;
|
||||||
|
|
@ -407,14 +407,14 @@ func (b *Writer) Buffered() int { return b.n }
|
||||||
// why the write is short.
|
// why the write is short.
|
||||||
func (b *Writer) Write(p []byte) (nn int, err os.Error) {
|
func (b *Writer) Write(p []byte) (nn int, err os.Error) {
|
||||||
if b.err != nil {
|
if b.err != nil {
|
||||||
return 0, b.err;
|
return 0, b.err
|
||||||
}
|
}
|
||||||
nn = 0;
|
nn = 0;
|
||||||
for len(p) > 0 {
|
for len(p) > 0 {
|
||||||
n := b.Available();
|
n := b.Available();
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
if b.Flush(); b.err != nil {
|
if b.Flush(); b.err != nil {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
n = b.Available();
|
n = b.Available();
|
||||||
}
|
}
|
||||||
|
|
@ -425,12 +425,12 @@ func (b *Writer) Write(p []byte) (nn int, err os.Error) {
|
||||||
nn += n;
|
nn += n;
|
||||||
p = p[n:len(p)];
|
p = p[n:len(p)];
|
||||||
if b.err != nil {
|
if b.err != nil {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if n > len(p) {
|
if n > len(p) {
|
||||||
n = len(p);
|
n = len(p)
|
||||||
}
|
}
|
||||||
copySlice(b.buf[b.n : b.n + n], p[0:n]);
|
copySlice(b.buf[b.n : b.n + n], p[0:n]);
|
||||||
b.n += n;
|
b.n += n;
|
||||||
|
|
@ -443,10 +443,10 @@ func (b *Writer) Write(p []byte) (nn int, err os.Error) {
|
||||||
// WriteByte writes a single byte.
|
// WriteByte writes a single byte.
|
||||||
func (b *Writer) WriteByte(c byte) os.Error {
|
func (b *Writer) WriteByte(c byte) os.Error {
|
||||||
if b.err != nil {
|
if b.err != nil {
|
||||||
return b.err;
|
return b.err
|
||||||
}
|
}
|
||||||
if b.Available() <= 0 && b.Flush() != nil {
|
if b.Available() <= 0 && b.Flush() != nil {
|
||||||
return b.err;
|
return b.err
|
||||||
}
|
}
|
||||||
b.buf[b.n] = c;
|
b.buf[b.n] = c;
|
||||||
b.n++;
|
b.n++;
|
||||||
|
|
@ -456,7 +456,7 @@ func (b *Writer) WriteByte(c byte) os.Error {
|
||||||
// WriteString writes a string.
|
// WriteString writes a string.
|
||||||
func (b *Writer) WriteString(s string) os.Error {
|
func (b *Writer) WriteString(s string) os.Error {
|
||||||
if b.err != nil {
|
if b.err != nil {
|
||||||
return b.err;
|
return b.err
|
||||||
}
|
}
|
||||||
// Common case, worth making fast.
|
// Common case, worth making fast.
|
||||||
if b.Available() >= len(s) || len(b.buf) >= len(s) && b.Flush() == nil {
|
if b.Available() >= len(s) || len(b.buf) >= len(s) && b.Flush() == nil {
|
||||||
|
|
@ -467,7 +467,7 @@ func (b *Writer) WriteString(s string) os.Error {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
for i := 0; i < len(s); i++ { // loop over bytes, not runes.
|
for i := 0; i < len(s); i++ { // loop over bytes, not runes.
|
||||||
b.WriteByte(s[i]);
|
b.WriteByte(s[i])
|
||||||
}
|
}
|
||||||
return b.err;
|
return b.err;
|
||||||
}
|
}
|
||||||
|
|
@ -483,5 +483,5 @@ type ReadWriter struct {
|
||||||
|
|
||||||
// NewReadWriter allocates a new ReadWriter that dispatches to r and w.
|
// NewReadWriter allocates a new ReadWriter that dispatches to r and w.
|
||||||
func NewReadWriter(r *Reader, w *Writer) *ReadWriter {
|
func NewReadWriter(r *Reader, w *Writer) *ReadWriter {
|
||||||
return &ReadWriter{r, w};
|
return &ReadWriter{r, w}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,14 +28,14 @@ func newRot13Reader(r io.Reader) *rot13Reader {
|
||||||
func (r13 *rot13Reader) Read(p []byte) (int, os.Error) {
|
func (r13 *rot13Reader) Read(p []byte) (int, os.Error) {
|
||||||
n, e := r13.r.Read(p);
|
n, e := r13.r.Read(p);
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return n, e;
|
return n, e
|
||||||
}
|
}
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
c := p[i]|0x20; // lowercase byte
|
c := p[i]|0x20; // lowercase byte
|
||||||
if 'a' <= c && c <= 'm' {
|
if 'a' <= c && c <= 'm' {
|
||||||
p[i] += 13;
|
p[i] += 13
|
||||||
} else if 'n' <= c && c <= 'z' {
|
} else if 'n' <= c && c <= 'z' {
|
||||||
p[i] -= 13;
|
p[i] -= 13
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return n, nil;
|
return n, nil;
|
||||||
|
|
@ -48,10 +48,10 @@ func readBytes(buf *Reader) string {
|
||||||
for {
|
for {
|
||||||
c, e := buf.ReadByte();
|
c, e := buf.ReadByte();
|
||||||
if e == os.EOF {
|
if e == os.EOF {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
if e != nil {
|
if e != nil {
|
||||||
panic("Data: " + e.String());
|
panic("Data: " + e.String())
|
||||||
}
|
}
|
||||||
b[nb] = c;
|
b[nb] = c;
|
||||||
nb++;
|
nb++;
|
||||||
|
|
@ -63,12 +63,12 @@ func TestReaderSimple(t *testing.T) {
|
||||||
data := "hello world";
|
data := "hello world";
|
||||||
b := NewReader(bytes.NewBufferString(data));
|
b := NewReader(bytes.NewBufferString(data));
|
||||||
if s := readBytes(b); s != "hello world" {
|
if s := readBytes(b); s != "hello world" {
|
||||||
t.Errorf("simple hello world test failed: got %q", s);
|
t.Errorf("simple hello world test failed: got %q", s)
|
||||||
}
|
}
|
||||||
|
|
||||||
b = NewReader(newRot13Reader(bytes.NewBufferString(data)));
|
b = NewReader(newRot13Reader(bytes.NewBufferString(data)));
|
||||||
if s := readBytes(b); s != "uryyb jbeyq" {
|
if s := readBytes(b); s != "uryyb jbeyq" {
|
||||||
t.Error("rot13 hello world test failed: got %q", s);
|
t.Error("rot13 hello world test failed: got %q", s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,10 +92,10 @@ func readLines(b *Reader) string {
|
||||||
for {
|
for {
|
||||||
s1, e := b.ReadString('\n');
|
s1, e := b.ReadString('\n');
|
||||||
if e == os.EOF {
|
if e == os.EOF {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
if e != nil {
|
if e != nil {
|
||||||
panic("GetLines: " + e.String());
|
panic("GetLines: " + e.String())
|
||||||
}
|
}
|
||||||
s += s1;
|
s += s1;
|
||||||
}
|
}
|
||||||
|
|
@ -110,7 +110,7 @@ func reads(buf *Reader, m int) string {
|
||||||
n, e := buf.Read(b[nb : nb+m]);
|
n, e := buf.Read(b[nb : nb+m]);
|
||||||
nb += n;
|
nb += n;
|
||||||
if e == os.EOF {
|
if e == os.EOF {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return string(b[0:nb]);
|
return string(b[0:nb]);
|
||||||
|
|
@ -161,7 +161,7 @@ func TestReader(t *testing.T) {
|
||||||
s := bufreader.fn(buf);
|
s := bufreader.fn(buf);
|
||||||
if s != text {
|
if s != text {
|
||||||
t.Errorf("reader=%s fn=%s bufsize=%d want=%q got=%q",
|
t.Errorf("reader=%s fn=%s bufsize=%d want=%q got=%q",
|
||||||
readmaker.name, bufreader.name, bufsize, text, s);
|
readmaker.name, bufreader.name, bufsize, text, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -179,12 +179,12 @@ func (r *StringReader) Read(p []byte) (n int, err os.Error) {
|
||||||
if r.step < len(r.data) {
|
if r.step < len(r.data) {
|
||||||
s := r.data[r.step];
|
s := r.data[r.step];
|
||||||
for i := 0; i < len(s); i++ {
|
for i := 0; i < len(s); i++ {
|
||||||
p[i] = s[i];
|
p[i] = s[i]
|
||||||
}
|
}
|
||||||
n = len(s);
|
n = len(s);
|
||||||
r.step++;
|
r.step++;
|
||||||
} else {
|
} else {
|
||||||
err = os.EOF;
|
err = os.EOF
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -197,14 +197,14 @@ func readRuneSegments(t *testing.T, segments []string) {
|
||||||
rune, _, err := r.ReadRune();
|
rune, _, err := r.ReadRune();
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != os.EOF {
|
if err != os.EOF {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
got += string(rune);
|
got += string(rune);
|
||||||
}
|
}
|
||||||
if got != want {
|
if got != want {
|
||||||
t.Errorf("segments=%v got=%s want=%s", segments, got, want);
|
t.Errorf("segments=%v got=%s want=%s", segments, got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,7 +221,7 @@ var segmentList = [][]string{
|
||||||
|
|
||||||
func TestReadRune(t *testing.T) {
|
func TestReadRune(t *testing.T) {
|
||||||
for _, s := range segmentList {
|
for _, s := range segmentList {
|
||||||
readRuneSegments(t, s);
|
readRuneSegments(t, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -229,7 +229,7 @@ func TestWriter(t *testing.T) {
|
||||||
var data [8192]byte;
|
var data [8192]byte;
|
||||||
|
|
||||||
for i := 0; i < len(data); i++ {
|
for i := 0; i < len(data); i++ {
|
||||||
data[i] = byte(' ' + i%('~'-' '));
|
data[i] = byte(' ' + i%('~'-' '))
|
||||||
}
|
}
|
||||||
w := new(bytes.Buffer);
|
w := new(bytes.Buffer);
|
||||||
for i := 0; i < len(bufsizes); i++ {
|
for i := 0; i < len(bufsizes); i++ {
|
||||||
|
|
@ -254,12 +254,12 @@ func TestWriter(t *testing.T) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if e = buf.Flush(); e != nil {
|
if e = buf.Flush(); e != nil {
|
||||||
t.Errorf("%s: buf.Flush = %v", context, e);
|
t.Errorf("%s: buf.Flush = %v", context, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
written := w.Bytes();
|
written := w.Bytes();
|
||||||
if len(written) != nwrite {
|
if len(written) != nwrite {
|
||||||
t.Errorf("%s: %d bytes written", context, len(written));
|
t.Errorf("%s: %d bytes written", context, len(written))
|
||||||
}
|
}
|
||||||
for l := 0; l < len(written); l++ {
|
for l := 0; l < len(written); l++ {
|
||||||
if written[i] != data[i] {
|
if written[i] != data[i] {
|
||||||
|
|
@ -281,7 +281,7 @@ type errorWriterTest struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w errorWriterTest) Write(p []byte) (int, os.Error) {
|
func (w errorWriterTest) Write(p []byte) (int, os.Error) {
|
||||||
return len(p) * w.n / w.m, w.err;
|
return len(p) * w.n / w.m, w.err
|
||||||
}
|
}
|
||||||
|
|
||||||
var errorWriterTests = []errorWriterTest{
|
var errorWriterTests = []errorWriterTest{
|
||||||
|
|
@ -303,7 +303,7 @@ func TestWriteErrors(t *testing.T) {
|
||||||
}
|
}
|
||||||
e = buf.Flush();
|
e = buf.Flush();
|
||||||
if e != w.expect {
|
if e != w.expect {
|
||||||
t.Errorf("Flush %v: got %v, wanted %v", w, e, w.expect);
|
t.Errorf("Flush %v: got %v, wanted %v", w, e, w.expect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -312,23 +312,23 @@ func TestNewReaderSizeIdempotent(t *testing.T) {
|
||||||
const BufSize = 1000;
|
const BufSize = 1000;
|
||||||
b, err := NewReaderSize(bytes.NewBufferString("hello world"), BufSize);
|
b, err := NewReaderSize(bytes.NewBufferString("hello world"), BufSize);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("NewReaderSize create fail", err);
|
t.Error("NewReaderSize create fail", err)
|
||||||
}
|
}
|
||||||
// Does it recognize itself?
|
// Does it recognize itself?
|
||||||
b1, err2 := NewReaderSize(b, BufSize);
|
b1, err2 := NewReaderSize(b, BufSize);
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
t.Error("NewReaderSize #2 create fail", err2);
|
t.Error("NewReaderSize #2 create fail", err2)
|
||||||
}
|
}
|
||||||
if b1 != b {
|
if b1 != b {
|
||||||
t.Error("NewReaderSize did not detect underlying Reader");
|
t.Error("NewReaderSize did not detect underlying Reader")
|
||||||
}
|
}
|
||||||
// Does it wrap if existing buffer is too small?
|
// Does it wrap if existing buffer is too small?
|
||||||
b2, err3 := NewReaderSize(b, 2*BufSize);
|
b2, err3 := NewReaderSize(b, 2*BufSize);
|
||||||
if err3 != nil {
|
if err3 != nil {
|
||||||
t.Error("NewReaderSize #3 create fail", err3);
|
t.Error("NewReaderSize #3 create fail", err3)
|
||||||
}
|
}
|
||||||
if b2 == b {
|
if b2 == b {
|
||||||
t.Error("NewReaderSize did not enlarge buffer");
|
t.Error("NewReaderSize did not enlarge buffer")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -336,23 +336,23 @@ func TestNewWriterSizeIdempotent(t *testing.T) {
|
||||||
const BufSize = 1000;
|
const BufSize = 1000;
|
||||||
b, err := NewWriterSize(new(bytes.Buffer), BufSize);
|
b, err := NewWriterSize(new(bytes.Buffer), BufSize);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("NewWriterSize create fail", err);
|
t.Error("NewWriterSize create fail", err)
|
||||||
}
|
}
|
||||||
// Does it recognize itself?
|
// Does it recognize itself?
|
||||||
b1, err2 := NewWriterSize(b, BufSize);
|
b1, err2 := NewWriterSize(b, BufSize);
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
t.Error("NewWriterSize #2 create fail", err2);
|
t.Error("NewWriterSize #2 create fail", err2)
|
||||||
}
|
}
|
||||||
if b1 != b {
|
if b1 != b {
|
||||||
t.Error("NewWriterSize did not detect underlying Writer");
|
t.Error("NewWriterSize did not detect underlying Writer")
|
||||||
}
|
}
|
||||||
// Does it wrap if existing buffer is too small?
|
// Does it wrap if existing buffer is too small?
|
||||||
b2, err3 := NewWriterSize(b, 2*BufSize);
|
b2, err3 := NewWriterSize(b, 2*BufSize);
|
||||||
if err3 != nil {
|
if err3 != nil {
|
||||||
t.Error("NewWriterSize #3 create fail", err3);
|
t.Error("NewWriterSize #3 create fail", err3)
|
||||||
}
|
}
|
||||||
if b2 == b {
|
if b2 == b {
|
||||||
t.Error("NewWriterSize did not enlarge buffer");
|
t.Error("NewWriterSize did not enlarge buffer")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -361,7 +361,7 @@ func TestWriteString(t *testing.T) {
|
||||||
buf := new(bytes.Buffer);
|
buf := new(bytes.Buffer);
|
||||||
b, err := NewWriterSize(buf, BufSize);
|
b, err := NewWriterSize(buf, BufSize);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("NewWriterSize create fail", err);
|
t.Error("NewWriterSize create fail", err)
|
||||||
}
|
}
|
||||||
b.WriteString("0"); // easy
|
b.WriteString("0"); // easy
|
||||||
b.WriteString("123456"); // still easy
|
b.WriteString("123456"); // still easy
|
||||||
|
|
@ -370,10 +370,10 @@ func TestWriteString(t *testing.T) {
|
||||||
b.WriteString("z");
|
b.WriteString("z");
|
||||||
b.Flush();
|
b.Flush();
|
||||||
if b.err != nil {
|
if b.err != nil {
|
||||||
t.Error("WriteString", b.err);
|
t.Error("WriteString", b.err)
|
||||||
}
|
}
|
||||||
s := "01234567890abcdefghijklmnopqrstuvwxyz";
|
s := "01234567890abcdefghijklmnopqrstuvwxyz";
|
||||||
if string(buf.Bytes()) != s {
|
if string(buf.Bytes()) != s {
|
||||||
t.Errorf("WriteString wants %q gets %q", s, string(buf.Bytes()));
|
t.Errorf("WriteString wants %q gets %q", s, string(buf.Bytes()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ func (b *Buffer) Bytes() []byte { return b.buf[b.off : len(b.buf)] }
|
||||||
func (b *Buffer) String() string {
|
func (b *Buffer) String() string {
|
||||||
if b == nil {
|
if b == nil {
|
||||||
// Special case, useful in debugging.
|
// Special case, useful in debugging.
|
||||||
return "<nil>";
|
return "<nil>"
|
||||||
}
|
}
|
||||||
return string(b.buf[b.off : len(b.buf)]);
|
return string(b.buf[b.off : len(b.buf)]);
|
||||||
}
|
}
|
||||||
|
|
@ -58,7 +58,7 @@ func (b *Buffer) Len() int { return len(b.buf) - b.off }
|
||||||
func (b *Buffer) Truncate(n int) {
|
func (b *Buffer) Truncate(n int) {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
// Reuse buffer space.
|
// Reuse buffer space.
|
||||||
b.off = 0;
|
b.off = 0
|
||||||
}
|
}
|
||||||
b.buf = b.buf[0 : b.off + n];
|
b.buf = b.buf[0 : b.off + n];
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +78,7 @@ func (b *Buffer) Write(p []byte) (n int, err os.Error) {
|
||||||
buf := b.buf;
|
buf := b.buf;
|
||||||
if m+n > cap(b.buf) {
|
if m+n > cap(b.buf) {
|
||||||
// not enough space anywhere
|
// not enough space anywhere
|
||||||
buf = make([]byte, 2*cap(b.buf) + n);
|
buf = make([]byte, 2*cap(b.buf) + n)
|
||||||
}
|
}
|
||||||
copyBytes(buf, 0, b.buf[b.off : b.off + m]);
|
copyBytes(buf, 0, b.buf[b.off : b.off + m]);
|
||||||
b.buf = buf;
|
b.buf = buf;
|
||||||
|
|
@ -101,7 +101,7 @@ func (b *Buffer) WriteString(s string) (n int, err os.Error) {
|
||||||
buf := b.buf;
|
buf := b.buf;
|
||||||
if m+n > cap(b.buf) {
|
if m+n > cap(b.buf) {
|
||||||
// not enough space anywhere
|
// not enough space anywhere
|
||||||
buf = make([]byte, 2*cap(b.buf) + n);
|
buf = make([]byte, 2*cap(b.buf) + n)
|
||||||
}
|
}
|
||||||
copyBytes(buf, 0, b.buf[b.off : b.off + m]);
|
copyBytes(buf, 0, b.buf[b.off : b.off + m]);
|
||||||
b.buf = buf;
|
b.buf = buf;
|
||||||
|
|
@ -119,7 +119,7 @@ func (b *Buffer) WriteString(s string) (n int, err os.Error) {
|
||||||
func (b *Buffer) WriteByte(c byte) os.Error {
|
func (b *Buffer) WriteByte(c byte) os.Error {
|
||||||
if b.oneByte == nil {
|
if b.oneByte == nil {
|
||||||
// Only happens once per Buffer, and then we have a slice.
|
// Only happens once per Buffer, and then we have a slice.
|
||||||
b.oneByte = make([]byte, 1);
|
b.oneByte = make([]byte, 1)
|
||||||
}
|
}
|
||||||
b.oneByte[0] = c;
|
b.oneByte[0] = c;
|
||||||
b.Write(b.oneByte);
|
b.Write(b.oneByte);
|
||||||
|
|
@ -132,14 +132,14 @@ func (b *Buffer) WriteByte(c byte) os.Error {
|
||||||
// otherwise it is nil.
|
// otherwise it is nil.
|
||||||
func (b *Buffer) Read(p []byte) (n int, err os.Error) {
|
func (b *Buffer) Read(p []byte) (n int, err os.Error) {
|
||||||
if b.off >= len(b.buf) {
|
if b.off >= len(b.buf) {
|
||||||
return 0, os.EOF;
|
return 0, os.EOF
|
||||||
}
|
}
|
||||||
m := b.Len();
|
m := b.Len();
|
||||||
n = len(p);
|
n = len(p);
|
||||||
|
|
||||||
if n > m {
|
if n > m {
|
||||||
// more bytes requested than available
|
// more bytes requested than available
|
||||||
n = m;
|
n = m
|
||||||
}
|
}
|
||||||
|
|
||||||
copyBytes(p, 0, b.buf[b.off : b.off + n]);
|
copyBytes(p, 0, b.buf[b.off : b.off + n]);
|
||||||
|
|
@ -151,7 +151,7 @@ func (b *Buffer) Read(p []byte) (n int, err os.Error) {
|
||||||
// If no byte is available, it returns error os.EOF.
|
// If no byte is available, it returns error os.EOF.
|
||||||
func (b *Buffer) ReadByte() (c byte, err os.Error) {
|
func (b *Buffer) ReadByte() (c byte, err os.Error) {
|
||||||
if b.off >= len(b.buf) {
|
if b.off >= len(b.buf) {
|
||||||
return 0, os.EOF;
|
return 0, os.EOF
|
||||||
}
|
}
|
||||||
c = b.buf[b.off];
|
c = b.buf[b.off];
|
||||||
b.off++;
|
b.off++;
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ var bytes []byte // test data; same as data but as a slice.
|
||||||
func init() {
|
func init() {
|
||||||
bytes = make([]byte, N);
|
bytes = make([]byte, N);
|
||||||
for i := 0; i < N; i++ {
|
for i := 0; i < N; i++ {
|
||||||
bytes[i] = 'a'+byte(i%26);
|
bytes[i] = 'a'+byte(i%26)
|
||||||
}
|
}
|
||||||
data = string(bytes);
|
data = string(bytes);
|
||||||
}
|
}
|
||||||
|
|
@ -29,19 +29,19 @@ func check(t *testing.T, testname string, buf *Buffer, s string) {
|
||||||
bytes := buf.Bytes();
|
bytes := buf.Bytes();
|
||||||
str := buf.String();
|
str := buf.String();
|
||||||
if buf.Len() != len(bytes) {
|
if buf.Len() != len(bytes) {
|
||||||
t.Errorf("%s: buf.Len() == %d, len(buf.Bytes()) == %d\n", testname, buf.Len(), len(bytes));
|
t.Errorf("%s: buf.Len() == %d, len(buf.Bytes()) == %d\n", testname, buf.Len(), len(bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
if buf.Len() != len(str) {
|
if buf.Len() != len(str) {
|
||||||
t.Errorf("%s: buf.Len() == %d, len(buf.String()) == %d\n", testname, buf.Len(), len(str));
|
t.Errorf("%s: buf.Len() == %d, len(buf.String()) == %d\n", testname, buf.Len(), len(str))
|
||||||
}
|
}
|
||||||
|
|
||||||
if buf.Len() != len(s) {
|
if buf.Len() != len(s) {
|
||||||
t.Errorf("%s: buf.Len() == %d, len(s) == %d\n", testname, buf.Len(), len(s));
|
t.Errorf("%s: buf.Len() == %d, len(s) == %d\n", testname, buf.Len(), len(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
if string(bytes) != s {
|
if string(bytes) != s {
|
||||||
t.Errorf("%s: string(buf.Bytes()) == %q, s == %q\n", testname, string(bytes), s);
|
t.Errorf("%s: string(buf.Bytes()) == %q, s == %q\n", testname, string(bytes), s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,10 +54,10 @@ func fillString(t *testing.T, testname string, buf *Buffer, s string, n int, fus
|
||||||
for ; n > 0; n-- {
|
for ; n > 0; n-- {
|
||||||
m, err := buf.WriteString(fus);
|
m, err := buf.WriteString(fus);
|
||||||
if m != len(fus) {
|
if m != len(fus) {
|
||||||
t.Errorf(testname + " (fill 2): m == %d, expected %d\n", m, len(fus));
|
t.Errorf(testname + " (fill 2): m == %d, expected %d\n", m, len(fus))
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(testname + " (fill 3): err should always be nil, found err == %s\n", err);
|
t.Errorf(testname + " (fill 3): err should always be nil, found err == %s\n", err)
|
||||||
}
|
}
|
||||||
s += fus;
|
s += fus;
|
||||||
check(t, testname + " (fill 4)", buf, s);
|
check(t, testname + " (fill 4)", buf, s);
|
||||||
|
|
@ -74,10 +74,10 @@ func fillBytes(t *testing.T, testname string, buf *Buffer, s string, n int, fub
|
||||||
for ; n > 0; n-- {
|
for ; n > 0; n-- {
|
||||||
m, err := buf.Write(fub);
|
m, err := buf.Write(fub);
|
||||||
if m != len(fub) {
|
if m != len(fub) {
|
||||||
t.Errorf(testname + " (fill 2): m == %d, expected %d\n", m, len(fub));
|
t.Errorf(testname + " (fill 2): m == %d, expected %d\n", m, len(fub))
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(testname + " (fill 3): err should always be nil, found err == %s\n", err);
|
t.Errorf(testname + " (fill 3): err should always be nil, found err == %s\n", err)
|
||||||
}
|
}
|
||||||
s += string(fub);
|
s += string(fub);
|
||||||
check(t, testname + " (fill 4)", buf, s);
|
check(t, testname + " (fill 4)", buf, s);
|
||||||
|
|
@ -106,10 +106,10 @@ func empty(t *testing.T, testname string, buf *Buffer, s string, fub []byte) {
|
||||||
for {
|
for {
|
||||||
n, err := buf.Read(fub);
|
n, err := buf.Read(fub);
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(testname + " (empty 2): err should always be nil, found err == %s\n", err);
|
t.Errorf(testname + " (empty 2): err should always be nil, found err == %s\n", err)
|
||||||
}
|
}
|
||||||
s = s[n:len(s)];
|
s = s[n:len(s)];
|
||||||
check(t, testname + " (empty 3)", buf, s);
|
check(t, testname + " (empty 3)", buf, s);
|
||||||
|
|
@ -133,10 +133,10 @@ func TestBasicOperations(t *testing.T) {
|
||||||
|
|
||||||
n, err := buf.Write(Bytes(data[0:1]));
|
n, err := buf.Write(Bytes(data[0:1]));
|
||||||
if n != 1 {
|
if n != 1 {
|
||||||
t.Errorf("wrote 1 byte, but n == %d\n", n);
|
t.Errorf("wrote 1 byte, but n == %d\n", n)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("err should always be nil, but err == %s\n", err);
|
t.Errorf("err should always be nil, but err == %s\n", err)
|
||||||
}
|
}
|
||||||
check(t, "TestBasicOperations (4)", &buf, "a");
|
check(t, "TestBasicOperations (4)", &buf, "a");
|
||||||
|
|
||||||
|
|
@ -145,7 +145,7 @@ func TestBasicOperations(t *testing.T) {
|
||||||
|
|
||||||
n, err = buf.Write(Bytes(data[2:26]));
|
n, err = buf.Write(Bytes(data[2:26]));
|
||||||
if n != 24 {
|
if n != 24 {
|
||||||
t.Errorf("wrote 25 bytes, but n == %d\n", n);
|
t.Errorf("wrote 25 bytes, but n == %d\n", n)
|
||||||
}
|
}
|
||||||
check(t, "TestBasicOperations (6)", &buf, string(data[0:26]));
|
check(t, "TestBasicOperations (6)", &buf, string(data[0:26]));
|
||||||
|
|
||||||
|
|
@ -161,14 +161,14 @@ func TestBasicOperations(t *testing.T) {
|
||||||
buf.WriteByte(data[1]);
|
buf.WriteByte(data[1]);
|
||||||
c, err := buf.ReadByte();
|
c, err := buf.ReadByte();
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("ReadByte unexpected eof\n");
|
t.Errorf("ReadByte unexpected eof\n")
|
||||||
}
|
}
|
||||||
if c != data[1] {
|
if c != data[1] {
|
||||||
t.Errorf("ReadByte wrong value c=%v\n", c);
|
t.Errorf("ReadByte wrong value c=%v\n", c)
|
||||||
}
|
}
|
||||||
c, err = buf.ReadByte();
|
c, err = buf.ReadByte();
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("ReadByte unexpected not eof\n");
|
t.Errorf("ReadByte unexpected not eof\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -220,9 +220,9 @@ func TestMixedReadsAndWrites(t *testing.T) {
|
||||||
for i := 0; i < 50; i++ {
|
for i := 0; i < 50; i++ {
|
||||||
wlen := rand.Intn(len(data));
|
wlen := rand.Intn(len(data));
|
||||||
if i%2 == 0 {
|
if i%2 == 0 {
|
||||||
s = fillString(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, data[0:wlen]);
|
s = fillString(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, data[0:wlen])
|
||||||
} else {
|
} else {
|
||||||
s = fillBytes(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, bytes[0:wlen]);
|
s = fillBytes(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, bytes[0:wlen])
|
||||||
}
|
}
|
||||||
|
|
||||||
rlen := rand.Intn(len(data));
|
rlen := rand.Intn(len(data));
|
||||||
|
|
@ -237,6 +237,6 @@ func TestMixedReadsAndWrites(t *testing.T) {
|
||||||
func TestNil(t *testing.T) {
|
func TestNil(t *testing.T) {
|
||||||
var b *Buffer;
|
var b *Buffer;
|
||||||
if b.String() != "<nil>" {
|
if b.String() != "<nil>" {
|
||||||
t.Error("expcted <nil>; got %q", b.String());
|
t.Error("expcted <nil>; got %q", b.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,16 @@ func Compare(a, b []byte) int {
|
||||||
for i := 0; i < len(a) && i < len(b); i++ {
|
for i := 0; i < len(a) && i < len(b); i++ {
|
||||||
switch {
|
switch {
|
||||||
case a[i] > b[i]:
|
case a[i] > b[i]:
|
||||||
return 1;
|
return 1
|
||||||
case a[i] < b[i]:
|
case a[i] < b[i]:
|
||||||
return -1;
|
return -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case len(a) < len(b):
|
case len(a) < len(b):
|
||||||
return -1;
|
return -1
|
||||||
case len(a) > len(b):
|
case len(a) > len(b):
|
||||||
return 1;
|
return 1
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -34,11 +34,11 @@ 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 {
|
||||||
if len(a) != len(b) {
|
if len(a) != len(b) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
for i := 0; i < len(a); i++ {
|
for i := 0; i < len(a); i++ {
|
||||||
if a[i] != b[i] {
|
if a[i] != b[i] {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -50,10 +50,10 @@ func Equal(a, b []byte) bool {
|
||||||
// It returns the number of bytes copied.
|
// It returns the number of bytes copied.
|
||||||
func Copy(dst, src []byte) int {
|
func Copy(dst, src []byte) int {
|
||||||
if len(src) > len(dst) {
|
if len(src) > len(dst) {
|
||||||
src = src[0:len(dst)];
|
src = src[0:len(dst)]
|
||||||
}
|
}
|
||||||
for i, x := range src {
|
for i, x := range src {
|
||||||
dst[i] = x;
|
dst[i] = x
|
||||||
}
|
}
|
||||||
return len(src);
|
return len(src);
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +62,7 @@ func Copy(dst, src []byte) int {
|
||||||
// up to a maximum of n byte arrays. Invalid UTF-8 sequences are chopped into individual bytes.
|
// up to a maximum of n byte arrays. Invalid UTF-8 sequences are chopped into individual bytes.
|
||||||
func explode(s []byte, n int) [][]byte {
|
func explode(s []byte, n int) [][]byte {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
n = len(s);
|
n = len(s)
|
||||||
}
|
}
|
||||||
a := make([][]byte, n);
|
a := make([][]byte, n);
|
||||||
var size int;
|
var size int;
|
||||||
|
|
@ -84,7 +84,7 @@ 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 {
|
if len(sep) == 0 {
|
||||||
return utf8.RuneCount(s) + 1;
|
return utf8.RuneCount(s) + 1
|
||||||
}
|
}
|
||||||
c := sep[0];
|
c := sep[0];
|
||||||
n := 0;
|
n := 0;
|
||||||
|
|
@ -101,12 +101,12 @@ func Count(s, sep []byte) int {
|
||||||
func Index(s, sep []byte) int {
|
func Index(s, sep []byte) int {
|
||||||
n := len(sep);
|
n := len(sep);
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
c := sep[0];
|
c := sep[0];
|
||||||
for i := 0; i+n <= len(s); i++ {
|
for i := 0; i+n <= len(s); i++ {
|
||||||
if s[i] == c && (n == 1 || Equal(s[i : i+n], sep)) {
|
if s[i] == c && (n == 1 || Equal(s[i : i+n], sep)) {
|
||||||
return i;
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -116,12 +116,12 @@ func Index(s, sep []byte) int {
|
||||||
func LastIndex(s, sep []byte) int {
|
func LastIndex(s, sep []byte) int {
|
||||||
n := len(sep);
|
n := len(sep);
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return len(s);
|
return len(s)
|
||||||
}
|
}
|
||||||
c := sep[0];
|
c := sep[0];
|
||||||
for i := len(s)-n; i >= 0; i-- {
|
for i := len(s)-n; i >= 0; i-- {
|
||||||
if s[i] == c && (n == 1 || Equal(s[i : i+n], sep)) {
|
if s[i] == c && (n == 1 || Equal(s[i : i+n], sep)) {
|
||||||
return i;
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -131,10 +131,10 @@ func LastIndex(s, sep []byte) int {
|
||||||
// including sepSave bytes of sep in the subarrays.
|
// including sepSave bytes of sep in the subarrays.
|
||||||
func genSplit(s, sep []byte, sepSave, n int) [][]byte {
|
func genSplit(s, sep []byte, sepSave, n int) [][]byte {
|
||||||
if len(sep) == 0 {
|
if len(sep) == 0 {
|
||||||
return explode(s, n);
|
return explode(s, n)
|
||||||
}
|
}
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
n = Count(s, sep) + 1;
|
n = Count(s, sep) + 1
|
||||||
}
|
}
|
||||||
c := sep[0];
|
c := sep[0];
|
||||||
start := 0;
|
start := 0;
|
||||||
|
|
@ -162,21 +162,21 @@ func Split(s, sep []byte, n int) [][]byte { return genSplit(s, sep, 0, n) }
|
||||||
// If n > 0, SplitAfter splits s into at most n subarrays; the last subarray will contain an
|
// If n > 0, SplitAfter splits s into at most n subarrays; the last subarray will contain an
|
||||||
// unsplit remainder.
|
// unsplit remainder.
|
||||||
func SplitAfter(s, sep []byte, n int) [][]byte {
|
func SplitAfter(s, sep []byte, n int) [][]byte {
|
||||||
return genSplit(s, sep, len(sep), n);
|
return genSplit(s, sep, len(sep), n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Join concatenates the elements of a to create a single byte array. The separator
|
// Join concatenates the elements of a to create a single byte array. The separator
|
||||||
// sep is placed between elements in the resulting array.
|
// sep is placed between elements in the resulting array.
|
||||||
func Join(a [][]byte, sep []byte) []byte {
|
func Join(a [][]byte, sep []byte) []byte {
|
||||||
if len(a) == 0 {
|
if len(a) == 0 {
|
||||||
return []byte{};
|
return []byte{}
|
||||||
}
|
}
|
||||||
if len(a) == 1 {
|
if len(a) == 1 {
|
||||||
return a[0];
|
return a[0]
|
||||||
}
|
}
|
||||||
n := len(sep)*(len(a)-1);
|
n := len(sep)*(len(a)-1);
|
||||||
for i := 0; i < len(a); i++ {
|
for i := 0; i < len(a); i++ {
|
||||||
n += len(a[i]);
|
n += len(a[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
b := make([]byte, n);
|
b := make([]byte, n);
|
||||||
|
|
@ -200,12 +200,12 @@ func Join(a [][]byte, sep []byte) []byte {
|
||||||
|
|
||||||
// HasPrefix tests whether the byte array s begins with prefix.
|
// HasPrefix tests whether the byte array s begins with prefix.
|
||||||
func HasPrefix(s, prefix []byte) bool {
|
func HasPrefix(s, prefix []byte) bool {
|
||||||
return len(s) >= len(prefix) && Equal(s[0:len(prefix)], prefix);
|
return len(s) >= len(prefix) && Equal(s[0:len(prefix)], prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasSuffix tests whether the byte array s ends with suffix.
|
// HasSuffix tests whether the byte array s ends with suffix.
|
||||||
func HasSuffix(s, suffix []byte) bool {
|
func HasSuffix(s, suffix []byte) bool {
|
||||||
return len(s) >= len(suffix) && Equal(s[len(s)-len(suffix) : len(s)], suffix);
|
return len(s) >= len(suffix) && Equal(s[len(s)-len(suffix) : len(s)], suffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map returns a copy of the byte array s with all its characters modified
|
// Map returns a copy of the byte array s with all its characters modified
|
||||||
|
|
@ -221,9 +221,9 @@ func Map(mapping func(rune int) int, s []byte) []byte {
|
||||||
wid := 1;
|
wid := 1;
|
||||||
rune := int(s[i]);
|
rune := int(s[i]);
|
||||||
if rune < utf8.RuneSelf {
|
if rune < utf8.RuneSelf {
|
||||||
rune = mapping(rune);
|
rune = mapping(rune)
|
||||||
} else {
|
} else {
|
||||||
rune, wid = utf8.DecodeRune(s[i:len(s)]);
|
rune, wid = utf8.DecodeRune(s[i:len(s)])
|
||||||
}
|
}
|
||||||
rune = mapping(rune);
|
rune = mapping(rune);
|
||||||
if nbytes + utf8.RuneLen(rune) > maxbytes {
|
if nbytes + utf8.RuneLen(rune) > maxbytes {
|
||||||
|
|
@ -231,7 +231,7 @@ func Map(mapping func(rune int) int, s []byte) []byte {
|
||||||
maxbytes = maxbytes*2 + utf8.UTFMax;
|
maxbytes = maxbytes*2 + utf8.UTFMax;
|
||||||
nb := make([]byte, maxbytes);
|
nb := make([]byte, maxbytes);
|
||||||
for i, c := range b[0:nbytes] {
|
for i, c := range b[0:nbytes] {
|
||||||
nb[i] = c;
|
nb[i] = c
|
||||||
}
|
}
|
||||||
b = nb;
|
b = nb;
|
||||||
}
|
}
|
||||||
|
|
@ -258,10 +258,10 @@ func TrimSpace(s []byte) []byte {
|
||||||
wid := 1;
|
wid := 1;
|
||||||
rune := int(s[start]);
|
rune := int(s[start]);
|
||||||
if rune >= utf8.RuneSelf {
|
if rune >= utf8.RuneSelf {
|
||||||
rune, wid = utf8.DecodeRune(s[start:end]);
|
rune, wid = utf8.DecodeRune(s[start:end])
|
||||||
}
|
}
|
||||||
if !unicode.IsSpace(rune) {
|
if !unicode.IsSpace(rune) {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
start += wid;
|
start += wid;
|
||||||
}
|
}
|
||||||
|
|
@ -273,12 +273,12 @@ func TrimSpace(s []byte) []byte {
|
||||||
for wid = 2; start <= end-wid && !utf8.RuneStart(s[end-wid]); wid++ {
|
for wid = 2; start <= end-wid && !utf8.RuneStart(s[end-wid]); wid++ {
|
||||||
}
|
}
|
||||||
if start > end-wid { // invalid UTF-8 sequence; stop processing
|
if start > end-wid { // invalid UTF-8 sequence; stop processing
|
||||||
return s[start:end];
|
return s[start:end]
|
||||||
}
|
}
|
||||||
rune, wid = utf8.DecodeRune(s[end-wid : end]);
|
rune, wid = utf8.DecodeRune(s[end-wid : end]);
|
||||||
}
|
}
|
||||||
if !unicode.IsSpace(rune) {
|
if !unicode.IsSpace(rune) {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
end -= wid;
|
end -= wid;
|
||||||
}
|
}
|
||||||
|
|
@ -289,7 +289,7 @@ func TrimSpace(s []byte) []byte {
|
||||||
// Heuristic: Scale by 50% to give n log n time.
|
// Heuristic: Scale by 50% to give n log n time.
|
||||||
func resize(n int) int {
|
func resize(n int) int {
|
||||||
if n < 16 {
|
if n < 16 {
|
||||||
n = 16;
|
n = 16
|
||||||
}
|
}
|
||||||
return n + n/2;
|
return n + n/2;
|
||||||
}
|
}
|
||||||
|
|
@ -301,7 +301,7 @@ func Add(s, t []byte) []byte {
|
||||||
lens := len(s);
|
lens := len(s);
|
||||||
lent := len(t);
|
lent := len(t);
|
||||||
if lens+lent <= cap(s) {
|
if lens+lent <= cap(s) {
|
||||||
s = s[0 : lens+lent];
|
s = s[0 : lens+lent]
|
||||||
} else {
|
} else {
|
||||||
news := make([]byte, lens+lent, resize(lens+lent));
|
news := make([]byte, lens+lent, resize(lens+lent));
|
||||||
Copy(news, s);
|
Copy(news, s);
|
||||||
|
|
@ -317,7 +317,7 @@ func Add(s, t []byte) []byte {
|
||||||
func AddByte(s []byte, t byte) []byte {
|
func AddByte(s []byte, t byte) []byte {
|
||||||
lens := len(s);
|
lens := len(s);
|
||||||
if lens+1 <= cap(s) {
|
if lens+1 <= cap(s) {
|
||||||
s = s[0 : lens+1];
|
s = s[0 : lens+1]
|
||||||
} else {
|
} else {
|
||||||
news := make([]byte, lens+1, resize(lens+1));
|
news := make([]byte, lens+1, resize(lens+1));
|
||||||
Copy(news, s);
|
Copy(news, s);
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,11 @@ import (
|
||||||
|
|
||||||
func eq(a, b []string) bool {
|
func eq(a, b []string) bool {
|
||||||
if len(a) != len(b) {
|
if len(a) != len(b) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
for i := 0; i < len(a); i++ {
|
for i := 0; i < len(a); i++ {
|
||||||
if a[i] != b[i] {
|
if a[i] != b[i] {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -26,7 +26,7 @@ func eq(a, b []string) bool {
|
||||||
func arrayOfString(a [][]byte) []string {
|
func arrayOfString(a [][]byte) []string {
|
||||||
result := make([]string, len(a));
|
result := make([]string, len(a));
|
||||||
for j := 0; j < len(a); j++ {
|
for j := 0; j < len(a); j++ {
|
||||||
result[j] = string(a[j]);
|
result[j] = string(a[j])
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -66,10 +66,10 @@ func TestCompare(t *testing.T) {
|
||||||
cmp := Compare(a, b);
|
cmp := Compare(a, b);
|
||||||
eql := Equal(a, b);
|
eql := Equal(a, b);
|
||||||
if cmp != tt.cmp {
|
if cmp != tt.cmp {
|
||||||
t.Errorf(`Compare(%q, %q) = %v`, tt.a, tt.b, cmp);
|
t.Errorf(`Compare(%q, %q) = %v`, tt.a, tt.b, cmp)
|
||||||
}
|
}
|
||||||
if eql != (tt.cmp == 0) {
|
if eql != (tt.cmp == 0) {
|
||||||
t.Errorf(`Equal(%q, %q) = %v`, tt.a, tt.b, eql);
|
t.Errorf(`Equal(%q, %q) = %v`, tt.a, tt.b, eql)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +97,7 @@ func TestExplode(t *testing.T) {
|
||||||
}
|
}
|
||||||
s := Join(a, []byte{});
|
s := Join(a, []byte{});
|
||||||
if string(s) != tt.s {
|
if string(s) != tt.s {
|
||||||
t.Errorf(`Join(Explode("%s", %d), "") = "%s"`, tt.s, tt.n, s);
|
t.Errorf(`Join(Explode("%s", %d), "") = "%s"`, tt.s, tt.n, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +136,7 @@ func TestSplit(t *testing.T) {
|
||||||
}
|
}
|
||||||
s := Join(a, strings.Bytes(tt.sep));
|
s := Join(a, strings.Bytes(tt.sep));
|
||||||
if string(s) != tt.s {
|
if string(s) != tt.s {
|
||||||
t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s);
|
t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -167,7 +167,7 @@ func TestSplitAfter(t *testing.T) {
|
||||||
}
|
}
|
||||||
s := Join(a, nil);
|
s := Join(a, nil);
|
||||||
if string(s) != tt.s {
|
if string(s) != tt.s {
|
||||||
t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s);
|
t.Errorf(`Join(Split(%q, %q, %d), %q) = %q`, tt.s, tt.sep, tt.n, tt.sep, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -244,7 +244,7 @@ var trimSpaceTests = []StringTest{
|
||||||
func Bytes(s string) []byte {
|
func Bytes(s string) []byte {
|
||||||
b := make([]byte, len(s));
|
b := make([]byte, len(s));
|
||||||
for i := 0; i < len(s); i++ {
|
for i := 0; i < len(s); i++ {
|
||||||
b[i] = s[i];
|
b[i] = s[i]
|
||||||
}
|
}
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
@ -255,7 +255,7 @@ func runStringTests(t *testing.T, f func([]byte) []byte, funcName string, testCa
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
actual := string(f(Bytes(tc.in)));
|
actual := string(f(Bytes(tc.in)));
|
||||||
if actual != tc.out {
|
if actual != tc.out {
|
||||||
t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out);
|
t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -263,7 +263,7 @@ func runStringTests(t *testing.T, f func([]byte) []byte, funcName string, testCa
|
||||||
func tenRunes(rune int) string {
|
func tenRunes(rune int) string {
|
||||||
r := make([]int, 10);
|
r := make([]int, 10);
|
||||||
for i := range r {
|
for i := range r {
|
||||||
r[i] = rune;
|
r[i] = rune
|
||||||
}
|
}
|
||||||
return string(r);
|
return string(r);
|
||||||
}
|
}
|
||||||
|
|
@ -276,14 +276,14 @@ func TestMap(t *testing.T) {
|
||||||
m := Map(maxRune, Bytes(a));
|
m := Map(maxRune, Bytes(a));
|
||||||
expect := tenRunes(unicode.MaxRune);
|
expect := tenRunes(unicode.MaxRune);
|
||||||
if string(m) != expect {
|
if string(m) != expect {
|
||||||
t.Errorf("growing: expected %q got %q", expect, m);
|
t.Errorf("growing: expected %q got %q", expect, m)
|
||||||
}
|
}
|
||||||
// 2. Shrink
|
// 2. Shrink
|
||||||
minRune := func(rune int) int { return 'a' };
|
minRune := func(rune int) int { return 'a' };
|
||||||
m = Map(minRune, Bytes(tenRunes(unicode.MaxRune)));
|
m = Map(minRune, Bytes(tenRunes(unicode.MaxRune)));
|
||||||
expect = a;
|
expect = a;
|
||||||
if string(m) != expect {
|
if string(m) != expect {
|
||||||
t.Errorf("shrinking: expected %q got %q", expect, m);
|
t.Errorf("shrinking: expected %q got %q", expect, m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -309,11 +309,11 @@ func TestAdd(t *testing.T) {
|
||||||
for _, test := range addtests {
|
for _, test := range addtests {
|
||||||
b := make([]byte, len(test.s), test.cap);
|
b := make([]byte, len(test.s), test.cap);
|
||||||
for i := 0; i < len(test.s); i++ {
|
for i := 0; i < len(test.s); i++ {
|
||||||
b[i] = test.s[i];
|
b[i] = test.s[i]
|
||||||
}
|
}
|
||||||
b = Add(b, strings.Bytes(test.t));
|
b = Add(b, strings.Bytes(test.t));
|
||||||
if string(b) != test.s + test.t {
|
if string(b) != test.s + test.t {
|
||||||
t.Errorf("Add(%q,%q) = %q", test.s, test.t, string(b));
|
t.Errorf("Add(%q,%q) = %q", test.s, test.t, string(b))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -322,14 +322,14 @@ func TestAddByte(t *testing.T) {
|
||||||
const N = 2e5;
|
const N = 2e5;
|
||||||
b := make([]byte, 0);
|
b := make([]byte, 0);
|
||||||
for i := 0; i < N; i++ {
|
for i := 0; i < N; i++ {
|
||||||
b = AddByte(b, byte(i));
|
b = AddByte(b, byte(i))
|
||||||
}
|
}
|
||||||
if len(b) != N {
|
if len(b) != N {
|
||||||
t.Errorf("AddByte: too small; expected %d got %d", N, len(b));
|
t.Errorf("AddByte: too small; expected %d got %d", N, len(b))
|
||||||
}
|
}
|
||||||
for i, c := range b {
|
for i, c := range b {
|
||||||
if c != byte(i) {
|
if c != byte(i) {
|
||||||
t.Fatalf("AddByte: b[%d] should be %d is %d", i, c, byte(i));
|
t.Fatalf("AddByte: b[%d] should be %d is %d", i, c, byte(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -132,15 +132,15 @@ func (d *deflater) fillWindow(index int) (int, os.Error) {
|
||||||
index -= wSize;
|
index -= wSize;
|
||||||
d.windowEnd -= wSize;
|
d.windowEnd -= wSize;
|
||||||
if d.blockStart >= wSize {
|
if d.blockStart >= wSize {
|
||||||
d.blockStart -= wSize;
|
d.blockStart -= wSize
|
||||||
} else {
|
} else {
|
||||||
d.blockStart = math.MaxInt32;
|
d.blockStart = math.MaxInt32
|
||||||
}
|
}
|
||||||
for i, h := range d.hashHead {
|
for i, h := range d.hashHead {
|
||||||
d.hashHead[i] = max(h-wSize, -1);
|
d.hashHead[i] = max(h-wSize, -1)
|
||||||
}
|
}
|
||||||
for i, h := range d.hashPrev {
|
for i, h := range d.hashPrev {
|
||||||
d.hashPrev[i] = max(h-wSize, -1);
|
d.hashPrev[i] = max(h-wSize, -1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var count int;
|
var count int;
|
||||||
|
|
@ -148,7 +148,7 @@ func (d *deflater) fillWindow(index int) (int, os.Error) {
|
||||||
count, err = io.ReadAtLeast(d.r, d.window[d.windowEnd : len(d.window)], 1);
|
count, err = io.ReadAtLeast(d.r, d.window[d.windowEnd : len(d.window)], 1);
|
||||||
d.windowEnd += count;
|
d.windowEnd += count;
|
||||||
if err == os.EOF {
|
if err == os.EOF {
|
||||||
return index, nil;
|
return index, nil
|
||||||
}
|
}
|
||||||
return index, err;
|
return index, err;
|
||||||
}
|
}
|
||||||
|
|
@ -157,7 +157,7 @@ func (d *deflater) writeBlock(tokens []token, index int, eof bool) os.Error {
|
||||||
if index > 0 || eof {
|
if index > 0 || eof {
|
||||||
var window []byte;
|
var window []byte;
|
||||||
if d.blockStart <= index {
|
if d.blockStart <= index {
|
||||||
window = d.window[d.blockStart : index];
|
window = d.window[d.blockStart : index]
|
||||||
}
|
}
|
||||||
d.blockStart = index;
|
d.blockStart = index;
|
||||||
d.w.writeBlock(tokens, eof, window);
|
d.w.writeBlock(tokens, eof, window);
|
||||||
|
|
@ -178,7 +178,7 @@ func (d *deflater) findMatch(pos int, prevHead int, prevLength int, lookahead in
|
||||||
tries := d.maxChainLength;
|
tries := d.maxChainLength;
|
||||||
length = prevLength;
|
length = prevLength;
|
||||||
if length >= d.goodMatch {
|
if length >= d.goodMatch {
|
||||||
tries >>= 2;
|
tries >>= 2
|
||||||
}
|
}
|
||||||
|
|
||||||
w0 := win[pos];
|
w0 := win[pos];
|
||||||
|
|
@ -192,7 +192,7 @@ func (d *deflater) findMatch(pos int, prevHead int, prevLength int, lookahead in
|
||||||
|
|
||||||
n := 3;
|
n := 3;
|
||||||
for pos+n < len(win) && win[i+n] == win[pos+n] {
|
for pos+n < len(win) && win[i+n] == win[pos+n] {
|
||||||
n++;
|
n++
|
||||||
}
|
}
|
||||||
if n > length && (n > 3 || pos-i <= 4096) {
|
if n > length && (n > 3 || pos-i <= 4096) {
|
||||||
length = n;
|
length = n;
|
||||||
|
|
@ -200,17 +200,17 @@ func (d *deflater) findMatch(pos int, prevHead int, prevLength int, lookahead in
|
||||||
ok = true;
|
ok = true;
|
||||||
if n >= nice {
|
if n >= nice {
|
||||||
// The match is good enough that we don't try to find a better one.
|
// The match is good enough that we don't try to find a better one.
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
wEnd = win[pos+n];
|
wEnd = win[pos+n];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if i == minIndex {
|
if i == minIndex {
|
||||||
// hashPrev[i & windowMask] has already been overwritten, so stop now.
|
// hashPrev[i & windowMask] has already been overwritten, so stop now.
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
if i = d.hashPrev[i & d.windowMask]; i < minIndex || i < 0 {
|
if i = d.hashPrev[i & d.windowMask]; i < minIndex || i < 0 {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -218,7 +218,7 @@ func (d *deflater) findMatch(pos int, prevHead int, prevLength int, lookahead in
|
||||||
|
|
||||||
func (d *deflater) writeStoredBlock(buf []byte) os.Error {
|
func (d *deflater) writeStoredBlock(buf []byte) os.Error {
|
||||||
if d.w.writeStoredHeader(len(buf), false); d.w.err != nil {
|
if d.w.writeStoredHeader(len(buf), false); d.w.err != nil {
|
||||||
return d.w.err;
|
return d.w.err
|
||||||
}
|
}
|
||||||
d.w.writeBytes(buf);
|
d.w.writeBytes(buf);
|
||||||
return d.w.err;
|
return d.w.err;
|
||||||
|
|
@ -230,12 +230,12 @@ func (d *deflater) storedDeflate() os.Error {
|
||||||
n, err := d.r.Read(buf);
|
n, err := d.r.Read(buf);
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
if err := d.writeStoredBlock(buf[0:n]); err != nil {
|
if err := d.writeStoredBlock(buf[0:n]); err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == os.EOF {
|
if err == os.EOF {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
@ -263,7 +263,7 @@ func (d *deflater) doDeflate() (err os.Error) {
|
||||||
index := 0;
|
index := 0;
|
||||||
// run
|
// run
|
||||||
if index, err = d.fillWindow(index); err != nil {
|
if index, err = d.fillWindow(index); err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
maxOffset := d.windowMask + 1; // (1 << logWindowSize);
|
maxOffset := d.windowMask + 1; // (1 << logWindowSize);
|
||||||
// only need to change when you refill the window
|
// only need to change when you refill the window
|
||||||
|
|
@ -273,26 +273,26 @@ func (d *deflater) doDeflate() (err os.Error) {
|
||||||
|
|
||||||
hash := int(0);
|
hash := int(0);
|
||||||
if index < maxInsertIndex {
|
if index < maxInsertIndex {
|
||||||
hash = int(d.window[index]) << hashShift + int(d.window[index+1]);
|
hash = int(d.window[index]) << hashShift + int(d.window[index+1])
|
||||||
}
|
}
|
||||||
chainHead := -1;
|
chainHead := -1;
|
||||||
for {
|
for {
|
||||||
if index > windowEnd {
|
if index > windowEnd {
|
||||||
panic("index > windowEnd");
|
panic("index > windowEnd")
|
||||||
}
|
}
|
||||||
lookahead := windowEnd - index;
|
lookahead := windowEnd - index;
|
||||||
if lookahead < minMatchLength + maxMatchLength {
|
if lookahead < minMatchLength + maxMatchLength {
|
||||||
if index, err = d.fillWindow(index); err != nil {
|
if index, err = d.fillWindow(index); err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
windowEnd = d.windowEnd;
|
windowEnd = d.windowEnd;
|
||||||
if index > windowEnd {
|
if index > windowEnd {
|
||||||
panic("index > windowEnd");
|
panic("index > windowEnd")
|
||||||
}
|
}
|
||||||
maxInsertIndex = windowEnd - (minMatchLength - 1);
|
maxInsertIndex = windowEnd - (minMatchLength - 1);
|
||||||
lookahead = windowEnd - index;
|
lookahead = windowEnd - index;
|
||||||
if lookahead == 0 {
|
if lookahead == 0 {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if index < maxInsertIndex {
|
if index < maxInsertIndex {
|
||||||
|
|
@ -321,9 +321,9 @@ func (d *deflater) doDeflate() (err os.Error) {
|
||||||
// There was a match at the previous step, and the current match is
|
// There was a match at the previous step, and the current match is
|
||||||
// not better. Output the previous match.
|
// not better. Output the previous match.
|
||||||
if isFastDeflate {
|
if isFastDeflate {
|
||||||
tokens[ti] = matchToken(uint32(length - minMatchLength), uint32(offset - minOffsetSize));
|
tokens[ti] = matchToken(uint32(length - minMatchLength), uint32(offset - minOffsetSize))
|
||||||
} else {
|
} else {
|
||||||
tokens[ti] = matchToken(uint32(prevLength - minMatchLength), uint32(prevOffset - minOffsetSize));
|
tokens[ti] = matchToken(uint32(prevLength - minMatchLength), uint32(prevOffset - minOffsetSize))
|
||||||
}
|
}
|
||||||
ti++;
|
ti++;
|
||||||
// Insert in the hash table all strings up to the end of the match.
|
// Insert in the hash table all strings up to the end of the match.
|
||||||
|
|
@ -333,9 +333,9 @@ func (d *deflater) doDeflate() (err os.Error) {
|
||||||
if length <= l.fastSkipHashing {
|
if length <= l.fastSkipHashing {
|
||||||
var newIndex int;
|
var newIndex int;
|
||||||
if isFastDeflate {
|
if isFastDeflate {
|
||||||
newIndex = index+length;
|
newIndex = index+length
|
||||||
} else {
|
} else {
|
||||||
newIndex = prevLength - 1;
|
newIndex = prevLength - 1
|
||||||
}
|
}
|
||||||
for index++; index < newIndex; index++ {
|
for index++; index < newIndex; index++ {
|
||||||
if index < maxInsertIndex {
|
if index < maxInsertIndex {
|
||||||
|
|
@ -360,7 +360,7 @@ func (d *deflater) doDeflate() (err os.Error) {
|
||||||
if ti == maxFlateBlockTokens {
|
if ti == maxFlateBlockTokens {
|
||||||
// The block includes the current character
|
// The block includes the current character
|
||||||
if err = d.writeBlock(tokens, index, false); err != nil {
|
if err = d.writeBlock(tokens, index, false); err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
ti = 0;
|
ti = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -368,20 +368,20 @@ func (d *deflater) doDeflate() (err os.Error) {
|
||||||
if isFastDeflate || byteAvailable {
|
if isFastDeflate || byteAvailable {
|
||||||
i := index-1;
|
i := index-1;
|
||||||
if isFastDeflate {
|
if isFastDeflate {
|
||||||
i = index;
|
i = index
|
||||||
}
|
}
|
||||||
tokens[ti] = literalToken(uint32(d.window[i])&0xFF);
|
tokens[ti] = literalToken(uint32(d.window[i])&0xFF);
|
||||||
ti++;
|
ti++;
|
||||||
if ti == maxFlateBlockTokens {
|
if ti == maxFlateBlockTokens {
|
||||||
if err = d.writeBlock(tokens, i+1, false); err != nil {
|
if err = d.writeBlock(tokens, i+1, false); err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
ti = 0;
|
ti = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
if !isFastDeflate {
|
if !isFastDeflate {
|
||||||
byteAvailable = true;
|
byteAvailable = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -394,7 +394,7 @@ func (d *deflater) doDeflate() (err os.Error) {
|
||||||
|
|
||||||
if ti > 0 {
|
if ti > 0 {
|
||||||
if err = d.writeBlock(tokens[0:ti], index, false); err != nil {
|
if err = d.writeBlock(tokens[0:ti], index, false); err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -408,21 +408,21 @@ func (d *deflater) deflater(r io.Reader, w io.Writer, level int, logWindowSize u
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case level == NoCompression:
|
case level == NoCompression:
|
||||||
err = d.storedDeflate();
|
err = d.storedDeflate()
|
||||||
case level == DefaultCompression:
|
case level == DefaultCompression:
|
||||||
d.level = 6;
|
d.level = 6;
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case 1 <= level && level <= 9:
|
case 1 <= level && level <= 9:
|
||||||
err = d.doDeflate();
|
err = d.doDeflate()
|
||||||
default:
|
default:
|
||||||
return WrongValueError{"level", 0, 9, int32(level)};
|
return WrongValueError{"level", 0, 9, int32(level)}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
if d.w.writeStoredHeader(0, true); d.w.err != nil {
|
if d.w.writeStoredHeader(0, true); d.w.err != nil {
|
||||||
return d.w.err;
|
return d.w.err
|
||||||
}
|
}
|
||||||
return d.flush();
|
return d.flush();
|
||||||
}
|
}
|
||||||
|
|
@ -438,5 +438,5 @@ func newDeflater(w io.Writer, level int, logWindowSize uint) io.WriteCloser {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDeflater(w io.Writer, level int) io.WriteCloser {
|
func NewDeflater(w io.Writer, level int) io.WriteCloser {
|
||||||
return newDeflater(w, level, logMaxOffsetSize);
|
return newDeflater(w, level, logMaxOffsetSize)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ var reverseBitsTests = []*reverseBitsTest{
|
||||||
func getLargeDataChunk() []byte {
|
func getLargeDataChunk() []byte {
|
||||||
result := make([]byte, 100000);
|
result := make([]byte, 100000);
|
||||||
for i := range result {
|
for i := range result {
|
||||||
result[i] = byte(int64(i)*int64(i)&0xFF);
|
result[i] = byte(int64(i)*int64(i)&0xFF)
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +85,7 @@ func TestDeflate(t *testing.T) {
|
||||||
w.Close();
|
w.Close();
|
||||||
if bytes.Compare(buffer.Bytes(), h.out) != 0 {
|
if bytes.Compare(buffer.Bytes(), h.out) != 0 {
|
||||||
t.Errorf("buffer is wrong; level = %v, buffer.Bytes() = %v, expected output = %v",
|
t.Errorf("buffer is wrong; level = %v, buffer.Bytes() = %v, expected output = %v",
|
||||||
h.level, buffer.Bytes(), h.out);
|
h.level, buffer.Bytes(), h.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -103,20 +103,20 @@ func testToFromWithLevel(t *testing.T, level int, input []byte, name string) os.
|
||||||
}
|
}
|
||||||
inflater.Close();
|
inflater.Close();
|
||||||
if bytes.Compare(input, decompressed) != 0 {
|
if bytes.Compare(input, decompressed) != 0 {
|
||||||
t.Errorf("decompress(compress(data)) != data: level=%d input=%s", level, name);
|
t.Errorf("decompress(compress(data)) != data: level=%d input=%s", level, name)
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
func testToFrom(t *testing.T, input []byte, name string) {
|
func testToFrom(t *testing.T, input []byte, name string) {
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
testToFromWithLevel(t, i, input, name);
|
testToFromWithLevel(t, i, input, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeflateInflate(t *testing.T) {
|
func TestDeflateInflate(t *testing.T) {
|
||||||
for i, h := range deflateInflateTests {
|
for i, h := range deflateInflateTests {
|
||||||
testToFrom(t, h.in, fmt.Sprintf("#%d", i));
|
testToFrom(t, h.in, fmt.Sprintf("#%d", i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,7 +124,7 @@ func TestReverseBits(t *testing.T) {
|
||||||
for _, h := range reverseBitsTests {
|
for _, h := range reverseBitsTests {
|
||||||
if v := reverseBits(h.in, h.bitCount); v != h.out {
|
if v := reverseBits(h.in, h.bitCount); v != h.out {
|
||||||
t.Errorf("reverseBits(%v,%v) = %v, want %v",
|
t.Errorf("reverseBits(%v,%v) = %v, want %v",
|
||||||
h.in, h.bitCount, v, h.out);
|
h.in, h.bitCount, v, h.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -260,5 +260,5 @@ func getEdata() string {
|
||||||
"30186739439716388611764209004068663398856841681003872389214483176070116684503887" +
|
"30186739439716388611764209004068663398856841681003872389214483176070116684503887" +
|
||||||
"21236436704331409115573328018297798873659091665961240202177855885487617616198937" +
|
"21236436704331409115573328018297798873659091665961240202177855885487617616198937" +
|
||||||
"07943800566633648843650891448055710397652146960276625835990519870423001794655367" +
|
"07943800566633648843650891448055710397652146960276625835990519870423001794655367" +
|
||||||
"9";
|
"9"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ func TestInitDecoder(t *testing.T) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(&h, &tt.out) {
|
if !reflect.DeepEqual(&h, &tt.out) {
|
||||||
t.Errorf("test %d:\nhave %v\nwant %v", i, h, tt.out);
|
t.Errorf("test %d:\nhave %v\nwant %v", i, h, tt.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -131,9 +131,9 @@ func TestUncompressedSource(t *testing.T) {
|
||||||
output := make([]byte, 1);
|
output := make([]byte, 1);
|
||||||
n, error := decoder.Read(output);
|
n, error := decoder.Read(output);
|
||||||
if n != 1 || error != nil {
|
if n != 1 || error != nil {
|
||||||
t.Fatalf("decoder.Read() = %d, %v, want 1, nil", n, error);
|
t.Fatalf("decoder.Read() = %d, %v, want 1, nil", n, error)
|
||||||
}
|
}
|
||||||
if output[0] != 0x11 {
|
if output[0] != 0x11 {
|
||||||
t.Errorf("output[0] = %x, want 0x11", output[0]);
|
t.Errorf("output[0] = %x, want 0x11", output[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,12 +106,12 @@ func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter {
|
||||||
literalEncoding: newHuffmanEncoder(maxLit),
|
literalEncoding: newHuffmanEncoder(maxLit),
|
||||||
offsetEncoding: newHuffmanEncoder(extendedOffsetCodeCount),
|
offsetEncoding: newHuffmanEncoder(extendedOffsetCodeCount),
|
||||||
codegenEncoding: newHuffmanEncoder(codegenCodeCount),
|
codegenEncoding: newHuffmanEncoder(codegenCodeCount),
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err WrongValueError) String() string {
|
func (err WrongValueError) String() string {
|
||||||
return "huffmanBitWriter: " + err.name + " should belong to [" + strconv.Itoa64(int64(err.from)) + ";" +
|
return "huffmanBitWriter: " + err.name + " should belong to [" + strconv.Itoa64(int64(err.from)) + ";" +
|
||||||
strconv.Itoa64(int64(err.to)) + "] but actual value is " + strconv.Itoa64(int64(err.value));
|
strconv.Itoa64(int64(err.to)) + "] but actual value is " + strconv.Itoa64(int64(err.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *huffmanBitWriter) flushBits() {
|
func (w *huffmanBitWriter) flushBits() {
|
||||||
|
|
@ -157,13 +157,13 @@ func (w *huffmanBitWriter) flush() {
|
||||||
func (w *huffmanBitWriter) writeBits(b, nb int32) {
|
func (w *huffmanBitWriter) writeBits(b, nb int32) {
|
||||||
w.bits |= uint32(b) << w.nbits;
|
w.bits |= uint32(b) << w.nbits;
|
||||||
if w.nbits += uint32(nb); w.nbits >= 16 {
|
if w.nbits += uint32(nb); w.nbits >= 16 {
|
||||||
w.flushBits();
|
w.flushBits()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *huffmanBitWriter) writeBytes(bytes []byte) {
|
func (w *huffmanBitWriter) writeBytes(bytes []byte) {
|
||||||
if w.err != nil {
|
if w.err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
n := w.nbytes;
|
n := w.nbytes;
|
||||||
if w.nbits == 8 {
|
if w.nbits == 8 {
|
||||||
|
|
@ -178,7 +178,7 @@ func (w *huffmanBitWriter) writeBytes(bytes []byte) {
|
||||||
if n != 0 {
|
if n != 0 {
|
||||||
_, w.err = w.w.Write(w.bytes[0:n]);
|
_, w.err = w.w.Write(w.bytes[0:n]);
|
||||||
if w.err != nil {
|
if w.err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.nbytes = 0;
|
w.nbytes = 0;
|
||||||
|
|
@ -270,7 +270,7 @@ func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int) {
|
||||||
|
|
||||||
func (w *huffmanBitWriter) writeCode(code *huffmanEncoder, literal uint32) {
|
func (w *huffmanBitWriter) writeCode(code *huffmanEncoder, literal uint32) {
|
||||||
if w.err != nil {
|
if w.err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
w.writeBits(int32(code.code[literal]), int32(code.codeBits[literal]));
|
w.writeBits(int32(code.code[literal]), int32(code.codeBits[literal]));
|
||||||
}
|
}
|
||||||
|
|
@ -282,11 +282,11 @@ func (w *huffmanBitWriter) writeCode(code *huffmanEncoder, literal uint32) {
|
||||||
// numCodegens Tne number of codegens used in codegen
|
// numCodegens Tne number of codegens used in codegen
|
||||||
func (w *huffmanBitWriter) writeDynamicHeader(numLiterals int, numOffsets int, numCodegens int, isEof bool) {
|
func (w *huffmanBitWriter) writeDynamicHeader(numLiterals int, numOffsets int, numCodegens int, isEof bool) {
|
||||||
if w.err != nil {
|
if w.err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
var firstBits int32 = 4;
|
var firstBits int32 = 4;
|
||||||
if isEof {
|
if isEof {
|
||||||
firstBits = 5;
|
firstBits = 5
|
||||||
}
|
}
|
||||||
w.writeBits(firstBits, 3);
|
w.writeBits(firstBits, 3);
|
||||||
w.writeBits(int32(numLiterals - 257), 5);
|
w.writeBits(int32(numLiterals - 257), 5);
|
||||||
|
|
@ -295,7 +295,7 @@ func (w *huffmanBitWriter) writeDynamicHeader(numLiterals int, numOffsets int, n
|
||||||
w.writeBits(int32(offsetCodeCount + ((numOffsets - (1 + offsetCodeCount))>>3)), 5);
|
w.writeBits(int32(offsetCodeCount + ((numOffsets - (1 + offsetCodeCount))>>3)), 5);
|
||||||
w.writeBits(int32((numOffsets - (1 + offsetCodeCount))&0x7), 3);
|
w.writeBits(int32((numOffsets - (1 + offsetCodeCount))&0x7), 3);
|
||||||
} else {
|
} else {
|
||||||
w.writeBits(int32(numOffsets - 1), 5);
|
w.writeBits(int32(numOffsets - 1), 5)
|
||||||
}
|
}
|
||||||
w.writeBits(int32(numCodegens - 4), 4);
|
w.writeBits(int32(numCodegens - 4), 4);
|
||||||
|
|
||||||
|
|
@ -309,7 +309,7 @@ func (w *huffmanBitWriter) writeDynamicHeader(numLiterals int, numOffsets int, n
|
||||||
var codeWord int = int(w.codegen[i]);
|
var codeWord int = int(w.codegen[i]);
|
||||||
i++;
|
i++;
|
||||||
if codeWord == badCode {
|
if codeWord == badCode {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
// The low byte contains the actual code to generate.
|
// The low byte contains the actual code to generate.
|
||||||
w.writeCode(w.codegenEncoding, uint32(codeWord));
|
w.writeCode(w.codegenEncoding, uint32(codeWord));
|
||||||
|
|
@ -333,11 +333,11 @@ func (w *huffmanBitWriter) writeDynamicHeader(numLiterals int, numOffsets int, n
|
||||||
|
|
||||||
func (w *huffmanBitWriter) writeStoredHeader(length int, isEof bool) {
|
func (w *huffmanBitWriter) writeStoredHeader(length int, isEof bool) {
|
||||||
if w.err != nil {
|
if w.err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
var flag int32;
|
var flag int32;
|
||||||
if isEof {
|
if isEof {
|
||||||
flag = 1;
|
flag = 1
|
||||||
}
|
}
|
||||||
w.writeBits(flag, 3);
|
w.writeBits(flag, 3);
|
||||||
w.flush();
|
w.flush();
|
||||||
|
|
@ -347,19 +347,19 @@ func (w *huffmanBitWriter) writeStoredHeader(length int, isEof bool) {
|
||||||
|
|
||||||
func (w *huffmanBitWriter) writeFixedHeader(isEof bool) {
|
func (w *huffmanBitWriter) writeFixedHeader(isEof bool) {
|
||||||
if w.err != nil {
|
if w.err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
// Indicate that we are a fixed Huffman block
|
// Indicate that we are a fixed Huffman block
|
||||||
var value int32 = 2;
|
var value int32 = 2;
|
||||||
if isEof {
|
if isEof {
|
||||||
value = 3;
|
value = 3
|
||||||
}
|
}
|
||||||
w.writeBits(value, 3);
|
w.writeBits(value, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) {
|
func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) {
|
||||||
if w.err != nil {
|
if w.err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
fillInt32s(w.literalFreq, 0);
|
fillInt32s(w.literalFreq, 0);
|
||||||
fillInt32s(w.offsetFreq, 0);
|
fillInt32s(w.offsetFreq, 0);
|
||||||
|
|
@ -390,16 +390,16 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) {
|
||||||
// get the number of literals
|
// get the number of literals
|
||||||
numLiterals := len(w.literalFreq);
|
numLiterals := len(w.literalFreq);
|
||||||
for w.literalFreq[numLiterals - 1] == 0 {
|
for w.literalFreq[numLiterals - 1] == 0 {
|
||||||
numLiterals--;
|
numLiterals--
|
||||||
}
|
}
|
||||||
// get the number of offsets
|
// get the number of offsets
|
||||||
numOffsets := len(w.offsetFreq);
|
numOffsets := len(w.offsetFreq);
|
||||||
for numOffsets > 1 && w.offsetFreq[numOffsets - 1] == 0 {
|
for numOffsets > 1 && w.offsetFreq[numOffsets - 1] == 0 {
|
||||||
numOffsets--;
|
numOffsets--
|
||||||
}
|
}
|
||||||
storedBytes := 0;
|
storedBytes := 0;
|
||||||
if input != nil {
|
if input != nil {
|
||||||
storedBytes = len(input);
|
storedBytes = len(input)
|
||||||
}
|
}
|
||||||
var extraBits int64;
|
var extraBits int64;
|
||||||
var storedSize int64;
|
var storedSize int64;
|
||||||
|
|
@ -411,14 +411,14 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) {
|
||||||
// against stored encoding.
|
// against stored encoding.
|
||||||
for lengthCode := lengthCodesStart + 8; lengthCode < numLiterals; lengthCode++ {
|
for lengthCode := lengthCodesStart + 8; lengthCode < numLiterals; lengthCode++ {
|
||||||
// First eight length codes have extra size = 0.
|
// First eight length codes have extra size = 0.
|
||||||
extraBits += int64(w.literalFreq[lengthCode])*int64(lengthExtraBits[lengthCode - lengthCodesStart]);
|
extraBits += int64(w.literalFreq[lengthCode])*int64(lengthExtraBits[lengthCode - lengthCodesStart])
|
||||||
}
|
}
|
||||||
for offsetCode := 4; offsetCode < numOffsets; offsetCode++ {
|
for offsetCode := 4; offsetCode < numOffsets; offsetCode++ {
|
||||||
// First four offset codes have extra size = 0.
|
// First four offset codes have extra size = 0.
|
||||||
extraBits += int64(w.offsetFreq[offsetCode])*int64(offsetExtraBits[offsetCode]);
|
extraBits += int64(w.offsetFreq[offsetCode])*int64(offsetExtraBits[offsetCode])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
storedSize = math.MaxInt32;
|
storedSize = math.MaxInt32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Figure out which generates smaller code, fixed Huffman, dynamic
|
// Figure out which generates smaller code, fixed Huffman, dynamic
|
||||||
|
|
@ -428,7 +428,7 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) {
|
||||||
fixedSize = int64(3) +
|
fixedSize = int64(3) +
|
||||||
fixedLiteralEncoding.bitLength(w.literalFreq) +
|
fixedLiteralEncoding.bitLength(w.literalFreq) +
|
||||||
fixedOffsetEncoding.bitLength(w.offsetFreq) +
|
fixedOffsetEncoding.bitLength(w.offsetFreq) +
|
||||||
extraBits;
|
extraBits
|
||||||
}
|
}
|
||||||
// Generate codegen and codegenFrequencies, which indicates how to encode
|
// Generate codegen and codegenFrequencies, which indicates how to encode
|
||||||
// the literalEncoding and the offsetEncoding.
|
// the literalEncoding and the offsetEncoding.
|
||||||
|
|
@ -436,11 +436,11 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) {
|
||||||
w.codegenEncoding.generate(w.codegenFreq, 7);
|
w.codegenEncoding.generate(w.codegenFreq, 7);
|
||||||
numCodegens := len(w.codegenFreq);
|
numCodegens := len(w.codegenFreq);
|
||||||
for numCodegens > 4 && w.codegenFreq[codegenOrder[numCodegens - 1]] == 0 {
|
for numCodegens > 4 && w.codegenFreq[codegenOrder[numCodegens - 1]] == 0 {
|
||||||
numCodegens--;
|
numCodegens--
|
||||||
}
|
}
|
||||||
extensionSummand := 0;
|
extensionSummand := 0;
|
||||||
if numOffsets > offsetCodeCount {
|
if numOffsets > offsetCodeCount {
|
||||||
extensionSummand = 3;
|
extensionSummand = 3
|
||||||
}
|
}
|
||||||
dynamicHeader := int64(3+5+5+4+(3 * numCodegens)) +
|
dynamicHeader := int64(3+5+5+4+(3 * numCodegens)) +
|
||||||
// Following line is an extension.
|
// Following line is an extension.
|
||||||
|
|
@ -500,7 +500,7 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("unknown token type: " + string(t));
|
panic("unknown token type: " + string(t))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ type levelInfo struct {
|
||||||
func maxNode() literalNode { return literalNode{math.MaxUint16, math.MaxInt32} }
|
func maxNode() literalNode { return literalNode{math.MaxUint16, math.MaxInt32} }
|
||||||
|
|
||||||
func newHuffmanEncoder(size int) *huffmanEncoder {
|
func newHuffmanEncoder(size int) *huffmanEncoder {
|
||||||
return &huffmanEncoder{make([]uint8, size), make([]uint16, size)};
|
return &huffmanEncoder{make([]uint8, size), make([]uint16, size)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generates a HuffmanCode corresponding to the fixed literal table
|
// Generates a HuffmanCode corresponding to the fixed literal table
|
||||||
|
|
@ -115,7 +115,7 @@ func (h *huffmanEncoder) bitLength(freq []int32) int64 {
|
||||||
var total int64;
|
var total int64;
|
||||||
for i, f := range freq {
|
for i, f := range freq {
|
||||||
if f != 0 {
|
if f != 0 {
|
||||||
total += int64(f)*int64(h.codeBits[i]);
|
total += int64(f)*int64(h.codeBits[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return total;
|
return total;
|
||||||
|
|
@ -163,14 +163,14 @@ func (h *huffmanEncoder) generateChains(top *levelInfo, list []literalNode) {
|
||||||
up := l.up;
|
up := l.up;
|
||||||
if up == nil {
|
if up == nil {
|
||||||
// All done!
|
// All done!
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
up.nextPairFreq = prevFreq + l.lastChain.freq;
|
up.nextPairFreq = prevFreq + l.lastChain.freq;
|
||||||
l = up;
|
l = up;
|
||||||
} else {
|
} else {
|
||||||
// If we stole from below, move down temporarily to replenish it.
|
// If we stole from below, move down temporarily to replenish it.
|
||||||
for l.down.needed > 0 {
|
for l.down.needed > 0 {
|
||||||
l = l.down;
|
l = l.down
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -215,7 +215,7 @@ func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 {
|
||||||
};
|
};
|
||||||
top.down.up = top;
|
top.down.up = top;
|
||||||
if level == 1 {
|
if level == 1 {
|
||||||
top.nextPairFreq = math.MaxInt32;
|
top.nextPairFreq = math.MaxInt32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -258,14 +258,14 @@ func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 {
|
||||||
up := l.up;
|
up := l.up;
|
||||||
if up == nil {
|
if up == nil {
|
||||||
// All done!
|
// All done!
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
up.nextPairFreq = prevFreq + l.lastChain.freq;
|
up.nextPairFreq = prevFreq + l.lastChain.freq;
|
||||||
l = up;
|
l = up;
|
||||||
} else {
|
} else {
|
||||||
// If we stole from below, move down temporarily to replenish it.
|
// If we stole from below, move down temporarily to replenish it.
|
||||||
for l.down.needed > 0 {
|
for l.down.needed > 0 {
|
||||||
l = l.down;
|
l = l.down
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -274,7 +274,7 @@ func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 {
|
||||||
// Somethings is wrong if at the end, the top level is null or hasn't used
|
// Somethings is wrong if at the end, the top level is null or hasn't used
|
||||||
// all of the leaves.
|
// all of the leaves.
|
||||||
if top.lastChain.leafCount != n {
|
if top.lastChain.leafCount != n {
|
||||||
panic("top.lastChain.leafCount != n");
|
panic("top.lastChain.leafCount != n")
|
||||||
}
|
}
|
||||||
|
|
||||||
bitCount := make([]int32, maxBits+1);
|
bitCount := make([]int32, maxBits+1);
|
||||||
|
|
@ -295,7 +295,7 @@ func (h *huffmanEncoder) assignEncodingAndSize(bitCount []int32, list []literalN
|
||||||
for n, bits := range bitCount {
|
for n, bits := range bitCount {
|
||||||
code <<= 1;
|
code <<= 1;
|
||||||
if n == 0 || bits == 0 {
|
if n == 0 || bits == 0 {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
// The literals list[len(list)-bits] .. list[len(list)-bits]
|
// The literals list[len(list)-bits] .. list[len(list)-bits]
|
||||||
// are encoded using "bits" bits, and get the values
|
// are encoded using "bits" bits, and get the values
|
||||||
|
|
@ -326,7 +326,7 @@ func (h *huffmanEncoder) generate(freq []int32, maxBits int32) {
|
||||||
list[count] = literalNode{uint16(i), f};
|
list[count] = literalNode{uint16(i), f};
|
||||||
count++;
|
count++;
|
||||||
} else {
|
} else {
|
||||||
h.codeBits[i] = 0;
|
h.codeBits[i] = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If freq[] is shorter than codeBits[], fill rest of codeBits[] with zeros
|
// If freq[] is shorter than codeBits[], fill rest of codeBits[] with zeros
|
||||||
|
|
@ -358,7 +358,7 @@ type literalNodeSorter struct {
|
||||||
func (s literalNodeSorter) Len() int { return len(s.a) }
|
func (s literalNodeSorter) Len() int { return len(s.a) }
|
||||||
|
|
||||||
func (s literalNodeSorter) Less(i, j int) bool {
|
func (s literalNodeSorter) Less(i, j int) bool {
|
||||||
return s.less(i, j);
|
return s.less(i, j)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s literalNodeSorter) Swap(i, j int) { s.a[i], s.a[j] = s.a[j], s.a[i] }
|
func (s literalNodeSorter) Swap(i, j int) { s.a[i], s.a[j] = s.a[j], s.a[i] }
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ const (
|
||||||
type CorruptInputError int64
|
type CorruptInputError int64
|
||||||
|
|
||||||
func (e CorruptInputError) String() string {
|
func (e CorruptInputError) String() string {
|
||||||
return "flate: corrupt input before offset " + strconv.Itoa64(int64(e));
|
return "flate: corrupt input before offset " + strconv.Itoa64(int64(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
// An InternalError reports an error in the flate code itself.
|
// An InternalError reports an error in the flate code itself.
|
||||||
|
|
@ -41,7 +41,7 @@ type ReadError struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ReadError) String() string {
|
func (e *ReadError) String() string {
|
||||||
return "flate: read error at offset " + strconv.Itoa64(e.Offset) + ": " + e.Error.String();
|
return "flate: read error at offset " + strconv.Itoa64(e.Offset) + ": " + e.Error.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// A WriteError reports an error encountered while writing output.
|
// A WriteError reports an error encountered while writing output.
|
||||||
|
|
@ -51,7 +51,7 @@ type WriteError struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *WriteError) String() string {
|
func (e *WriteError) String() string {
|
||||||
return "flate: write error at offset " + strconv.Itoa64(e.Offset) + ": " + e.Error.String();
|
return "flate: write error at offset " + strconv.Itoa64(e.Offset) + ": " + e.Error.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Huffman decoder is based on
|
// Huffman decoder is based on
|
||||||
|
|
@ -85,18 +85,18 @@ func (h *huffmanDecoder) init(bits []int) bool {
|
||||||
var min, max int;
|
var min, max int;
|
||||||
for _, n := range bits {
|
for _, n := range bits {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if min == 0 || n < min {
|
if min == 0 || n < min {
|
||||||
min = n;
|
min = n
|
||||||
}
|
}
|
||||||
if n > max {
|
if n > max {
|
||||||
max = n;
|
max = n
|
||||||
}
|
}
|
||||||
count[n]++;
|
count[n]++;
|
||||||
}
|
}
|
||||||
if max == 0 {
|
if max == 0 {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
h.min = min;
|
h.min = min;
|
||||||
|
|
@ -122,11 +122,11 @@ func (h *huffmanDecoder) init(bits []int) bool {
|
||||||
|
|
||||||
// Make array mapping sequence numbers to codes.
|
// Make array mapping sequence numbers to codes.
|
||||||
if len(h.codes) < len(bits) {
|
if len(h.codes) < len(bits) {
|
||||||
h.codes = make([]int, len(bits));
|
h.codes = make([]int, len(bits))
|
||||||
}
|
}
|
||||||
for i, n := range bits {
|
for i, n := range bits {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
code := nextcode[n];
|
code := nextcode[n];
|
||||||
nextcode[n]++;
|
nextcode[n]++;
|
||||||
|
|
@ -229,7 +229,7 @@ func (f *inflater) inflate() (err os.Error) {
|
||||||
for err == nil && !final {
|
for err == nil && !final {
|
||||||
for f.nb < 1+2 {
|
for f.nb < 1+2 {
|
||||||
if err = f.moreBits(); err != nil {
|
if err = f.moreBits(); err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final = f.b & 1 == 1;
|
final = f.b & 1 == 1;
|
||||||
|
|
@ -239,18 +239,18 @@ func (f *inflater) inflate() (err os.Error) {
|
||||||
f.nb -= 1+2;
|
f.nb -= 1+2;
|
||||||
switch typ {
|
switch typ {
|
||||||
case 0:
|
case 0:
|
||||||
err = f.dataBlock();
|
err = f.dataBlock()
|
||||||
case 1:
|
case 1:
|
||||||
// compressed, fixed Huffman tables
|
// compressed, fixed Huffman tables
|
||||||
err = f.decodeBlock(&fixedHuffmanDecoder, nil);
|
err = f.decodeBlock(&fixedHuffmanDecoder, nil)
|
||||||
case 2:
|
case 2:
|
||||||
// compressed, dynamic Huffman tables
|
// compressed, dynamic Huffman tables
|
||||||
if err = f.readHuffman(); err == nil {
|
if err = f.readHuffman(); err == nil {
|
||||||
err = f.decodeBlock(&f.h1, &f.h2);
|
err = f.decodeBlock(&f.h1, &f.h2)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
// 3 is reserved.
|
// 3 is reserved.
|
||||||
err = CorruptInputError(f.roffset);
|
err = CorruptInputError(f.roffset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -265,7 +265,7 @@ func (f *inflater) readHuffman() os.Error {
|
||||||
// HLIT[5], HDIST[5], HCLEN[4].
|
// HLIT[5], HDIST[5], HCLEN[4].
|
||||||
for f.nb < 5+5+4 {
|
for f.nb < 5+5+4 {
|
||||||
if err := f.moreBits(); err != nil {
|
if err := f.moreBits(); err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nlit := int(f.b & 0x1F)+257;
|
nlit := int(f.b & 0x1F)+257;
|
||||||
|
|
@ -280,7 +280,7 @@ func (f *inflater) readHuffman() os.Error {
|
||||||
for i := 0; i < nclen; i++ {
|
for i := 0; i < nclen; i++ {
|
||||||
for f.nb < 3 {
|
for f.nb < 3 {
|
||||||
if err := f.moreBits(); err != nil {
|
if err := f.moreBits(); err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.codebits[codeOrder[i]] = int(f.b & 0x7);
|
f.codebits[codeOrder[i]] = int(f.b & 0x7);
|
||||||
|
|
@ -288,10 +288,10 @@ func (f *inflater) readHuffman() os.Error {
|
||||||
f.nb -= 3;
|
f.nb -= 3;
|
||||||
}
|
}
|
||||||
for i := nclen; i < len(codeOrder); i++ {
|
for i := nclen; i < len(codeOrder); i++ {
|
||||||
f.codebits[codeOrder[i]] = 0;
|
f.codebits[codeOrder[i]] = 0
|
||||||
}
|
}
|
||||||
if !f.h1.init(&f.codebits) {
|
if !f.h1.init(&f.codebits) {
|
||||||
return CorruptInputError(f.roffset);
|
return CorruptInputError(f.roffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HLIT + 257 code lengths, HDIST + 1 code lengths,
|
// HLIT + 257 code lengths, HDIST + 1 code lengths,
|
||||||
|
|
@ -299,7 +299,7 @@ func (f *inflater) readHuffman() os.Error {
|
||||||
for i, n := 0, nlit+ndist; i < n; {
|
for i, n := 0, nlit+ndist; i < n; {
|
||||||
x, err := f.huffSym(&f.h1);
|
x, err := f.huffSym(&f.h1);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
if x < 16 {
|
if x < 16 {
|
||||||
// Actual length.
|
// Actual length.
|
||||||
|
|
@ -313,12 +313,12 @@ func (f *inflater) readHuffman() os.Error {
|
||||||
var b int;
|
var b int;
|
||||||
switch x {
|
switch x {
|
||||||
default:
|
default:
|
||||||
return InternalError("unexpected length code");
|
return InternalError("unexpected length code")
|
||||||
case 16:
|
case 16:
|
||||||
rep = 3;
|
rep = 3;
|
||||||
nb = 2;
|
nb = 2;
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
return CorruptInputError(f.roffset);
|
return CorruptInputError(f.roffset)
|
||||||
}
|
}
|
||||||
b = f.bits[i-1];
|
b = f.bits[i-1];
|
||||||
case 17:
|
case 17:
|
||||||
|
|
@ -332,14 +332,14 @@ func (f *inflater) readHuffman() os.Error {
|
||||||
}
|
}
|
||||||
for f.nb < nb {
|
for f.nb < nb {
|
||||||
if err := f.moreBits(); err != nil {
|
if err := f.moreBits(); err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rep += int(f.b & uint32(1<<nb - 1));
|
rep += int(f.b & uint32(1<<nb - 1));
|
||||||
f.b >>= nb;
|
f.b >>= nb;
|
||||||
f.nb -= nb;
|
f.nb -= nb;
|
||||||
if i+rep > n {
|
if i+rep > n {
|
||||||
return CorruptInputError(f.roffset);
|
return CorruptInputError(f.roffset)
|
||||||
}
|
}
|
||||||
for j := 0; j < rep; j++ {
|
for j := 0; j < rep; j++ {
|
||||||
f.bits[i] = b;
|
f.bits[i] = b;
|
||||||
|
|
@ -348,7 +348,7 @@ func (f *inflater) readHuffman() os.Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !f.h1.init(f.bits[0:nlit]) || !f.h2.init(f.bits[nlit : nlit+ndist]) {
|
if !f.h1.init(f.bits[0:nlit]) || !f.h2.init(f.bits[nlit : nlit+ndist]) {
|
||||||
return CorruptInputError(f.roffset);
|
return CorruptInputError(f.roffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
|
|
@ -362,7 +362,7 @@ func (f *inflater) decodeBlock(hl, hd *huffmanDecoder) os.Error {
|
||||||
for {
|
for {
|
||||||
v, err := f.huffSym(hl);
|
v, err := f.huffSym(hl);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
var n uint; // number of bits extra
|
var n uint; // number of bits extra
|
||||||
var length int;
|
var length int;
|
||||||
|
|
@ -372,12 +372,12 @@ func (f *inflater) decodeBlock(hl, hd *huffmanDecoder) os.Error {
|
||||||
f.hp++;
|
f.hp++;
|
||||||
if f.hp == len(f.hist) {
|
if f.hp == len(f.hist) {
|
||||||
if err = f.flush(); err != nil {
|
if err = f.flush(); err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
case v == 256:
|
case v == 256:
|
||||||
return nil;
|
return nil
|
||||||
// otherwise, reference to older data
|
// otherwise, reference to older data
|
||||||
case v < 265:
|
case v < 265:
|
||||||
length = v-(257-3);
|
length = v-(257-3);
|
||||||
|
|
@ -404,7 +404,7 @@ func (f *inflater) decodeBlock(hl, hd *huffmanDecoder) os.Error {
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
for f.nb < n {
|
for f.nb < n {
|
||||||
if err = f.moreBits(); err != nil {
|
if err = f.moreBits(); err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
length += int(f.b & uint32(1<<n - 1));
|
length += int(f.b & uint32(1<<n - 1));
|
||||||
|
|
@ -416,7 +416,7 @@ func (f *inflater) decodeBlock(hl, hd *huffmanDecoder) os.Error {
|
||||||
if hd == nil {
|
if hd == nil {
|
||||||
for f.nb < 5 {
|
for f.nb < 5 {
|
||||||
if err = f.moreBits(); err != nil {
|
if err = f.moreBits(); err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dist = int(reverseByte[(f.b & 0x1F)<<3]);
|
dist = int(reverseByte[(f.b & 0x1F)<<3]);
|
||||||
|
|
@ -424,22 +424,22 @@ func (f *inflater) decodeBlock(hl, hd *huffmanDecoder) os.Error {
|
||||||
f.nb -= 5;
|
f.nb -= 5;
|
||||||
} else {
|
} else {
|
||||||
if dist, err = f.huffSym(hd); err != nil {
|
if dist, err = f.huffSym(hd); err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case dist < 4:
|
case dist < 4:
|
||||||
dist++;
|
dist++
|
||||||
case dist >= 30:
|
case dist >= 30:
|
||||||
return CorruptInputError(f.roffset);
|
return CorruptInputError(f.roffset)
|
||||||
default:
|
default:
|
||||||
nb := uint(dist-2)>>1;
|
nb := uint(dist-2)>>1;
|
||||||
// have 1 bit in bottom of dist, need nb more.
|
// have 1 bit in bottom of dist, need nb more.
|
||||||
extra := (dist&1)<<nb;
|
extra := (dist&1)<<nb;
|
||||||
for f.nb < nb {
|
for f.nb < nb {
|
||||||
if err = f.moreBits(); err != nil {
|
if err = f.moreBits(); err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extra |= int(f.b & uint32(1<<nb - 1));
|
extra |= int(f.b & uint32(1<<nb - 1));
|
||||||
|
|
@ -450,17 +450,17 @@ func (f *inflater) decodeBlock(hl, hd *huffmanDecoder) os.Error {
|
||||||
|
|
||||||
// Copy history[-dist:-dist+length] into output.
|
// Copy history[-dist:-dist+length] into output.
|
||||||
if dist > len(f.hist) {
|
if dist > len(f.hist) {
|
||||||
return InternalError("bad history distance");
|
return InternalError("bad history distance")
|
||||||
}
|
}
|
||||||
|
|
||||||
// No check on length; encoding can be prescient.
|
// No check on length; encoding can be prescient.
|
||||||
if !f.hfull && dist > f.hp {
|
if !f.hfull && dist > f.hp {
|
||||||
return CorruptInputError(f.roffset);
|
return CorruptInputError(f.roffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
p := f.hp - dist;
|
p := f.hp - dist;
|
||||||
if p < 0 {
|
if p < 0 {
|
||||||
p += len(f.hist);
|
p += len(f.hist)
|
||||||
}
|
}
|
||||||
for i := 0; i < length; i++ {
|
for i := 0; i < length; i++ {
|
||||||
f.hist[f.hp] = f.hist[p];
|
f.hist[f.hp] = f.hist[p];
|
||||||
|
|
@ -468,11 +468,11 @@ func (f *inflater) decodeBlock(hl, hd *huffmanDecoder) os.Error {
|
||||||
p++;
|
p++;
|
||||||
if f.hp == len(f.hist) {
|
if f.hp == len(f.hist) {
|
||||||
if err = f.flush(); err != nil {
|
if err = f.flush(); err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p == len(f.hist) {
|
if p == len(f.hist) {
|
||||||
p = 0;
|
p = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -490,12 +490,12 @@ func (f *inflater) dataBlock() os.Error {
|
||||||
nr, err := io.ReadFull(f.r, f.buf[0:4]);
|
nr, err := io.ReadFull(f.r, f.buf[0:4]);
|
||||||
f.roffset += int64(nr);
|
f.roffset += int64(nr);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &ReadError{f.roffset, err};
|
return &ReadError{f.roffset, err}
|
||||||
}
|
}
|
||||||
n := int(f.buf[0]) | int(f.buf[1])<<8;
|
n := int(f.buf[0]) | int(f.buf[1])<<8;
|
||||||
nn := int(f.buf[2]) | int(f.buf[3])<<8;
|
nn := int(f.buf[2]) | int(f.buf[3])<<8;
|
||||||
if uint16(nn) != uint16(^n) {
|
if uint16(nn) != uint16(^n) {
|
||||||
return CorruptInputError(f.roffset);
|
return CorruptInputError(f.roffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read len bytes into history,
|
// Read len bytes into history,
|
||||||
|
|
@ -503,18 +503,18 @@ func (f *inflater) dataBlock() os.Error {
|
||||||
for n > 0 {
|
for n > 0 {
|
||||||
m := len(f.hist) - f.hp;
|
m := len(f.hist) - f.hp;
|
||||||
if m > n {
|
if m > n {
|
||||||
m = n;
|
m = n
|
||||||
}
|
}
|
||||||
m, err := io.ReadFull(f.r, f.hist[f.hp : f.hp + m]);
|
m, err := io.ReadFull(f.r, f.hist[f.hp : f.hp + m]);
|
||||||
f.roffset += int64(m);
|
f.roffset += int64(m);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &ReadError{f.roffset, err};
|
return &ReadError{f.roffset, err}
|
||||||
}
|
}
|
||||||
n -= m;
|
n -= m;
|
||||||
f.hp += m;
|
f.hp += m;
|
||||||
if f.hp == len(f.hist) {
|
if f.hp == len(f.hist) {
|
||||||
if err = f.flush(); err != nil {
|
if err = f.flush(); err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -525,7 +525,7 @@ func (f *inflater) moreBits() os.Error {
|
||||||
c, err := f.r.ReadByte();
|
c, err := f.r.ReadByte();
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == os.EOF {
|
if err == os.EOF {
|
||||||
err = io.ErrUnexpectedEOF;
|
err = io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
@ -540,11 +540,11 @@ func (f *inflater) huffSym(h *huffmanDecoder) (int, os.Error) {
|
||||||
for n := uint(h.min); n <= uint(h.max); n++ {
|
for n := uint(h.min); n <= uint(h.max); n++ {
|
||||||
lim := h.limit[n];
|
lim := h.limit[n];
|
||||||
if lim == -1 {
|
if lim == -1 {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
for f.nb < n {
|
for f.nb < n {
|
||||||
if err := f.moreBits(); err != nil {
|
if err := f.moreBits(); err != nil {
|
||||||
return 0, err;
|
return 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v := int(f.b & uint32(1<<n - 1));
|
v := int(f.b & uint32(1<<n - 1));
|
||||||
|
|
@ -562,14 +562,14 @@ func (f *inflater) huffSym(h *huffmanDecoder) (int, os.Error) {
|
||||||
// Flush any buffered output to the underlying writer.
|
// Flush any buffered output to the underlying writer.
|
||||||
func (f *inflater) flush() os.Error {
|
func (f *inflater) flush() os.Error {
|
||||||
if f.hp == 0 {
|
if f.hp == 0 {
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
n, err := f.w.Write(f.hist[0 : f.hp]);
|
n, err := f.w.Write(f.hist[0 : f.hp]);
|
||||||
if n != f.hp && err == nil {
|
if n != f.hp && err == nil {
|
||||||
err = io.ErrShortWrite;
|
err = io.ErrShortWrite
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &WriteError{f.woffset, err};
|
return &WriteError{f.woffset, err}
|
||||||
}
|
}
|
||||||
f.woffset += int64(f.hp);
|
f.woffset += int64(f.hp);
|
||||||
f.hp = 0;
|
f.hp = 0;
|
||||||
|
|
@ -579,7 +579,7 @@ func (f *inflater) flush() os.Error {
|
||||||
|
|
||||||
func makeReader(r io.Reader) Reader {
|
func makeReader(r io.Reader) Reader {
|
||||||
if rr, ok := r.(Reader); ok {
|
if rr, ok := r.(Reader); ok {
|
||||||
return rr;
|
return rr
|
||||||
}
|
}
|
||||||
return bufio.NewReader(r);
|
return bufio.NewReader(r);
|
||||||
}
|
}
|
||||||
|
|
@ -591,10 +591,10 @@ func (f *inflater) inflater(r io.Reader, w io.Writer) os.Error {
|
||||||
f.w = w;
|
f.w = w;
|
||||||
f.woffset = 0;
|
f.woffset = 0;
|
||||||
if err := f.inflate(); err != nil {
|
if err := f.inflate(); err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
if err := f.flush(); err != nil {
|
if err := f.flush(); err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,9 @@ var reverseByte = [256]byte{
|
||||||
}
|
}
|
||||||
|
|
||||||
func reverseUint16(v uint16) uint16 {
|
func reverseUint16(v uint16) uint16 {
|
||||||
return uint16(reverseByte[v>>8]) | uint16(reverseByte[v&0xFF])<<8;
|
return uint16(reverseByte[v>>8]) | uint16(reverseByte[v&0xFF])<<8
|
||||||
}
|
}
|
||||||
|
|
||||||
func reverseBits(number uint16, bitLength byte) uint16 {
|
func reverseBits(number uint16, bitLength byte) uint16 {
|
||||||
return reverseUint16(number<<uint8(16 - bitLength));
|
return reverseUint16(number<<uint8(16 - bitLength))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ func literalToken(literal uint32) token { return token(literalType + literal) }
|
||||||
|
|
||||||
// Convert a < xlength, xoffset > pair into a match token.
|
// Convert a < xlength, xoffset > pair into a match token.
|
||||||
func matchToken(xlength uint32, xoffset uint32) token {
|
func matchToken(xlength uint32, xoffset uint32) token {
|
||||||
return token(matchType + xlength << lengthShift + xoffset);
|
return token(matchType + xlength << lengthShift + xoffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the type of a token
|
// Returns the type of a token
|
||||||
|
|
@ -93,11 +93,11 @@ func offsetCode(off uint32) uint32 {
|
||||||
const n = uint32(len(offsetCodes));
|
const n = uint32(len(offsetCodes));
|
||||||
switch {
|
switch {
|
||||||
case off < n:
|
case off < n:
|
||||||
return offsetCodes[off];
|
return offsetCodes[off]
|
||||||
case off>>7 < n:
|
case off>>7 < n:
|
||||||
return offsetCodes[off>>7] + 14;
|
return offsetCodes[off>>7] + 14
|
||||||
default:
|
default:
|
||||||
return offsetCodes[off>>14] + 28;
|
return offsetCodes[off>>14] + 28
|
||||||
}
|
}
|
||||||
panic("unreachable");
|
panic("unreachable");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,59 +6,59 @@ package flate
|
||||||
|
|
||||||
func min(left int, right int) int {
|
func min(left int, right int) int {
|
||||||
if left < right {
|
if left < right {
|
||||||
return left;
|
return left
|
||||||
}
|
}
|
||||||
return right;
|
return right;
|
||||||
}
|
}
|
||||||
|
|
||||||
func minInt32(left int32, right int32) int32 {
|
func minInt32(left int32, right int32) int32 {
|
||||||
if left < right {
|
if left < right {
|
||||||
return left;
|
return left
|
||||||
}
|
}
|
||||||
return right;
|
return right;
|
||||||
}
|
}
|
||||||
|
|
||||||
func max(left int, right int) int {
|
func max(left int, right int) int {
|
||||||
if left > right {
|
if left > right {
|
||||||
return left;
|
return left
|
||||||
}
|
}
|
||||||
return right;
|
return right;
|
||||||
}
|
}
|
||||||
|
|
||||||
func fillInts(a []int, value int) {
|
func fillInts(a []int, value int) {
|
||||||
for i := range a {
|
for i := range a {
|
||||||
a[i] = value;
|
a[i] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fillInt32s(a []int32, value int32) {
|
func fillInt32s(a []int32, value int32) {
|
||||||
for i := range a {
|
for i := range a {
|
||||||
a[i] = value;
|
a[i] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fillBytes(a []byte, value byte) {
|
func fillBytes(a []byte, value byte) {
|
||||||
for i := range a {
|
for i := range a {
|
||||||
a[i] = value;
|
a[i] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fillInt8s(a []int8, value int8) {
|
func fillInt8s(a []int8, value int8) {
|
||||||
for i := range a {
|
for i := range a {
|
||||||
a[i] = value;
|
a[i] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fillUint8s(a []uint8, value uint8) {
|
func fillUint8s(a []uint8, value uint8) {
|
||||||
for i := range a {
|
for i := range a {
|
||||||
a[i] = value;
|
a[i] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyInt8s(dst []int8, src []int8) int {
|
func copyInt8s(dst []int8, src []int8) int {
|
||||||
cnt := min(len(dst), len(src));
|
cnt := min(len(dst), len(src));
|
||||||
for i := 0; i < cnt; i++ {
|
for i := 0; i < cnt; i++ {
|
||||||
dst[i] = src[i];
|
dst[i] = src[i]
|
||||||
}
|
}
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +66,7 @@ func copyInt8s(dst []int8, src []int8) int {
|
||||||
func copyUint8s(dst []uint8, src []uint8) int {
|
func copyUint8s(dst []uint8, src []uint8) int {
|
||||||
cnt := min(len(dst), len(src));
|
cnt := min(len(dst), len(src));
|
||||||
for i := 0; i < cnt; i++ {
|
for i := 0; i < cnt; i++ {
|
||||||
dst[i] = src[i];
|
dst[i] = src[i]
|
||||||
}
|
}
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ const (
|
||||||
|
|
||||||
func makeReader(r io.Reader) flate.Reader {
|
func makeReader(r io.Reader) flate.Reader {
|
||||||
if rr, ok := r.(flate.Reader); ok {
|
if rr, ok := r.(flate.Reader); ok {
|
||||||
return rr;
|
return rr
|
||||||
}
|
}
|
||||||
return bufio.NewReader(r);
|
return bufio.NewReader(r);
|
||||||
}
|
}
|
||||||
|
|
@ -85,21 +85,21 @@ func NewInflater(r io.Reader) (*Inflater, os.Error) {
|
||||||
|
|
||||||
// GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950).
|
// GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950).
|
||||||
func get4(p []byte) uint32 {
|
func get4(p []byte) uint32 {
|
||||||
return uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24;
|
return uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24
|
||||||
}
|
}
|
||||||
|
|
||||||
func (z *Inflater) readString() (string, os.Error) {
|
func (z *Inflater) readString() (string, os.Error) {
|
||||||
var err os.Error;
|
var err os.Error;
|
||||||
for i := 0; ; i++ {
|
for i := 0; ; i++ {
|
||||||
if i >= len(z.buf) {
|
if i >= len(z.buf) {
|
||||||
return "", HeaderError;
|
return "", HeaderError
|
||||||
}
|
}
|
||||||
z.buf[i], err = z.r.ReadByte();
|
z.buf[i], err = z.r.ReadByte();
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err;
|
return "", err
|
||||||
}
|
}
|
||||||
if z.buf[i] == 0 {
|
if z.buf[i] == 0 {
|
||||||
return string(z.buf[0:i]), nil;
|
return string(z.buf[0:i]), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic("not reached");
|
panic("not reached");
|
||||||
|
|
@ -108,7 +108,7 @@ func (z *Inflater) readString() (string, os.Error) {
|
||||||
func (z *Inflater) read2() (uint32, os.Error) {
|
func (z *Inflater) read2() (uint32, os.Error) {
|
||||||
_, err := z.r.Read(z.buf[0:2]);
|
_, err := z.r.Read(z.buf[0:2]);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err;
|
return 0, err
|
||||||
}
|
}
|
||||||
return uint32(z.buf[0]) | uint32(z.buf[1])<<8, nil;
|
return uint32(z.buf[0]) | uint32(z.buf[1])<<8, nil;
|
||||||
}
|
}
|
||||||
|
|
@ -116,10 +116,10 @@ func (z *Inflater) read2() (uint32, os.Error) {
|
||||||
func (z *Inflater) readHeader(save bool) os.Error {
|
func (z *Inflater) readHeader(save bool) os.Error {
|
||||||
_, err := io.ReadFull(z.r, z.buf[0:10]);
|
_, err := io.ReadFull(z.r, z.buf[0:10]);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
if z.buf[0] != gzipID1 || z.buf[1] != gzipID2 || z.buf[2] != gzipDeflate {
|
if z.buf[0] != gzipID1 || z.buf[1] != gzipID2 || z.buf[2] != gzipDeflate {
|
||||||
return HeaderError;
|
return HeaderError
|
||||||
}
|
}
|
||||||
z.flg = z.buf[3];
|
z.flg = z.buf[3];
|
||||||
if save {
|
if save {
|
||||||
|
|
@ -133,44 +133,44 @@ func (z *Inflater) readHeader(save bool) os.Error {
|
||||||
if z.flg & flagExtra != 0 {
|
if z.flg & flagExtra != 0 {
|
||||||
n, err := z.read2();
|
n, err := z.read2();
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
data := make([]byte, n);
|
data := make([]byte, n);
|
||||||
if _, err = io.ReadFull(z.r, data); err != nil {
|
if _, err = io.ReadFull(z.r, data); err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
if save {
|
if save {
|
||||||
z.Extra = data;
|
z.Extra = data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var s string;
|
var s string;
|
||||||
if z.flg & flagName != 0 {
|
if z.flg & flagName != 0 {
|
||||||
if s, err = z.readString(); err != nil {
|
if s, err = z.readString(); err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
if save {
|
if save {
|
||||||
z.Name = s;
|
z.Name = s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if z.flg & flagComment != 0 {
|
if z.flg & flagComment != 0 {
|
||||||
if s, err = z.readString(); err != nil {
|
if s, err = z.readString(); err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
if save {
|
if save {
|
||||||
z.Comment = s;
|
z.Comment = s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if z.flg & flagHdrCrc != 0 {
|
if z.flg & flagHdrCrc != 0 {
|
||||||
n, err := z.read2();
|
n, err := z.read2();
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
sum := z.digest.Sum32() & 0xFFFF;
|
sum := z.digest.Sum32() & 0xFFFF;
|
||||||
if n != sum {
|
if n != sum {
|
||||||
return HeaderError;
|
return HeaderError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -181,10 +181,10 @@ func (z *Inflater) readHeader(save bool) os.Error {
|
||||||
|
|
||||||
func (z *Inflater) Read(p []byte) (n int, err os.Error) {
|
func (z *Inflater) Read(p []byte) (n int, err os.Error) {
|
||||||
if z.err != nil {
|
if z.err != nil {
|
||||||
return 0, z.err;
|
return 0, z.err
|
||||||
}
|
}
|
||||||
if z.eof || len(p) == 0 {
|
if z.eof || len(p) == 0 {
|
||||||
return 0, nil;
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err = z.inflater.Read(p);
|
n, err = z.inflater.Read(p);
|
||||||
|
|
|
||||||
|
|
@ -290,16 +290,16 @@ func TestInflater(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer gzip.Close();
|
defer gzip.Close();
|
||||||
if tt.name != gzip.Name {
|
if tt.name != gzip.Name {
|
||||||
t.Errorf("%s: got name %s", tt.name, gzip.Name);
|
t.Errorf("%s: got name %s", tt.name, gzip.Name)
|
||||||
}
|
}
|
||||||
b.Reset();
|
b.Reset();
|
||||||
n, err := io.Copy(b, gzip);
|
n, err := io.Copy(b, gzip);
|
||||||
if err != tt.err {
|
if err != tt.err {
|
||||||
t.Errorf("%s: io.Copy: %v want %v", tt.name, err, tt.err);
|
t.Errorf("%s: io.Copy: %v want %v", tt.name, err, tt.err)
|
||||||
}
|
}
|
||||||
s := b.String();
|
s := b.String();
|
||||||
if s != tt.raw {
|
if s != tt.raw {
|
||||||
t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.name, n, s, len(tt.raw), tt.raw);
|
t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.name, n, s, len(tt.raw), tt.raw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,21 +35,21 @@ type reader struct {
|
||||||
func NewInflater(r io.Reader) (io.ReadCloser, os.Error) {
|
func NewInflater(r io.Reader) (io.ReadCloser, os.Error) {
|
||||||
z := new(reader);
|
z := new(reader);
|
||||||
if fr, ok := r.(flate.Reader); ok {
|
if fr, ok := r.(flate.Reader); ok {
|
||||||
z.r = fr;
|
z.r = fr
|
||||||
} else {
|
} else {
|
||||||
z.r = bufio.NewReader(r);
|
z.r = bufio.NewReader(r)
|
||||||
}
|
}
|
||||||
_, err := io.ReadFull(z.r, z.scratch[0:2]);
|
_, err := io.ReadFull(z.r, z.scratch[0:2]);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err;
|
return nil, err
|
||||||
}
|
}
|
||||||
h := uint(z.scratch[0])<<8 | uint(z.scratch[1]);
|
h := uint(z.scratch[0])<<8 | uint(z.scratch[1]);
|
||||||
if (z.scratch[0] & 0x0f != zlibDeflate) || (h%31 != 0) {
|
if (z.scratch[0] & 0x0f != zlibDeflate) || (h%31 != 0) {
|
||||||
return nil, HeaderError;
|
return nil, HeaderError
|
||||||
}
|
}
|
||||||
if z.scratch[1] & 0x20 != 0 {
|
if z.scratch[1] & 0x20 != 0 {
|
||||||
// BUG(nigeltao): The zlib package does not implement the FDICT flag.
|
// BUG(nigeltao): The zlib package does not implement the FDICT flag.
|
||||||
return nil, UnsupportedError;
|
return nil, UnsupportedError
|
||||||
}
|
}
|
||||||
z.digest = adler32.New();
|
z.digest = adler32.New();
|
||||||
z.inflater = flate.NewInflater(z.r);
|
z.inflater = flate.NewInflater(z.r);
|
||||||
|
|
@ -58,10 +58,10 @@ func NewInflater(r io.Reader) (io.ReadCloser, os.Error) {
|
||||||
|
|
||||||
func (z *reader) Read(p []byte) (n int, err os.Error) {
|
func (z *reader) Read(p []byte) (n int, err os.Error) {
|
||||||
if z.err != nil {
|
if z.err != nil {
|
||||||
return 0, z.err;
|
return 0, z.err
|
||||||
}
|
}
|
||||||
if len(p) == 0 {
|
if len(p) == 0 {
|
||||||
return 0, nil;
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err = z.inflater.Read(p);
|
n, err = z.inflater.Read(p);
|
||||||
|
|
@ -88,7 +88,7 @@ func (z *reader) Read(p []byte) (n int, err os.Error) {
|
||||||
// Calling Close does not close the wrapped io.Reader originally passed to NewInflater.
|
// Calling Close does not close the wrapped io.Reader originally passed to NewInflater.
|
||||||
func (z *reader) Close() os.Error {
|
func (z *reader) Close() os.Error {
|
||||||
if z.err != nil {
|
if z.err != nil {
|
||||||
return z.err;
|
return z.err
|
||||||
}
|
}
|
||||||
z.err = z.inflater.Close();
|
z.err = z.inflater.Close();
|
||||||
return z.err;
|
return z.err;
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ func TestInflater(t *testing.T) {
|
||||||
zlib, err := NewInflater(in);
|
zlib, err := NewInflater(in);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != tt.err {
|
if err != tt.err {
|
||||||
t.Errorf("%s: NewInflater: %s", tt.desc, err);
|
t.Errorf("%s: NewInflater: %s", tt.desc, err)
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -83,13 +83,13 @@ func TestInflater(t *testing.T) {
|
||||||
n, err := io.Copy(b, zlib);
|
n, err := io.Copy(b, zlib);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != tt.err {
|
if err != tt.err {
|
||||||
t.Errorf("%s: io.Copy: %v want %v", tt.desc, err, tt.err);
|
t.Errorf("%s: io.Copy: %v want %v", tt.desc, err, tt.err)
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
s := b.String();
|
s := b.String();
|
||||||
if s != tt.raw {
|
if s != tt.raw {
|
||||||
t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.desc, n, s, len(tt.raw), tt.raw);
|
t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.desc, n, s, len(tt.raw), tt.raw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ type writer struct {
|
||||||
|
|
||||||
// NewDeflater calls NewDeflaterLevel with the default compression level.
|
// NewDeflater calls NewDeflaterLevel with the default compression level.
|
||||||
func NewDeflater(w io.Writer) (io.WriteCloser, os.Error) {
|
func NewDeflater(w io.Writer) (io.WriteCloser, os.Error) {
|
||||||
return NewDeflaterLevel(w, DefaultCompression);
|
return NewDeflaterLevel(w, DefaultCompression)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDeflater creates a new io.WriteCloser that satisfies writes by compressing data written to w.
|
// NewDeflater creates a new io.WriteCloser that satisfies writes by compressing data written to w.
|
||||||
|
|
@ -50,19 +50,19 @@ func NewDeflaterLevel(w io.Writer, level int) (io.WriteCloser, os.Error) {
|
||||||
// The final five FCHECK bits form a mod-31 checksum.
|
// The final five FCHECK bits form a mod-31 checksum.
|
||||||
switch level {
|
switch level {
|
||||||
case 0, 1:
|
case 0, 1:
|
||||||
z.scratch[1] = 0x01;
|
z.scratch[1] = 0x01
|
||||||
case 2, 3, 4, 5:
|
case 2, 3, 4, 5:
|
||||||
z.scratch[1] = 0x5e;
|
z.scratch[1] = 0x5e
|
||||||
case 6, -1:
|
case 6, -1:
|
||||||
z.scratch[1] = 0x9c;
|
z.scratch[1] = 0x9c
|
||||||
case 7, 8, 9:
|
case 7, 8, 9:
|
||||||
z.scratch[1] = 0xda;
|
z.scratch[1] = 0xda
|
||||||
default:
|
default:
|
||||||
return nil, os.NewError("level out of range");
|
return nil, os.NewError("level out of range")
|
||||||
}
|
}
|
||||||
_, err := w.Write(z.scratch[0:2]);
|
_, err := w.Write(z.scratch[0:2]);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err;
|
return nil, err
|
||||||
}
|
}
|
||||||
z.w = w;
|
z.w = w;
|
||||||
z.deflater = flate.NewDeflater(w, level);
|
z.deflater = flate.NewDeflater(w, level);
|
||||||
|
|
@ -72,10 +72,10 @@ func NewDeflaterLevel(w io.Writer, level int) (io.WriteCloser, os.Error) {
|
||||||
|
|
||||||
func (z *writer) Write(p []byte) (n int, err os.Error) {
|
func (z *writer) Write(p []byte) (n int, err os.Error) {
|
||||||
if z.err != nil {
|
if z.err != nil {
|
||||||
return 0, z.err;
|
return 0, z.err
|
||||||
}
|
}
|
||||||
if len(p) == 0 {
|
if len(p) == 0 {
|
||||||
return 0, nil;
|
return 0, nil
|
||||||
}
|
}
|
||||||
n, err = z.deflater.Write(p);
|
n, err = z.deflater.Write(p);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -89,11 +89,11 @@ func (z *writer) Write(p []byte) (n int, err os.Error) {
|
||||||
// Calling Close does not close the wrapped io.Writer originally passed to NewDeflater.
|
// Calling Close does not close the wrapped io.Writer originally passed to NewDeflater.
|
||||||
func (z *writer) Close() os.Error {
|
func (z *writer) Close() os.Error {
|
||||||
if z.err != nil {
|
if z.err != nil {
|
||||||
return z.err;
|
return z.err
|
||||||
}
|
}
|
||||||
z.err = z.deflater.Close();
|
z.err = z.deflater.Close();
|
||||||
if z.err != nil {
|
if z.err != nil {
|
||||||
return z.err;
|
return z.err
|
||||||
}
|
}
|
||||||
checksum := z.digest.Sum32();
|
checksum := z.digest.Sum32();
|
||||||
// ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
|
// ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
|
||||||
|
|
|
||||||
|
|
@ -53,14 +53,14 @@ func testFileLevel(t *testing.T, fn string, level int) {
|
||||||
_, err1 := zlibw.Write(b[0:n]);
|
_, err1 := zlibw.Write(b[0:n]);
|
||||||
if err1 == os.EPIPE {
|
if err1 == os.EPIPE {
|
||||||
// Fail, but do not report the error, as some other (presumably reportable) error broke the pipe.
|
// Fail, but do not report the error, as some other (presumably reportable) error broke the pipe.
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
t.Errorf("%s (level=%d): %v", fn, level, err1);
|
t.Errorf("%s (level=%d): %v", fn, level, err1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if err0 == os.EOF {
|
if err0 == os.EOF {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
@ -99,7 +99,7 @@ func TestWriter(t *testing.T) {
|
||||||
testFileLevel(t, fn, DefaultCompression);
|
testFileLevel(t, fn, DefaultCompression);
|
||||||
testFileLevel(t, fn, NoCompression);
|
testFileLevel(t, fn, NoCompression);
|
||||||
for level := BestSpeed; level <= BestCompression; level++ {
|
for level := BestSpeed; level <= BestCompression; level++ {
|
||||||
testFileLevel(t, fn, level);
|
testFileLevel(t, fn, level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ func up(h Interface, j int) {
|
||||||
for {
|
for {
|
||||||
i := (j-1)/2;
|
i := (j-1)/2;
|
||||||
if i == j || h.Less(i, j) {
|
if i == j || h.Less(i, j) {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
h.Swap(i, j);
|
h.Swap(i, j);
|
||||||
j = i;
|
j = i;
|
||||||
|
|
@ -80,13 +80,13 @@ func down(h Interface, i, n int) {
|
||||||
for {
|
for {
|
||||||
j := 2*i + 1;
|
j := 2*i + 1;
|
||||||
if j >= n {
|
if j >= n {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
if j1 := j+1; j1 < n && !h.Less(j, j1) {
|
if j1 := j+1; j1 < n && !h.Less(j, j1) {
|
||||||
j = j1; // = 2*i + 2
|
j = j1 // = 2*i + 2
|
||||||
}
|
}
|
||||||
if h.Less(i, j) {
|
if h.Less(i, j) {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
h.Swap(i, j);
|
h.Swap(i, j);
|
||||||
i = j;
|
i = j;
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ func (h *myHeap) Pop() interface{} { return h.IntVector.Pop() }
|
||||||
func TestInit(t *testing.T) {
|
func TestInit(t *testing.T) {
|
||||||
h := newHeap();
|
h := newHeap();
|
||||||
for i := 20; i > 0; i-- {
|
for i := 20; i > 0; i-- {
|
||||||
h.Push(i);
|
h.Push(i)
|
||||||
}
|
}
|
||||||
Init(h);
|
Init(h);
|
||||||
h.verify(t, 0);
|
h.verify(t, 0);
|
||||||
|
|
@ -61,7 +61,7 @@ func TestInit(t *testing.T) {
|
||||||
x := Pop(h).(int);
|
x := Pop(h).(int);
|
||||||
h.verify(t, 0);
|
h.verify(t, 0);
|
||||||
if x != i {
|
if x != i {
|
||||||
t.Errorf("%d.th pop got %d; want %d", i, x, i);
|
t.Errorf("%d.th pop got %d; want %d", i, x, i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +72,7 @@ func Test(t *testing.T) {
|
||||||
h.verify(t, 0);
|
h.verify(t, 0);
|
||||||
|
|
||||||
for i := 20; i > 10; i-- {
|
for i := 20; i > 10; i-- {
|
||||||
h.Push(i);
|
h.Push(i)
|
||||||
}
|
}
|
||||||
Init(h);
|
Init(h);
|
||||||
h.verify(t, 0);
|
h.verify(t, 0);
|
||||||
|
|
@ -85,11 +85,11 @@ func Test(t *testing.T) {
|
||||||
for i := 1; h.Len() > 0; i++ {
|
for i := 1; h.Len() > 0; i++ {
|
||||||
x := Pop(h).(int);
|
x := Pop(h).(int);
|
||||||
if i < 20 {
|
if i < 20 {
|
||||||
Push(h, 20+i);
|
Push(h, 20+i)
|
||||||
}
|
}
|
||||||
h.verify(t, 0);
|
h.verify(t, 0);
|
||||||
if x != i {
|
if x != i {
|
||||||
t.Errorf("%d.th pop got %d; want %d", i, x, i);
|
t.Errorf("%d.th pop got %d; want %d", i, x, i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,17 +52,17 @@ func (l *List) Back() *Element { return l.back }
|
||||||
// Remove removes the element from the list.
|
// Remove removes the element from the list.
|
||||||
func (l *List) Remove(e *Element) {
|
func (l *List) Remove(e *Element) {
|
||||||
if e.id != l.id {
|
if e.id != l.id {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if e.prev == nil {
|
if e.prev == nil {
|
||||||
l.front = e.next;
|
l.front = e.next
|
||||||
} else {
|
} else {
|
||||||
e.prev.next = e.next;
|
e.prev.next = e.next
|
||||||
}
|
}
|
||||||
if e.next == nil {
|
if e.next == nil {
|
||||||
l.back = e.prev;
|
l.back = e.prev
|
||||||
} else {
|
} else {
|
||||||
e.next.prev = e.prev;
|
e.next.prev = e.prev
|
||||||
}
|
}
|
||||||
|
|
||||||
e.prev = nil;
|
e.prev = nil;
|
||||||
|
|
@ -73,9 +73,9 @@ func (l *List) Remove(e *Element) {
|
||||||
func (l *List) insertBefore(e *Element, mark *Element) {
|
func (l *List) insertBefore(e *Element, mark *Element) {
|
||||||
if mark.prev == nil {
|
if mark.prev == nil {
|
||||||
// new front of the list
|
// new front of the list
|
||||||
l.front = e;
|
l.front = e
|
||||||
} else {
|
} else {
|
||||||
mark.prev.next = e;
|
mark.prev.next = e
|
||||||
}
|
}
|
||||||
e.prev = mark.prev;
|
e.prev = mark.prev;
|
||||||
mark.prev = e;
|
mark.prev = e;
|
||||||
|
|
@ -86,9 +86,9 @@ func (l *List) insertBefore(e *Element, mark *Element) {
|
||||||
func (l *List) insertAfter(e *Element, mark *Element) {
|
func (l *List) insertAfter(e *Element, mark *Element) {
|
||||||
if mark.next == nil {
|
if mark.next == nil {
|
||||||
// new back of the list
|
// new back of the list
|
||||||
l.back = e;
|
l.back = e
|
||||||
} else {
|
} else {
|
||||||
mark.next.prev = e;
|
mark.next.prev = e
|
||||||
}
|
}
|
||||||
e.next = mark.next;
|
e.next = mark.next;
|
||||||
mark.next = e;
|
mark.next = e;
|
||||||
|
|
@ -121,7 +121,7 @@ func (l *List) insertBack(e *Element) {
|
||||||
// PushFront inserts the value at the front of the list and returns a new Element containing the value.
|
// PushFront inserts the value at the front of the list and returns a new Element containing the value.
|
||||||
func (l *List) PushFront(value interface{}) *Element {
|
func (l *List) PushFront(value interface{}) *Element {
|
||||||
if l.id == nil {
|
if l.id == nil {
|
||||||
l.Init();
|
l.Init()
|
||||||
}
|
}
|
||||||
e := &Element{nil, nil, l.id, value};
|
e := &Element{nil, nil, l.id, value};
|
||||||
l.insertFront(e);
|
l.insertFront(e);
|
||||||
|
|
@ -131,7 +131,7 @@ func (l *List) PushFront(value interface{}) *Element {
|
||||||
// PushBack inserts the value at the back of the list and returns a new Element containing the value.
|
// PushBack inserts the value at the back of the list and returns a new Element containing the value.
|
||||||
func (l *List) PushBack(value interface{}) *Element {
|
func (l *List) PushBack(value interface{}) *Element {
|
||||||
if l.id == nil {
|
if l.id == nil {
|
||||||
l.Init();
|
l.Init()
|
||||||
}
|
}
|
||||||
e := &Element{nil, nil, l.id, value};
|
e := &Element{nil, nil, l.id, value};
|
||||||
l.insertBack(e);
|
l.insertBack(e);
|
||||||
|
|
@ -141,7 +141,7 @@ func (l *List) PushBack(value interface{}) *Element {
|
||||||
// InsertBefore inserts the value immediately before mark and returns a new Element containing the value.
|
// InsertBefore inserts the value immediately before mark and returns a new Element containing the value.
|
||||||
func (l *List) InsertBefore(value interface{}, mark *Element) *Element {
|
func (l *List) InsertBefore(value interface{}, mark *Element) *Element {
|
||||||
if mark.id != l.id {
|
if mark.id != l.id {
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
e := &Element{nil, nil, l.id, value};
|
e := &Element{nil, nil, l.id, value};
|
||||||
l.insertBefore(e, mark);
|
l.insertBefore(e, mark);
|
||||||
|
|
@ -151,7 +151,7 @@ func (l *List) InsertBefore(value interface{}, mark *Element) *Element {
|
||||||
// InsertAfter inserts the value immediately after mark and returns a new Element containing the value.
|
// InsertAfter inserts the value immediately after mark and returns a new Element containing the value.
|
||||||
func (l *List) InsertAfter(value interface{}, mark *Element) *Element {
|
func (l *List) InsertAfter(value interface{}, mark *Element) *Element {
|
||||||
if mark.id != l.id {
|
if mark.id != l.id {
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
e := &Element{nil, nil, l.id, value};
|
e := &Element{nil, nil, l.id, value};
|
||||||
l.insertAfter(e, mark);
|
l.insertAfter(e, mark);
|
||||||
|
|
@ -161,7 +161,7 @@ func (l *List) InsertAfter(value interface{}, mark *Element) *Element {
|
||||||
// MoveToFront moves the element to the front of the list.
|
// MoveToFront moves the element to the front of the list.
|
||||||
func (l *List) MoveToFront(e *Element) {
|
func (l *List) MoveToFront(e *Element) {
|
||||||
if e.id != l.id || l.front == e {
|
if e.id != l.id || l.front == e {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
l.Remove(e);
|
l.Remove(e);
|
||||||
l.insertFront(e);
|
l.insertFront(e);
|
||||||
|
|
@ -170,7 +170,7 @@ func (l *List) MoveToFront(e *Element) {
|
||||||
// MoveToBack moves the element to the back of the list.
|
// MoveToBack moves the element to the back of the list.
|
||||||
func (l *List) MoveToBack(e *Element) {
|
func (l *List) MoveToBack(e *Element) {
|
||||||
if e.id != l.id || l.back == e {
|
if e.id != l.id || l.back == e {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
l.Remove(e);
|
l.Remove(e);
|
||||||
l.insertBack(e);
|
l.insertBack(e);
|
||||||
|
|
@ -181,7 +181,7 @@ func (l *List) Len() int { return l.len }
|
||||||
|
|
||||||
func (l *List) iterate(c chan<- interface{}) {
|
func (l *List) iterate(c chan<- interface{}) {
|
||||||
for e := l.front; e != nil; e = e.next {
|
for e := l.front; e != nil; e = e.next {
|
||||||
c <- e.Value;
|
c <- e.Value
|
||||||
}
|
}
|
||||||
close(c);
|
close(c);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,39 +11,39 @@ import (
|
||||||
func checkListPointers(t *testing.T, l *List, es []*Element) {
|
func checkListPointers(t *testing.T, l *List, es []*Element) {
|
||||||
if len(es) == 0 {
|
if len(es) == 0 {
|
||||||
if l.front != nil || l.back != nil {
|
if l.front != nil || l.back != nil {
|
||||||
t.Errorf("l.front/l.back = %v/%v should be nil/nil", l.front, l.back);
|
t.Errorf("l.front/l.back = %v/%v should be nil/nil", l.front, l.back)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if l.front != es[0] {
|
if l.front != es[0] {
|
||||||
t.Errorf("l.front = %v, want %v", l.front, es[0]);
|
t.Errorf("l.front = %v, want %v", l.front, es[0])
|
||||||
}
|
}
|
||||||
if last := es[len(es)-1]; l.back != last {
|
if last := es[len(es)-1]; l.back != last {
|
||||||
t.Errorf("l.back = %v, want %v", l.back, last);
|
t.Errorf("l.back = %v, want %v", l.back, last)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(es); i++ {
|
for i := 0; i < len(es); i++ {
|
||||||
e := es[i];
|
e := es[i];
|
||||||
var e_prev, e_next *Element = nil, nil;
|
var e_prev, e_next *Element = nil, nil;
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
e_prev = es[i-1];
|
e_prev = es[i-1]
|
||||||
}
|
}
|
||||||
if i < len(es)-1 {
|
if i < len(es)-1 {
|
||||||
e_next = es[i+1];
|
e_next = es[i+1]
|
||||||
}
|
}
|
||||||
if e.prev != e_prev {
|
if e.prev != e_prev {
|
||||||
t.Errorf("elt #%d (%v) has prev=%v, want %v", i, e, e.prev, e_prev);
|
t.Errorf("elt #%d (%v) has prev=%v, want %v", i, e, e.prev, e_prev)
|
||||||
}
|
}
|
||||||
if e.next != e_next {
|
if e.next != e_next {
|
||||||
t.Errorf("elt #%d (%v) has next=%v, want %v", i, e, e.next, e_next);
|
t.Errorf("elt #%d (%v) has next=%v, want %v", i, e, e.next, e_next)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkListLen(t *testing.T, l *List, n int) {
|
func checkListLen(t *testing.T, l *List, n int) {
|
||||||
if an := l.Len(); an != n {
|
if an := l.Len(); an != n {
|
||||||
t.Errorf("l.Len() = %d, want %d", an, n);
|
t.Errorf("l.Len() = %d, want %d", an, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,11 +118,11 @@ func TestList(t *testing.T) {
|
||||||
sum := 0;
|
sum := 0;
|
||||||
for e := range l.Iter() {
|
for e := range l.Iter() {
|
||||||
if i, ok := e.(int); ok {
|
if i, ok := e.(int); ok {
|
||||||
sum += i;
|
sum += i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sum != 4 {
|
if sum != 4 {
|
||||||
t.Errorf("sum over l.Iter() = %d, want 4", sum);
|
t.Errorf("sum over l.Iter() = %d, want 4", sum)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear all elements by iterating
|
// Clear all elements by iterating
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ func (r *Ring) init() *Ring {
|
||||||
// Next returns the next ring element. r must not be empty.
|
// Next returns the next ring element. r must not be empty.
|
||||||
func (r *Ring) Next() *Ring {
|
func (r *Ring) Next() *Ring {
|
||||||
if r.next == nil {
|
if r.next == nil {
|
||||||
return r.init();
|
return r.init()
|
||||||
}
|
}
|
||||||
return r.next;
|
return r.next;
|
||||||
}
|
}
|
||||||
|
|
@ -36,7 +36,7 @@ func (r *Ring) Next() *Ring {
|
||||||
// Prev returns the previous ring element. r must not be empty.
|
// Prev returns the previous ring element. r must not be empty.
|
||||||
func (r *Ring) Prev() *Ring {
|
func (r *Ring) Prev() *Ring {
|
||||||
if r.next == nil {
|
if r.next == nil {
|
||||||
return r.init();
|
return r.init()
|
||||||
}
|
}
|
||||||
return r.prev;
|
return r.prev;
|
||||||
}
|
}
|
||||||
|
|
@ -47,16 +47,16 @@ func (r *Ring) Prev() *Ring {
|
||||||
//
|
//
|
||||||
func (r *Ring) Move(n int) *Ring {
|
func (r *Ring) Move(n int) *Ring {
|
||||||
if r.next == nil {
|
if r.next == nil {
|
||||||
return r.init();
|
return r.init()
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case n < 0:
|
case n < 0:
|
||||||
for ; n < 0; n++ {
|
for ; n < 0; n++ {
|
||||||
r = r.prev;
|
r = r.prev
|
||||||
}
|
}
|
||||||
case n > 0:
|
case n > 0:
|
||||||
for ; n > 0; n-- {
|
for ; n > 0; n-- {
|
||||||
r = r.next;
|
r = r.next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
|
@ -66,7 +66,7 @@ func (r *Ring) Move(n int) *Ring {
|
||||||
// New creates a ring of n elements.
|
// New creates a ring of n elements.
|
||||||
func New(n int) *Ring {
|
func New(n int) *Ring {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
r := new(Ring);
|
r := new(Ring);
|
||||||
p := r;
|
p := r;
|
||||||
|
|
@ -117,7 +117,7 @@ func (r *Ring) Link(s *Ring) *Ring {
|
||||||
//
|
//
|
||||||
func (r *Ring) Unlink(n int) *Ring {
|
func (r *Ring) Unlink(n int) *Ring {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
return r.Link(r.Move(n+1));
|
return r.Link(r.Move(n+1));
|
||||||
}
|
}
|
||||||
|
|
@ -131,7 +131,7 @@ func (r *Ring) Len() int {
|
||||||
if r != nil {
|
if r != nil {
|
||||||
n = 1;
|
n = 1;
|
||||||
for p := r.Next(); p != r; p = p.next {
|
for p := r.Next(); p != r; p = p.next {
|
||||||
n++;
|
n++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
|
|
@ -144,7 +144,7 @@ func (r *Ring) Iter() <-chan interface{} {
|
||||||
if r != nil {
|
if r != nil {
|
||||||
c <- r.Value;
|
c <- r.Value;
|
||||||
for p := r.Next(); p != r; p = p.next {
|
for p := r.Next(); p != r; p = p.next {
|
||||||
c <- p.Value;
|
c <- p.Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(c);
|
close(c);
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ func verify(t *testing.T, r *Ring, N int, sum int) {
|
||||||
// Len
|
// Len
|
||||||
n := r.Len();
|
n := r.Len();
|
||||||
if n != N {
|
if n != N {
|
||||||
t.Errorf("r.Len() == %d; expected %d", n, N);
|
t.Errorf("r.Len() == %d; expected %d", n, N)
|
||||||
}
|
}
|
||||||
|
|
||||||
// iteration
|
// iteration
|
||||||
|
|
@ -38,18 +38,18 @@ func verify(t *testing.T, r *Ring, N int, sum int) {
|
||||||
for p := range r.Iter() {
|
for p := range r.Iter() {
|
||||||
n++;
|
n++;
|
||||||
if p != nil {
|
if p != nil {
|
||||||
s += p.(int);
|
s += p.(int)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if n != N {
|
if n != N {
|
||||||
t.Errorf("number of forward iterations == %d; expected %d", n, N);
|
t.Errorf("number of forward iterations == %d; expected %d", n, N)
|
||||||
}
|
}
|
||||||
if sum >= 0 && s != sum {
|
if sum >= 0 && s != sum {
|
||||||
t.Errorf("forward ring sum = %d; expected %d", s, sum);
|
t.Errorf("forward ring sum = %d; expected %d", s, sum)
|
||||||
}
|
}
|
||||||
|
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// connections
|
// connections
|
||||||
|
|
@ -57,41 +57,41 @@ func verify(t *testing.T, r *Ring, N int, sum int) {
|
||||||
var p *Ring; // previous element
|
var p *Ring; // previous element
|
||||||
for q := r; p == nil || q != r; q = q.next {
|
for q := r; p == nil || q != r; q = q.next {
|
||||||
if p != nil && p != q.prev {
|
if p != nil && p != q.prev {
|
||||||
t.Errorf("prev = %p, expected q.prev = %p\n", p, q.prev);
|
t.Errorf("prev = %p, expected q.prev = %p\n", p, q.prev)
|
||||||
}
|
}
|
||||||
p = q;
|
p = q;
|
||||||
}
|
}
|
||||||
if p != r.prev {
|
if p != r.prev {
|
||||||
t.Errorf("prev = %p, expected r.prev = %p\n", p, r.prev);
|
t.Errorf("prev = %p, expected r.prev = %p\n", p, r.prev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next, Prev
|
// Next, Prev
|
||||||
if r.Next() != r.next {
|
if r.Next() != r.next {
|
||||||
t.Errorf("r.Next() != r.next");
|
t.Errorf("r.Next() != r.next")
|
||||||
}
|
}
|
||||||
if r.Prev() != r.prev {
|
if r.Prev() != r.prev {
|
||||||
t.Errorf("r.Prev() != r.prev");
|
t.Errorf("r.Prev() != r.prev")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move
|
// Move
|
||||||
if r.Move(0) != r {
|
if r.Move(0) != r {
|
||||||
t.Errorf("r.Move(0) != r");
|
t.Errorf("r.Move(0) != r")
|
||||||
}
|
}
|
||||||
if r.Move(N) != r {
|
if r.Move(N) != r {
|
||||||
t.Errorf("r.Move(%d) != r", N);
|
t.Errorf("r.Move(%d) != r", N)
|
||||||
}
|
}
|
||||||
if r.Move(-N) != r {
|
if r.Move(-N) != r {
|
||||||
t.Errorf("r.Move(%d) != r", -N);
|
t.Errorf("r.Move(%d) != r", -N)
|
||||||
}
|
}
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
ni := N+i;
|
ni := N+i;
|
||||||
mi := ni%N;
|
mi := ni%N;
|
||||||
if r.Move(ni) != r.Move(mi) {
|
if r.Move(ni) != r.Move(mi) {
|
||||||
t.Errorf("r.Move(%d) != r.Move(%d)", ni, mi);
|
t.Errorf("r.Move(%d) != r.Move(%d)", ni, mi)
|
||||||
}
|
}
|
||||||
if r.Move(-ni) != r.Move(-mi) {
|
if r.Move(-ni) != r.Move(-mi) {
|
||||||
t.Errorf("r.Move(%d) != r.Move(%d)", -ni, -mi);
|
t.Errorf("r.Move(%d) != r.Move(%d)", -ni, -mi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -132,7 +132,7 @@ func makeN(n int) *Ring {
|
||||||
func sum(r *Ring) int {
|
func sum(r *Ring) int {
|
||||||
s := 0;
|
s := 0;
|
||||||
for p := range r.Iter() {
|
for p := range r.Iter() {
|
||||||
s += p.(int);
|
s += p.(int)
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
@ -159,13 +159,13 @@ func TestLink1(t *testing.T) {
|
||||||
r2a := r1a.Link(&r1b);
|
r2a := r1a.Link(&r1b);
|
||||||
verify(t, r2a, 2, 1);
|
verify(t, r2a, 2, 1);
|
||||||
if r2a != r1a {
|
if r2a != r1a {
|
||||||
t.Errorf("a) 2-element link failed");
|
t.Errorf("a) 2-element link failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
r2b := r2a.Link(r2a.Next());
|
r2b := r2a.Link(r2a.Next());
|
||||||
verify(t, r2b, 2, 1);
|
verify(t, r2b, 2, 1);
|
||||||
if r2b != r2a.Next() {
|
if r2b != r2a.Next() {
|
||||||
t.Errorf("b) 2-element link failed");
|
t.Errorf("b) 2-element link failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
r1c := r2b.Link(r2b);
|
r1c := r2b.Link(r2b);
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ func (p *IntVector) Last() int { return p.Vector.Last().(int) }
|
||||||
func (p *IntVector) Data() []int {
|
func (p *IntVector) Data() []int {
|
||||||
arr := make([]int, p.Len());
|
arr := make([]int, p.Len());
|
||||||
for i, v := range p.a {
|
for i, v := range p.a {
|
||||||
arr[i] = v.(int);
|
arr[i] = v.(int)
|
||||||
}
|
}
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
@ -54,14 +54,14 @@ func (p *IntVector) Insert(i int, x int) { p.Vector.Insert(i, x) }
|
||||||
// InsertVector inserts into the vector the contents of the Vector
|
// InsertVector inserts into the vector the contents of the Vector
|
||||||
// x such that the 0th element of x appears at index i after insertion.
|
// x such that the 0th element of x appears at index i after insertion.
|
||||||
func (p *IntVector) InsertVector(i int, x *IntVector) {
|
func (p *IntVector) InsertVector(i int, x *IntVector) {
|
||||||
p.Vector.InsertVector(i, &x.Vector);
|
p.Vector.InsertVector(i, &x.Vector)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Slice returns a new IntVector by slicing the old one to extract slice [i:j].
|
// Slice returns a new IntVector by slicing the old one to extract slice [i:j].
|
||||||
// The elements are copied. The original vector is unchanged.
|
// The elements are copied. The original vector is unchanged.
|
||||||
func (p *IntVector) Slice(i, j int) *IntVector {
|
func (p *IntVector) Slice(i, j int) *IntVector {
|
||||||
return &IntVector{*p.Vector.Slice(i, j)};
|
return &IntVector{*p.Vector.Slice(i, j)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -75,7 +75,7 @@ func (p *IntVector) Pop() int { return p.Vector.Pop().(int) }
|
||||||
|
|
||||||
// AppendVector appends the entire IntVector x to the end of this vector.
|
// AppendVector appends the entire IntVector x to the end of this vector.
|
||||||
func (p *IntVector) AppendVector(x *IntVector) {
|
func (p *IntVector) AppendVector(x *IntVector) {
|
||||||
p.Vector.InsertVector(len(p.a), &x.Vector);
|
p.Vector.InsertVector(len(p.a), &x.Vector)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -87,7 +87,7 @@ func (p *IntVector) Less(i, j int) bool { return p.At(i) < p.At(j) }
|
||||||
// Iterate over all elements; driver for range
|
// Iterate over all elements; driver for range
|
||||||
func (p *IntVector) iterate(c chan<- int) {
|
func (p *IntVector) iterate(c chan<- int) {
|
||||||
for _, v := range p.a {
|
for _, v := range p.a {
|
||||||
c <- v.(int);
|
c <- v.(int)
|
||||||
}
|
}
|
||||||
close(c);
|
close(c);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ func (p *StringVector) Last() string { return p.Vector.Last().(string) }
|
||||||
func (p *StringVector) Data() []string {
|
func (p *StringVector) Data() []string {
|
||||||
arr := make([]string, p.Len());
|
arr := make([]string, p.Len());
|
||||||
for i, v := range p.a {
|
for i, v := range p.a {
|
||||||
arr[i] = v.(string);
|
arr[i] = v.(string)
|
||||||
}
|
}
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
@ -48,21 +48,21 @@ func (p *StringVector) Data() []string {
|
||||||
// Insert inserts into the vector an element of value x before
|
// Insert inserts into the vector an element of value x before
|
||||||
// the current element at index i.
|
// the current element at index i.
|
||||||
func (p *StringVector) Insert(i int, x string) {
|
func (p *StringVector) Insert(i int, x string) {
|
||||||
p.Vector.Insert(i, x);
|
p.Vector.Insert(i, x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// InsertVector inserts into the vector the contents of the Vector
|
// InsertVector inserts into the vector the contents of the Vector
|
||||||
// x such that the 0th element of x appears at index i after insertion.
|
// x such that the 0th element of x appears at index i after insertion.
|
||||||
func (p *StringVector) InsertVector(i int, x *StringVector) {
|
func (p *StringVector) InsertVector(i int, x *StringVector) {
|
||||||
p.Vector.InsertVector(i, &x.Vector);
|
p.Vector.InsertVector(i, &x.Vector)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Slice returns a new StringVector by slicing the old one to extract slice [i:j].
|
// Slice returns a new StringVector by slicing the old one to extract slice [i:j].
|
||||||
// The elements are copied. The original vector is unchanged.
|
// The elements are copied. The original vector is unchanged.
|
||||||
func (p *StringVector) Slice(i, j int) *StringVector {
|
func (p *StringVector) Slice(i, j int) *StringVector {
|
||||||
return &StringVector{*p.Vector.Slice(i, j)};
|
return &StringVector{*p.Vector.Slice(i, j)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -76,7 +76,7 @@ func (p *StringVector) Pop() string { return p.Vector.Pop().(string) }
|
||||||
|
|
||||||
// AppendVector appends the entire StringVector x to the end of this vector.
|
// AppendVector appends the entire StringVector x to the end of this vector.
|
||||||
func (p *StringVector) AppendVector(x *StringVector) {
|
func (p *StringVector) AppendVector(x *StringVector) {
|
||||||
p.Vector.InsertVector(len(p.a), &x.Vector);
|
p.Vector.InsertVector(len(p.a), &x.Vector)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -88,7 +88,7 @@ func (p *StringVector) Less(i, j int) bool { return p.At(i) < p.At(j) }
|
||||||
// Iterate over all elements; driver for range
|
// Iterate over all elements; driver for range
|
||||||
func (p *StringVector) iterate(c chan<- string) {
|
func (p *StringVector) iterate(c chan<- string) {
|
||||||
for _, v := range p.a {
|
for _, v := range p.a {
|
||||||
c <- v.(string);
|
c <- v.(string)
|
||||||
}
|
}
|
||||||
close(c);
|
close(c);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ type Vector struct {
|
||||||
|
|
||||||
func copy(dst, src []Element) {
|
func copy(dst, src []Element) {
|
||||||
for i := 0; i < len(src); i++ {
|
for i := 0; i < len(src); i++ {
|
||||||
dst[i] = src[i];
|
dst[i] = src[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,13 +32,13 @@ func expand(a []Element, i, n int) []Element {
|
||||||
len1 := len0+n;
|
len1 := len0+n;
|
||||||
if len1 < cap(a) {
|
if len1 < cap(a) {
|
||||||
// enough space - just expand
|
// enough space - just expand
|
||||||
a = a[0:len1];
|
a = a[0:len1]
|
||||||
} else {
|
} else {
|
||||||
// not enough space - double capacity
|
// not enough space - double capacity
|
||||||
capb := cap(a)*2;
|
capb := cap(a)*2;
|
||||||
if capb < len1 {
|
if capb < len1 {
|
||||||
// still not enough - use required length
|
// still not enough - use required length
|
||||||
capb = len1;
|
capb = len1
|
||||||
}
|
}
|
||||||
// capb >= len1
|
// capb >= len1
|
||||||
b := make([]Element, len1, capb);
|
b := make([]Element, len1, capb);
|
||||||
|
|
@ -48,7 +48,7 @@ func expand(a []Element, i, n int) []Element {
|
||||||
|
|
||||||
// make a hole
|
// make a hole
|
||||||
for j := len0-1; j >= i; j-- {
|
for j := len0-1; j >= i; j-- {
|
||||||
a[j+n] = a[j];
|
a[j+n] = a[j]
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
@ -63,13 +63,13 @@ func (p *Vector) Init(initial_len int) *Vector {
|
||||||
if cap(a) == 0 || cap(a) < initial_len {
|
if cap(a) == 0 || cap(a) < initial_len {
|
||||||
n := 8; // initial capacity
|
n := 8; // initial capacity
|
||||||
if initial_len > n {
|
if initial_len > n {
|
||||||
n = initial_len;
|
n = initial_len
|
||||||
}
|
}
|
||||||
a = make([]Element, n);
|
a = make([]Element, n);
|
||||||
} else {
|
} else {
|
||||||
// nil out entries
|
// nil out entries
|
||||||
for j := len(a)-1; j >= 0; j-- {
|
for j := len(a)-1; j >= 0; j-- {
|
||||||
a[j] = nil;
|
a[j] = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,7 +86,7 @@ func New(len int) *Vector { return new(Vector).Init(len) }
|
||||||
// Len is 0 if p == nil.
|
// Len is 0 if p == nil.
|
||||||
func (p *Vector) Len() int {
|
func (p *Vector) Len() int {
|
||||||
if p == nil {
|
if p == nil {
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
return len(p.a);
|
return len(p.a);
|
||||||
}
|
}
|
||||||
|
|
@ -108,7 +108,7 @@ func (p *Vector) Last() Element { return p.a[len(p.a)-1] }
|
||||||
func (p *Vector) Data() []Element {
|
func (p *Vector) Data() []Element {
|
||||||
arr := make([]Element, p.Len());
|
arr := make([]Element, p.Len());
|
||||||
for i, v := range p.a {
|
for i, v := range p.a {
|
||||||
arr[i] = v;
|
arr[i] = v
|
||||||
}
|
}
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
@ -150,7 +150,7 @@ func (p *Vector) Cut(i, j int) {
|
||||||
|
|
||||||
copy(a[i:m], a[j:n]);
|
copy(a[i:m], a[j:n]);
|
||||||
for k := m; k < n; k++ {
|
for k := m; k < n; k++ {
|
||||||
a[k] = nil; // support GC, nil out entries
|
a[k] = nil // support GC, nil out entries
|
||||||
}
|
}
|
||||||
|
|
||||||
p.a = a[0:m];
|
p.a = a[0:m];
|
||||||
|
|
@ -170,7 +170,7 @@ func (p *Vector) Slice(i, j int) *Vector {
|
||||||
// The function should not change the indexing of the vector underfoot.
|
// The function should not change the indexing of the vector underfoot.
|
||||||
func (p *Vector) Do(f func(elem Element)) {
|
func (p *Vector) Do(f func(elem Element)) {
|
||||||
for i := 0; i < len(p.a); i++ {
|
for i := 0; i < len(p.a); i++ {
|
||||||
f(p.a[i]); // not too safe if f changes the Vector
|
f(p.a[i]) // not too safe if f changes the Vector
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -217,7 +217,7 @@ func (p *Vector) Swap(i, j int) {
|
||||||
// Iterate over all elements; driver for range
|
// Iterate over all elements; driver for range
|
||||||
func (p *Vector) iterate(c chan<- Element) {
|
func (p *Vector) iterate(c chan<- Element) {
|
||||||
for _, v := range p.a {
|
for _, v := range p.a {
|
||||||
c <- v;
|
c <- v
|
||||||
}
|
}
|
||||||
close(c);
|
close(c);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,11 @@ import "fmt"
|
||||||
func TestZeroLen(t *testing.T) {
|
func TestZeroLen(t *testing.T) {
|
||||||
var a *Vector;
|
var a *Vector;
|
||||||
if a.Len() != 0 {
|
if a.Len() != 0 {
|
||||||
t.Errorf("A) expected 0, got %d", a.Len());
|
t.Errorf("A) expected 0, got %d", a.Len())
|
||||||
}
|
}
|
||||||
a = New(0);
|
a = New(0);
|
||||||
if a.Len() != 0 {
|
if a.Len() != 0 {
|
||||||
t.Errorf("B) expected 0, got %d", a.Len());
|
t.Errorf("B) expected 0, got %d", a.Len())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -24,26 +24,26 @@ func TestZeroLen(t *testing.T) {
|
||||||
func TestInit(t *testing.T) {
|
func TestInit(t *testing.T) {
|
||||||
var a Vector;
|
var a Vector;
|
||||||
if a.Init(0).Len() != 0 {
|
if a.Init(0).Len() != 0 {
|
||||||
t.Error("A");
|
t.Error("A")
|
||||||
}
|
}
|
||||||
if a.Init(1).Len() != 1 {
|
if a.Init(1).Len() != 1 {
|
||||||
t.Error("B");
|
t.Error("B")
|
||||||
}
|
}
|
||||||
if a.Init(10).Len() != 10 {
|
if a.Init(10).Len() != 10 {
|
||||||
t.Error("C");
|
t.Error("C")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func TestNew(t *testing.T) {
|
func TestNew(t *testing.T) {
|
||||||
if New(0).Len() != 0 {
|
if New(0).Len() != 0 {
|
||||||
t.Error("A");
|
t.Error("A")
|
||||||
}
|
}
|
||||||
if New(1).Len() != 1 {
|
if New(1).Len() != 1 {
|
||||||
t.Error("B");
|
t.Error("B")
|
||||||
}
|
}
|
||||||
if New(10).Len() != 10 {
|
if New(10).Len() != 10 {
|
||||||
t.Error("C");
|
t.Error("C")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,11 +56,11 @@ func TestAccess(t *testing.T) {
|
||||||
var a Vector;
|
var a Vector;
|
||||||
a.Init(n);
|
a.Init(n);
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
a.Set(i, val(i));
|
a.Set(i, val(i))
|
||||||
}
|
}
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
if a.At(i).(int) != val(i) {
|
if a.At(i).(int) != val(i) {
|
||||||
t.Error(i);
|
t.Error(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -72,41 +72,41 @@ func TestInsertDeleteClear(t *testing.T) {
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
if a.Len() != i {
|
if a.Len() != i {
|
||||||
t.Errorf("A) wrong len %d (expected %d)", a.Len(), i);
|
t.Errorf("A) wrong len %d (expected %d)", a.Len(), i)
|
||||||
}
|
}
|
||||||
a.Insert(0, val(i));
|
a.Insert(0, val(i));
|
||||||
if a.Last().(int) != val(0) {
|
if a.Last().(int) != val(0) {
|
||||||
t.Error("B");
|
t.Error("B")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := n-1; i >= 0; i-- {
|
for i := n-1; i >= 0; i-- {
|
||||||
if a.Last().(int) != val(0) {
|
if a.Last().(int) != val(0) {
|
||||||
t.Error("C");
|
t.Error("C")
|
||||||
}
|
}
|
||||||
if a.At(0).(int) != val(i) {
|
if a.At(0).(int) != val(i) {
|
||||||
t.Error("D");
|
t.Error("D")
|
||||||
}
|
}
|
||||||
a.Delete(0);
|
a.Delete(0);
|
||||||
if a.Len() != i {
|
if a.Len() != i {
|
||||||
t.Errorf("E) wrong len %d (expected %d)", a.Len(), i);
|
t.Errorf("E) wrong len %d (expected %d)", a.Len(), i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.Len() != 0 {
|
if a.Len() != 0 {
|
||||||
t.Errorf("F) wrong len %d (expected 0)", a.Len());
|
t.Errorf("F) wrong len %d (expected 0)", a.Len())
|
||||||
}
|
}
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
a.Push(val(i));
|
a.Push(val(i));
|
||||||
if a.Len() != i+1 {
|
if a.Len() != i+1 {
|
||||||
t.Errorf("G) wrong len %d (expected %d)", a.Len(), i+1);
|
t.Errorf("G) wrong len %d (expected %d)", a.Len(), i+1)
|
||||||
}
|
}
|
||||||
if a.Last().(int) != val(i) {
|
if a.Last().(int) != val(i) {
|
||||||
t.Error("H");
|
t.Error("H")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a.Init(0);
|
a.Init(0);
|
||||||
if a.Len() != 0 {
|
if a.Len() != 0 {
|
||||||
t.Errorf("I wrong len %d (expected 0)", a.Len());
|
t.Errorf("I wrong len %d (expected 0)", a.Len())
|
||||||
}
|
}
|
||||||
|
|
||||||
const m = 5;
|
const m = 5;
|
||||||
|
|
@ -116,15 +116,15 @@ func TestInsertDeleteClear(t *testing.T) {
|
||||||
x := val(i);
|
x := val(i);
|
||||||
a.Push(x);
|
a.Push(x);
|
||||||
if a.Pop().(int) != x {
|
if a.Pop().(int) != x {
|
||||||
t.Error("J");
|
t.Error("J")
|
||||||
}
|
}
|
||||||
if a.Len() != j+1 {
|
if a.Len() != j+1 {
|
||||||
t.Errorf("K) wrong len %d (expected %d)", a.Len(), j+1);
|
t.Errorf("K) wrong len %d (expected %d)", a.Len(), j+1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if a.Len() != m {
|
if a.Len() != m {
|
||||||
t.Errorf("L) wrong len %d (expected %d)", a.Len(), m);
|
t.Errorf("L) wrong len %d (expected %d)", a.Len(), m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,14 +132,14 @@ func TestInsertDeleteClear(t *testing.T) {
|
||||||
func verify_slice(t *testing.T, x *Vector, elt, i, j int) {
|
func verify_slice(t *testing.T, x *Vector, elt, i, j int) {
|
||||||
for k := i; k < j; k++ {
|
for k := i; k < j; k++ {
|
||||||
if x.At(k).(int) != elt {
|
if x.At(k).(int) != elt {
|
||||||
t.Errorf("M) wrong [%d] element %d (expected %d)", k, x.At(k).(int), elt);
|
t.Errorf("M) wrong [%d] element %d (expected %d)", k, x.At(k).(int), elt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s := x.Slice(i, j);
|
s := x.Slice(i, j);
|
||||||
for k, n := 0, j-i; k < n; k++ {
|
for k, n := 0, j-i; k < n; k++ {
|
||||||
if s.At(k).(int) != elt {
|
if s.At(k).(int) != elt {
|
||||||
t.Errorf("N) wrong [%d] element %d (expected %d)", k, x.At(k).(int), elt);
|
t.Errorf("N) wrong [%d] element %d (expected %d)", k, x.At(k).(int), elt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -148,7 +148,7 @@ func verify_slice(t *testing.T, x *Vector, elt, i, j int) {
|
||||||
func verify_pattern(t *testing.T, x *Vector, a, b, c int) {
|
func verify_pattern(t *testing.T, x *Vector, a, b, c int) {
|
||||||
n := a+b+c;
|
n := a+b+c;
|
||||||
if x.Len() != n {
|
if x.Len() != n {
|
||||||
t.Errorf("O) wrong len %d (expected %d)", x.Len(), n);
|
t.Errorf("O) wrong len %d (expected %d)", x.Len(), n)
|
||||||
}
|
}
|
||||||
verify_slice(t, x, 0, 0, a);
|
verify_slice(t, x, 0, 0, a);
|
||||||
verify_slice(t, x, 1, a, a+b);
|
verify_slice(t, x, 1, a, a+b);
|
||||||
|
|
@ -159,7 +159,7 @@ func verify_pattern(t *testing.T, x *Vector, a, b, c int) {
|
||||||
func make_vector(elt, len int) *Vector {
|
func make_vector(elt, len int) *Vector {
|
||||||
x := New(len);
|
x := New(len);
|
||||||
for i := 0; i < len; i++ {
|
for i := 0; i < len; i++ {
|
||||||
x.Set(i, elt);
|
x.Set(i, elt)
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
@ -195,18 +195,18 @@ func TestSorting(t *testing.T) {
|
||||||
|
|
||||||
a := NewIntVector(n);
|
a := NewIntVector(n);
|
||||||
for i := n-1; i >= 0; i-- {
|
for i := n-1; i >= 0; i-- {
|
||||||
a.Set(i, n-1-i);
|
a.Set(i, n-1-i)
|
||||||
}
|
}
|
||||||
if sort.IsSorted(a) {
|
if sort.IsSorted(a) {
|
||||||
t.Error("int vector not sorted");
|
t.Error("int vector not sorted")
|
||||||
}
|
}
|
||||||
|
|
||||||
b := NewStringVector(n);
|
b := NewStringVector(n);
|
||||||
for i := n-1; i >= 0; i-- {
|
for i := n-1; i >= 0; i-- {
|
||||||
b.Set(i, fmt.Sprint(n-1-i));
|
b.Set(i, fmt.Sprint(n-1-i))
|
||||||
}
|
}
|
||||||
if sort.IsSorted(b) {
|
if sort.IsSorted(b) {
|
||||||
t.Error("string vector not sorted");
|
t.Error("string vector not sorted")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -216,18 +216,18 @@ func TestDo(t *testing.T) {
|
||||||
const salt = 17;
|
const salt = 17;
|
||||||
a := NewIntVector(n);
|
a := NewIntVector(n);
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
a.Set(i, salt*i);
|
a.Set(i, salt*i)
|
||||||
}
|
}
|
||||||
count := 0;
|
count := 0;
|
||||||
a.Do(func(e Element) {
|
a.Do(func(e Element) {
|
||||||
i := e.(int);
|
i := e.(int);
|
||||||
if i != count*salt {
|
if i != count*salt {
|
||||||
t.Error("value at", count, "should be", count*salt, "not", i);
|
t.Error("value at", count, "should be", count*salt, "not", i)
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
});
|
});
|
||||||
if count != n {
|
if count != n {
|
||||||
t.Error("should visit", n, "values; did visit", count);
|
t.Error("should visit", n, "values; did visit", count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,16 +236,16 @@ func TestIter(t *testing.T) {
|
||||||
const Len = 100;
|
const Len = 100;
|
||||||
x := New(Len);
|
x := New(Len);
|
||||||
for i := 0; i < Len; i++ {
|
for i := 0; i < Len; i++ {
|
||||||
x.Set(i, i*i);
|
x.Set(i, i*i)
|
||||||
}
|
}
|
||||||
i := 0;
|
i := 0;
|
||||||
for v := range x.Iter() {
|
for v := range x.Iter() {
|
||||||
if v.(int) != i*i {
|
if v.(int) != i*i {
|
||||||
t.Error("Iter expected", i*i, "got", v.(int));
|
t.Error("Iter expected", i*i, "got", v.(int))
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if i != Len {
|
if i != Len {
|
||||||
t.Error("Iter stopped at", i, "not", Len);
|
t.Error("Iter stopped at", i, "not", Len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,11 @@ func TestPowx(t *testing.T) {
|
||||||
p := 1;
|
p := 1;
|
||||||
for i := 0; i < len(powx); i++ {
|
for i := 0; i < len(powx); i++ {
|
||||||
if powx[i] != byte(p) {
|
if powx[i] != byte(p) {
|
||||||
t.Errorf("powx[%d] = %#x, want %#x", i, powx[i], p);
|
t.Errorf("powx[%d] = %#x, want %#x", i, powx[i], p)
|
||||||
}
|
}
|
||||||
p <<= 1;
|
p <<= 1;
|
||||||
if p&0x100 != 0 {
|
if p&0x100 != 0 {
|
||||||
p ^= poly;
|
p ^= poly
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -42,7 +42,7 @@ func mul(b, c uint32) uint32 {
|
||||||
// i *= x in GF(2) modulo the polynomial
|
// i *= x in GF(2) modulo the polynomial
|
||||||
i <<= 1;
|
i <<= 1;
|
||||||
if i&0x100 != 0 {
|
if i&0x100 != 0 {
|
||||||
i ^= poly;
|
i ^= poly
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
|
@ -57,12 +57,12 @@ func TestMul(t *testing.T) {
|
||||||
for k := uint(0); k < 8; k++ {
|
for k := uint(0); k < 8; k++ {
|
||||||
for l := uint(0); l < 8; l++ {
|
for l := uint(0); l < 8; l++ {
|
||||||
if i&(1<<k) != 0 && j&(1<<l) != 0 {
|
if i&(1<<k) != 0 && j&(1<<l) != 0 {
|
||||||
s ^= powx[k+l];
|
s ^= powx[k+l]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if x := mul(i, j); x != uint32(s) {
|
if x := mul(i, j); x != uint32(s) {
|
||||||
t.Fatalf("mul(%#x, %#x) = %#x, want %#x", i, j, x, s);
|
t.Fatalf("mul(%#x, %#x) = %#x, want %#x", i, j, x, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -75,10 +75,10 @@ func TestMul(t *testing.T) {
|
||||||
func TestSboxes(t *testing.T) {
|
func TestSboxes(t *testing.T) {
|
||||||
for i := 0; i < 256; i++ {
|
for i := 0; i < 256; i++ {
|
||||||
if j := sbox0[sbox1[i]]; j != byte(i) {
|
if j := sbox0[sbox1[i]]; j != byte(i) {
|
||||||
t.Errorf("sbox0[sbox1[%#x]] = %#x", i, j);
|
t.Errorf("sbox0[sbox1[%#x]] = %#x", i, j)
|
||||||
}
|
}
|
||||||
if j := sbox1[sbox0[i]]; j != byte(i) {
|
if j := sbox1[sbox0[i]]; j != byte(i) {
|
||||||
t.Errorf("sbox1[sbox0[%#x]] = %#x", i, j);
|
t.Errorf("sbox1[sbox0[%#x]] = %#x", i, j)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -93,7 +93,7 @@ func TestTe(t *testing.T) {
|
||||||
w := s2<<24 | s<<16 | s<<8 | s3;
|
w := s2<<24 | s<<16 | s<<8 | s3;
|
||||||
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)
|
||||||
}
|
}
|
||||||
w = w<<24 | w>>8;
|
w = w<<24 | w>>8;
|
||||||
}
|
}
|
||||||
|
|
@ -112,7 +112,7 @@ func TestTd(t *testing.T) {
|
||||||
w := se<<24 | s9<<16 | sd<<8 | sb;
|
w := se<<24 | s9<<16 | sd<<8 | sb;
|
||||||
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)
|
||||||
}
|
}
|
||||||
w = w<<24 | w>>8;
|
w = w<<24 | w>>8;
|
||||||
}
|
}
|
||||||
|
|
@ -217,7 +217,7 @@ L:
|
||||||
enc := make([]uint32, len(tt.enc));
|
enc := make([]uint32, len(tt.enc));
|
||||||
var dec []uint32;
|
var dec []uint32;
|
||||||
if tt.dec != nil {
|
if tt.dec != nil {
|
||||||
dec = make([]uint32, len(tt.dec));
|
dec = make([]uint32, len(tt.dec))
|
||||||
}
|
}
|
||||||
expandKey(tt.key, enc, dec);
|
expandKey(tt.key, enc, dec);
|
||||||
for j, v := range enc {
|
for j, v := range enc {
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ func subw(w uint32) uint32 {
|
||||||
return uint32(sbox0[w>>24])<<24 |
|
return uint32(sbox0[w>>24])<<24 |
|
||||||
uint32(sbox0[w>>16&0xff])<<16 |
|
uint32(sbox0[w>>16&0xff])<<16 |
|
||||||
uint32(sbox0[w>>8&0xff])<<8 |
|
uint32(sbox0[w>>8&0xff])<<8 |
|
||||||
uint32(sbox0[w&0xff]);
|
uint32(sbox0[w&0xff])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rotate
|
// Rotate
|
||||||
|
|
@ -144,14 +144,14 @@ func expandKey(key []byte, enc, dec []uint32) {
|
||||||
var i int;
|
var i int;
|
||||||
nk := len(key)/4;
|
nk := len(key)/4;
|
||||||
for i = 0; i < nk; i++ {
|
for i = 0; i < nk; i++ {
|
||||||
enc[i] = uint32(key[4*i])<<24 | uint32(key[4*i + 1])<<16 | uint32(key[4*i + 2])<<8 | uint32(key[4*i + 3]);
|
enc[i] = uint32(key[4*i])<<24 | uint32(key[4*i + 1])<<16 | uint32(key[4*i + 2])<<8 | uint32(key[4*i + 3])
|
||||||
}
|
}
|
||||||
for ; i < len(enc); i++ {
|
for ; i < len(enc); i++ {
|
||||||
t := enc[i-1];
|
t := enc[i-1];
|
||||||
if i%nk == 0 {
|
if i%nk == 0 {
|
||||||
t = subw(rotw(t))^(uint32(powx[i/nk - 1])<<24);
|
t = subw(rotw(t))^(uint32(powx[i/nk - 1])<<24)
|
||||||
} else if nk > 6 && i%nk == 4 {
|
} else if nk > 6 && i%nk == 4 {
|
||||||
t = subw(t);
|
t = subw(t)
|
||||||
}
|
}
|
||||||
enc[i] = enc[i-nk]^t;
|
enc[i] = enc[i-nk]^t;
|
||||||
}
|
}
|
||||||
|
|
@ -160,7 +160,7 @@ func expandKey(key []byte, enc, dec []uint32) {
|
||||||
// Reverse the 4-word round key sets from enc to produce dec.
|
// Reverse the 4-word round key sets from enc to produce dec.
|
||||||
// All sets but the first and last get the MixColumn transform applied.
|
// All sets but the first and last get the MixColumn transform applied.
|
||||||
if dec == nil {
|
if dec == nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
n := len(enc);
|
n := len(enc);
|
||||||
for i := 0; i < n; i += 4 {
|
for i := 0; i < n; i += 4 {
|
||||||
|
|
@ -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 = td[0][sbox0[x>>24]]^td[1][sbox0[x>>16&0xff]]^td[2][sbox0[x>>8&0xff]]^td[3][sbox0[x&0xff]]
|
||||||
}
|
}
|
||||||
dec[i+j] = x;
|
dec[i+j] = x;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ type Cipher struct {
|
||||||
type KeySizeError int
|
type KeySizeError int
|
||||||
|
|
||||||
func (k KeySizeError) String() string {
|
func (k KeySizeError) String() string {
|
||||||
return "crypto/aes: invalid key size " + strconv.Itoa(int(k));
|
return "crypto/aes: invalid key size " + strconv.Itoa(int(k))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCipher creates and returns a new Cipher.
|
// NewCipher creates and returns a new Cipher.
|
||||||
|
|
@ -32,9 +32,9 @@ func NewCipher(key []byte) (*Cipher, os.Error) {
|
||||||
k := len(key);
|
k := len(key);
|
||||||
switch k {
|
switch k {
|
||||||
default:
|
default:
|
||||||
return nil, KeySizeError(k);
|
return nil, KeySizeError(k)
|
||||||
case 16, 24, 32:
|
case 16, 24, 32:
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
n := k+28;
|
n := k+28;
|
||||||
|
|
@ -63,9 +63,9 @@ func (c *Cipher) Decrypt(src, dst []byte) { decryptBlock(c.dec, src, dst) }
|
||||||
// appear in the process's memory.
|
// appear in the process's memory.
|
||||||
func (c *Cipher) Reset() {
|
func (c *Cipher) Reset() {
|
||||||
for i := 0; i < len(c.enc); i++ {
|
for i := 0; i < len(c.enc); i++ {
|
||||||
c.enc[i] = 0;
|
c.enc[i] = 0
|
||||||
}
|
}
|
||||||
for i := 0; i < len(c.dec); i++ {
|
for i := 0; i < len(c.dec); i++ {
|
||||||
c.dec[i] = 0;
|
c.dec[i] = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,11 @@ func (x *cbcCipher) BlockSize() int { return x.blockSize }
|
||||||
|
|
||||||
func (x *cbcCipher) Encrypt(src, dst []byte) {
|
func (x *cbcCipher) Encrypt(src, dst []byte) {
|
||||||
for i := 0; i < x.blockSize; i++ {
|
for i := 0; i < x.blockSize; i++ {
|
||||||
x.iv[i] ^= src[i];
|
x.iv[i] ^= src[i]
|
||||||
}
|
}
|
||||||
x.c.Encrypt(x.iv, x.iv);
|
x.c.Encrypt(x.iv, x.iv);
|
||||||
for i := 0; i < x.blockSize; i++ {
|
for i := 0; i < x.blockSize; i++ {
|
||||||
dst[i] = x.iv[i];
|
dst[i] = x.iv[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,7 +58,7 @@ func (x *cbcCipher) Decrypt(src, dst []byte) {
|
||||||
// The returned Reader does not buffer or read ahead except
|
// The returned Reader does not buffer or read ahead except
|
||||||
// as required by the cipher's block size.
|
// as required by the cipher's block size.
|
||||||
func NewCBCDecrypter(c Cipher, iv []byte, r io.Reader) io.Reader {
|
func NewCBCDecrypter(c Cipher, iv []byte, r io.Reader) io.Reader {
|
||||||
return NewECBDecrypter(newCBC(c, iv), r);
|
return NewECBDecrypter(newCBC(c, iv), r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCBCEncrypter returns a writer that encrypts data using c
|
// NewCBCEncrypter returns a writer that encrypts data using c
|
||||||
|
|
@ -67,5 +67,5 @@ func NewCBCDecrypter(c Cipher, iv []byte, r io.Reader) io.Reader {
|
||||||
// The returned Writer does no buffering except as required
|
// The returned Writer does no buffering except as required
|
||||||
// by the cipher's block size, so there is no need for a Flush method.
|
// by the cipher's block size, so there is no need for a Flush method.
|
||||||
func NewCBCEncrypter(c Cipher, iv []byte, w io.Writer) io.Writer {
|
func NewCBCEncrypter(c Cipher, iv []byte, w io.Writer) io.Writer {
|
||||||
return NewECBEncrypter(newCBC(c, iv), w);
|
return NewECBEncrypter(newCBC(c, iv), w)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,9 +80,9 @@ func TestCBC_AES(t *testing.T) {
|
||||||
var r io.Reader = bytes.NewBuffer(tt.in);
|
var r io.Reader = bytes.NewBuffer(tt.in);
|
||||||
n, err := io.Copy(w, r);
|
n, err := io.Copy(w, r);
|
||||||
if n != int64(len(tt.in)) || err != nil {
|
if n != int64(len(tt.in)) || err != nil {
|
||||||
t.Errorf("%s: CBCEncrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.in));
|
t.Errorf("%s: CBCEncrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.in))
|
||||||
} else if d := crypt.Bytes(); !same(tt.out, d) {
|
} else if d := crypt.Bytes(); !same(tt.out, d) {
|
||||||
t.Errorf("%s: CBCEncrypter\nhave %x\nwant %x", test, d, tt.out);
|
t.Errorf("%s: CBCEncrypter\nhave %x\nwant %x", test, d, tt.out)
|
||||||
}
|
}
|
||||||
|
|
||||||
var plain bytes.Buffer;
|
var plain bytes.Buffer;
|
||||||
|
|
@ -90,13 +90,13 @@ func TestCBC_AES(t *testing.T) {
|
||||||
w = &plain;
|
w = &plain;
|
||||||
n, err = io.Copy(w, r);
|
n, err = io.Copy(w, r);
|
||||||
if n != int64(len(tt.out)) || err != nil {
|
if n != int64(len(tt.out)) || err != nil {
|
||||||
t.Errorf("%s: CBCDecrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.out));
|
t.Errorf("%s: CBCDecrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.out))
|
||||||
} else if d := plain.Bytes(); !same(tt.in, d) {
|
} else if d := plain.Bytes(); !same(tt.in, d) {
|
||||||
t.Errorf("%s: CBCDecrypter\nhave %x\nwant %x", test, d, tt.in);
|
t.Errorf("%s: CBCDecrypter\nhave %x\nwant %x", test, d, tt.in)
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.Failed() {
|
if t.Failed() {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ type cfbCipher struct {
|
||||||
|
|
||||||
func newCFB(c Cipher, s int, iv []byte) *cfbCipher {
|
func newCFB(c Cipher, s int, iv []byte) *cfbCipher {
|
||||||
if s == 0 || s%8 != 0 {
|
if s == 0 || s%8 != 0 {
|
||||||
panicln("crypto/block: invalid CFB mode", s);
|
panicln("crypto/block: invalid CFB mode", s)
|
||||||
}
|
}
|
||||||
b := c.BlockSize();
|
b := c.BlockSize();
|
||||||
x := new(cfbCipher);
|
x := new(cfbCipher);
|
||||||
|
|
@ -44,16 +44,16 @@ func (x *cfbCipher) Encrypt(src, dst []byte) {
|
||||||
// Encrypt old IV and xor prefix with src to make dst.
|
// Encrypt old IV and xor prefix with src to make dst.
|
||||||
x.c.Encrypt(x.iv, x.tmp);
|
x.c.Encrypt(x.iv, x.tmp);
|
||||||
for i := 0; i < x.blockSize; i++ {
|
for i := 0; i < x.blockSize; i++ {
|
||||||
dst[i] = src[i] ^ x.tmp[i];
|
dst[i] = src[i] ^ x.tmp[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slide unused IV pieces down and insert dst at end.
|
// Slide unused IV pieces down and insert dst at end.
|
||||||
for i := 0; i < x.cipherSize - x.blockSize; i++ {
|
for i := 0; i < x.cipherSize - x.blockSize; i++ {
|
||||||
x.iv[i] = x.iv[i + x.blockSize];
|
x.iv[i] = x.iv[i + x.blockSize]
|
||||||
}
|
}
|
||||||
off := x.cipherSize - x.blockSize;
|
off := x.cipherSize - x.blockSize;
|
||||||
for i := off; i < x.cipherSize; i++ {
|
for i := off; i < x.cipherSize; i++ {
|
||||||
x.iv[i] = dst[i-off];
|
x.iv[i] = dst[i-off]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,18 +61,18 @@ func (x *cfbCipher) Decrypt(src, dst []byte) {
|
||||||
// Encrypt [sic] old IV and xor prefix with src to make dst.
|
// Encrypt [sic] old IV and xor prefix with src to make dst.
|
||||||
x.c.Encrypt(x.iv, x.tmp);
|
x.c.Encrypt(x.iv, x.tmp);
|
||||||
for i := 0; i < x.blockSize; i++ {
|
for i := 0; i < x.blockSize; i++ {
|
||||||
dst[i] = src[i] ^ x.tmp[i];
|
dst[i] = src[i] ^ x.tmp[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slide unused IV pieces down and insert src at top.
|
// Slide unused IV pieces down and insert src at top.
|
||||||
for i := 0; i < x.cipherSize - x.blockSize; i++ {
|
for i := 0; i < x.cipherSize - x.blockSize; i++ {
|
||||||
x.iv[i] = x.iv[i + x.blockSize];
|
x.iv[i] = x.iv[i + x.blockSize]
|
||||||
}
|
}
|
||||||
off := x.cipherSize - x.blockSize;
|
off := x.cipherSize - x.blockSize;
|
||||||
for i := off; i < x.cipherSize; i++ {
|
for i := off; i < x.cipherSize; i++ {
|
||||||
// Reconstruct src = dst ^ x.tmp
|
// Reconstruct src = dst ^ x.tmp
|
||||||
// in case we overwrote src (src == dst).
|
// in case we overwrote src (src == dst).
|
||||||
x.iv[i] = dst[i-off] ^ x.tmp[i-off];
|
x.iv[i] = dst[i-off] ^ x.tmp[i-off]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,7 +82,7 @@ func (x *cfbCipher) Decrypt(src, dst []byte) {
|
||||||
// as required by the cipher's block size.
|
// as required by the cipher's block size.
|
||||||
// Modes for s not a multiple of 8 are unimplemented.
|
// Modes for s not a multiple of 8 are unimplemented.
|
||||||
func NewCFBDecrypter(c Cipher, s int, iv []byte, r io.Reader) io.Reader {
|
func NewCFBDecrypter(c Cipher, s int, iv []byte, r io.Reader) io.Reader {
|
||||||
return NewECBDecrypter(newCFB(c, s, iv), r);
|
return NewECBDecrypter(newCFB(c, s, iv), r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCFBEncrypter returns a writer that encrypts data using c
|
// NewCFBEncrypter returns a writer that encrypts data using c
|
||||||
|
|
@ -92,5 +92,5 @@ func NewCFBDecrypter(c Cipher, s int, iv []byte, r io.Reader) io.Reader {
|
||||||
// by the cipher's block size, so there is no need for a Flush method.
|
// by the cipher's block size, so there is no need for a Flush method.
|
||||||
// Modes for s not a multiple of 8 are unimplemented.
|
// Modes for s not a multiple of 8 are unimplemented.
|
||||||
func NewCFBEncrypter(c Cipher, s int, iv []byte, w io.Writer) io.Writer {
|
func NewCFBEncrypter(c Cipher, s int, iv []byte, w io.Writer) io.Writer {
|
||||||
return NewECBEncrypter(newCFB(c, s, iv), w);
|
return NewECBEncrypter(newCFB(c, s, iv), w)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -275,7 +275,7 @@ func TestCFB_AES(t *testing.T) {
|
||||||
|
|
||||||
if tt.s == 1 {
|
if tt.s == 1 {
|
||||||
// 1-bit CFB not implemented
|
// 1-bit CFB not implemented
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := aes.NewCipher(tt.key);
|
c, err := aes.NewCipher(tt.key);
|
||||||
|
|
@ -289,9 +289,9 @@ func TestCFB_AES(t *testing.T) {
|
||||||
var r io.Reader = bytes.NewBuffer(tt.in);
|
var r io.Reader = bytes.NewBuffer(tt.in);
|
||||||
n, err := io.Copy(w, r);
|
n, err := io.Copy(w, r);
|
||||||
if n != int64(len(tt.in)) || err != nil {
|
if n != int64(len(tt.in)) || err != nil {
|
||||||
t.Errorf("%s: CFBEncrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.in));
|
t.Errorf("%s: CFBEncrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.in))
|
||||||
} else if d := crypt.Bytes(); !same(tt.out, d) {
|
} else if d := crypt.Bytes(); !same(tt.out, d) {
|
||||||
t.Errorf("%s: CFBEncrypter\nhave %x\nwant %x", test, d, tt.out);
|
t.Errorf("%s: CFBEncrypter\nhave %x\nwant %x", test, d, tt.out)
|
||||||
}
|
}
|
||||||
|
|
||||||
var plain bytes.Buffer;
|
var plain bytes.Buffer;
|
||||||
|
|
@ -299,13 +299,13 @@ func TestCFB_AES(t *testing.T) {
|
||||||
w = &plain;
|
w = &plain;
|
||||||
n, err = io.Copy(w, r);
|
n, err = io.Copy(w, r);
|
||||||
if n != int64(len(tt.out)) || err != nil {
|
if n != int64(len(tt.out)) || err != nil {
|
||||||
t.Errorf("%s: CFBDecrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.out));
|
t.Errorf("%s: CFBDecrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.out))
|
||||||
} else if d := plain.Bytes(); !same(tt.in, d) {
|
} else if d := plain.Bytes(); !same(tt.in, d) {
|
||||||
t.Errorf("%s: CFBDecrypter\nhave %x\nwant %x", test, d, tt.in);
|
t.Errorf("%s: CFBDecrypter\nhave %x\nwant %x", test, d, tt.in)
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.Failed() {
|
if t.Failed() {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,11 @@ func shift1(src, dst []byte) byte {
|
||||||
|
|
||||||
func same(p, q []byte) bool {
|
func same(p, q []byte) bool {
|
||||||
if len(p) != len(q) {
|
if len(p) != len(q) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
for i := 0; i < len(p); i++ {
|
for i := 0; i < len(p); i++ {
|
||||||
if p[i] != q[i] {
|
if p[i] != q[i] {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -52,7 +52,7 @@ func same(p, q []byte) bool {
|
||||||
func copy(p []byte) []byte {
|
func copy(p []byte) []byte {
|
||||||
q := make([]byte, len(p));
|
q := make([]byte, len(p));
|
||||||
for i, b := range p {
|
for i, b := range p {
|
||||||
q[i] = b;
|
q[i] = b
|
||||||
}
|
}
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,11 @@ func NewCMAC(c Cipher) hash.Hash {
|
||||||
n := c.BlockSize();
|
n := c.BlockSize();
|
||||||
switch n {
|
switch n {
|
||||||
case 64/8:
|
case 64/8:
|
||||||
r = r64;
|
r = r64
|
||||||
case 128/8:
|
case 128/8:
|
||||||
r = r128;
|
r = r128
|
||||||
default:
|
default:
|
||||||
panic("crypto/block: NewCMAC: invalid cipher block size", n);
|
panic("crypto/block: NewCMAC: invalid cipher block size", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
d := new(cmac);
|
d := new(cmac);
|
||||||
|
|
@ -50,10 +50,10 @@ func NewCMAC(c Cipher) hash.Hash {
|
||||||
// Subkey generation, p. 7
|
// Subkey generation, p. 7
|
||||||
c.Encrypt(d.k1, d.k1);
|
c.Encrypt(d.k1, d.k1);
|
||||||
if shift1(d.k1, d.k1) != 0 {
|
if shift1(d.k1, d.k1) != 0 {
|
||||||
d.k1[n-1] ^= r;
|
d.k1[n-1] ^= r
|
||||||
}
|
}
|
||||||
if shift1(d.k1, d.k2) != 0 {
|
if shift1(d.k1, d.k2) != 0 {
|
||||||
d.k2[n-1] ^= r;
|
d.k2[n-1] ^= r
|
||||||
}
|
}
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
|
|
@ -62,7 +62,7 @@ func NewCMAC(c Cipher) hash.Hash {
|
||||||
// Reset clears the digest state, starting a new digest.
|
// Reset clears the digest state, starting a new digest.
|
||||||
func (d *cmac) Reset() {
|
func (d *cmac) Reset() {
|
||||||
for i := range d.ci {
|
for i := range d.ci {
|
||||||
d.ci[i] = 0;
|
d.ci[i] = 0
|
||||||
}
|
}
|
||||||
d.p = 0;
|
d.p = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -90,13 +90,13 @@ func (d *cmac) Sum() []byte {
|
||||||
// to keep digesting after call to Sum.
|
// to keep digesting after call to Sum.
|
||||||
k := d.k1;
|
k := d.k1;
|
||||||
if d.p < len(d.digest) {
|
if d.p < len(d.digest) {
|
||||||
k = d.k2;
|
k = d.k2
|
||||||
}
|
}
|
||||||
for i := 0; i < len(d.ci); i++ {
|
for i := 0; i < len(d.ci); i++ {
|
||||||
d.digest[i] = d.ci[i] ^ k[i];
|
d.digest[i] = d.ci[i] ^ k[i]
|
||||||
}
|
}
|
||||||
if d.p < len(d.digest) {
|
if d.p < len(d.digest) {
|
||||||
d.digest[d.p] ^= 0x80;
|
d.digest[d.p] ^= 0x80
|
||||||
}
|
}
|
||||||
d.c.Encrypt(d.digest, d.digest);
|
d.c.Encrypt(d.digest, d.digest);
|
||||||
return d.digest;
|
return d.digest;
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ func (x *ctrStream) Next() []byte {
|
||||||
for i := len(x.ctr)-1; i >= 0; i-- {
|
for i := len(x.ctr)-1; i >= 0; i-- {
|
||||||
x.ctr[i]++;
|
x.ctr[i]++;
|
||||||
if x.ctr[i] != 0 {
|
if x.ctr[i] != 0 {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@ func (x *ctrStream) Next() []byte {
|
||||||
// a CTR reader applied to an encrypted stream produces a decrypted
|
// a CTR reader applied to an encrypted stream produces a decrypted
|
||||||
// stream and vice versa.
|
// stream and vice versa.
|
||||||
func NewCTRReader(c Cipher, iv []byte, r io.Reader) io.Reader {
|
func NewCTRReader(c Cipher, iv []byte, r io.Reader) io.Reader {
|
||||||
return newXorReader(newCTRStream(c, iv), r);
|
return newXorReader(newCTRStream(c, iv), r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCTRWriter returns a writer that encrypts (or decrypts) data using c
|
// NewCTRWriter returns a writer that encrypts (or decrypts) data using c
|
||||||
|
|
@ -63,5 +63,5 @@ func NewCTRReader(c Cipher, iv []byte, r io.Reader) io.Reader {
|
||||||
// a CTR writer applied to an decrypted stream produces an encrypted
|
// a CTR writer applied to an decrypted stream produces an encrypted
|
||||||
// stream and vice versa.
|
// stream and vice versa.
|
||||||
func NewCTRWriter(c Cipher, iv []byte, w io.Writer) io.Writer {
|
func NewCTRWriter(c Cipher, iv []byte, w io.Writer) io.Writer {
|
||||||
return newXorWriter(newCTRStream(c, iv), w);
|
return newXorWriter(newCTRStream(c, iv), w)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,9 +84,9 @@ func TestCTR_AES(t *testing.T) {
|
||||||
var r io.Reader = bytes.NewBuffer(in);
|
var r io.Reader = bytes.NewBuffer(in);
|
||||||
n, err := io.Copy(w, r);
|
n, err := io.Copy(w, r);
|
||||||
if n != int64(len(in)) || err != nil {
|
if n != int64(len(in)) || err != nil {
|
||||||
t.Errorf("%s/%d: CTRWriter io.Copy = %d, %v want %d, nil", test, len(in), n, err, len(in));
|
t.Errorf("%s/%d: CTRWriter io.Copy = %d, %v want %d, nil", test, len(in), n, err, len(in))
|
||||||
} else if d, out := crypt.Bytes(), tt.out[0:len(in)]; !same(out, d) {
|
} else if d, out := crypt.Bytes(), tt.out[0:len(in)]; !same(out, d) {
|
||||||
t.Errorf("%s/%d: CTRWriter\ninpt %x\nhave %x\nwant %x", test, len(in), in, d, out);
|
t.Errorf("%s/%d: CTRWriter\ninpt %x\nhave %x\nwant %x", test, len(in), in, d, out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,14 +97,14 @@ func TestCTR_AES(t *testing.T) {
|
||||||
w := &plain;
|
w := &plain;
|
||||||
n, err := io.Copy(w, r);
|
n, err := io.Copy(w, r);
|
||||||
if n != int64(len(out)) || err != nil {
|
if n != int64(len(out)) || err != nil {
|
||||||
t.Errorf("%s/%d: CTRReader io.Copy = %d, %v want %d, nil", test, len(out), n, err, len(out));
|
t.Errorf("%s/%d: CTRReader io.Copy = %d, %v want %d, nil", test, len(out), n, err, len(out))
|
||||||
} else if d, in := plain.Bytes(), tt.in[0:len(out)]; !same(in, d) {
|
} else if d, in := plain.Bytes(), tt.in[0:len(out)]; !same(in, d) {
|
||||||
t.Errorf("%s/%d: CTRReader\nhave %x\nwant %x", test, len(out), d, in);
|
t.Errorf("%s/%d: CTRReader\nhave %x\nwant %x", test, len(out), d, in)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.Failed() {
|
if t.Failed() {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,13 +30,13 @@ type EAXTagError struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EAXTagError) String() string {
|
func (e *EAXTagError) String() string {
|
||||||
return fmt.Sprintf("crypto/block: EAX tag mismatch: read %x but computed %x", e.Read, e.Computed);
|
return fmt.Sprintf("crypto/block: EAX tag mismatch: read %x but computed %x", e.Read, e.Computed)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupEAX(c Cipher, iv, hdr []byte, tagBytes int) (ctrIV, tag []byte, cmac hash.Hash) {
|
func setupEAX(c Cipher, iv, hdr []byte, tagBytes int) (ctrIV, tag []byte, cmac hash.Hash) {
|
||||||
n := len(iv);
|
n := len(iv);
|
||||||
if n != c.BlockSize() {
|
if n != c.BlockSize() {
|
||||||
panicln("crypto/block: EAX: iv length", n, "!=", c.BlockSize());
|
panicln("crypto/block: EAX: iv length", n, "!=", c.BlockSize())
|
||||||
}
|
}
|
||||||
buf := make([]byte, n); // zeroed
|
buf := make([]byte, n); // zeroed
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ func setupEAX(c Cipher, iv, hdr []byte, tagBytes int) (ctrIV, tag []byte, cmac h
|
||||||
cmac.Write(hdr);
|
cmac.Write(hdr);
|
||||||
sum = cmac.Sum();
|
sum = cmac.Sum();
|
||||||
for i := 0; i < tagBytes; i++ {
|
for i := 0; i < tagBytes; i++ {
|
||||||
tag[i] ^= sum[i];
|
tag[i] ^= sum[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
cmac.Reset();
|
cmac.Reset();
|
||||||
|
|
@ -68,7 +68,7 @@ func finishEAX(tag []byte, cmac hash.Hash) {
|
||||||
// Finish CMAC #2 and xor into tag.
|
// Finish CMAC #2 and xor into tag.
|
||||||
sum := cmac.Sum();
|
sum := cmac.Sum();
|
||||||
for i := range tag {
|
for i := range tag {
|
||||||
tag[i] ^= sum[i];
|
tag[i] ^= sum[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,7 +110,7 @@ func NewEAXEncrypter(c Cipher, iv []byte, hdr []byte, tagBytes int, w io.Writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *eaxEncrypter) Write(p []byte) (n int, err os.Error) {
|
func (x *eaxEncrypter) Write(p []byte) (n int, err os.Error) {
|
||||||
return x.ctr.Write(p);
|
return x.ctr.Write(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *eaxEncrypter) Close() os.Error {
|
func (x *eaxEncrypter) Close() os.Error {
|
||||||
|
|
@ -120,7 +120,7 @@ func (x *eaxEncrypter) Close() os.Error {
|
||||||
finishEAX(x.tag, x.cw.cmac);
|
finishEAX(x.tag, x.cw.cmac);
|
||||||
n, err := x.cw.w.Write(x.tag);
|
n, err := x.cw.w.Write(x.tag);
|
||||||
if n != len(x.tag) && err == nil {
|
if n != len(x.tag) && err == nil {
|
||||||
err = io.ErrShortWrite;
|
err = io.ErrShortWrite
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
@ -154,7 +154,7 @@ func (cr *cmacReader) Read(p []byte) (n int, err os.Error) {
|
||||||
tag = tag[0 : nt+nn];
|
tag = tag[0 : nt+nn];
|
||||||
cr.tag = tag;
|
cr.tag = tag;
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
return 0, err1;
|
return 0, err1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -163,15 +163,15 @@ func (cr *cmacReader) Read(p []byte) (n int, err os.Error) {
|
||||||
// If p is big, try to read directly into p to avoid a copy.
|
// If p is big, try to read directly into p to avoid a copy.
|
||||||
n, err = cr.r.Read(p[tagBytes:len(p)]);
|
n, err = cr.r.Read(p[tagBytes:len(p)]);
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
goto out;
|
goto out
|
||||||
}
|
}
|
||||||
// copy old tag into p
|
// copy old tag into p
|
||||||
for i := 0; i < tagBytes; i++ {
|
for i := 0; i < tagBytes; i++ {
|
||||||
p[i] = tag[i];
|
p[i] = tag[i]
|
||||||
}
|
}
|
||||||
// copy new tag out of p
|
// copy new tag out of p
|
||||||
for i := 0; i < tagBytes; i++ {
|
for i := 0; i < tagBytes; i++ {
|
||||||
tag[i] = p[n+i];
|
tag[i] = p[n+i]
|
||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
@ -179,7 +179,7 @@ func (cr *cmacReader) Read(p []byte) (n int, err os.Error) {
|
||||||
// Otherwise, read into p and then slide data
|
// Otherwise, read into p and then slide data
|
||||||
n, err = cr.r.Read(p);
|
n, err = cr.r.Read(p);
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
goto out;
|
goto out
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy tag+p into p+tmp and then swap tmp, tag
|
// copy tag+p into p+tmp and then swap tmp, tag
|
||||||
|
|
@ -187,14 +187,14 @@ func (cr *cmacReader) Read(p []byte) (n int, err os.Error) {
|
||||||
for i := n+tagBytes-1; i >= 0; i-- {
|
for i := n+tagBytes-1; i >= 0; i-- {
|
||||||
var c byte;
|
var c byte;
|
||||||
if i < tagBytes {
|
if i < tagBytes {
|
||||||
c = tag[i];
|
c = tag[i]
|
||||||
} else {
|
} else {
|
||||||
c = p[i-tagBytes];
|
c = p[i-tagBytes]
|
||||||
}
|
}
|
||||||
if i < n {
|
if i < n {
|
||||||
p[i] = c;
|
p[i] = c
|
||||||
} else {
|
} else {
|
||||||
tmp[i] = c;
|
tmp[i] = c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cr.tmp, cr.tag = tag, tmp;
|
cr.tmp, cr.tag = tag, tmp;
|
||||||
|
|
@ -247,7 +247,7 @@ func (x *eaxDecrypter) checkTag() os.Error {
|
||||||
func (x *eaxDecrypter) Read(p []byte) (n int, err os.Error) {
|
func (x *eaxDecrypter) Read(p []byte) (n int, err os.Error) {
|
||||||
n, err = x.ctr.Read(p);
|
n, err = x.ctr.Read(p);
|
||||||
if n == 0 && err == nil {
|
if n == 0 && err == nil {
|
||||||
err = x.checkTag();
|
err = x.checkTag()
|
||||||
}
|
}
|
||||||
return n, err;
|
return n, err;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,20 +101,20 @@ func TestEAXEncrypt_AES(t *testing.T) {
|
||||||
test := fmt.Sprintf("test %d", i);
|
test := fmt.Sprintf("test %d", i);
|
||||||
c, err := aes.NewCipher(tt.key);
|
c, err := aes.NewCipher(tt.key);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err);
|
t.Fatalf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
|
||||||
}
|
}
|
||||||
b.Reset();
|
b.Reset();
|
||||||
enc := NewEAXEncrypter(c, tt.nonce, tt.header, 16, b);
|
enc := NewEAXEncrypter(c, tt.nonce, tt.header, 16, b);
|
||||||
n, err := io.Copy(enc, bytes.NewBuffer(tt.msg));
|
n, err := io.Copy(enc, bytes.NewBuffer(tt.msg));
|
||||||
if n != int64(len(tt.msg)) || err != nil {
|
if n != int64(len(tt.msg)) || err != nil {
|
||||||
t.Fatalf("%s: io.Copy into encrypter: %d, %s", test, n, err);
|
t.Fatalf("%s: io.Copy into encrypter: %d, %s", test, n, err)
|
||||||
}
|
}
|
||||||
err = enc.Close();
|
err = enc.Close();
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%s: enc.Close: %s", test, err);
|
t.Fatalf("%s: enc.Close: %s", test, err)
|
||||||
}
|
}
|
||||||
if d := b.Bytes(); !same(d, tt.cipher) {
|
if d := b.Bytes(); !same(d, tt.cipher) {
|
||||||
t.Fatalf("%s: got %x want %x", test, d, tt.cipher);
|
t.Fatalf("%s: got %x want %x", test, d, tt.cipher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -125,16 +125,16 @@ func TestEAXDecrypt_AES(t *testing.T) {
|
||||||
test := fmt.Sprintf("test %d", i);
|
test := fmt.Sprintf("test %d", i);
|
||||||
c, err := aes.NewCipher(tt.key);
|
c, err := aes.NewCipher(tt.key);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err);
|
t.Fatalf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
|
||||||
}
|
}
|
||||||
b.Reset();
|
b.Reset();
|
||||||
dec := NewEAXDecrypter(c, tt.nonce, tt.header, 16, bytes.NewBuffer(tt.cipher));
|
dec := NewEAXDecrypter(c, tt.nonce, tt.header, 16, bytes.NewBuffer(tt.cipher));
|
||||||
n, err := io.Copy(b, dec);
|
n, err := io.Copy(b, dec);
|
||||||
if n != int64(len(tt.msg)) || err != nil {
|
if n != int64(len(tt.msg)) || err != nil {
|
||||||
t.Fatalf("%s: io.Copy into decrypter: %d, %s", test, n, err);
|
t.Fatalf("%s: io.Copy into decrypter: %d, %s", test, n, err)
|
||||||
}
|
}
|
||||||
if d := b.Bytes(); !same(d, tt.msg) {
|
if d := b.Bytes(); !same(d, tt.msg) {
|
||||||
t.Fatalf("%s: got %x want %x", test, d, tt.msg);
|
t.Fatalf("%s: got %x want %x", test, d, tt.msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ func (x *ecbDecrypter) fillCrypt() os.Error {
|
||||||
m, err = x.r.Read(x.crypt[off : x.blockSize]);
|
m, err = x.r.Read(x.crypt[off : x.blockSize]);
|
||||||
x.crypt = x.crypt[0 : off+m];
|
x.crypt = x.crypt[0 : off+m];
|
||||||
if m == 0 {
|
if m == 0 {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// If an error happened but we got enough
|
// If an error happened but we got enough
|
||||||
|
|
@ -50,7 +50,7 @@ func (x *ecbDecrypter) fillCrypt() os.Error {
|
||||||
// But if we don't have enough to decrypt,
|
// But if we don't have enough to decrypt,
|
||||||
// have to stop now.
|
// have to stop now.
|
||||||
if err != nil && len(x.crypt) < x.blockSize {
|
if err != nil && len(x.crypt) < x.blockSize {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
|
|
@ -60,15 +60,15 @@ func (x *ecbDecrypter) fillCrypt() os.Error {
|
||||||
func (x *ecbDecrypter) readPlain(p []byte) int {
|
func (x *ecbDecrypter) readPlain(p []byte) int {
|
||||||
n := len(x.plain);
|
n := len(x.plain);
|
||||||
if n > len(p) {
|
if n > len(p) {
|
||||||
n = len(p);
|
n = len(p)
|
||||||
}
|
}
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
p[i] = x.plain[i];
|
p[i] = x.plain[i]
|
||||||
}
|
}
|
||||||
if n < len(x.plain) {
|
if n < len(x.plain) {
|
||||||
x.plain = x.plain[n:len(x.plain)];
|
x.plain = x.plain[n:len(x.plain)]
|
||||||
} else {
|
} else {
|
||||||
x.plain = nil;
|
x.plain = nil
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
@ -76,12 +76,12 @@ func (x *ecbDecrypter) readPlain(p []byte) int {
|
||||||
type ecbFragmentError int
|
type ecbFragmentError int
|
||||||
|
|
||||||
func (n ecbFragmentError) String() string {
|
func (n ecbFragmentError) String() string {
|
||||||
return "crypto/block: " + strconv.Itoa(int(n)) + "-byte fragment at EOF";
|
return "crypto/block: " + strconv.Itoa(int(n)) + "-byte fragment at EOF"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ecbDecrypter) Read(p []byte) (n int, err os.Error) {
|
func (x *ecbDecrypter) Read(p []byte) (n int, err os.Error) {
|
||||||
if len(p) == 0 {
|
if len(p) == 0 {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's no plaintext waiting and p is not big enough
|
// If there's no plaintext waiting and p is not big enough
|
||||||
|
|
@ -89,7 +89,7 @@ func (x *ecbDecrypter) Read(p []byte) (n int, err os.Error) {
|
||||||
// cipher text buffer. Set it to non-nil so that the
|
// cipher text buffer. Set it to non-nil so that the
|
||||||
// code below will fill it.
|
// code below will fill it.
|
||||||
if x.plain == nil && len(p) < x.blockSize && x.crypt == nil {
|
if x.plain == nil && len(p) < x.blockSize && x.crypt == nil {
|
||||||
x.crypt = x.buf[0:0];
|
x.crypt = x.buf[0:0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is a leftover cipher text buffer,
|
// If there is a leftover cipher text buffer,
|
||||||
|
|
@ -97,7 +97,7 @@ func (x *ecbDecrypter) Read(p []byte) (n int, err os.Error) {
|
||||||
if x.crypt != nil {
|
if x.crypt != nil {
|
||||||
err = x.fillCrypt();
|
err = x.fillCrypt();
|
||||||
if err != nil || len(x.crypt) == 0 {
|
if err != nil || len(x.crypt) == 0 {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
x.c.Decrypt(x.crypt, x.crypt);
|
x.c.Decrypt(x.crypt, x.crypt);
|
||||||
x.plain = x.crypt;
|
x.plain = x.crypt;
|
||||||
|
|
@ -128,7 +128,7 @@ func (x *ecbDecrypter) Read(p []byte) (n int, err os.Error) {
|
||||||
if i < n {
|
if i < n {
|
||||||
p = p[i:n];
|
p = p[i:n];
|
||||||
for j, v := range p {
|
for j, v := range p {
|
||||||
x.buf[j] = v;
|
x.buf[j] = v
|
||||||
}
|
}
|
||||||
x.crypt = x.buf[0:len(p)];
|
x.crypt = x.buf[0:len(p)];
|
||||||
n = i;
|
n = i;
|
||||||
|
|
@ -168,17 +168,17 @@ type ecbEncrypter struct {
|
||||||
// Flush the x.crypt buffer to x.w.
|
// Flush the x.crypt buffer to x.w.
|
||||||
func (x *ecbEncrypter) flushCrypt() os.Error {
|
func (x *ecbEncrypter) flushCrypt() os.Error {
|
||||||
if len(x.crypt) == 0 {
|
if len(x.crypt) == 0 {
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
n, err := x.w.Write(x.crypt);
|
n, err := x.w.Write(x.crypt);
|
||||||
if n < len(x.crypt) {
|
if n < len(x.crypt) {
|
||||||
x.crypt = x.crypt[n:len(x.crypt)];
|
x.crypt = x.crypt[n:len(x.crypt)];
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = io.ErrShortWrite;
|
err = io.ErrShortWrite
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err;
|
return err
|
||||||
}
|
}
|
||||||
x.crypt = nil;
|
x.crypt = nil;
|
||||||
return nil;
|
return nil;
|
||||||
|
|
@ -189,12 +189,12 @@ func (x *ecbEncrypter) flushCrypt() os.Error {
|
||||||
// so this is cheap enough.
|
// so this is cheap enough.
|
||||||
func (x *ecbEncrypter) slidePlain() {
|
func (x *ecbEncrypter) slidePlain() {
|
||||||
if len(x.plain) == 0 {
|
if len(x.plain) == 0 {
|
||||||
x.plain = x.buf[0:0];
|
x.plain = x.buf[0:0]
|
||||||
} else if cap(x.plain) < cap(x.buf) {
|
} else if cap(x.plain) < cap(x.buf) {
|
||||||
// plain and buf share same data,
|
// plain and buf share same data,
|
||||||
// but buf is before plain, so forward loop is correct
|
// but buf is before plain, so forward loop is correct
|
||||||
for i := 0; i < len(x.plain); i++ {
|
for i := 0; i < len(x.plain); i++ {
|
||||||
x.buf[i] = x.plain[i];
|
x.buf[i] = x.plain[i]
|
||||||
}
|
}
|
||||||
x.plain = x.buf[0:len(x.plain)];
|
x.plain = x.buf[0:len(x.plain)];
|
||||||
}
|
}
|
||||||
|
|
@ -206,11 +206,11 @@ func (x *ecbEncrypter) fillPlain(p []byte) int {
|
||||||
off := len(x.plain);
|
off := len(x.plain);
|
||||||
n := len(p);
|
n := len(p);
|
||||||
if max := cap(x.plain)-off; n > max {
|
if max := cap(x.plain)-off; n > max {
|
||||||
n = max;
|
n = max
|
||||||
}
|
}
|
||||||
x.plain = x.plain[0 : off+n];
|
x.plain = x.plain[0 : off+n];
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
x.plain[off+i] = p[i];
|
x.plain[off+i] = p[i]
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
@ -233,7 +233,7 @@ func (x *ecbEncrypter) Write(p []byte) (n int, err os.Error) {
|
||||||
// This can happen on the first iteration
|
// This can happen on the first iteration
|
||||||
// if a write failed in an earlier call.
|
// if a write failed in an earlier call.
|
||||||
if err = x.flushCrypt(); err != nil {
|
if err = x.flushCrypt(); err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that encrypted data is gone (flush ran),
|
// Now that encrypted data is gone (flush ran),
|
||||||
|
|
@ -243,7 +243,7 @@ func (x *ecbEncrypter) Write(p []byte) (n int, err os.Error) {
|
||||||
// Fill plaintext buffer from p.
|
// Fill plaintext buffer from p.
|
||||||
m := x.fillPlain(p);
|
m := x.fillPlain(p);
|
||||||
if m == 0 {
|
if m == 0 {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
n += m;
|
n += m;
|
||||||
p = p[m:len(p)];
|
p = p[m:len(p)];
|
||||||
|
|
@ -253,7 +253,7 @@ func (x *ecbEncrypter) Write(p []byte) (n int, err os.Error) {
|
||||||
|
|
||||||
// Write x.crypt.
|
// Write x.crypt.
|
||||||
if err = x.flushCrypt(); err != nil {
|
if err = x.flushCrypt(); err != nil {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -105,9 +105,9 @@ func TestECB_AES(t *testing.T) {
|
||||||
var r io.Reader = bytes.NewBuffer(tt.in);
|
var r io.Reader = bytes.NewBuffer(tt.in);
|
||||||
n, err := io.Copy(w, r);
|
n, err := io.Copy(w, r);
|
||||||
if n != int64(len(tt.in)) || err != nil {
|
if n != int64(len(tt.in)) || err != nil {
|
||||||
t.Errorf("%s: ECBReader io.Copy = %d, %v want %d, nil", test, n, err, len(tt.in));
|
t.Errorf("%s: ECBReader io.Copy = %d, %v want %d, nil", test, n, err, len(tt.in))
|
||||||
} else if d := crypt.Bytes(); !same(tt.out, d) {
|
} else if d := crypt.Bytes(); !same(tt.out, d) {
|
||||||
t.Errorf("%s: ECBReader\nhave %x\nwant %x", test, d, tt.out);
|
t.Errorf("%s: ECBReader\nhave %x\nwant %x", test, d, tt.out)
|
||||||
}
|
}
|
||||||
|
|
||||||
var plain bytes.Buffer;
|
var plain bytes.Buffer;
|
||||||
|
|
@ -115,13 +115,13 @@ func TestECB_AES(t *testing.T) {
|
||||||
w = &plain;
|
w = &plain;
|
||||||
n, err = io.Copy(w, r);
|
n, err = io.Copy(w, r);
|
||||||
if n != int64(len(tt.out)) || err != nil {
|
if n != int64(len(tt.out)) || err != nil {
|
||||||
t.Errorf("%s: ECBWriter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.out));
|
t.Errorf("%s: ECBWriter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.out))
|
||||||
} else if d := plain.Bytes(); !same(tt.in, d) {
|
} else if d := plain.Bytes(); !same(tt.in, d) {
|
||||||
t.Errorf("%s: ECBWriter\nhave %x\nwant %x", test, d, tt.in);
|
t.Errorf("%s: ECBWriter\nhave %x\nwant %x", test, d, tt.in)
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.Failed() {
|
if t.Failed() {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,34 +24,34 @@ func (c *IncCipher) BlockSize() int { return c.blockSize }
|
||||||
|
|
||||||
func (c *IncCipher) Encrypt(src, dst []byte) {
|
func (c *IncCipher) Encrypt(src, dst []byte) {
|
||||||
if !c.encrypting {
|
if !c.encrypting {
|
||||||
panicln("encrypt: not encrypting");
|
panicln("encrypt: not encrypting")
|
||||||
}
|
}
|
||||||
if len(src) != c.blockSize || len(dst) != c.blockSize {
|
if len(src) != c.blockSize || len(dst) != c.blockSize {
|
||||||
panicln("encrypt: wrong block size", c.blockSize, len(src), len(dst));
|
panicln("encrypt: wrong block size", c.blockSize, len(src), len(dst))
|
||||||
}
|
}
|
||||||
c.delta++;
|
c.delta++;
|
||||||
for i, b := range src {
|
for i, b := range src {
|
||||||
dst[i] = b + c.delta;
|
dst[i] = b + c.delta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *IncCipher) Decrypt(src, dst []byte) {
|
func (c *IncCipher) Decrypt(src, dst []byte) {
|
||||||
if c.encrypting {
|
if c.encrypting {
|
||||||
panicln("decrypt: not decrypting");
|
panicln("decrypt: not decrypting")
|
||||||
}
|
}
|
||||||
if len(src) != c.blockSize || len(dst) != c.blockSize {
|
if len(src) != c.blockSize || len(dst) != c.blockSize {
|
||||||
panicln("decrypt: wrong block size", c.blockSize, len(src), len(dst));
|
panicln("decrypt: wrong block size", c.blockSize, len(src), len(dst))
|
||||||
}
|
}
|
||||||
c.delta--;
|
c.delta--;
|
||||||
for i, b := range src {
|
for i, b := range src {
|
||||||
dst[i] = b + c.delta;
|
dst[i] = b + c.delta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestECBEncrypter(t *testing.T) {
|
func TestECBEncrypter(t *testing.T) {
|
||||||
var plain, crypt [256]byte;
|
var plain, crypt [256]byte;
|
||||||
for i := 0; i < len(plain); i++ {
|
for i := 0; i < len(plain); i++ {
|
||||||
plain[i] = byte(i);
|
plain[i] = byte(i)
|
||||||
}
|
}
|
||||||
b := new(bytes.Buffer);
|
b := new(bytes.Buffer);
|
||||||
for block := 1; block <= 64; block *= 2 {
|
for block := 1; block <= 64; block *= 2 {
|
||||||
|
|
@ -59,7 +59,7 @@ func TestECBEncrypter(t *testing.T) {
|
||||||
delta := byte(0);
|
delta := byte(0);
|
||||||
for i := 0; i < len(crypt); i++ {
|
for i := 0; i < len(crypt); i++ {
|
||||||
if i%block == 0 {
|
if i%block == 0 {
|
||||||
delta++;
|
delta++
|
||||||
}
|
}
|
||||||
crypt[i] = plain[i]+delta;
|
crypt[i] = plain[i]+delta;
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +82,7 @@ func TestECBEncrypter(t *testing.T) {
|
||||||
for n := 1; n <= len(plain)/2; n *= 2 {
|
for n := 1; n <= len(plain)/2; n *= 2 {
|
||||||
_, err := io.Copyn(w, r, int64(n));
|
_, err := io.Copyn(w, r, int64(n));
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("block=%d frag=%d: Copyn %d: %s", block, frag, n, err);
|
t.Errorf("block=%d frag=%d: Copyn %d: %s", block, frag, n, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if frag != 0 {
|
if frag != 0 {
|
||||||
|
|
@ -101,7 +101,7 @@ func TestECBEncrypter(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if string(data) != string(&crypt) {
|
if string(data) != string(&crypt) {
|
||||||
t.Errorf("block=%d frag=%d: want %x got %x", block, frag, data, crypt);
|
t.Errorf("block=%d frag=%d: want %x got %x", block, frag, data, crypt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +115,7 @@ func testECBDecrypter(t *testing.T, maxio int) {
|
||||||
};
|
};
|
||||||
var plain, crypt [256]byte;
|
var plain, crypt [256]byte;
|
||||||
for i := 0; i < len(plain); i++ {
|
for i := 0; i < len(plain); i++ {
|
||||||
plain[i] = byte(255-i);
|
plain[i] = byte(255-i)
|
||||||
}
|
}
|
||||||
b := new(bytes.Buffer);
|
b := new(bytes.Buffer);
|
||||||
for block := 1; block <= 64 && block <= maxio; block *= 2 {
|
for block := 1; block <= 64 && block <= maxio; block *= 2 {
|
||||||
|
|
@ -123,7 +123,7 @@ func testECBDecrypter(t *testing.T, maxio int) {
|
||||||
delta := byte(0);
|
delta := byte(0);
|
||||||
for i := 0; i < len(crypt); i++ {
|
for i := 0; i < len(crypt); i++ {
|
||||||
if i%block == 0 {
|
if i%block == 0 {
|
||||||
delta++;
|
delta++
|
||||||
}
|
}
|
||||||
crypt[i] = plain[i]+delta;
|
crypt[i] = plain[i]+delta;
|
||||||
}
|
}
|
||||||
|
|
@ -147,7 +147,7 @@ func testECBDecrypter(t *testing.T, maxio int) {
|
||||||
for n := 1; n <= maxio/2; n *= 2 {
|
for n := 1; n <= maxio/2; n *= 2 {
|
||||||
_, err := io.Copyn(b, r, int64(n));
|
_, err := io.Copyn(b, r, int64(n));
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s: Copyn %d: %s", test, n, err);
|
t.Errorf("%s: Copyn %d: %s", test, n, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if frag != 0 {
|
if frag != 0 {
|
||||||
|
|
@ -166,7 +166,7 @@ func testECBDecrypter(t *testing.T, maxio int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if string(data) != string(plain[0:maxio]) {
|
if string(data) != string(plain[0:maxio]) {
|
||||||
t.Errorf("%s: input=%x want %x got %x", test, crypt[0:maxio], plain[0:maxio], data);
|
t.Errorf("%s: input=%x want %x got %x", test, crypt[0:maxio], plain[0:maxio], data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -176,6 +176,6 @@ func testECBDecrypter(t *testing.T, maxio int) {
|
||||||
func TestECBDecrypter(t *testing.T) {
|
func TestECBDecrypter(t *testing.T) {
|
||||||
// Do shorter I/O sizes first; they're easier to debug.
|
// Do shorter I/O sizes first; they're easier to debug.
|
||||||
for n := 1; n <= 256 && !t.Failed(); n *= 2 {
|
for n := 1; n <= 256 && !t.Failed(); n *= 2 {
|
||||||
testECBDecrypter(t, n);
|
testECBDecrypter(t, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ func newOFBStream(c Cipher, iv []byte) *ofbStream {
|
||||||
x.c = c;
|
x.c = c;
|
||||||
n := len(iv);
|
n := len(iv);
|
||||||
if n != c.BlockSize() {
|
if n != c.BlockSize() {
|
||||||
panicln("crypto/block: newOFBStream: invalid iv size", n, "!=", c.BlockSize());
|
panicln("crypto/block: newOFBStream: invalid iv size", n, "!=", c.BlockSize())
|
||||||
}
|
}
|
||||||
x.iv = copy(iv);
|
x.iv = copy(iv);
|
||||||
return x;
|
return x;
|
||||||
|
|
@ -44,7 +44,7 @@ func (x *ofbStream) Next() []byte {
|
||||||
// an OFB reader applied to an encrypted stream produces a decrypted
|
// an OFB reader applied to an encrypted stream produces a decrypted
|
||||||
// stream and vice versa.
|
// stream and vice versa.
|
||||||
func NewOFBReader(c Cipher, iv []byte, r io.Reader) io.Reader {
|
func NewOFBReader(c Cipher, iv []byte, r io.Reader) io.Reader {
|
||||||
return newXorReader(newOFBStream(c, iv), r);
|
return newXorReader(newOFBStream(c, iv), r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewOFBWriter returns a writer that encrypts (or decrypts) data using c
|
// NewOFBWriter returns a writer that encrypts (or decrypts) data using c
|
||||||
|
|
@ -55,5 +55,5 @@ func NewOFBReader(c Cipher, iv []byte, r io.Reader) io.Reader {
|
||||||
// an OFB writer applied to an decrypted stream produces an encrypted
|
// an OFB writer applied to an decrypted stream produces an encrypted
|
||||||
// stream and vice versa.
|
// stream and vice versa.
|
||||||
func NewOFBWriter(c Cipher, iv []byte, w io.Writer) io.Writer {
|
func NewOFBWriter(c Cipher, iv []byte, w io.Writer) io.Writer {
|
||||||
return newXorWriter(newOFBStream(c, iv), w);
|
return newXorWriter(newOFBStream(c, iv), w)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,9 +82,9 @@ func TestOFB_AES(t *testing.T) {
|
||||||
var r io.Reader = bytes.NewBuffer(in);
|
var r io.Reader = bytes.NewBuffer(in);
|
||||||
n, err := io.Copy(w, r);
|
n, err := io.Copy(w, r);
|
||||||
if n != int64(len(in)) || err != nil {
|
if n != int64(len(in)) || err != nil {
|
||||||
t.Errorf("%s/%d: OFBWriter io.Copy = %d, %v want %d, nil", test, len(in), n, err, len(in));
|
t.Errorf("%s/%d: OFBWriter io.Copy = %d, %v want %d, nil", test, len(in), n, err, len(in))
|
||||||
} else if d, out := crypt.Bytes(), tt.out[0:len(in)]; !same(out, d) {
|
} else if d, out := crypt.Bytes(), tt.out[0:len(in)]; !same(out, d) {
|
||||||
t.Errorf("%s/%d: OFBWriter\ninpt %x\nhave %x\nwant %x", test, len(in), in, d, out);
|
t.Errorf("%s/%d: OFBWriter\ninpt %x\nhave %x\nwant %x", test, len(in), in, d, out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,14 +95,14 @@ func TestOFB_AES(t *testing.T) {
|
||||||
w := &plain;
|
w := &plain;
|
||||||
n, err := io.Copy(w, r);
|
n, err := io.Copy(w, r);
|
||||||
if n != int64(len(out)) || err != nil {
|
if n != int64(len(out)) || err != nil {
|
||||||
t.Errorf("%s/%d: OFBReader io.Copy = %d, %v want %d, nil", test, len(out), n, err, len(out));
|
t.Errorf("%s/%d: OFBReader io.Copy = %d, %v want %d, nil", test, len(out), n, err, len(out))
|
||||||
} else if d, in := plain.Bytes(), tt.in[0:len(out)]; !same(in, d) {
|
} else if d, in := plain.Bytes(), tt.in[0:len(out)]; !same(in, d) {
|
||||||
t.Errorf("%s/%d: OFBReader\nhave %x\nwant %x", test, len(out), d, in);
|
t.Errorf("%s/%d: OFBReader\nhave %x\nwant %x", test, len(out), d, in)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.Failed() {
|
if t.Failed() {
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,16 +75,16 @@ func (x *xorWriter) Write(p []byte) (n int, err os.Error) {
|
||||||
if nn := len(x.extra); nn > 0 {
|
if nn := len(x.extra); nn > 0 {
|
||||||
// extra points into work, so edit directly
|
// extra points into work, so edit directly
|
||||||
if m > nn {
|
if m > nn {
|
||||||
m = nn;
|
m = nn
|
||||||
}
|
}
|
||||||
for i := 0; i < m; i++ {
|
for i := 0; i < m; i++ {
|
||||||
x.extra[i] ^= p[i];
|
x.extra[i] ^= p[i]
|
||||||
}
|
}
|
||||||
chunk = x.extra[0:m];
|
chunk = x.extra[0:m];
|
||||||
} else {
|
} else {
|
||||||
// xor p ^ buf into work, refreshing buf as needed
|
// xor p ^ buf into work, refreshing buf as needed
|
||||||
if nn := len(x.work); m > nn {
|
if nn := len(x.work); m > nn {
|
||||||
m = nn;
|
m = nn
|
||||||
}
|
}
|
||||||
bp := 0;
|
bp := 0;
|
||||||
buf := x.buf;
|
buf := x.buf;
|
||||||
|
|
@ -104,19 +104,19 @@ func (x *xorWriter) Write(p []byte) (n int, err os.Error) {
|
||||||
var nn int;
|
var nn int;
|
||||||
nn, err = x.w.Write(chunk);
|
nn, err = x.w.Write(chunk);
|
||||||
if nn != len(chunk) && err == nil {
|
if nn != len(chunk) && err == nil {
|
||||||
err = io.ErrShortWrite;
|
err = io.ErrShortWrite
|
||||||
}
|
}
|
||||||
if nn < len(chunk) {
|
if nn < len(chunk) {
|
||||||
// Reconstruct the random bits from the unwritten
|
// Reconstruct the random bits from the unwritten
|
||||||
// data and save them for next time.
|
// data and save them for next time.
|
||||||
for i := nn; i < m; i++ {
|
for i := nn; i < m; i++ {
|
||||||
chunk[i] ^= p[i];
|
chunk[i] ^= p[i]
|
||||||
}
|
}
|
||||||
x.extra = chunk[nn:len(chunk)];
|
x.extra = chunk[nn:len(chunk)];
|
||||||
}
|
}
|
||||||
n += nn;
|
n += nn;
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
p = p[m:len(p)];
|
p = p[m:len(p)];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ func (x *incStream) Next() []byte {
|
||||||
func testXorWriter(t *testing.T, maxio int) {
|
func testXorWriter(t *testing.T, maxio int) {
|
||||||
var plain, crypt [256]byte;
|
var plain, crypt [256]byte;
|
||||||
for i := 0; i < len(plain); i++ {
|
for i := 0; i < len(plain); i++ {
|
||||||
plain[i] = byte(i);
|
plain[i] = byte(i)
|
||||||
}
|
}
|
||||||
b := new(bytes.Buffer);
|
b := new(bytes.Buffer);
|
||||||
for block := 1; block <= 64 && block <= maxio; block *= 2 {
|
for block := 1; block <= 64 && block <= maxio; block *= 2 {
|
||||||
|
|
@ -44,7 +44,7 @@ func testXorWriter(t *testing.T, maxio int) {
|
||||||
n := byte(0);
|
n := byte(0);
|
||||||
for i := 0; i < len(crypt); i++ {
|
for i := 0; i < len(crypt); i++ {
|
||||||
if i%block == 0 {
|
if i%block == 0 {
|
||||||
n++;
|
n++
|
||||||
}
|
}
|
||||||
crypt[i] = plain[i]^n;
|
crypt[i] = plain[i]^n;
|
||||||
n++;
|
n++;
|
||||||
|
|
@ -69,7 +69,7 @@ func testXorWriter(t *testing.T, maxio int) {
|
||||||
for n := 1; n <= len(plain)/2; n *= 2 {
|
for n := 1; n <= len(plain)/2; n *= 2 {
|
||||||
_, err := io.Copyn(w, r, int64(n));
|
_, err := io.Copyn(w, r, int64(n));
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s: Copyn %d: %s", test, n, err);
|
t.Errorf("%s: Copyn %d: %s", test, n, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,7 +82,7 @@ func testXorWriter(t *testing.T, maxio int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if string(data) != string(crypt) {
|
if string(data) != string(crypt) {
|
||||||
t.Errorf("%s: want %x got %x", test, data, crypt);
|
t.Errorf("%s: want %x got %x", test, data, crypt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +92,7 @@ func testXorWriter(t *testing.T, maxio int) {
|
||||||
func TestXorWriter(t *testing.T) {
|
func TestXorWriter(t *testing.T) {
|
||||||
// Do shorter I/O sizes first; they're easier to debug.
|
// Do shorter I/O sizes first; they're easier to debug.
|
||||||
for n := 1; n <= 256 && !t.Failed(); n *= 2 {
|
for n := 1; n <= 256 && !t.Failed(); n *= 2 {
|
||||||
testXorWriter(t, n);
|
testXorWriter(t, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,7 +104,7 @@ func testXorReader(t *testing.T, maxio int) {
|
||||||
};
|
};
|
||||||
var plain, crypt [256]byte;
|
var plain, crypt [256]byte;
|
||||||
for i := 0; i < len(plain); i++ {
|
for i := 0; i < len(plain); i++ {
|
||||||
plain[i] = byte(255-i);
|
plain[i] = byte(255-i)
|
||||||
}
|
}
|
||||||
b := new(bytes.Buffer);
|
b := new(bytes.Buffer);
|
||||||
for block := 1; block <= 64 && block <= maxio; block *= 2 {
|
for block := 1; block <= 64 && block <= maxio; block *= 2 {
|
||||||
|
|
@ -112,7 +112,7 @@ func testXorReader(t *testing.T, maxio int) {
|
||||||
n := byte(0);
|
n := byte(0);
|
||||||
for i := 0; i < len(crypt); i++ {
|
for i := 0; i < len(crypt); i++ {
|
||||||
if i%block == 0 {
|
if i%block == 0 {
|
||||||
n++;
|
n++
|
||||||
}
|
}
|
||||||
crypt[i] = plain[i]^n;
|
crypt[i] = plain[i]^n;
|
||||||
n++;
|
n++;
|
||||||
|
|
@ -137,7 +137,7 @@ func testXorReader(t *testing.T, maxio int) {
|
||||||
for n := 1; n <= maxio/2; n *= 2 {
|
for n := 1; n <= maxio/2; n *= 2 {
|
||||||
_, err := io.Copyn(b, r, int64(n));
|
_, err := io.Copyn(b, r, int64(n));
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s: Copyn %d: %s", test, n, err);
|
t.Errorf("%s: Copyn %d: %s", test, n, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,7 +151,7 @@ func testXorReader(t *testing.T, maxio int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if string(data) != string(plain) {
|
if string(data) != string(plain) {
|
||||||
t.Errorf("%s: input=%x want %x got %x", test, crypt, plain, data);
|
t.Errorf("%s: input=%x want %x got %x", test, crypt, plain, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -161,7 +161,7 @@ func testXorReader(t *testing.T, maxio int) {
|
||||||
func TestXorReader(t *testing.T) {
|
func TestXorReader(t *testing.T) {
|
||||||
// Do shorter I/O sizes first; they're easier to debug.
|
// Do shorter I/O sizes first; they're easier to debug.
|
||||||
for n := 1; n <= 256 && !t.Failed(); n *= 2 {
|
for n := 1; n <= 256 && !t.Failed(); n *= 2 {
|
||||||
testXorReader(t, n);
|
testXorReader(t, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,10 +42,10 @@ type hmac struct {
|
||||||
|
|
||||||
func (h *hmac) tmpPad(xor byte) {
|
func (h *hmac) tmpPad(xor byte) {
|
||||||
for i, k := range h.key {
|
for i, k := range h.key {
|
||||||
h.tmp[i] = xor^k;
|
h.tmp[i] = xor^k
|
||||||
}
|
}
|
||||||
for i := len(h.key); i < padSize; i++ {
|
for i := len(h.key); i < padSize; i++ {
|
||||||
h.tmp[i] = xor;
|
h.tmp[i] = xor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ func (h *hmac) Sum() []byte {
|
||||||
h.tmpPad(0x5c);
|
h.tmpPad(0x5c);
|
||||||
sum := h.inner.Sum();
|
sum := h.inner.Sum();
|
||||||
for i, b := range sum {
|
for i, b := range sum {
|
||||||
h.tmp[padSize+i] = b;
|
h.tmp[padSize+i] = b
|
||||||
}
|
}
|
||||||
h.inner.Reset();
|
h.inner.Reset();
|
||||||
h.inner.Write(h.tmp);
|
h.inner.Write(h.tmp);
|
||||||
|
|
@ -61,7 +61,7 @@ func (h *hmac) Sum() []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *hmac) Write(p []byte) (n int, err os.Error) {
|
func (h *hmac) Write(p []byte) (n int, err os.Error) {
|
||||||
return h.inner.Write(p);
|
return h.inner.Write(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *hmac) Size() int { return h.size }
|
func (h *hmac) Size() int { return h.size }
|
||||||
|
|
@ -84,7 +84,7 @@ func New(h hash.Hash, key []byte) hash.Hash {
|
||||||
hm.size = h.Size();
|
hm.size = h.Size();
|
||||||
hm.key = make([]byte, len(key));
|
hm.key = make([]byte, len(key));
|
||||||
for i, k := range key {
|
for i, k := range key {
|
||||||
hm.key[i] = k;
|
hm.key[i] = k
|
||||||
}
|
}
|
||||||
hm.tmp = make([]byte, padSize + hm.size);
|
hm.tmp = make([]byte, padSize + hm.size);
|
||||||
hm.Reset();
|
hm.Reset();
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ func TestHMAC(t *testing.T) {
|
||||||
}
|
}
|
||||||
sum := fmt.Sprintf("%x", h.Sum());
|
sum := fmt.Sprintf("%x", h.Sum());
|
||||||
if sum != tt.out {
|
if sum != tt.out {
|
||||||
t.Errorf("test %d.%d: have %s want %s\n", i, j, sum, tt.out);
|
t.Errorf("test %d.%d: have %s want %s\n", i, j, sum, tt.out)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second iteration: make sure reset works.
|
// Second iteration: make sure reset works.
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,10 @@ func (d *digest) Write(p []byte) (nn int, err os.Error) {
|
||||||
if d.nx > 0 {
|
if d.nx > 0 {
|
||||||
n := len(p);
|
n := len(p);
|
||||||
if n > _Chunk - d.nx {
|
if n > _Chunk - d.nx {
|
||||||
n = _Chunk - d.nx;
|
n = _Chunk - d.nx
|
||||||
}
|
}
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
d.x[d.nx + i] = p[i];
|
d.x[d.nx + i] = p[i]
|
||||||
}
|
}
|
||||||
d.nx += n;
|
d.nx += n;
|
||||||
if d.nx == _Chunk {
|
if d.nx == _Chunk {
|
||||||
|
|
@ -69,7 +69,7 @@ func (d *digest) Write(p []byte) (nn int, err os.Error) {
|
||||||
p = p[n:len(p)];
|
p = p[n:len(p)];
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
for i := 0; i < len(p); i++ {
|
for i := 0; i < len(p); i++ {
|
||||||
d.x[i] = p[i];
|
d.x[i] = p[i]
|
||||||
}
|
}
|
||||||
d.nx = len(p);
|
d.nx = len(p);
|
||||||
}
|
}
|
||||||
|
|
@ -82,20 +82,20 @@ func (d *digest) Sum() []byte {
|
||||||
var tmp [64]byte;
|
var tmp [64]byte;
|
||||||
tmp[0] = 0x80;
|
tmp[0] = 0x80;
|
||||||
if len%64 < 56 {
|
if len%64 < 56 {
|
||||||
d.Write(tmp[0 : 56 - len%64]);
|
d.Write(tmp[0 : 56 - len%64])
|
||||||
} else {
|
} else {
|
||||||
d.Write(tmp[0 : 64 + 56 - len%64]);
|
d.Write(tmp[0 : 64 + 56 - len%64])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Length in bits.
|
// Length in bits.
|
||||||
len <<= 3;
|
len <<= 3;
|
||||||
for i := uint(0); i < 8; i++ {
|
for i := uint(0); i < 8; i++ {
|
||||||
tmp[i] = byte(len>>(8*i));
|
tmp[i] = byte(len>>(8*i))
|
||||||
}
|
}
|
||||||
d.Write(tmp[0:8]);
|
d.Write(tmp[0:8]);
|
||||||
|
|
||||||
if d.nx != 0 {
|
if d.nx != 0 {
|
||||||
panicln("oops");
|
panicln("oops")
|
||||||
}
|
}
|
||||||
|
|
||||||
p := make([]byte, 16);
|
p := make([]byte, 16);
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ type Cipher struct {
|
||||||
type KeySizeError int
|
type KeySizeError int
|
||||||
|
|
||||||
func (k KeySizeError) String() string {
|
func (k KeySizeError) String() string {
|
||||||
return "crypto/rc4: invalid key size " + strconv.Itoa(int(k));
|
return "crypto/rc4: invalid key size " + strconv.Itoa(int(k))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCipher creates and returns a new Cipher. The key argument should be the
|
// NewCipher creates and returns a new Cipher. The key argument should be the
|
||||||
|
|
@ -31,11 +31,11 @@ func (k KeySizeError) String() string {
|
||||||
func NewCipher(key []byte) (*Cipher, os.Error) {
|
func NewCipher(key []byte) (*Cipher, os.Error) {
|
||||||
k := len(key);
|
k := len(key);
|
||||||
if k < 1 || k > 256 {
|
if k < 1 || k > 256 {
|
||||||
return nil, KeySizeError(k);
|
return nil, KeySizeError(k)
|
||||||
}
|
}
|
||||||
var c Cipher;
|
var c Cipher;
|
||||||
for i := 0; i < 256; i++ {
|
for i := 0; i < 256; i++ {
|
||||||
c.s[i] = uint8(i);
|
c.s[i] = uint8(i)
|
||||||
}
|
}
|
||||||
var j uint8 = 0;
|
var j uint8 = 0;
|
||||||
for i := 0; i < 256; i++ {
|
for i := 0; i < 256; i++ {
|
||||||
|
|
@ -60,7 +60,7 @@ func (c *Cipher) XORKeyStream(buf []byte) {
|
||||||
// process's memory.
|
// process's memory.
|
||||||
func (c *Cipher) Reset() {
|
func (c *Cipher) Reset() {
|
||||||
for i := range c.s {
|
for i := range c.s {
|
||||||
c.s[i] = 0;
|
c.s[i] = 0
|
||||||
}
|
}
|
||||||
c.i, c.j = 0, 0;
|
c.i, c.j = 0, 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, er
|
||||||
ps, mm := em[1 : len(em)-len(msg)-1], em[len(em)-len(msg) : len(em)];
|
ps, mm := em[1 : len(em)-len(msg)-1], em[len(em)-len(msg) : len(em)];
|
||||||
err = nonZeroRandomBytes(ps, rand);
|
err = nonZeroRandomBytes(ps, rand);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
em[len(em)-len(msg)-1] = 0;
|
em[len(em)-len(msg)-1] = 0;
|
||||||
bytes.Copy(mm, msg);
|
bytes.Copy(mm, msg);
|
||||||
|
|
@ -47,7 +47,7 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, er
|
||||||
func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err os.Error) {
|
func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err os.Error) {
|
||||||
valid, out, err := decryptPKCS1v15(rand, priv, ciphertext);
|
valid, out, err := decryptPKCS1v15(rand, priv, ciphertext);
|
||||||
if err == nil && valid == 0 {
|
if err == nil && valid == 0 {
|
||||||
err = DecryptionError{};
|
err = DecryptionError{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -75,7 +75,7 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by
|
||||||
|
|
||||||
valid, msg, err := decryptPKCS1v15(rand, priv, ciphertext);
|
valid, msg, err := decryptPKCS1v15(rand, priv, ciphertext);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
valid &= subtle.ConstantTimeEq(int32(len(msg)), int32(len(key)));
|
valid &= subtle.ConstantTimeEq(int32(len(msg)), int32(len(key)));
|
||||||
|
|
@ -93,7 +93,7 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid
|
||||||
c := new(big.Int).SetBytes(ciphertext);
|
c := new(big.Int).SetBytes(ciphertext);
|
||||||
m, err := decrypt(rand, priv, c);
|
m, err := decrypt(rand, priv, c);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
em := leftPad(m.Bytes(), k);
|
em := leftPad(m.Bytes(), k);
|
||||||
|
|
@ -122,14 +122,14 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid
|
||||||
func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) {
|
func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) {
|
||||||
_, err = io.ReadFull(rand, s);
|
_, err = io.ReadFull(rand, s);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(s); i++ {
|
for i := 0; i < len(s); i++ {
|
||||||
for s[i] == 0 {
|
for s[i] == 0 {
|
||||||
_, err = rand.Read(s[i : i+1]);
|
_, err = rand.Read(s[i : i+1]);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ func decodeBase64(in string) []byte {
|
||||||
out := make([]byte, base64.StdEncoding.DecodedLen(len(in)));
|
out := make([]byte, base64.StdEncoding.DecodedLen(len(in)));
|
||||||
n, err := base64.StdEncoding.Decode(out, strings.Bytes(in));
|
n, err := base64.StdEncoding.Decode(out, strings.Bytes(in));
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil;
|
return nil
|
||||||
}
|
}
|
||||||
return out[0:n];
|
return out[0:n];
|
||||||
}
|
}
|
||||||
|
|
@ -52,11 +52,11 @@ func TestDecryptPKCS1v15(t *testing.T) {
|
||||||
for i, test := range decryptPKCS1v15Tests {
|
for i, test := range decryptPKCS1v15Tests {
|
||||||
out, err := DecryptPKCS1v15(nil, rsaPrivateKey, decodeBase64(test.in));
|
out, err := DecryptPKCS1v15(nil, rsaPrivateKey, decodeBase64(test.in));
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("#%d error decrypting", i);
|
t.Errorf("#%d error decrypting", i)
|
||||||
}
|
}
|
||||||
want := strings.Bytes(test.out);
|
want := strings.Bytes(test.out);
|
||||||
if bytes.Compare(out, want) != 0 {
|
if bytes.Compare(out, want) != 0 {
|
||||||
t.Errorf("#%d got:%#v want:%#v", i, out, want);
|
t.Errorf("#%d got:%#v want:%#v", i, out, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -64,13 +64,13 @@ func TestDecryptPKCS1v15(t *testing.T) {
|
||||||
func TestEncryptPKCS1v15(t *testing.T) {
|
func TestEncryptPKCS1v15(t *testing.T) {
|
||||||
urandom, err := os.Open("/dev/urandom", os.O_RDONLY, 0);
|
urandom, err := os.Open("/dev/urandom", os.O_RDONLY, 0);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to open /dev/urandom");
|
t.Errorf("Failed to open /dev/urandom")
|
||||||
}
|
}
|
||||||
k := (rsaPrivateKey.N.Len() + 7)/8;
|
k := (rsaPrivateKey.N.Len() + 7)/8;
|
||||||
|
|
||||||
tryEncryptDecrypt := func(in []byte, blind bool) bool {
|
tryEncryptDecrypt := func(in []byte, blind bool) bool {
|
||||||
if len(in) > k-11 {
|
if len(in) > k-11 {
|
||||||
in = in[0 : k-11];
|
in = in[0 : k-11]
|
||||||
}
|
}
|
||||||
|
|
||||||
ciphertext, err := EncryptPKCS1v15(urandom, &rsaPrivateKey.PublicKey, in);
|
ciphertext, err := EncryptPKCS1v15(urandom, &rsaPrivateKey.PublicKey, in);
|
||||||
|
|
@ -81,9 +81,9 @@ func TestEncryptPKCS1v15(t *testing.T) {
|
||||||
|
|
||||||
var rand io.Reader;
|
var rand io.Reader;
|
||||||
if !blind {
|
if !blind {
|
||||||
rand = nil;
|
rand = nil
|
||||||
} else {
|
} else {
|
||||||
rand = urandom;
|
rand = urandom
|
||||||
}
|
}
|
||||||
plaintext, err := DecryptPKCS1v15(rand, rsaPrivateKey, ciphertext);
|
plaintext, err := DecryptPKCS1v15(rand, rsaPrivateKey, ciphertext);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -126,11 +126,11 @@ func TestEncryptPKCS1v15SessionKey(t *testing.T) {
|
||||||
key := strings.Bytes("FAIL");
|
key := strings.Bytes("FAIL");
|
||||||
err := DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, decodeBase64(test.in), key);
|
err := DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, decodeBase64(test.in), key);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("#%d error decrypting", i);
|
t.Errorf("#%d error decrypting", i)
|
||||||
}
|
}
|
||||||
want := strings.Bytes(test.out);
|
want := strings.Bytes(test.out);
|
||||||
if bytes.Compare(key, want) != 0 {
|
if bytes.Compare(key, want) != 0 {
|
||||||
t.Errorf("#%d got:%#v want:%#v", i, key, want);
|
t.Errorf("#%d got:%#v want:%#v", i, key, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -138,13 +138,13 @@ func TestEncryptPKCS1v15SessionKey(t *testing.T) {
|
||||||
func TestNonZeroRandomBytes(t *testing.T) {
|
func TestNonZeroRandomBytes(t *testing.T) {
|
||||||
urandom, err := os.Open("/dev/urandom", os.O_RDONLY, 0);
|
urandom, err := os.Open("/dev/urandom", os.O_RDONLY, 0);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to open /dev/urandom");
|
t.Errorf("Failed to open /dev/urandom")
|
||||||
}
|
}
|
||||||
|
|
||||||
b := make([]byte, 512);
|
b := make([]byte, 512);
|
||||||
err = nonZeroRandomBytes(b, urandom);
|
err = nonZeroRandomBytes(b, urandom);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("returned error: %s", err);
|
t.Errorf("returned error: %s", err)
|
||||||
}
|
}
|
||||||
for _, b := range b {
|
for _, b := range b {
|
||||||
if b == 0 {
|
if b == 0 {
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ func randomNumber(rand io.Reader, max *big.Int) (n *big.Int, err os.Error) {
|
||||||
// max.
|
// max.
|
||||||
r := uint(max.Len() % 8);
|
r := uint(max.Len() % 8);
|
||||||
if r == 0 {
|
if r == 0 {
|
||||||
r = 8;
|
r = 8
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes := make([]byte, k);
|
bytes := make([]byte, k);
|
||||||
|
|
@ -76,7 +76,7 @@ func randomNumber(rand io.Reader, max *big.Int) (n *big.Int, err os.Error) {
|
||||||
for {
|
for {
|
||||||
_, err = io.ReadFull(rand, bytes);
|
_, err = io.ReadFull(rand, bytes);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear bits in the first byte to increase the probability
|
// Clear bits in the first byte to increase the probability
|
||||||
|
|
@ -85,7 +85,7 @@ func randomNumber(rand io.Reader, max *big.Int) (n *big.Int, err os.Error) {
|
||||||
|
|
||||||
n.SetBytes(bytes);
|
n.SetBytes(bytes);
|
||||||
if big.CmpInt(n, max) < 0 {
|
if big.CmpInt(n, max) < 0 {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,7 +123,7 @@ func (priv PrivateKey) Validate() os.Error {
|
||||||
// Check that p*q == n.
|
// Check that p*q == n.
|
||||||
modulus := new(big.Int).Mul(priv.P, priv.Q);
|
modulus := new(big.Int).Mul(priv.P, priv.Q);
|
||||||
if big.CmpInt(modulus, priv.N) != 0 {
|
if big.CmpInt(modulus, priv.N) != 0 {
|
||||||
return os.ErrorString("invalid modulus");
|
return os.ErrorString("invalid modulus")
|
||||||
}
|
}
|
||||||
// Check that e and totient(p, q) are coprime.
|
// Check that e and totient(p, q) are coprime.
|
||||||
pminus1 := new(big.Int).Sub(priv.P, bigOne);
|
pminus1 := new(big.Int).Sub(priv.P, bigOne);
|
||||||
|
|
@ -135,13 +135,13 @@ func (priv PrivateKey) Validate() os.Error {
|
||||||
y := new(big.Int);
|
y := new(big.Int);
|
||||||
big.GcdInt(gcd, x, y, totient, e);
|
big.GcdInt(gcd, x, y, totient, e);
|
||||||
if big.CmpInt(gcd, bigOne) != 0 {
|
if big.CmpInt(gcd, bigOne) != 0 {
|
||||||
return os.ErrorString("invalid public exponent E");
|
return os.ErrorString("invalid public exponent E")
|
||||||
}
|
}
|
||||||
// Check that de ≡ 1 (mod totient(p, q))
|
// Check that de ≡ 1 (mod totient(p, q))
|
||||||
de := new(big.Int).Mul(priv.D, e);
|
de := new(big.Int).Mul(priv.D, e);
|
||||||
de.Mod(de, totient);
|
de.Mod(de, totient);
|
||||||
if big.CmpInt(de, bigOne) != 0 {
|
if big.CmpInt(de, bigOne) != 0 {
|
||||||
return os.ErrorString("invalid private exponent D");
|
return os.ErrorString("invalid private exponent D")
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
@ -209,13 +209,13 @@ func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
|
||||||
// incCounter increments a four byte, big-endian counter.
|
// incCounter increments a four byte, big-endian counter.
|
||||||
func incCounter(c *[4]byte) {
|
func incCounter(c *[4]byte) {
|
||||||
if c[3]++; c[3] != 0 {
|
if c[3]++; c[3] != 0 {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if c[2]++; c[2] != 0 {
|
if c[2]++; c[2] != 0 {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if c[1]++; c[1] != 0 {
|
if c[1]++; c[1] != 0 {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
c[0]++;
|
c[0]++;
|
||||||
}
|
}
|
||||||
|
|
@ -245,7 +245,7 @@ func mgf1XOR(out []byte, hash hash.Hash, seed []byte) {
|
||||||
type MessageTooLongError struct{}
|
type MessageTooLongError struct{}
|
||||||
|
|
||||||
func (MessageTooLongError) String() string {
|
func (MessageTooLongError) String() string {
|
||||||
return "message too long for RSA public key size";
|
return "message too long for RSA public key size"
|
||||||
}
|
}
|
||||||
|
|
||||||
func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
|
func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
|
||||||
|
|
@ -279,7 +279,7 @@ func EncryptOAEP(hash hash.Hash, rand io.Reader, pub *PublicKey, msg []byte, lab
|
||||||
|
|
||||||
_, err = io.ReadFull(rand, seed);
|
_, err = io.ReadFull(rand, seed);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
mgf1XOR(db, hash, seed);
|
mgf1XOR(db, hash, seed);
|
||||||
|
|
@ -308,7 +308,7 @@ func modInverse(a, n *big.Int) (ia *big.Int) {
|
||||||
if big.CmpInt(x, bigOne) < 0 {
|
if big.CmpInt(x, bigOne) < 0 {
|
||||||
// 0 is not the multiplicative inverse of any element so, if x
|
// 0 is not the multiplicative inverse of any element so, if x
|
||||||
// < 1, then x is negative.
|
// < 1, then x is negative.
|
||||||
x.Add(x, n);
|
x.Add(x, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
|
|
@ -336,7 +336,7 @@ func decrypt(rand io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.E
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if big.CmpInt(r, bigZero) == 0 {
|
if big.CmpInt(r, bigZero) == 0 {
|
||||||
r = bigOne;
|
r = bigOne
|
||||||
}
|
}
|
||||||
ir = modInverse(r, priv.N);
|
ir = modInverse(r, priv.N);
|
||||||
bigE := big.NewInt(int64(priv.E));
|
bigE := big.NewInt(int64(priv.E));
|
||||||
|
|
@ -370,7 +370,7 @@ func DecryptOAEP(hash hash.Hash, rand io.Reader, priv *PrivateKey, ciphertext []
|
||||||
|
|
||||||
m, err := decrypt(rand, priv, c);
|
m, err := decrypt(rand, priv, c);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hash.Write(label);
|
hash.Write(label);
|
||||||
|
|
@ -431,7 +431,7 @@ func DecryptOAEP(hash hash.Hash, rand io.Reader, priv *PrivateKey, ciphertext []
|
||||||
func leftPad(input []byte, size int) (out []byte) {
|
func leftPad(input []byte, size int) (out []byte) {
|
||||||
n := len(input);
|
n := len(input);
|
||||||
if n > size {
|
if n > size {
|
||||||
n = size;
|
n = size
|
||||||
}
|
}
|
||||||
out = make([]byte, size);
|
out = make([]byte, size);
|
||||||
bytes.Copy(out[len(out)-n : len(out)], input);
|
bytes.Copy(out[len(out)-n : len(out)], input);
|
||||||
|
|
|
||||||
|
|
@ -72,10 +72,10 @@ func TestEncryptOAEP(t *testing.T) {
|
||||||
randomSource := bytes.NewBuffer(message.seed);
|
randomSource := bytes.NewBuffer(message.seed);
|
||||||
out, err := EncryptOAEP(sha1, randomSource, &public, message.in, nil);
|
out, err := EncryptOAEP(sha1, randomSource, &public, message.in, nil);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("#%d,%d error: %s", i, j, err);
|
t.Errorf("#%d,%d error: %s", i, j, err)
|
||||||
}
|
}
|
||||||
if bytes.Compare(out, message.out) != 0 {
|
if bytes.Compare(out, message.out) != 0 {
|
||||||
t.Errorf("#%d,%d bad result: %s (want %s)", i, j, out, message.out);
|
t.Errorf("#%d,%d bad result: %s (want %s)", i, j, out, message.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -84,7 +84,7 @@ func TestEncryptOAEP(t *testing.T) {
|
||||||
func TestDecryptOAEP(t *testing.T) {
|
func TestDecryptOAEP(t *testing.T) {
|
||||||
urandom, err := os.Open("/dev/urandom", os.O_RDONLY, 0);
|
urandom, err := os.Open("/dev/urandom", os.O_RDONLY, 0);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to open /dev/urandom");
|
t.Errorf("Failed to open /dev/urandom")
|
||||||
}
|
}
|
||||||
|
|
||||||
sha1 := sha1.New();
|
sha1 := sha1.New();
|
||||||
|
|
@ -98,17 +98,17 @@ func TestDecryptOAEP(t *testing.T) {
|
||||||
for j, message := range test.msgs {
|
for j, message := range test.msgs {
|
||||||
out, err := DecryptOAEP(sha1, nil, &private, message.out, nil);
|
out, err := DecryptOAEP(sha1, nil, &private, message.out, nil);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("#%d,%d error: %s", i, j, err);
|
t.Errorf("#%d,%d error: %s", i, j, err)
|
||||||
} else if bytes.Compare(out, message.in) != 0 {
|
} else if bytes.Compare(out, message.in) != 0 {
|
||||||
t.Errorf("#%d,%d bad result: %#v (want %#v)", i, j, out, message.in);
|
t.Errorf("#%d,%d bad result: %#v (want %#v)", i, j, out, message.in)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt with blinding.
|
// Decrypt with blinding.
|
||||||
out, err = DecryptOAEP(sha1, urandom, &private, message.out, nil);
|
out, err = DecryptOAEP(sha1, urandom, &private, message.out, nil);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("#%d,%d (blind) error: %s", i, j, err);
|
t.Errorf("#%d,%d (blind) error: %s", i, j, err)
|
||||||
} else if bytes.Compare(out, message.in) != 0 {
|
} else if bytes.Compare(out, message.in) != 0 {
|
||||||
t.Errorf("#%d,%d (blind) bad result: %#v (want %#v)", i, j, out, message.in);
|
t.Errorf("#%d,%d (blind) bad result: %#v (want %#v)", i, j, out, message.in)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,10 +55,10 @@ func (d *digest) Write(p []byte) (nn int, err os.Error) {
|
||||||
if d.nx > 0 {
|
if d.nx > 0 {
|
||||||
n := len(p);
|
n := len(p);
|
||||||
if n > _Chunk - d.nx {
|
if n > _Chunk - d.nx {
|
||||||
n = _Chunk - d.nx;
|
n = _Chunk - d.nx
|
||||||
}
|
}
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
d.x[d.nx + i] = p[i];
|
d.x[d.nx + i] = p[i]
|
||||||
}
|
}
|
||||||
d.nx += n;
|
d.nx += n;
|
||||||
if d.nx == _Chunk {
|
if d.nx == _Chunk {
|
||||||
|
|
@ -71,7 +71,7 @@ func (d *digest) Write(p []byte) (nn int, err os.Error) {
|
||||||
p = p[n:len(p)];
|
p = p[n:len(p)];
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
for i := 0; i < len(p); i++ {
|
for i := 0; i < len(p); i++ {
|
||||||
d.x[i] = p[i];
|
d.x[i] = p[i]
|
||||||
}
|
}
|
||||||
d.nx = len(p);
|
d.nx = len(p);
|
||||||
}
|
}
|
||||||
|
|
@ -84,20 +84,20 @@ func (d *digest) Sum() []byte {
|
||||||
var tmp [64]byte;
|
var tmp [64]byte;
|
||||||
tmp[0] = 0x80;
|
tmp[0] = 0x80;
|
||||||
if len%64 < 56 {
|
if len%64 < 56 {
|
||||||
d.Write(tmp[0 : 56 - len%64]);
|
d.Write(tmp[0 : 56 - len%64])
|
||||||
} else {
|
} else {
|
||||||
d.Write(tmp[0 : 64 + 56 - len%64]);
|
d.Write(tmp[0 : 64 + 56 - len%64])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Length in bits.
|
// Length in bits.
|
||||||
len <<= 3;
|
len <<= 3;
|
||||||
for i := uint(0); i < 8; i++ {
|
for i := uint(0); i < 8; i++ {
|
||||||
tmp[i] = byte(len>>(56 - 8*i));
|
tmp[i] = byte(len>>(56 - 8*i))
|
||||||
}
|
}
|
||||||
d.Write(tmp[0:8]);
|
d.Write(tmp[0:8]);
|
||||||
|
|
||||||
if d.nx != 0 {
|
if d.nx != 0 {
|
||||||
panicln("oops");
|
panicln("oops")
|
||||||
}
|
}
|
||||||
|
|
||||||
p := make([]byte, 20);
|
p := make([]byte, 20);
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ func ConstantTimeCompare(x, y []byte) int {
|
||||||
var v byte;
|
var v byte;
|
||||||
|
|
||||||
for i := 0; i < len(x); i++ {
|
for i := 0; i < len(x); i++ {
|
||||||
v |= x[i]^y[i];
|
v |= x[i]^y[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
return ConstantTimeByteEq(v, 0);
|
return ConstantTimeByteEq(v, 0);
|
||||||
|
|
@ -51,7 +51,7 @@ func ConstantTimeCopy(v int, x, y []byte) {
|
||||||
xmask := byte(v-1);
|
xmask := byte(v-1);
|
||||||
ymask := byte(^(v-1));
|
ymask := byte(^(v-1));
|
||||||
for i := 0; i < len(x); i++ {
|
for i := 0; i < len(x); i++ {
|
||||||
x[i] = x[i]&xmask | y[i]&ymask;
|
x[i] = x[i]&xmask | y[i]&ymask
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ var testConstandTimeCompareData = []TestConstantTimeCompareStruct{
|
||||||
func TestConstantTimeCompare(t *testing.T) {
|
func TestConstantTimeCompare(t *testing.T) {
|
||||||
for i, test := range testConstandTimeCompareData {
|
for i, test := range testConstandTimeCompareData {
|
||||||
if r := ConstantTimeCompare(test.a, test.b); r != test.out {
|
if r := ConstantTimeCompare(test.a, test.b); r != test.out {
|
||||||
t.Errorf("#%d bad result (got %x, want %x)", i, r, test.out);
|
t.Errorf("#%d bad result (got %x, want %x)", i, r, test.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -44,7 +44,7 @@ var testConstandTimeByteEqData = []TestConstantTimeByteEqStruct{
|
||||||
|
|
||||||
func byteEq(a, b uint8) int {
|
func byteEq(a, b uint8) int {
|
||||||
if a == b {
|
if a == b {
|
||||||
return 1;
|
return 1
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -52,18 +52,18 @@ func byteEq(a, b uint8) int {
|
||||||
func TestConstantTimeByteEq(t *testing.T) {
|
func TestConstantTimeByteEq(t *testing.T) {
|
||||||
for i, test := range testConstandTimeByteEqData {
|
for i, test := range testConstandTimeByteEqData {
|
||||||
if r := ConstantTimeByteEq(test.a, test.b); r != test.out {
|
if r := ConstantTimeByteEq(test.a, test.b); r != test.out {
|
||||||
t.Errorf("#%d bad result (got %x, want %x)", i, r, test.out);
|
t.Errorf("#%d bad result (got %x, want %x)", i, r, test.out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := quick.CheckEqual(ConstantTimeByteEq, byteEq, nil);
|
err := quick.CheckEqual(ConstantTimeByteEq, byteEq, nil);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err);
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func eq(a, b int32) int {
|
func eq(a, b int32) int {
|
||||||
if a == b {
|
if a == b {
|
||||||
return 1;
|
return 1
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -71,27 +71,27 @@ func eq(a, b int32) int {
|
||||||
func TestConstantTimeEq(t *testing.T) {
|
func TestConstantTimeEq(t *testing.T) {
|
||||||
err := quick.CheckEqual(ConstantTimeEq, eq, nil);
|
err := quick.CheckEqual(ConstantTimeEq, eq, nil);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err);
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func copy(v int, x, y []byte) []byte {
|
func copy(v int, x, y []byte) []byte {
|
||||||
if len(x) > len(y) {
|
if len(x) > len(y) {
|
||||||
x = x[0:len(y)];
|
x = x[0:len(y)]
|
||||||
} else {
|
} else {
|
||||||
y = y[0:len(x)];
|
y = y[0:len(x)]
|
||||||
}
|
}
|
||||||
if v == 1 {
|
if v == 1 {
|
||||||
bytes.Copy(x, y);
|
bytes.Copy(x, y)
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
func constantTimeCopyWrapper(v int, x, y []byte) []byte {
|
func constantTimeCopyWrapper(v int, x, y []byte) []byte {
|
||||||
if len(x) > len(y) {
|
if len(x) > len(y) {
|
||||||
x = x[0:len(y)];
|
x = x[0:len(y)]
|
||||||
} else {
|
} else {
|
||||||
y = y[0:len(x)];
|
y = y[0:len(x)]
|
||||||
}
|
}
|
||||||
v &= 1;
|
v &= 1;
|
||||||
ConstantTimeCopy(v, x, y);
|
ConstantTimeCopy(v, x, y);
|
||||||
|
|
@ -101,6 +101,6 @@ func constantTimeCopyWrapper(v int, x, y []byte) []byte {
|
||||||
func TestConstantTimeCopy(t *testing.T) {
|
func TestConstantTimeCopy(t *testing.T) {
|
||||||
err := quick.CheckEqual(constantTimeCopyWrapper, copy, nil);
|
err := quick.CheckEqual(constantTimeCopyWrapper, copy, nil);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err);
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,12 +92,12 @@ type encryptor interface {
|
||||||
func mutualVersion(theirMajor, theirMinor uint8) (major, minor uint8, ok bool) {
|
func mutualVersion(theirMajor, theirMinor uint8) (major, minor uint8, ok bool) {
|
||||||
// We don't deal with peers < TLS 1.0 (aka version 3.1).
|
// We don't deal with peers < TLS 1.0 (aka version 3.1).
|
||||||
if theirMajor < 3 || theirMajor == 3 && theirMinor < 1 {
|
if theirMajor < 3 || theirMajor == 3 && theirMinor < 1 {
|
||||||
return 0, 0, false;
|
return 0, 0, false
|
||||||
}
|
}
|
||||||
major = 3;
|
major = 3;
|
||||||
minor = 2;
|
minor = 2;
|
||||||
if theirMinor < minor {
|
if theirMinor < minor {
|
||||||
minor = theirMinor;
|
minor = theirMinor
|
||||||
}
|
}
|
||||||
ok = true;
|
ok = true;
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue