diff options
Diffstat (limited to 'src/pkg/reflect')
-rw-r--r-- | src/pkg/reflect/Makefile | 13 | ||||
-rw-r--r-- | src/pkg/reflect/all_test.go | 1566 | ||||
-rw-r--r-- | src/pkg/reflect/deepequal.go | 126 | ||||
-rw-r--r-- | src/pkg/reflect/set_test.go | 211 | ||||
-rw-r--r-- | src/pkg/reflect/tostring_test.go | 96 | ||||
-rw-r--r-- | src/pkg/reflect/type.go | 1167 | ||||
-rw-r--r-- | src/pkg/reflect/value.go | 1724 |
7 files changed, 0 insertions, 4903 deletions
diff --git a/src/pkg/reflect/Makefile b/src/pkg/reflect/Makefile deleted file mode 100644 index b946449a3..000000000 --- a/src/pkg/reflect/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -include ../../Make.inc - -TARG=reflect -GOFILES=\ - deepequal.go\ - type.go\ - value.go\ - -include ../../Make.pkg diff --git a/src/pkg/reflect/all_test.go b/src/pkg/reflect/all_test.go deleted file mode 100644 index 34d74b37a..000000000 --- a/src/pkg/reflect/all_test.go +++ /dev/null @@ -1,1566 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package reflect_test - -import ( - "bytes" - "container/vector" - "fmt" - "io" - "os" - . "reflect" - "runtime" - "testing" - "unsafe" -) - -type integer int -type T struct { - a int - b float64 - c string - d *int -} - -type pair struct { - i interface{} - s string -} - -func isDigit(c uint8) bool { return '0' <= c && c <= '9' } - -func assert(t *testing.T, s, want string) { - if s != want { - t.Errorf("have %#q want %#q", s, want) - } -} - -func typestring(i interface{}) string { return TypeOf(i).String() } - -var typeTests = []pair{ - {struct{ x int }{}, "int"}, - {struct{ x int8 }{}, "int8"}, - {struct{ x int16 }{}, "int16"}, - {struct{ x int32 }{}, "int32"}, - {struct{ x int64 }{}, "int64"}, - {struct{ x uint }{}, "uint"}, - {struct{ x uint8 }{}, "uint8"}, - {struct{ x uint16 }{}, "uint16"}, - {struct{ x uint32 }{}, "uint32"}, - {struct{ x uint64 }{}, "uint64"}, - {struct{ x float32 }{}, "float32"}, - {struct{ x float64 }{}, "float64"}, - {struct{ x int8 }{}, "int8"}, - {struct{ x (**int8) }{}, "**int8"}, - {struct{ x (**integer) }{}, "**reflect_test.integer"}, - {struct{ x ([32]int32) }{}, "[32]int32"}, - {struct{ x ([]int8) }{}, "[]int8"}, - {struct{ x (map[string]int32) }{}, "map[string] int32"}, - {struct{ x (chan<- string) }{}, "chan<- string"}, - {struct { - x struct { - c chan *int32 - d float32 - } - }{}, - "struct { c chan *int32; d float32 }", - }, - {struct{ x (func(a int8, b int32)) }{}, "func(int8, int32)"}, - {struct { - x struct { - c func(chan *integer, *int8) - } - }{}, - "struct { c func(chan *reflect_test.integer, *int8) }", - }, - {struct { - x struct { - a int8 - b int32 - } - }{}, - "struct { a int8; b int32 }", - }, - {struct { - x struct { - a int8 - b int8 - c int32 - } - }{}, - "struct { a int8; b int8; c int32 }", - }, - {struct { - x struct { - a int8 - b int8 - c int8 - d int32 - } - }{}, - "struct { a int8; b int8; c int8; d int32 }", - }, - {struct { - x struct { - a int8 - b int8 - c int8 - d int8 - e int32 - } - }{}, - "struct { a int8; b int8; c int8; d int8; e int32 }", - }, - {struct { - x struct { - a int8 - b int8 - c int8 - d int8 - e int8 - f int32 - } - }{}, - "struct { a int8; b int8; c int8; d int8; e int8; f int32 }", - }, - {struct { - x struct { - a int8 `reflect:"hi there"` - } - }{}, - `struct { a int8 "reflect:\"hi there\"" }`, - }, - {struct { - x struct { - a int8 `reflect:"hi \x00there\t\n\"\\"` - } - }{}, - `struct { a int8 "reflect:\"hi \\x00there\\t\\n\\\"\\\\\"" }`, - }, - {struct { - x struct { - f func(args ...int) - } - }{}, - "struct { f func(...int) }", - }, - {struct { - x (interface { - a(func(func(int) int) func(func(int)) int) - b() - }) - }{}, - "interface { reflect_test.a(func(func(int) int) func(func(int)) int); reflect_test.b() }", - }, -} - -var valueTests = []pair{ - {new(int8), "8"}, - {new(int16), "16"}, - {new(int32), "32"}, - {new(int64), "64"}, - {new(uint8), "8"}, - {new(uint16), "16"}, - {new(uint32), "32"}, - {new(uint64), "64"}, - {new(float32), "256.25"}, - {new(float64), "512.125"}, - {new(string), "stringy cheese"}, - {new(bool), "true"}, - {new(*int8), "*int8(0)"}, - {new(**int8), "**int8(0)"}, - {new([5]int32), "[5]int32{0, 0, 0, 0, 0}"}, - {new(**integer), "**reflect_test.integer(0)"}, - {new(map[string]int32), "map[string] int32{<can't iterate on maps>}"}, - {new(chan<- string), "chan<- string"}, - {new(func(a int8, b int32)), "func(int8, int32)(0)"}, - {new(struct { - c chan *int32 - d float32 - }), - "struct { c chan *int32; d float32 }{chan *int32, 0}", - }, - {new(struct{ c func(chan *integer, *int8) }), - "struct { c func(chan *reflect_test.integer, *int8) }{func(chan *reflect_test.integer, *int8)(0)}", - }, - {new(struct { - a int8 - b int32 - }), - "struct { a int8; b int32 }{0, 0}", - }, - {new(struct { - a int8 - b int8 - c int32 - }), - "struct { a int8; b int8; c int32 }{0, 0, 0}", - }, -} - -func testType(t *testing.T, i int, typ Type, want string) { - s := typ.String() - if s != want { - t.Errorf("#%d: have %#q, want %#q", i, s, want) - } -} - -func TestTypes(t *testing.T) { - for i, tt := range typeTests { - testType(t, i, ValueOf(tt.i).Field(0).Type(), tt.s) - } -} - -func TestSet(t *testing.T) { - for i, tt := range valueTests { - v := ValueOf(tt.i).Elem() - switch v.Kind() { - case Int: - v.SetInt(132) - case Int8: - v.SetInt(8) - case Int16: - v.SetInt(16) - case Int32: - v.SetInt(32) - case Int64: - v.SetInt(64) - case Uint: - v.SetUint(132) - case Uint8: - v.SetUint(8) - case Uint16: - v.SetUint(16) - case Uint32: - v.SetUint(32) - case Uint64: - v.SetUint(64) - case Float32: - v.SetFloat(256.25) - case Float64: - v.SetFloat(512.125) - case Complex64: - v.SetComplex(532.125 + 10i) - case Complex128: - v.SetComplex(564.25 + 1i) - case String: - v.SetString("stringy cheese") - case Bool: - v.SetBool(true) - } - s := valueToString(v) - if s != tt.s { - t.Errorf("#%d: have %#q, want %#q", i, s, tt.s) - } - } -} - -func TestSetValue(t *testing.T) { - for i, tt := range valueTests { - v := ValueOf(tt.i).Elem() - switch v.Kind() { - case Int: - v.Set(ValueOf(int(132))) - case Int8: - v.Set(ValueOf(int8(8))) - case Int16: - v.Set(ValueOf(int16(16))) - case Int32: - v.Set(ValueOf(int32(32))) - case Int64: - v.Set(ValueOf(int64(64))) - case Uint: - v.Set(ValueOf(uint(132))) - case Uint8: - v.Set(ValueOf(uint8(8))) - case Uint16: - v.Set(ValueOf(uint16(16))) - case Uint32: - v.Set(ValueOf(uint32(32))) - case Uint64: - v.Set(ValueOf(uint64(64))) - case Float32: - v.Set(ValueOf(float32(256.25))) - case Float64: - v.Set(ValueOf(512.125)) - case Complex64: - v.Set(ValueOf(complex64(532.125 + 10i))) - case Complex128: - v.Set(ValueOf(complex128(564.25 + 1i))) - case String: - v.Set(ValueOf("stringy cheese")) - case Bool: - v.Set(ValueOf(true)) - } - s := valueToString(v) - if s != tt.s { - t.Errorf("#%d: have %#q, want %#q", i, s, tt.s) - } - } -} - -var _i = 7 - -var valueToStringTests = []pair{ - {123, "123"}, - {123.5, "123.5"}, - {byte(123), "123"}, - {"abc", "abc"}, - {T{123, 456.75, "hello", &_i}, "reflect_test.T{123, 456.75, hello, *int(&7)}"}, - {new(chan *T), "*chan *reflect_test.T(&chan *reflect_test.T)"}, - {[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"}, - {&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[10]int(&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"}, - {[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"}, - {&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[]int(&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"}, -} - -func TestValueToString(t *testing.T) { - for i, test := range valueToStringTests { - s := valueToString(ValueOf(test.i)) - if s != test.s { - t.Errorf("#%d: have %#q, want %#q", i, s, test.s) - } - } -} - -func TestArrayElemSet(t *testing.T) { - v := ValueOf(&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}).Elem() - v.Index(4).SetInt(123) - s := valueToString(v) - const want = "[10]int{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}" - if s != want { - t.Errorf("[10]int: have %#q want %#q", s, want) - } - - v = ValueOf([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) - v.Index(4).SetInt(123) - s = valueToString(v) - const want1 = "[]int{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}" - if s != want1 { - t.Errorf("[]int: have %#q want %#q", s, want1) - } -} - -func TestPtrPointTo(t *testing.T) { - var ip *int32 - var i int32 = 1234 - vip := ValueOf(&ip) - vi := ValueOf(&i).Elem() - vip.Elem().Set(vi.Addr()) - if *ip != 1234 { - t.Errorf("got %d, want 1234", *ip) - } - - ip = nil - vp := ValueOf(&ip).Elem() - vp.Set(Zero(vp.Type())) - if ip != nil { - t.Errorf("got non-nil (%p), want nil", ip) - } -} - -func TestPtrSetNil(t *testing.T) { - var i int32 = 1234 - ip := &i - vip := ValueOf(&ip) - vip.Elem().Set(Zero(vip.Elem().Type())) - if ip != nil { - t.Errorf("got non-nil (%d), want nil", *ip) - } -} - -func TestMapSetNil(t *testing.T) { - m := make(map[string]int) - vm := ValueOf(&m) - vm.Elem().Set(Zero(vm.Elem().Type())) - if m != nil { - t.Errorf("got non-nil (%p), want nil", m) - } -} - - -func TestAll(t *testing.T) { - testType(t, 1, TypeOf((int8)(0)), "int8") - testType(t, 2, TypeOf((*int8)(nil)).Elem(), "int8") - - typ := TypeOf((*struct { - c chan *int32 - d float32 - })(nil)) - testType(t, 3, typ, "*struct { c chan *int32; d float32 }") - etyp := typ.Elem() - testType(t, 4, etyp, "struct { c chan *int32; d float32 }") - styp := etyp - f := styp.Field(0) - testType(t, 5, f.Type, "chan *int32") - - f, present := styp.FieldByName("d") - if !present { - t.Errorf("FieldByName says present field is absent") - } - testType(t, 6, f.Type, "float32") - - f, present = styp.FieldByName("absent") - if present { - t.Errorf("FieldByName says absent field is present") - } - - typ = TypeOf([32]int32{}) - testType(t, 7, typ, "[32]int32") - testType(t, 8, typ.Elem(), "int32") - - typ = TypeOf((map[string]*int32)(nil)) - testType(t, 9, typ, "map[string] *int32") - mtyp := typ - testType(t, 10, mtyp.Key(), "string") - testType(t, 11, mtyp.Elem(), "*int32") - - typ = TypeOf((chan<- string)(nil)) - testType(t, 12, typ, "chan<- string") - testType(t, 13, typ.Elem(), "string") - - // make sure tag strings are not part of element type - typ = TypeOf(struct { - d []uint32 `reflect:"TAG"` - }{}).Field(0).Type - testType(t, 14, typ, "[]uint32") -} - -func TestInterfaceGet(t *testing.T) { - var inter struct { - E interface{} - } - inter.E = 123.456 - v1 := ValueOf(&inter) - v2 := v1.Elem().Field(0) - assert(t, v2.Type().String(), "interface { }") - i2 := v2.Interface() - v3 := ValueOf(i2) - assert(t, v3.Type().String(), "float64") -} - -func TestInterfaceValue(t *testing.T) { - var inter struct { - E interface{} - } - inter.E = 123.456 - v1 := ValueOf(&inter) - v2 := v1.Elem().Field(0) - assert(t, v2.Type().String(), "interface { }") - v3 := v2.Elem() - assert(t, v3.Type().String(), "float64") - - i3 := v2.Interface() - if _, ok := i3.(float64); !ok { - t.Error("v2.Interface() did not return float64, got ", TypeOf(i3)) - } -} - -func TestFunctionValue(t *testing.T) { - var x interface{} = func() {} - v := ValueOf(x) - if v.Interface() != v.Interface() || v.Interface() != x { - t.Fatalf("TestFunction != itself") - } - assert(t, v.Type().String(), "func()") -} - -var appendTests = []struct { - orig, extra []int -}{ - {make([]int, 2, 4), []int{22}}, - {make([]int, 2, 4), []int{22, 33, 44}}, -} - -func sameInts(x, y []int) bool { - if len(x) != len(y) { - return false - } - for i, xx := range x { - if xx != y[i] { - return false - } - } - return true -} - -func TestAppend(t *testing.T) { - for i, test := range appendTests { - origLen, extraLen := len(test.orig), len(test.extra) - want := append(test.orig, test.extra...) - // Convert extra from []int to []Value. - e0 := make([]Value, len(test.extra)) - for j, e := range test.extra { - e0[j] = ValueOf(e) - } - // Convert extra from []int to *SliceValue. - e1 := ValueOf(test.extra) - // Test Append. - a0 := ValueOf(test.orig) - have0 := Append(a0, e0...).Interface().([]int) - if !sameInts(have0, want) { - t.Errorf("Append #%d: have %v, want %v (%p %p)", i, have0, want, test.orig, have0) - } - // Check that the orig and extra slices were not modified. - if len(test.orig) != origLen { - t.Errorf("Append #%d origLen: have %v, want %v", i, len(test.orig), origLen) - } - if len(test.extra) != extraLen { - t.Errorf("Append #%d extraLen: have %v, want %v", i, len(test.extra), extraLen) - } - // Test AppendSlice. - a1 := ValueOf(test.orig) - have1 := AppendSlice(a1, e1).Interface().([]int) - if !sameInts(have1, want) { - t.Errorf("AppendSlice #%d: have %v, want %v", i, have1, want) - } - // Check that the orig and extra slices were not modified. - if len(test.orig) != origLen { - t.Errorf("AppendSlice #%d origLen: have %v, want %v", i, len(test.orig), origLen) - } - if len(test.extra) != extraLen { - t.Errorf("AppendSlice #%d extraLen: have %v, want %v", i, len(test.extra), extraLen) - } - } -} - -func TestCopy(t *testing.T) { - a := []int{1, 2, 3, 4, 10, 9, 8, 7} - b := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44} - c := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44} - for i := 0; i < len(b); i++ { - if b[i] != c[i] { - t.Fatalf("b != c before test") - } - } - a1 := a - b1 := b - aa := ValueOf(&a1).Elem() - ab := ValueOf(&b1).Elem() - for tocopy := 1; tocopy <= 7; tocopy++ { - aa.SetLen(tocopy) - Copy(ab, aa) - aa.SetLen(8) - for i := 0; i < tocopy; i++ { - if a[i] != b[i] { - t.Errorf("(i) tocopy=%d a[%d]=%d, b[%d]=%d", - tocopy, i, a[i], i, b[i]) - } - } - for i := tocopy; i < len(b); i++ { - if b[i] != c[i] { - if i < len(a) { - t.Errorf("(ii) tocopy=%d a[%d]=%d, b[%d]=%d, c[%d]=%d", - tocopy, i, a[i], i, b[i], i, c[i]) - } else { - t.Errorf("(iii) tocopy=%d b[%d]=%d, c[%d]=%d", - tocopy, i, b[i], i, c[i]) - } - } else { - t.Logf("tocopy=%d elem %d is okay\n", tocopy, i) - } - } - } -} - -func TestCopyArray(t *testing.T) { - a := [8]int{1, 2, 3, 4, 10, 9, 8, 7} - b := [11]int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44} - c := b - aa := ValueOf(&a).Elem() - ab := ValueOf(&b).Elem() - Copy(ab, aa) - for i := 0; i < len(a); i++ { - if a[i] != b[i] { - t.Errorf("(i) a[%d]=%d, b[%d]=%d", i, a[i], i, b[i]) - } - } - for i := len(a); i < len(b); i++ { - if b[i] != c[i] { - t.Errorf("(ii) b[%d]=%d, c[%d]=%d", i, b[i], i, c[i]) - } else { - t.Logf("elem %d is okay\n", i) - } - } -} - -func TestBigUnnamedStruct(t *testing.T) { - b := struct{ a, b, c, d int64 }{1, 2, 3, 4} - v := ValueOf(b) - b1 := v.Interface().(struct { - a, b, c, d int64 - }) - if b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d { - t.Errorf("ValueOf(%v).Interface().(*Big) = %v", b, b1) - } -} - -type big struct { - a, b, c, d, e int64 -} - -func TestBigStruct(t *testing.T) { - b := big{1, 2, 3, 4, 5} - v := ValueOf(b) - b1 := v.Interface().(big) - if b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d || b1.e != b.e { - t.Errorf("ValueOf(%v).Interface().(big) = %v", b, b1) - } -} - -type Basic struct { - x int - y float32 -} - -type NotBasic Basic - -type DeepEqualTest struct { - a, b interface{} - eq bool -} - -var deepEqualTests = []DeepEqualTest{ - // Equalities - {1, 1, true}, - {int32(1), int32(1), true}, - {0.5, 0.5, true}, - {float32(0.5), float32(0.5), true}, - {"hello", "hello", true}, - {make([]int, 10), make([]int, 10), true}, - {&[3]int{1, 2, 3}, &[3]int{1, 2, 3}, true}, - {Basic{1, 0.5}, Basic{1, 0.5}, true}, - {os.Error(nil), os.Error(nil), true}, - {map[int]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, true}, - - // Inequalities - {1, 2, false}, - {int32(1), int32(2), false}, - {0.5, 0.6, false}, - {float32(0.5), float32(0.6), false}, - {"hello", "hey", false}, - {make([]int, 10), make([]int, 11), false}, - {&[3]int{1, 2, 3}, &[3]int{1, 2, 4}, false}, - {Basic{1, 0.5}, Basic{1, 0.6}, false}, - {Basic{1, 0}, Basic{2, 0}, false}, - {map[int]string{1: "one", 3: "two"}, map[int]string{2: "two", 1: "one"}, false}, - {map[int]string{1: "one", 2: "txo"}, map[int]string{2: "two", 1: "one"}, false}, - {map[int]string{1: "one"}, map[int]string{2: "two", 1: "one"}, false}, - {map[int]string{2: "two", 1: "one"}, map[int]string{1: "one"}, false}, - {nil, 1, false}, - {1, nil, false}, - - // Mismatched types - {1, 1.0, false}, - {int32(1), int64(1), false}, - {0.5, "hello", false}, - {[]int{1, 2, 3}, [3]int{1, 2, 3}, false}, - {&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false}, - {Basic{1, 0.5}, NotBasic{1, 0.5}, false}, - {map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false}, -} - -func TestDeepEqual(t *testing.T) { - for _, test := range deepEqualTests { - if r := DeepEqual(test.a, test.b); r != test.eq { - t.Errorf("DeepEqual(%v, %v) = %v, want %v", test.a, test.b, r, test.eq) - } - } -} - -func TestTypeOf(t *testing.T) { - for _, test := range deepEqualTests { - v := ValueOf(test.a) - if !v.IsValid() { - continue - } - typ := TypeOf(test.a) - if typ != v.Type() { - t.Errorf("TypeOf(%v) = %v, but ValueOf(%v).Type() = %v", test.a, typ, test.a, v.Type()) - } - } -} - -type Recursive struct { - x int - r *Recursive -} - -func TestDeepEqualRecursiveStruct(t *testing.T) { - a, b := new(Recursive), new(Recursive) - *a = Recursive{12, a} - *b = Recursive{12, b} - if !DeepEqual(a, b) { - t.Error("DeepEqual(recursive same) = false, want true") - } -} - -type _Complex struct { - a int - b [3]*_Complex - c *string - d map[float64]float64 -} - -func TestDeepEqualComplexStruct(t *testing.T) { - m := make(map[float64]float64) - stra, strb := "hello", "hello" - a, b := new(_Complex), new(_Complex) - *a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m} - *b = _Complex{5, [3]*_Complex{b, a, a}, &strb, m} - if !DeepEqual(a, b) { - t.Error("DeepEqual(complex same) = false, want true") - } -} - -func TestDeepEqualComplexStructInequality(t *testing.T) { - m := make(map[float64]float64) - stra, strb := "hello", "helloo" // Difference is here - a, b := new(_Complex), new(_Complex) - *a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m} - *b = _Complex{5, [3]*_Complex{b, a, a}, &strb, m} - if DeepEqual(a, b) { - t.Error("DeepEqual(complex different) = true, want false") - } -} - -type UnexpT struct { - m map[int]int -} - -func TestDeepEqualUnexportedMap(t *testing.T) { - // Check that DeepEqual can look at unexported fields. - x1 := UnexpT{map[int]int{1: 2}} - x2 := UnexpT{map[int]int{1: 2}} - if !DeepEqual(&x1, &x2) { - t.Error("DeepEqual(x1, x2) = false, want true") - } - - y1 := UnexpT{map[int]int{2: 3}} - if DeepEqual(&x1, &y1) { - t.Error("DeepEqual(x1, y1) = true, want false") - } -} - - -func check2ndField(x interface{}, offs uintptr, t *testing.T) { - s := ValueOf(x) - f := s.Type().Field(1) - if f.Offset != offs { - t.Error("mismatched offsets in structure alignment:", f.Offset, offs) - } -} - -// Check that structure alignment & offsets viewed through reflect agree with those -// from the compiler itself. -func TestAlignment(t *testing.T) { - type T1inner struct { - a int - } - type T1 struct { - T1inner - f int - } - type T2inner struct { - a, b int - } - type T2 struct { - T2inner - f int - } - - x := T1{T1inner{2}, 17} - check2ndField(x, uintptr(unsafe.Pointer(&x.f))-uintptr(unsafe.Pointer(&x)), t) - - x1 := T2{T2inner{2, 3}, 17} - check2ndField(x1, uintptr(unsafe.Pointer(&x1.f))-uintptr(unsafe.Pointer(&x1)), t) -} - -func Nil(a interface{}, t *testing.T) { - n := ValueOf(a).Field(0) - if !n.IsNil() { - t.Errorf("%v should be nil", a) - } -} - -func NotNil(a interface{}, t *testing.T) { - n := ValueOf(a).Field(0) - if n.IsNil() { - t.Errorf("value of type %v should not be nil", ValueOf(a).Type().String()) - } -} - -func TestIsNil(t *testing.T) { - // These implement IsNil. - // Wrap in extra struct to hide interface type. - doNil := []interface{}{ - struct{ x *int }{}, - struct{ x interface{} }{}, - struct{ x map[string]int }{}, - struct{ x func() bool }{}, - struct{ x chan int }{}, - struct{ x []string }{}, - } - for _, ts := range doNil { - ty := TypeOf(ts).Field(0).Type - v := Zero(ty) - v.IsNil() // panics if not okay to call - } - - // Check the implementations - var pi struct { - x *int - } - Nil(pi, t) - pi.x = new(int) - NotNil(pi, t) - - var si struct { - x []int - } - Nil(si, t) - si.x = make([]int, 10) - NotNil(si, t) - - var ci struct { - x chan int - } - Nil(ci, t) - ci.x = make(chan int) - NotNil(ci, t) - - var mi struct { - x map[int]int - } - Nil(mi, t) - mi.x = make(map[int]int) - NotNil(mi, t) - - var ii struct { - x interface{} - } - Nil(ii, t) - ii.x = 2 - NotNil(ii, t) - - var fi struct { - x func(t *testing.T) - } - Nil(fi, t) - fi.x = TestIsNil - NotNil(fi, t) -} - -func TestInterfaceExtraction(t *testing.T) { - var s struct { - w io.Writer - } - - s.w = os.Stdout - v := Indirect(ValueOf(&s)).Field(0).Interface() - if v != s.w.(interface{}) { - t.Error("Interface() on interface: ", v, s.w) - } -} - -func TestNilPtrValueSub(t *testing.T) { - var pi *int - if pv := ValueOf(pi); pv.Elem().IsValid() { - t.Error("ValueOf((*int)(nil)).Elem().IsValid()") - } -} - -func TestMap(t *testing.T) { - m := map[string]int{"a": 1, "b": 2} - mv := ValueOf(m) - if n := mv.Len(); n != len(m) { - t.Errorf("Len = %d, want %d", n, len(m)) - } - keys := mv.MapKeys() - i := 0 - newmap := MakeMap(mv.Type()) - for k, v := range m { - // Check that returned Keys match keys in range. - // These aren't required to be in the same order, - // but they are in this implementation, which makes - // the test easier. - if i >= len(keys) { - t.Errorf("Missing key #%d %q", i, k) - } else if kv := keys[i]; kv.String() != k { - t.Errorf("Keys[%q] = %d, want %d", i, kv.Int(), k) - } - i++ - - // Check that value lookup is correct. - vv := mv.MapIndex(ValueOf(k)) - if vi := vv.Int(); vi != int64(v) { - t.Errorf("Key %q: have value %d, want %d", k, vi, v) - } - - // Copy into new map. - newmap.SetMapIndex(ValueOf(k), ValueOf(v)) - } - vv := mv.MapIndex(ValueOf("not-present")) - if vv.IsValid() { - t.Errorf("Invalid key: got non-nil value %s", valueToString(vv)) - } - - newm := newmap.Interface().(map[string]int) - if len(newm) != len(m) { - t.Errorf("length after copy: newm=%d, m=%d", newm, m) - } - - for k, v := range newm { - mv, ok := m[k] - if mv != v { - t.Errorf("newm[%q] = %d, but m[%q] = %d, %v", k, v, k, mv, ok) - } - } - - newmap.SetMapIndex(ValueOf("a"), Value{}) - v, ok := newm["a"] - if ok { - t.Errorf("newm[\"a\"] = %d after delete", v) - } - - mv = ValueOf(&m).Elem() - mv.Set(Zero(mv.Type())) - if m != nil { - t.Errorf("mv.Set(nil) failed") - } -} - -func TestChan(t *testing.T) { - for loop := 0; loop < 2; loop++ { - var c chan int - var cv Value - - // check both ways to allocate channels - switch loop { - case 1: - c = make(chan int, 1) - cv = ValueOf(c) - case 0: - cv = MakeChan(TypeOf(c), 1) - c = cv.Interface().(chan int) - } - - // Send - cv.Send(ValueOf(2)) - if i := <-c; i != 2 { - t.Errorf("reflect Send 2, native recv %d", i) - } - - // Recv - c <- 3 - if i, ok := cv.Recv(); i.Int() != 3 || !ok { - t.Errorf("native send 3, reflect Recv %d, %t", i.Int(), ok) - } - - // TryRecv fail - val, ok := cv.TryRecv() - if val.IsValid() || ok { - t.Errorf("TryRecv on empty chan: %s, %t", valueToString(val), ok) - } - - // TryRecv success - c <- 4 - val, ok = cv.TryRecv() - if !val.IsValid() { - t.Errorf("TryRecv on ready chan got nil") - } else if i := val.Int(); i != 4 || !ok { - t.Errorf("native send 4, TryRecv %d, %t", i, ok) - } - - // TrySend fail - c <- 100 - ok = cv.TrySend(ValueOf(5)) - i := <-c - if ok { - t.Errorf("TrySend on full chan succeeded: value %d", i) - } - - // TrySend success - ok = cv.TrySend(ValueOf(6)) - if !ok { - t.Errorf("TrySend on empty chan failed") - } else { - if i = <-c; i != 6 { - t.Errorf("TrySend 6, recv %d", i) - } - } - - // Close - c <- 123 - cv.Close() - if i, ok := cv.Recv(); i.Int() != 123 || !ok { - t.Errorf("send 123 then close; Recv %d, %t", i.Int(), ok) - } - if i, ok := cv.Recv(); i.Int() != 0 || ok { - t.Errorf("after close Recv %d, %t", i.Int(), ok) - } - } - - // check creation of unbuffered channel - var c chan int - cv := MakeChan(TypeOf(c), 0) - c = cv.Interface().(chan int) - if cv.TrySend(ValueOf(7)) { - t.Errorf("TrySend on sync chan succeeded") - } - if v, ok := cv.TryRecv(); v.IsValid() || ok { - t.Errorf("TryRecv on sync chan succeeded: isvalid=%v ok=%v", v.IsValid(), ok) - } - - // len/cap - cv = MakeChan(TypeOf(c), 10) - c = cv.Interface().(chan int) - for i := 0; i < 3; i++ { - c <- i - } - if l, m := cv.Len(), cv.Cap(); l != len(c) || m != cap(c) { - t.Errorf("Len/Cap = %d/%d want %d/%d", l, m, len(c), cap(c)) - } - -} - -// Difficult test for function call because of -// implicit padding between arguments. -func dummy(b byte, c int, d byte) (i byte, j int, k byte) { - return b, c, d -} - -func TestFunc(t *testing.T) { - ret := ValueOf(dummy).Call([]Value{ValueOf(byte(10)), ValueOf(20), ValueOf(byte(30))}) - if len(ret) != 3 { - t.Fatalf("Call returned %d values, want 3", len(ret)) - } - - i := byte(ret[0].Uint()) - j := int(ret[1].Int()) - k := byte(ret[2].Uint()) - if i != 10 || j != 20 || k != 30 { - t.Errorf("Call returned %d, %d, %d; want 10, 20, 30", i, j, k) - } -} - -type Point struct { - x, y int -} - -// This will be index 0. -func (p Point) AnotherMethod(scale int) int { - return -1 -} - -// This will be index 1. -func (p Point) Dist(scale int) int { - // println("Point.Dist", p.x, p.y, scale) - return p.x*p.x*scale + p.y*p.y*scale -} - -func TestMethod(t *testing.T) { - // Non-curried method of type. - p := Point{3, 4} - i := TypeOf(p).Method(1).Func.Call([]Value{ValueOf(p), ValueOf(10)})[0].Int() - if i != 250 { - t.Errorf("Type Method returned %d; want 250", i) - } - - m, ok := TypeOf(p).MethodByName("Dist") - if !ok { - t.Fatalf("method by name failed") - } - m.Func.Call([]Value{ValueOf(p), ValueOf(10)})[0].Int() - if i != 250 { - t.Errorf("Type MethodByName returned %d; want 250", i) - } - - i = TypeOf(&p).Method(1).Func.Call([]Value{ValueOf(&p), ValueOf(10)})[0].Int() - if i != 250 { - t.Errorf("Pointer Type Method returned %d; want 250", i) - } - - m, ok = TypeOf(&p).MethodByName("Dist") - if !ok { - t.Fatalf("ptr method by name failed") - } - i = m.Func.Call([]Value{ValueOf(&p), ValueOf(10)})[0].Int() - if i != 250 { - t.Errorf("Pointer Type MethodByName returned %d; want 250", i) - } - - // Curried method of value. - i = ValueOf(p).Method(1).Call([]Value{ValueOf(10)})[0].Int() - if i != 250 { - t.Errorf("Value Method returned %d; want 250", i) - } - i = ValueOf(p).MethodByName("Dist").Call([]Value{ValueOf(10)})[0].Int() - if i != 250 { - t.Errorf("Value MethodByName returned %d; want 250", i) - } - - // Curried method of pointer. - i = ValueOf(&p).Method(1).Call([]Value{ValueOf(10)})[0].Int() - if i != 250 { - t.Errorf("Pointer Value Method returned %d; want 250", i) - } - i = ValueOf(&p).MethodByName("Dist").Call([]Value{ValueOf(10)})[0].Int() - if i != 250 { - t.Errorf("Pointer Value MethodByName returned %d; want 250", i) - } - - // Curried method of interface value. - // Have to wrap interface value in a struct to get at it. - // Passing it to ValueOf directly would - // access the underlying Point, not the interface. - var s = struct { - X interface { - Dist(int) int - } - }{p} - pv := ValueOf(s).Field(0) - i = pv.Method(0).Call([]Value{ValueOf(10)})[0].Int() - if i != 250 { - t.Errorf("Interface Method returned %d; want 250", i) - } - i = pv.MethodByName("Dist").Call([]Value{ValueOf(10)})[0].Int() - if i != 250 { - t.Errorf("Interface MethodByName returned %d; want 250", i) - } -} - -func TestInterfaceSet(t *testing.T) { - p := &Point{3, 4} - - var s struct { - I interface{} - P interface { - Dist(int) int - } - } - sv := ValueOf(&s).Elem() - sv.Field(0).Set(ValueOf(p)) - if q := s.I.(*Point); q != p { - t.Errorf("i: have %p want %p", q, p) - } - - pv := sv.Field(1) - pv.Set(ValueOf(p)) - if q := s.P.(*Point); q != p { - t.Errorf("i: have %p want %p", q, p) - } - - i := pv.Method(0).Call([]Value{ValueOf(10)})[0].Int() - if i != 250 { - t.Errorf("Interface Method returned %d; want 250", i) - } -} - -type T1 struct { - a string - int -} - -func TestAnonymousFields(t *testing.T) { - var field StructField - var ok bool - var t1 T1 - type1 := TypeOf(t1) - if field, ok = type1.FieldByName("int"); !ok { - t.Error("no field 'int'") - } - if field.Index[0] != 1 { - t.Error("field index should be 1; is", field.Index) - } -} - -type FTest struct { - s interface{} - name string - index []int - value int -} - -type D1 struct { - d int -} -type D2 struct { - d int -} - -type S0 struct { - a, b, c int - D1 - D2 -} - -type S1 struct { - b int - S0 -} - -type S2 struct { - a int - *S1 -} - -type S1x struct { - S1 -} - -type S1y struct { - S1 -} - -type S3 struct { - S1x - S2 - d, e int - *S1y -} - -type S4 struct { - *S4 - a int -} - -var fieldTests = []FTest{ - {struct{}{}, "", nil, 0}, - {struct{}{}, "foo", nil, 0}, - {S0{a: 'a'}, "a", []int{0}, 'a'}, - {S0{}, "d", nil, 0}, - {S1{S0: S0{a: 'a'}}, "a", []int{1, 0}, 'a'}, - {S1{b: 'b'}, "b", []int{0}, 'b'}, - {S1{}, "S0", []int{1}, 0}, - {S1{S0: S0{c: 'c'}}, "c", []int{1, 2}, 'c'}, - {S2{a: 'a'}, "a", []int{0}, 'a'}, - {S2{}, "S1", []int{1}, 0}, - {S2{S1: &S1{b: 'b'}}, "b", []int{1, 0}, 'b'}, - {S2{S1: &S1{S0: S0{c: 'c'}}}, "c", []int{1, 1, 2}, 'c'}, - {S2{}, "d", nil, 0}, - {S3{}, "S1", nil, 0}, - {S3{S2: S2{a: 'a'}}, "a", []int{1, 0}, 'a'}, - {S3{}, "b", nil, 0}, - {S3{d: 'd'}, "d", []int{2}, 0}, - {S3{e: 'e'}, "e", []int{3}, 'e'}, - {S4{a: 'a'}, "a", []int{1}, 'a'}, - {S4{}, "b", nil, 0}, -} - -func TestFieldByIndex(t *testing.T) { - for _, test := range fieldTests { - s := TypeOf(test.s) - f := s.FieldByIndex(test.index) - if f.Name != "" { - if test.index != nil { - if f.Name != test.name { - t.Errorf("%s.%s found; want %s", s.Name(), f.Name, test.name) - } - } else { - t.Errorf("%s.%s found", s.Name(), f.Name) - } - } else if len(test.index) > 0 { - t.Errorf("%s.%s not found", s.Name(), test.name) - } - - if test.value != 0 { - v := ValueOf(test.s).FieldByIndex(test.index) - if v.IsValid() { - if x, ok := v.Interface().(int); ok { - if x != test.value { - t.Errorf("%s%v is %d; want %d", s.Name(), test.index, x, test.value) - } - } else { - t.Errorf("%s%v value not an int", s.Name(), test.index) - } - } else { - t.Errorf("%s%v value not found", s.Name(), test.index) - } - } - } -} - -func TestFieldByName(t *testing.T) { - for _, test := range fieldTests { - s := TypeOf(test.s) - f, found := s.FieldByName(test.name) - if found { - if test.index != nil { - // Verify field depth and index. - if len(f.Index) != len(test.index) { - t.Errorf("%s.%s depth %d; want %d", s.Name(), test.name, len(f.Index), len(test.index)) - } else { - for i, x := range f.Index { - if x != test.index[i] { - t.Errorf("%s.%s.Index[%d] is %d; want %d", s.Name(), test.name, i, x, test.index[i]) - } - } - } - } else { - t.Errorf("%s.%s found", s.Name(), f.Name) - } - } else if len(test.index) > 0 { - t.Errorf("%s.%s not found", s.Name(), test.name) - } - - if test.value != 0 { - v := ValueOf(test.s).FieldByName(test.name) - if v.IsValid() { - if x, ok := v.Interface().(int); ok { - if x != test.value { - t.Errorf("%s.%s is %d; want %d", s.Name(), test.name, x, test.value) - } - } else { - t.Errorf("%s.%s value not an int", s.Name(), test.name) - } - } else { - t.Errorf("%s.%s value not found", s.Name(), test.name) - } - } - } -} - -func TestImportPath(t *testing.T) { - if path := TypeOf(vector.Vector{}).PkgPath(); path != "container/vector" { - t.Errorf("TypeOf(vector.Vector{}).PkgPath() = %q, want \"container/vector\"", path) - } -} - -func TestDotDotDot(t *testing.T) { - // Test example from FuncType.DotDotDot documentation. - var f func(x int, y ...float64) - typ := TypeOf(f) - if typ.NumIn() == 2 && typ.In(0) == TypeOf(int(0)) { - sl := typ.In(1) - if sl.Kind() == Slice { - if sl.Elem() == TypeOf(0.0) { - // ok - return - } - } - } - - // Failed - t.Errorf("want NumIn() = 2, In(0) = int, In(1) = []float64") - s := fmt.Sprintf("have NumIn() = %d", typ.NumIn()) - for i := 0; i < typ.NumIn(); i++ { - s += fmt.Sprintf(", In(%d) = %s", i, typ.In(i)) - } - t.Error(s) -} - -type inner struct { - x int -} - -type outer struct { - y int - inner -} - -func (*inner) m() {} -func (*outer) m() {} - -func TestNestedMethods(t *testing.T) { - typ := TypeOf((*outer)(nil)) - if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*outer).m).Pointer() { - t.Errorf("Wrong method table for outer: (m=%p)", (*outer).m) - for i := 0; i < typ.NumMethod(); i++ { - m := typ.Method(i) - t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer()) - } - } -} - -type InnerInt struct { - X int -} - -type OuterInt struct { - Y int - InnerInt -} - -func (i *InnerInt) M() int { - return i.X -} - -func TestEmbeddedMethods(t *testing.T) { - typ := TypeOf((*OuterInt)(nil)) - if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*OuterInt).M).Pointer() { - t.Errorf("Wrong method table for OuterInt: (m=%p)", (*OuterInt).M) - for i := 0; i < typ.NumMethod(); i++ { - m := typ.Method(i) - t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer()) - } - } - - i := &InnerInt{3} - if v := ValueOf(i).Method(0).Call(nil)[0].Int(); v != 3 { - t.Errorf("i.M() = %d, want 3", v) - } - - o := &OuterInt{1, InnerInt{2}} - if v := ValueOf(o).Method(0).Call(nil)[0].Int(); v != 2 { - t.Errorf("i.M() = %d, want 2", v) - } - - f := (*OuterInt).M - if v := f(o); v != 2 { - t.Errorf("f(o) = %d, want 2", v) - } -} - -func TestPtrTo(t *testing.T) { - var i int - - typ := TypeOf(i) - for i = 0; i < 100; i++ { - typ = PtrTo(typ) - } - for i = 0; i < 100; i++ { - typ = typ.Elem() - } - if typ != TypeOf(i) { - t.Errorf("after 100 PtrTo and Elem, have %s, want %s", typ, TypeOf(i)) - } -} - -func TestAddr(t *testing.T) { - var p struct { - X, Y int - } - - v := ValueOf(&p) - v = v.Elem() - v = v.Addr() - v = v.Elem() - v = v.Field(0) - v.SetInt(2) - if p.X != 2 { - t.Errorf("Addr.Elem.Set failed to set value") - } - - // Again but take address of the ValueOf value. - // Exercises generation of PtrTypes not present in the binary. - q := &p - v = ValueOf(&q).Elem() - v = v.Addr() - v = v.Elem() - v = v.Elem() - v = v.Addr() - v = v.Elem() - v = v.Field(0) - v.SetInt(3) - if p.X != 3 { - t.Errorf("Addr.Elem.Set failed to set value") - } - - // Starting without pointer we should get changed value - // in interface. - qq := p - v = ValueOf(&qq).Elem() - v0 := v - v = v.Addr() - v = v.Elem() - v = v.Field(0) - v.SetInt(4) - if p.X != 3 { // should be unchanged from last time - t.Errorf("somehow value Set changed original p") - } - p = v0.Interface().(struct { - X, Y int - }) - if p.X != 4 { - t.Errorf("Addr.Elem.Set valued to set value in top value") - } -} - -func noAlloc(t *testing.T, n int, f func(int)) { - // once to prime everything - f(-1) - runtime.MemStats.Mallocs = 0 - - for j := 0; j < n; j++ { - f(j) - } - // A few allocs may happen in the testing package when GOMAXPROCS > 1, so don't - // require zero mallocs. - if runtime.MemStats.Mallocs > 5 { - t.Fatalf("%d mallocs after %d iterations", runtime.MemStats.Mallocs, n) - } -} - -func TestAllocations(t *testing.T) { - noAlloc(t, 100, func(j int) { - var i interface{} - var v Value - i = 42 + j - v = ValueOf(i) - if int(v.Int()) != 42+j { - panic("wrong int") - } - }) -} - -func TestSmallNegativeInt(t *testing.T) { - i := int16(-1) - v := ValueOf(i) - if v.Int() != -1 { - t.Errorf("int16(-1).Int() returned %v", v.Int()) - } -} - -func TestSlice(t *testing.T) { - xs := []int{1, 2, 3, 4, 5, 6, 7, 8} - v := ValueOf(xs).Slice(3, 5).Interface().([]int) - if len(v) != 2 || v[0] != 4 || v[1] != 5 { - t.Errorf("xs.Slice(3, 5) = %v", v) - } - - xa := [7]int{10, 20, 30, 40, 50, 60, 70} - v = ValueOf(&xa).Elem().Slice(2, 5).Interface().([]int) - if len(v) != 3 || v[0] != 30 || v[1] != 40 || v[2] != 50 { - t.Errorf("xa.Slice(2, 5) = %v", v) - } -} - -func TestVariadic(t *testing.T) { - var b bytes.Buffer - V := ValueOf - - b.Reset() - V(fmt.Fprintf).Call([]Value{V(&b), V("%s, %d world"), V("hello"), V(42)}) - if b.String() != "hello, 42 world" { - t.Errorf("after Fprintf Call: %q != %q", b.String(), "hello 42 world") - } - - b.Reset() - V(fmt.Fprintf).CallSlice([]Value{V(&b), V("%s, %d world"), V([]interface{}{"hello", 42})}) - if b.String() != "hello, 42 world" { - t.Errorf("after Fprintf CallSlice: %q != %q", b.String(), "hello 42 world") - } -} - -var tagGetTests = []struct { - Tag StructTag - Key string - Value string -}{ - {`protobuf:"PB(1,2)"`, `protobuf`, `PB(1,2)`}, - {`protobuf:"PB(1,2)"`, `foo`, ``}, - {`protobuf:"PB(1,2)"`, `rotobuf`, ``}, - {`protobuf:"PB(1,2)" json:"name"`, `json`, `name`}, - {`protobuf:"PB(1,2)" json:"name"`, `protobuf`, `PB(1,2)`}, -} - -func TestTagGet(t *testing.T) { - for _, tt := range tagGetTests { - if v := tt.Tag.Get(tt.Key); v != tt.Value { - t.Errorf("StructTag(%#q).Get(%#q) = %#q, want %#q", tt.Tag, tt.Key, v, tt.Value) - } - } -} diff --git a/src/pkg/reflect/deepequal.go b/src/pkg/reflect/deepequal.go deleted file mode 100644 index a483135b0..000000000 --- a/src/pkg/reflect/deepequal.go +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Deep equality test via reflection - -package reflect - -// During deepValueEqual, must keep track of checks that are -// in progress. The comparison algorithm assumes that all -// checks in progress are true when it reencounters them. -// Visited are stored in a map indexed by 17 * a1 + a2; -type visit struct { - a1 uintptr - a2 uintptr - typ Type - next *visit -} - -// Tests for deep equality using reflected types. The map argument tracks -// comparisons that have already been seen, which allows short circuiting on -// recursive types. -func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool) { - if !v1.IsValid() || !v2.IsValid() { - return v1.IsValid() == v2.IsValid() - } - if v1.Type() != v2.Type() { - return false - } - - // if depth > 10 { panic("deepValueEqual") } // for debugging - - if v1.CanAddr() && v2.CanAddr() { - addr1 := v1.UnsafeAddr() - addr2 := v2.UnsafeAddr() - if addr1 > addr2 { - // Canonicalize order to reduce number of entries in visited. - addr1, addr2 = addr2, addr1 - } - - // Short circuit if references are identical ... - if addr1 == addr2 { - return true - } - - // ... or already seen - h := 17*addr1 + addr2 - seen := visited[h] - typ := v1.Type() - for p := seen; p != nil; p = p.next { - if p.a1 == addr1 && p.a2 == addr2 && p.typ == typ { - return true - } - } - - // Remember for later. - visited[h] = &visit{addr1, addr2, typ, seen} - } - - switch v1.Kind() { - case Array: - if v1.Len() != v2.Len() { - return false - } - for i := 0; i < v1.Len(); i++ { - if !deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) { - return false - } - } - return true - case Slice: - if v1.Len() != v2.Len() { - return false - } - for i := 0; i < v1.Len(); i++ { - if !deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) { - return false - } - } - return true - case Interface: - if v1.IsNil() || v2.IsNil() { - return v1.IsNil() == v2.IsNil() - } - return deepValueEqual(v1.Elem(), v2.Elem(), visited, depth+1) - case Ptr: - return deepValueEqual(v1.Elem(), v2.Elem(), visited, depth+1) - case Struct: - for i, n := 0, v1.NumField(); i < n; i++ { - if !deepValueEqual(v1.Field(i), v2.Field(i), visited, depth+1) { - return false - } - } - return true - case Map: - if v1.Len() != v2.Len() { - return false - } - for _, k := range v1.MapKeys() { - if !deepValueEqual(v1.MapIndex(k), v2.MapIndex(k), visited, depth+1) { - return false - } - } - return true - default: - // Normal equality suffices - return v1.Interface() == v2.Interface() - } - - panic("Not reached") -} - -// DeepEqual tests for deep equality. It uses normal == equality where possible -// but will scan members of arrays, slices, and fields of structs. It correctly -// handles recursive types. -func DeepEqual(a1, a2 interface{}) bool { - if a1 == nil || a2 == nil { - return a1 == a2 - } - v1 := ValueOf(a1) - v2 := ValueOf(a2) - if v1.Type() != v2.Type() { - return false - } - return deepValueEqual(v1, v2, make(map[uintptr]*visit), 0) -} diff --git a/src/pkg/reflect/set_test.go b/src/pkg/reflect/set_test.go deleted file mode 100644 index 8135a4cd1..000000000 --- a/src/pkg/reflect/set_test.go +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package reflect_test - -import ( - "bytes" - "go/ast" - "io" - . "reflect" - "testing" - "unsafe" -) - -type MyBuffer bytes.Buffer - -func TestImplicitMapConversion(t *testing.T) { - // Test implicit conversions in MapIndex and SetMapIndex. - { - // direct - m := make(map[int]int) - mv := ValueOf(m) - mv.SetMapIndex(ValueOf(1), ValueOf(2)) - x, ok := m[1] - if x != 2 { - t.Errorf("#1 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m) - } - if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 { - t.Errorf("#1 MapIndex(1) = %d", n) - } - } - { - // convert interface key - m := make(map[interface{}]int) - mv := ValueOf(m) - mv.SetMapIndex(ValueOf(1), ValueOf(2)) - x, ok := m[1] - if x != 2 { - t.Errorf("#2 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m) - } - if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 { - t.Errorf("#2 MapIndex(1) = %d", n) - } - } - { - // convert interface value - m := make(map[int]interface{}) - mv := ValueOf(m) - mv.SetMapIndex(ValueOf(1), ValueOf(2)) - x, ok := m[1] - if x != 2 { - t.Errorf("#3 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m) - } - if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 { - t.Errorf("#3 MapIndex(1) = %d", n) - } - } - { - // convert both interface key and interface value - m := make(map[interface{}]interface{}) - mv := ValueOf(m) - mv.SetMapIndex(ValueOf(1), ValueOf(2)) - x, ok := m[1] - if x != 2 { - t.Errorf("#4 after SetMapIndex(1,2): %d, %t (map=%v)", x, ok, m) - } - if n := mv.MapIndex(ValueOf(1)).Interface().(int); n != 2 { - t.Errorf("#4 MapIndex(1) = %d", n) - } - } - { - // convert both, with non-empty interfaces - m := make(map[io.Reader]io.Writer) - mv := ValueOf(m) - b1 := new(bytes.Buffer) - b2 := new(bytes.Buffer) - mv.SetMapIndex(ValueOf(b1), ValueOf(b2)) - x, ok := m[b1] - if x != b2 { - t.Errorf("#5 after SetMapIndex(b1, b2): %p (!= %p), %t (map=%v)", x, b2, ok, m) - } - if p := mv.MapIndex(ValueOf(b1)).Elem().Pointer(); p != uintptr(unsafe.Pointer(b2)) { - t.Errorf("#5 MapIndex(b1) = %p want %p", p, b2) - } - } - { - // convert channel direction - m := make(map[<-chan int]chan int) - mv := ValueOf(m) - c1 := make(chan int) - c2 := make(chan int) - mv.SetMapIndex(ValueOf(c1), ValueOf(c2)) - x, ok := m[c1] - if x != c2 { - t.Errorf("#6 after SetMapIndex(c1, c2): %p (!= %p), %t (map=%v)", x, c2, ok, m) - } - if p := mv.MapIndex(ValueOf(c1)).Pointer(); p != ValueOf(c2).Pointer() { - t.Errorf("#6 MapIndex(c1) = %p want %p", p, c2) - } - } - { - // convert identical underlying types - // TODO(rsc): Should be able to define MyBuffer here. - // 6l prints very strange messages about .this.Bytes etc - // when we do that though, so MyBuffer is defined - // at top level. - m := make(map[*MyBuffer]*bytes.Buffer) - mv := ValueOf(m) - b1 := new(MyBuffer) - b2 := new(bytes.Buffer) - mv.SetMapIndex(ValueOf(b1), ValueOf(b2)) - x, ok := m[b1] - if x != b2 { - t.Errorf("#7 after SetMapIndex(b1, b2): %p (!= %p), %t (map=%v)", x, b2, ok, m) - } - if p := mv.MapIndex(ValueOf(b1)).Pointer(); p != uintptr(unsafe.Pointer(b2)) { - t.Errorf("#7 MapIndex(b1) = %p want %p", p, b2) - } - } - -} - -func TestImplicitSetConversion(t *testing.T) { - // Assume TestImplicitMapConversion covered the basics. - // Just make sure conversions are being applied at all. - var r io.Reader - b := new(bytes.Buffer) - rv := ValueOf(&r).Elem() - rv.Set(ValueOf(b)) - if r != b { - t.Errorf("after Set: r=%T(%v)", r, r) - } -} - -func TestImplicitSendConversion(t *testing.T) { - c := make(chan io.Reader, 10) - b := new(bytes.Buffer) - ValueOf(c).Send(ValueOf(b)) - if bb := <-c; bb != b { - t.Errorf("Received %p != %p", bb, b) - } -} - -func TestImplicitCallConversion(t *testing.T) { - // Arguments must be assignable to parameter types. - fv := ValueOf(io.WriteString) - b := new(bytes.Buffer) - fv.Call([]Value{ValueOf(b), ValueOf("hello world")}) - if b.String() != "hello world" { - t.Errorf("After call: string=%q want %q", b.String(), "hello world") - } -} - -func TestImplicitAppendConversion(t *testing.T) { - // Arguments must be assignable to the slice's element type. - s := []io.Reader{} - sv := ValueOf(&s).Elem() - b := new(bytes.Buffer) - sv.Set(Append(sv, ValueOf(b))) - if len(s) != 1 || s[0] != b { - t.Errorf("after append: s=%v want [%p]", s, b) - } -} - -var implementsTests = []struct { - x interface{} - t interface{} - b bool -}{ - {new(*bytes.Buffer), new(io.Reader), true}, - {new(bytes.Buffer), new(io.Reader), false}, - {new(*bytes.Buffer), new(io.ReaderAt), false}, - {new(*ast.Ident), new(ast.Expr), true}, -} - -func TestImplements(t *testing.T) { - for _, tt := range implementsTests { - xv := TypeOf(tt.x).Elem() - xt := TypeOf(tt.t).Elem() - if b := xv.Implements(xt); b != tt.b { - t.Errorf("(%s).Implements(%s) = %v, want %v", xv.String(), xt.String(), b, tt.b) - } - } -} - -var assignableTests = []struct { - x interface{} - t interface{} - b bool -}{ - {new(chan int), new(<-chan int), true}, - {new(<-chan int), new(chan int), false}, - {new(*int), new(IntPtr), true}, - {new(IntPtr), new(*int), true}, - {new(IntPtr), new(IntPtr1), false}, - // test runs implementsTests too -} - -type IntPtr *int -type IntPtr1 *int - -func TestAssignableTo(t *testing.T) { - for _, tt := range append(assignableTests, implementsTests...) { - xv := TypeOf(tt.x).Elem() - xt := TypeOf(tt.t).Elem() - if b := xv.AssignableTo(xt); b != tt.b { - t.Errorf("(%s).AssignableTo(%s) = %v, want %v", xv.String(), xt.String(), b, tt.b) - } - } -} diff --git a/src/pkg/reflect/tostring_test.go b/src/pkg/reflect/tostring_test.go deleted file mode 100644 index 5f5c52b77..000000000 --- a/src/pkg/reflect/tostring_test.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Formatting of reflection types and values for debugging. -// Not defined as methods so they do not need to be linked into most binaries; -// the functions are not used by the library itself, only in tests. - -package reflect_test - -import ( - . "reflect" - "strconv" -) - -// valueToString returns a textual representation of the reflection value val. -// For debugging only. -func valueToString(val Value) string { - var str string - if !val.IsValid() { - return "<zero Value>" - } - typ := val.Type() - switch val.Kind() { - case Int, Int8, Int16, Int32, Int64: - return strconv.Itoa64(val.Int()) - case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: - return strconv.Uitoa64(val.Uint()) - case Float32, Float64: - return strconv.Ftoa64(val.Float(), 'g', -1) - case Complex64, Complex128: - c := val.Complex() - return strconv.Ftoa64(real(c), 'g', -1) + "+" + strconv.Ftoa64(imag(c), 'g', -1) + "i" - case String: - return val.String() - case Bool: - if val.Bool() { - return "true" - } else { - return "false" - } - case Ptr: - v := val - str = typ.String() + "(" - if v.IsNil() { - str += "0" - } else { - str += "&" + valueToString(v.Elem()) - } - str += ")" - return str - case Array, Slice: - v := val - str += typ.String() - str += "{" - for i := 0; i < v.Len(); i++ { - if i > 0 { - str += ", " - } - str += valueToString(v.Index(i)) - } - str += "}" - return str - case Map: - t := typ - str = t.String() - str += "{" - str += "<can't iterate on maps>" - str += "}" - return str - case Chan: - str = typ.String() - return str - case Struct: - t := typ - v := val - str += t.String() - str += "{" - for i, n := 0, v.NumField(); i < n; i++ { - if i > 0 { - str += ", " - } - str += valueToString(v.Field(i)) - } - str += "}" - return str - case Interface: - return typ.String() + "(" + valueToString(val.Elem()) + ")" - case Func: - v := val - return typ.String() + "(" + strconv.Uitoa64(uint64(v.Pointer())) + ")" - default: - panic("valueToString: can't print type " + typ.String()) - } - return "valueToString: can't happen" -} diff --git a/src/pkg/reflect/type.go b/src/pkg/reflect/type.go deleted file mode 100644 index a120da732..000000000 --- a/src/pkg/reflect/type.go +++ /dev/null @@ -1,1167 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package reflect implements run-time reflection, allowing a program to -// manipulate objects with arbitrary types. The typical use is to take a value -// with static type interface{} and extract its dynamic type information by -// calling TypeOf, which returns a Type. -// -// A call to ValueOf returns a Value representing the run-time data. -// Zero takes a Type and returns a Value representing a zero value -// for that type. -package reflect - -import ( - "runtime" - "strconv" - "sync" - "unsafe" -) - -// Type is the representation of a Go type. -// -// Not all methods apply to all kinds of types. Restrictions, -// if any, are noted in the documentation for each method. -// Use the Kind method to find out the kind of type before -// calling kind-specific methods. Calling a method -// inappropriate to the kind of type causes a run-time panic. -type Type interface { - // Methods applicable to all types. - - // Align returns the alignment in bytes of a value of - // this type when allocated in memory. - Align() int - - // FieldAlign returns the alignment in bytes of a value of - // this type when used as a field in a struct. - FieldAlign() int - - // Method returns the i'th method in the type's method set. - // It panics if i is not in the range [0, NumMethod()). - // - // For a non-interface type T or *T, the returned Method's Type and Func - // fields describe a function whose first argument is the receiver. - // - // For an interface type, the returned Method's Type field gives the - // method signature, without a receiver, and the Func field is nil. - Method(int) Method - - // MethodByName returns the method with that name in the type's - // method set and a boolean indicating if the method was found. - // - // For a non-interface type T or *T, the returned Method's Type and Func - // fields describe a function whose first argument is the receiver. - // - // For an interface type, the returned Method's Type field gives the - // method signature, without a receiver, and the Func field is nil. - MethodByName(string) (Method, bool) - - // NumMethod returns the number of methods in the type's method set. - NumMethod() int - - // Name returns the type's name within its package. - // It returns an empty string for unnamed types. - Name() string - - // PkgPath returns the type's package path. - // The package path is a full package import path like "container/vector". - // PkgPath returns an empty string for unnamed types. - PkgPath() string - - // Size returns the number of bytes needed to store - // a value of the given type; it is analogous to unsafe.Sizeof. - Size() uintptr - - // String returns a string representation of the type. - // The string representation may use shortened package names - // (e.g., vector instead of "container/vector") and is not - // guaranteed to be unique among types. To test for equality, - // compare the Types directly. - String() string - - // Kind returns the specific kind of this type. - Kind() Kind - - // Implements returns true if the type implements the interface type u. - Implements(u Type) bool - - // AssignableTo returns true if a value of the type is assignable to type u. - AssignableTo(u Type) bool - - // Methods applicable only to some types, depending on Kind. - // The methods allowed for each kind are: - // - // Int*, Uint*, Float*, Complex*: Bits - // Array: Elem, Len - // Chan: ChanDir, Elem - // Func: In, NumIn, Out, NumOut, IsVariadic. - // Map: Key, Elem - // Ptr: Elem - // Slice: Elem - // Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumField - - // Bits returns the size of the type in bits. - // It panics if the type's Kind is not one of the - // sized or unsized Int, Uint, Float, or Complex kinds. - Bits() int - - // ChanDir returns a channel type's direction. - // It panics if the type's Kind is not Chan. - ChanDir() ChanDir - - // IsVariadic returns true if a function type's final input parameter - // is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the parameter's - // implicit actual type []T. - // - // For concreteness, if t represents func(x int, y ... float), then - // - // t.NumIn() == 2 - // t.In(0) is the reflect.Type for "int" - // t.In(1) is the reflect.Type for "[]float" - // t.IsVariadic() == true - // - // IsVariadic panics if the type's Kind is not Func. - IsVariadic() bool - - // Elem returns a type's element type. - // It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice. - Elem() Type - - // Field returns a struct type's i'th field. - // It panics if the type's Kind is not Struct. - // It panics if i is not in the range [0, NumField()). - Field(i int) StructField - - // FieldByIndex returns the nested field corresponding - // to the index sequence. It is equivalent to calling Field - // successively for each index i. - // It panics if the type's Kind is not Struct. - FieldByIndex(index []int) StructField - - // FieldByName returns the struct field with the given name - // and a boolean indicating if the field was found. - FieldByName(name string) (StructField, bool) - - // FieldByNameFunc returns the first struct field with a name - // that satisfies the match function and a boolean indicating if - // the field was found. - FieldByNameFunc(match func(string) bool) (StructField, bool) - - // In returns the type of a function type's i'th input parameter. - // It panics if the type's Kind is not Func. - // It panics if i is not in the range [0, NumIn()). - In(i int) Type - - // Key returns a map type's key type. - // It panics if the type's Kind is not Map. - Key() Type - - // Len returns an array type's length. - // It panics if the type's Kind is not Array. - Len() int - - // NumField returns a struct type's field count. - // It panics if the type's Kind is not Struct. - NumField() int - - // NumIn returns a function type's input parameter count. - // It panics if the type's Kind is not Func. - NumIn() int - - // NumOut returns a function type's output parameter count. - // It panics if the type's Kind is not Func. - NumOut() int - - // Out returns the type of a function type's i'th output parameter. - // It panics if the type's Kind is not Func. - // It panics if i is not in the range [0, NumOut()). - Out(i int) Type - - runtimeType() *runtime.Type - common() *commonType - uncommon() *uncommonType -} - -// A Kind represents the specific kind of type that a Type represents. -// The zero Kind is not a valid kind. -type Kind uint8 - -const ( - Invalid Kind = iota - Bool - Int - Int8 - Int16 - Int32 - Int64 - Uint - Uint8 - Uint16 - Uint32 - Uint64 - Uintptr - Float32 - Float64 - Complex64 - Complex128 - Array - Chan - Func - Interface - Map - Ptr - Slice - String - Struct - UnsafePointer -) - -/* - * Copy of data structures from ../runtime/type.go. - * For comments, see the ones in that file. - * - * These data structures are known to the compiler and the runtime. - * - * Putting these types in runtime instead of reflect means that - * reflect doesn't need to be autolinked into every binary, which - * simplifies bootstrapping and package dependencies. - * Unfortunately, it also means that reflect needs its own - * copy in order to access the private fields. - */ - -// commonType is the common implementation of most values. -// It is embedded in other, public struct types, but always -// with a unique tag like "uint" or "float" so that the client cannot -// convert from, say, *UintType to *FloatType. - -type commonType struct { - size uintptr - hash uint32 - alg uint8 - align uint8 - fieldAlign uint8 - kind uint8 - string *string - *uncommonType - ptrToThis *runtime.Type -} - -type method struct { - name *string - pkgPath *string - mtyp *runtime.Type - typ *runtime.Type - ifn unsafe.Pointer - tfn unsafe.Pointer -} - -type uncommonType struct { - name *string - pkgPath *string - methods []method -} - -// ChanDir represents a channel type's direction. -type ChanDir int - -const ( - RecvDir ChanDir = 1 << iota - SendDir - BothDir = RecvDir | SendDir -) - - -// arrayType represents a fixed array type. -type arrayType struct { - commonType `reflect:"array"` - elem *runtime.Type - slice *runtime.Type - len uintptr -} - -// chanType represents a channel type. -type chanType struct { - commonType `reflect:"chan"` - elem *runtime.Type - dir uintptr -} - -// funcType represents a function type. -type funcType struct { - commonType `reflect:"func"` - dotdotdot bool - in []*runtime.Type - out []*runtime.Type -} - -// imethod represents a method on an interface type -type imethod struct { - name *string - pkgPath *string - typ *runtime.Type -} - -// interfaceType represents an interface type. -type interfaceType struct { - commonType `reflect:"interface"` - methods []imethod -} - -// mapType represents a map type. -type mapType struct { - commonType `reflect:"map"` - key *runtime.Type - elem *runtime.Type -} - -// ptrType represents a pointer type. -type ptrType struct { - commonType `reflect:"ptr"` - elem *runtime.Type -} - -// sliceType represents a slice type. -type sliceType struct { - commonType `reflect:"slice"` - elem *runtime.Type -} - -// Struct field -type structField struct { - name *string - pkgPath *string - typ *runtime.Type - tag *string - offset uintptr -} - -// structType represents a struct type. -type structType struct { - commonType `reflect:"struct"` - fields []structField -} - - -/* - * The compiler knows the exact layout of all the data structures above. - * The compiler does not know about the data structures and methods below. - */ - -// Method represents a single method. -type Method struct { - PkgPath string // empty for uppercase Name - Name string - Type Type - Func Value - Index int -} - -// High bit says whether type has -// embedded pointers,to help garbage collector. -const kindMask = 0x7f - -func (k Kind) String() string { - if int(k) < len(kindNames) { - return kindNames[k] - } - return "kind" + strconv.Itoa(int(k)) -} - -var kindNames = []string{ - Invalid: "invalid", - Bool: "bool", - Int: "int", - Int8: "int8", - Int16: "int16", - Int32: "int32", - Int64: "int64", - Uint: "uint", - Uint8: "uint8", - Uint16: "uint16", - Uint32: "uint32", - Uint64: "uint64", - Uintptr: "uintptr", - Float32: "float32", - Float64: "float64", - Complex64: "complex64", - Complex128: "complex128", - Array: "array", - Chan: "chan", - Func: "func", - Interface: "interface", - Map: "map", - Ptr: "ptr", - Slice: "slice", - String: "string", - Struct: "struct", - UnsafePointer: "unsafe.Pointer", -} - -func (t *uncommonType) uncommon() *uncommonType { - return t -} - -func (t *uncommonType) PkgPath() string { - if t == nil || t.pkgPath == nil { - return "" - } - return *t.pkgPath -} - -func (t *uncommonType) Name() string { - if t == nil || t.name == nil { - return "" - } - return *t.name -} - -func (t *commonType) toType() Type { - if t == nil { - return nil - } - return t -} - -func (t *commonType) String() string { return *t.string } - -func (t *commonType) Size() uintptr { return t.size } - -func (t *commonType) Bits() int { - if t == nil { - panic("reflect: Bits of nil Type") - } - k := t.Kind() - if k < Int || k > Complex128 { - panic("reflect: Bits of non-arithmetic Type " + t.String()) - } - return int(t.size) * 8 -} - -func (t *commonType) Align() int { return int(t.align) } - -func (t *commonType) FieldAlign() int { return int(t.fieldAlign) } - -func (t *commonType) Kind() Kind { return Kind(t.kind & kindMask) } - -func (t *commonType) common() *commonType { return t } - -func (t *uncommonType) Method(i int) (m Method) { - if t == nil || i < 0 || i >= len(t.methods) { - return - } - p := &t.methods[i] - if p.name != nil { - m.Name = *p.name - } - flag := uint32(0) - if p.pkgPath != nil { - m.PkgPath = *p.pkgPath - flag |= flagRO - } - m.Type = toType(p.typ) - fn := p.tfn - m.Func = valueFromIword(flag, m.Type, iword(fn)) - m.Index = i - return -} - -func (t *uncommonType) NumMethod() int { - if t == nil { - return 0 - } - return len(t.methods) -} - -func (t *uncommonType) MethodByName(name string) (m Method, ok bool) { - if t == nil { - return - } - var p *method - for i := range t.methods { - p = &t.methods[i] - if p.name != nil && *p.name == name { - return t.Method(i), true - } - } - return -} - -// TODO(rsc): 6g supplies these, but they are not -// as efficient as they could be: they have commonType -// as the receiver instead of *commonType. -func (t *commonType) NumMethod() int { - if t.Kind() == Interface { - tt := (*interfaceType)(unsafe.Pointer(t)) - return tt.NumMethod() - } - return t.uncommonType.NumMethod() -} - -func (t *commonType) Method(i int) (m Method) { - if t.Kind() == Interface { - tt := (*interfaceType)(unsafe.Pointer(t)) - return tt.Method(i) - } - return t.uncommonType.Method(i) -} - -func (t *commonType) MethodByName(name string) (m Method, ok bool) { - if t.Kind() == Interface { - tt := (*interfaceType)(unsafe.Pointer(t)) - return tt.MethodByName(name) - } - return t.uncommonType.MethodByName(name) -} - -func (t *commonType) PkgPath() string { - return t.uncommonType.PkgPath() -} - -func (t *commonType) Name() string { - return t.uncommonType.Name() -} - -func (t *commonType) ChanDir() ChanDir { - if t.Kind() != Chan { - panic("reflect: ChanDir of non-chan type") - } - tt := (*chanType)(unsafe.Pointer(t)) - return ChanDir(tt.dir) -} - -func (t *commonType) IsVariadic() bool { - if t.Kind() != Func { - panic("reflect: IsVariadic of non-func type") - } - tt := (*funcType)(unsafe.Pointer(t)) - return tt.dotdotdot -} - -func (t *commonType) Elem() Type { - switch t.Kind() { - case Array: - tt := (*arrayType)(unsafe.Pointer(t)) - return toType(tt.elem) - case Chan: - tt := (*chanType)(unsafe.Pointer(t)) - return toType(tt.elem) - case Map: - tt := (*mapType)(unsafe.Pointer(t)) - return toType(tt.elem) - case Ptr: - tt := (*ptrType)(unsafe.Pointer(t)) - return toType(tt.elem) - case Slice: - tt := (*sliceType)(unsafe.Pointer(t)) - return toType(tt.elem) - } - panic("reflect; Elem of invalid type") -} - -func (t *commonType) Field(i int) StructField { - if t.Kind() != Struct { - panic("reflect: Field of non-struct type") - } - tt := (*structType)(unsafe.Pointer(t)) - return tt.Field(i) -} - -func (t *commonType) FieldByIndex(index []int) StructField { - if t.Kind() != Struct { - panic("reflect: FieldByIndex of non-struct type") - } - tt := (*structType)(unsafe.Pointer(t)) - return tt.FieldByIndex(index) -} - -func (t *commonType) FieldByName(name string) (StructField, bool) { - if t.Kind() != Struct { - panic("reflect: FieldByName of non-struct type") - } - tt := (*structType)(unsafe.Pointer(t)) - return tt.FieldByName(name) -} - -func (t *commonType) FieldByNameFunc(match func(string) bool) (StructField, bool) { - if t.Kind() != Struct { - panic("reflect: FieldByNameFunc of non-struct type") - } - tt := (*structType)(unsafe.Pointer(t)) - return tt.FieldByNameFunc(match) -} - -func (t *commonType) In(i int) Type { - if t.Kind() != Func { - panic("reflect: In of non-func type") - } - tt := (*funcType)(unsafe.Pointer(t)) - return toType(tt.in[i]) -} - -func (t *commonType) Key() Type { - if t.Kind() != Map { - panic("reflect: Key of non-map type") - } - tt := (*mapType)(unsafe.Pointer(t)) - return toType(tt.key) -} - -func (t *commonType) Len() int { - if t.Kind() != Array { - panic("reflect: Len of non-array type") - } - tt := (*arrayType)(unsafe.Pointer(t)) - return int(tt.len) -} - -func (t *commonType) NumField() int { - if t.Kind() != Struct { - panic("reflect: NumField of non-struct type") - } - tt := (*structType)(unsafe.Pointer(t)) - return len(tt.fields) -} - -func (t *commonType) NumIn() int { - if t.Kind() != Func { - panic("reflect; NumIn of non-func type") - } - tt := (*funcType)(unsafe.Pointer(t)) - return len(tt.in) -} - -func (t *commonType) NumOut() int { - if t.Kind() != Func { - panic("reflect; NumOut of non-func type") - } - tt := (*funcType)(unsafe.Pointer(t)) - return len(tt.out) -} - -func (t *commonType) Out(i int) Type { - if t.Kind() != Func { - panic("reflect: Out of non-func type") - } - tt := (*funcType)(unsafe.Pointer(t)) - return toType(tt.out[i]) -} - -func (d ChanDir) String() string { - switch d { - case SendDir: - return "chan<-" - case RecvDir: - return "<-chan" - case BothDir: - return "chan" - } - return "ChanDir" + strconv.Itoa(int(d)) -} - -// Method returns the i'th method in the type's method set. -func (t *interfaceType) Method(i int) (m Method) { - if i < 0 || i >= len(t.methods) { - return - } - p := &t.methods[i] - m.Name = *p.name - if p.pkgPath != nil { - m.PkgPath = *p.pkgPath - } - m.Type = toType(p.typ) - m.Index = i - return -} - -// NumMethod returns the number of interface methods in the type's method set. -func (t *interfaceType) NumMethod() int { return len(t.methods) } - -// MethodByName method with the given name in the type's method set. -func (t *interfaceType) MethodByName(name string) (m Method, ok bool) { - if t == nil { - return - } - var p *imethod - for i := range t.methods { - p = &t.methods[i] - if *p.name == name { - return t.Method(i), true - } - } - return -} - -type StructField struct { - PkgPath string // empty for uppercase Name - Name string - Type Type - Tag StructTag - Offset uintptr - Index []int - Anonymous bool -} - -// A StructTag is the tag string in a struct field. -// -// By convention, tag strings are a concatenation of -// optionally space-separated key:"value" pairs. -// Each key is a non-empty string consisting of non-control -// characters other than space (U+0020 ' '), quote (U+0022 '"'), -// and colon (U+003A ':'). Each value is quoted using U+0022 '"' -// characters and Go string literal syntax. -type StructTag string - -// Get returns the value associated with key in the tag string. -// If there is no such key in the tag, Get returns the empty string. -// If the tag does not have the conventional format, the value -// returned by Get is unspecified, -func (tag StructTag) Get(key string) string { - for tag != "" { - // skip leading space - i := 0 - for i < len(tag) && tag[i] == ' ' { - i++ - } - tag = tag[i:] - if tag == "" { - break - } - - // scan to colon. - // a space or a quote is a syntax error - i = 0 - for i < len(tag) && tag[i] != ' ' && tag[i] != ':' && tag[i] != '"' { - i++ - } - if i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' { - break - } - name := string(tag[:i]) - tag = tag[i+1:] - - // scan quoted string to find value - i = 1 - for i < len(tag) && tag[i] != '"' { - if tag[i] == '\\' { - i++ - } - i++ - } - if i >= len(tag) { - break - } - qvalue := string(tag[:i+1]) - tag = tag[i+1:] - - if key == name { - value, _ := strconv.Unquote(qvalue) - return value - } - } - return "" -} - -// Field returns the i'th struct field. -func (t *structType) Field(i int) (f StructField) { - if i < 0 || i >= len(t.fields) { - return - } - p := t.fields[i] - f.Type = toType(p.typ) - if p.name != nil { - f.Name = *p.name - } else { - t := f.Type - if t.Kind() == Ptr { - t = t.Elem() - } - f.Name = t.Name() - f.Anonymous = true - } - if p.pkgPath != nil { - f.PkgPath = *p.pkgPath - } - if p.tag != nil { - f.Tag = StructTag(*p.tag) - } - f.Offset = p.offset - f.Index = []int{i} - return -} - -// TODO(gri): Should there be an error/bool indicator if the index -// is wrong for FieldByIndex? - -// FieldByIndex returns the nested field corresponding to index. -func (t *structType) FieldByIndex(index []int) (f StructField) { - f.Type = Type(t.toType()) - for i, x := range index { - if i > 0 { - ft := f.Type - if ft.Kind() == Ptr && ft.Elem().Kind() == Struct { - ft = ft.Elem() - } - f.Type = ft - } - f = f.Type.Field(x) - } - return -} - -const inf = 1 << 30 // infinity - no struct has that many nesting levels - -func (t *structType) fieldByNameFunc(match func(string) bool, mark map[*structType]bool, depth int) (ff StructField, fd int) { - fd = inf // field depth - - if mark[t] { - // Struct already seen. - return - } - mark[t] = true - - var fi int // field index - n := 0 // number of matching fields at depth fd -L: - for i := range t.fields { - f := t.Field(i) - d := inf - switch { - case match(f.Name): - // Matching top-level field. - d = depth - case f.Anonymous: - ft := f.Type - if ft.Kind() == Ptr { - ft = ft.Elem() - } - switch { - case match(ft.Name()): - // Matching anonymous top-level field. - d = depth - case fd > depth: - // No top-level field yet; look inside nested structs. - if ft.Kind() == Struct { - st := (*structType)(unsafe.Pointer(ft.(*commonType))) - f, d = st.fieldByNameFunc(match, mark, depth+1) - } - } - } - - switch { - case d < fd: - // Found field at shallower depth. - ff, fi, fd = f, i, d - n = 1 - case d == fd: - // More than one matching field at the same depth (or d, fd == inf). - // Same as no field found at this depth. - n++ - if d == depth { - // Impossible to find a field at lower depth. - break L - } - } - } - - if n == 1 { - // Found matching field. - if len(ff.Index) <= depth { - ff.Index = make([]int, depth+1) - } - ff.Index[depth] = fi - } else { - // None or more than one matching field found. - fd = inf - } - - mark[t] = false, false - return -} - -// FieldByName returns the struct field with the given name -// and a boolean to indicate if the field was found. -func (t *structType) FieldByName(name string) (f StructField, present bool) { - return t.FieldByNameFunc(func(s string) bool { return s == name }) -} - -// FieldByNameFunc returns the struct field with a name that satisfies the -// match function and a boolean to indicate if the field was found. -func (t *structType) FieldByNameFunc(match func(string) bool) (f StructField, present bool) { - if ff, fd := t.fieldByNameFunc(match, make(map[*structType]bool), 0); fd < inf { - ff.Index = ff.Index[0 : fd+1] - f, present = ff, true - } - return -} - -// Convert runtime type to reflect type. -func toCommonType(p *runtime.Type) *commonType { - if p == nil { - return nil - } - type hdr struct { - x interface{} - t commonType - } - x := unsafe.Pointer(p) - if uintptr(x)&reflectFlags != 0 { - panic("invalid interface value") - } - return &(*hdr)(x).t -} - -func toType(p *runtime.Type) Type { - if p == nil { - return nil - } - return toCommonType(p).toType() -} - -// TypeOf returns the reflection Type of the value in the interface{}. -func TypeOf(i interface{}) Type { - eface := *(*emptyInterface)(unsafe.Pointer(&i)) - return toType(eface.typ) -} - -// ptrMap is the cache for PtrTo. -var ptrMap struct { - sync.RWMutex - m map[*commonType]*ptrType -} - -func (t *commonType) runtimeType() *runtime.Type { - // The runtime.Type always precedes the commonType in memory. - // Adjust pointer to find it. - var rt struct { - i runtime.Type - ct commonType - } - return (*runtime.Type)(unsafe.Pointer(uintptr(unsafe.Pointer(t)) - unsafe.Offsetof(rt.ct))) -} - -// PtrTo returns the pointer type with element t. -// For example, if t represents type Foo, PtrTo(t) represents *Foo. -func PtrTo(t Type) Type { - // If t records its pointer-to type, use it. - ct := t.(*commonType) - if p := ct.ptrToThis; p != nil { - return toType(p) - } - - // Otherwise, synthesize one. - // This only happens for pointers with no methods. - // We keep the mapping in a map on the side, because - // this operation is rare and a separate map lets us keep - // the type structures in read-only memory. - ptrMap.RLock() - if m := ptrMap.m; m != nil { - if p := m[ct]; p != nil { - ptrMap.RUnlock() - return p.commonType.toType() - } - } - ptrMap.RUnlock() - ptrMap.Lock() - if ptrMap.m == nil { - ptrMap.m = make(map[*commonType]*ptrType) - } - p := ptrMap.m[ct] - if p != nil { - // some other goroutine won the race and created it - ptrMap.Unlock() - return p - } - - var rt struct { - i runtime.Type - ptrType - } - rt.i = (*runtime.PtrType)(unsafe.Pointer(&rt.ptrType)) - - // initialize p using *byte's PtrType as a prototype. - // have to do assignment as PtrType, not runtime.PtrType, - // in order to write to unexported fields. - p = &rt.ptrType - bp := (*ptrType)(unsafe.Pointer(unsafe.Typeof((*byte)(nil)).(*runtime.PtrType))) - *p = *bp - - s := "*" + *ct.string - p.string = &s - - // For the type structures linked into the binary, the - // compiler provides a good hash of the string. - // Create a good hash for the new string by using - // the FNV-1 hash's mixing function to combine the - // old hash and the new "*". - p.hash = ct.hash*16777619 ^ '*' - - p.uncommonType = nil - p.ptrToThis = nil - p.elem = (*runtime.Type)(unsafe.Pointer(uintptr(unsafe.Pointer(ct)) - unsafe.Offsetof(rt.ptrType))) - - ptrMap.m[ct] = p - ptrMap.Unlock() - return p.commonType.toType() -} - -func (t *commonType) Implements(u Type) bool { - if u == nil { - panic("reflect: nil type passed to Type.Implements") - } - if u.Kind() != Interface { - panic("reflect: non-interface type passed to Type.Implements") - } - return implements(u.(*commonType), t) -} - -func (t *commonType) AssignableTo(u Type) bool { - if u == nil { - panic("reflect: nil type passed to Type.AssignableTo") - } - uu := u.(*commonType) - return directlyAssignable(uu, t) || implements(uu, t) -} - -// implements returns true if the type V implements the interface type T. -func implements(T, V *commonType) bool { - if T.Kind() != Interface { - return false - } - t := (*interfaceType)(unsafe.Pointer(T)) - if len(t.methods) == 0 { - return true - } - - // The same algorithm applies in both cases, but the - // method tables for an interface type and a concrete type - // are different, so the code is duplicated. - // In both cases the algorithm is a linear scan over the two - // lists - T's methods and V's methods - simultaneously. - // Since method tables are stored in a unique sorted order - // (alphabetical, with no duplicate method names), the scan - // through V's methods must hit a match for each of T's - // methods along the way, or else V does not implement T. - // This lets us run the scan in overall linear time instead of - // the quadratic time a naive search would require. - // See also ../runtime/iface.c. - if V.Kind() == Interface { - v := (*interfaceType)(unsafe.Pointer(V)) - i := 0 - for j := 0; j < len(v.methods); j++ { - tm := &t.methods[i] - vm := &v.methods[j] - if vm.name == tm.name && vm.pkgPath == tm.pkgPath && vm.typ == tm.typ { - if i++; i >= len(t.methods) { - return true - } - } - } - return false - } - - v := V.uncommon() - if v == nil { - return false - } - i := 0 - for j := 0; j < len(v.methods); j++ { - tm := &t.methods[i] - vm := &v.methods[j] - if vm.name == tm.name && vm.pkgPath == tm.pkgPath && vm.mtyp == tm.typ { - if i++; i >= len(t.methods) { - return true - } - } - } - return false -} - -// directlyAssignable returns true if a value x of type V can be directly -// assigned (using memmove) to a value of type T. -// http://golang.org/doc/go_spec.html#Assignability -// Ignoring the interface rules (implemented elsewhere) -// and the ideal constant rules (no ideal constants at run time). -func directlyAssignable(T, V *commonType) bool { - // x's type V is identical to T? - if T == V { - return true - } - - // Otherwise at least one of T and V must be unnamed - // and they must have the same kind. - if T.Name() != "" && V.Name() != "" || T.Kind() != V.Kind() { - return false - } - - // x's type T and V have identical underlying types. - // Since at least one is unnamed, only the composite types - // need to be considered. - switch T.Kind() { - case Array: - return T.Elem() == V.Elem() && T.Len() == V.Len() - - case Chan: - // Special case: - // x is a bidirectional channel value, T is a channel type, - // and x's type V and T have identical element types. - if V.ChanDir() == BothDir && T.Elem() == V.Elem() { - return true - } - - // Otherwise continue test for identical underlying type. - return V.ChanDir() == T.ChanDir() && T.Elem() == V.Elem() - - case Func: - t := (*funcType)(unsafe.Pointer(T)) - v := (*funcType)(unsafe.Pointer(V)) - if t.dotdotdot != v.dotdotdot || len(t.in) != len(v.in) || len(t.out) != len(v.out) { - return false - } - for i, typ := range t.in { - if typ != v.in[i] { - return false - } - } - for i, typ := range t.out { - if typ != v.out[i] { - return false - } - } - return true - - case Interface: - t := (*interfaceType)(unsafe.Pointer(T)) - v := (*interfaceType)(unsafe.Pointer(V)) - if len(t.methods) == 0 && len(v.methods) == 0 { - return true - } - // Might have the same methods but still - // need a run time conversion. - return false - - case Map: - return T.Key() == V.Key() && T.Elem() == V.Elem() - - case Ptr, Slice: - return T.Elem() == V.Elem() - - case Struct: - t := (*structType)(unsafe.Pointer(T)) - v := (*structType)(unsafe.Pointer(V)) - if len(t.fields) != len(v.fields) { - return false - } - for i := range t.fields { - tf := &t.fields[i] - vf := &v.fields[i] - if tf.name != vf.name || tf.pkgPath != vf.pkgPath || - tf.typ != vf.typ || tf.tag != vf.tag || tf.offset != vf.offset { - return false - } - } - return true - } - - return false -} diff --git a/src/pkg/reflect/value.go b/src/pkg/reflect/value.go deleted file mode 100644 index bfeb3267c..000000000 --- a/src/pkg/reflect/value.go +++ /dev/null @@ -1,1724 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package reflect - -import ( - "math" - "runtime" - "strconv" - "unsafe" -) - -const ptrSize = unsafe.Sizeof((*byte)(nil)) -const cannotSet = "cannot set value obtained from unexported struct field" - -// TODO: This will have to go away when -// the new gc goes in. -func memmove(adst, asrc unsafe.Pointer, n uintptr) { - dst := uintptr(adst) - src := uintptr(asrc) - switch { - case src < dst && src+n > dst: - // byte copy backward - // careful: i is unsigned - for i := n; i > 0; { - i-- - *(*byte)(unsafe.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(src + i)) - } - case (n|src|dst)&(ptrSize-1) != 0: - // byte copy forward - for i := uintptr(0); i < n; i++ { - *(*byte)(unsafe.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(src + i)) - } - default: - // word copy forward - for i := uintptr(0); i < n; i += ptrSize { - *(*uintptr)(unsafe.Pointer(dst + i)) = *(*uintptr)(unsafe.Pointer(src + i)) - } - } -} - -// Value is the reflection interface to a Go value. -// -// Not all methods apply to all kinds of values. Restrictions, -// if any, are noted in the documentation for each method. -// Use the Kind method to find out the kind of value before -// calling kind-specific methods. Calling a method -// inappropriate to the kind of type causes a run time panic. -// -// The zero Value represents no value. -// Its IsValid method returns false, its Kind method returns Invalid, -// its String method returns "<invalid Value>", and all other methods panic. -// Most functions and methods never return an invalid value. -// If one does, its documentation states the conditions explicitly. -// -// The fields of Value are exported so that clients can copy and -// pass Values around, but they should not be edited or inspected -// directly. A future language change may make it possible not to -// export these fields while still keeping Values usable as values. -type Value struct { - Internal interface{} - InternalMethod int -} - -// A ValueError occurs when a Value method is invoked on -// a Value that does not support it. Such cases are documented -// in the description of each method. -type ValueError struct { - Method string - Kind Kind -} - -func (e *ValueError) String() string { - if e.Kind == 0 { - return "reflect: call of " + e.Method + " on zero Value" - } - return "reflect: call of " + e.Method + " on " + e.Kind.String() + " Value" -} - -// methodName returns the name of the calling method, -// assumed to be two stack frames above. -func methodName() string { - pc, _, _, _ := runtime.Caller(2) - f := runtime.FuncForPC(pc) - if f == nil { - return "unknown method" - } - return f.Name() -} - -// An iword is the word that would be stored in an -// interface to represent a given value v. Specifically, if v is -// bigger than a pointer, its word is a pointer to v's data. -// Otherwise, its word is a zero uintptr with the data stored -// in the leading bytes. -type iword uintptr - -func loadIword(p unsafe.Pointer, size uintptr) iword { - // Run the copy ourselves instead of calling memmove - // to avoid moving v to the heap. - w := iword(0) - switch size { - default: - panic("reflect: internal error: loadIword of " + strconv.Itoa(int(size)) + "-byte value") - case 0: - case 1: - *(*uint8)(unsafe.Pointer(&w)) = *(*uint8)(p) - case 2: - *(*uint16)(unsafe.Pointer(&w)) = *(*uint16)(p) - case 3: - *(*[3]byte)(unsafe.Pointer(&w)) = *(*[3]byte)(p) - case 4: - *(*uint32)(unsafe.Pointer(&w)) = *(*uint32)(p) - case 5: - *(*[5]byte)(unsafe.Pointer(&w)) = *(*[5]byte)(p) - case 6: - *(*[6]byte)(unsafe.Pointer(&w)) = *(*[6]byte)(p) - case 7: - *(*[7]byte)(unsafe.Pointer(&w)) = *(*[7]byte)(p) - case 8: - *(*uint64)(unsafe.Pointer(&w)) = *(*uint64)(p) - } - return w -} - -func storeIword(p unsafe.Pointer, w iword, size uintptr) { - // Run the copy ourselves instead of calling memmove - // to avoid moving v to the heap. - switch size { - default: - panic("reflect: internal error: storeIword of " + strconv.Itoa(int(size)) + "-byte value") - case 0: - case 1: - *(*uint8)(p) = *(*uint8)(unsafe.Pointer(&w)) - case 2: - *(*uint16)(p) = *(*uint16)(unsafe.Pointer(&w)) - case 3: - *(*[3]byte)(p) = *(*[3]byte)(unsafe.Pointer(&w)) - case 4: - *(*uint32)(p) = *(*uint32)(unsafe.Pointer(&w)) - case 5: - *(*[5]byte)(p) = *(*[5]byte)(unsafe.Pointer(&w)) - case 6: - *(*[6]byte)(p) = *(*[6]byte)(unsafe.Pointer(&w)) - case 7: - *(*[7]byte)(p) = *(*[7]byte)(unsafe.Pointer(&w)) - case 8: - *(*uint64)(p) = *(*uint64)(unsafe.Pointer(&w)) - } -} - -// emptyInterface is the header for an interface{} value. -type emptyInterface struct { - typ *runtime.Type - word iword -} - -// nonEmptyInterface is the header for a interface value with methods. -type nonEmptyInterface struct { - // see ../runtime/iface.c:/Itab - itab *struct { - ityp *runtime.Type // static interface type - typ *runtime.Type // dynamic concrete type - link unsafe.Pointer - bad int32 - unused int32 - fun [100000]unsafe.Pointer // method table - } - word iword -} - -// Regarding the implementation of Value: -// -// The Internal interface is a true interface value in the Go sense, -// but it also serves as a (type, address) pair in which one cannot -// be changed separately from the other. That is, it serves as a way -// to prevent unsafe mutations of the Internal state even though -// we cannot (yet?) hide the field while preserving the ability for -// clients to make copies of Values. -// -// The internal method converts a Value into the expanded internalValue struct. -// If we could avoid exporting fields we'd probably make internalValue the -// definition of Value. -// -// If a Value is addressable (CanAddr returns true), then the Internal -// interface value holds a pointer to the actual field data, and Set stores -// through that pointer. If a Value is not addressable (CanAddr returns false), -// then the Internal interface value holds the actual value. -// -// In addition to whether a value is addressable, we track whether it was -// obtained by using an unexported struct field. Such values are allowed -// to be read, mainly to make fmt.Print more useful, but they are not -// allowed to be written. We call such values read-only. -// -// A Value can be set (via the Set, SetUint, etc. methods) only if it is both -// addressable and not read-only. -// -// The two permission bits - addressable and read-only - are stored in -// the bottom two bits of the type pointer in the interface value. -// -// ordinary value: Internal = value -// addressable value: Internal = value, Internal.typ |= flagAddr -// read-only value: Internal = value, Internal.typ |= flagRO -// addressable, read-only value: Internal = value, Internal.typ |= flagAddr | flagRO -// -// It is important that the read-only values have the extra bit set -// (as opposed to using the bit to mean writable), because client code -// can grab the interface field and try to use it. Having the extra bit -// set makes the type pointer compare not equal to any real type, -// so that a client cannot, say, write through v.Internal.(*int). -// The runtime routines that access interface types reject types with -// low bits set. -// -// If a Value fv = v.Method(i), then fv = v with the InternalMethod -// field set to i+1. Methods are never addressable. -// -// All in all, this is a lot of effort just to avoid making this new API -// depend on a language change we'll probably do anyway, but -// it's helpful to keep the two separate, and much of the logic is -// necessary to implement the Interface method anyway. - -const ( - flagAddr uint32 = 1 << iota // holds address of value - flagRO // read-only - - reflectFlags = 3 -) - -// An internalValue is the unpacked form of a Value. -// The zero Value unpacks to a zero internalValue -type internalValue struct { - typ *commonType // type of value - kind Kind // kind of value - flag uint32 - word iword - addr unsafe.Pointer - rcvr iword - method bool - nilmethod bool -} - -func (v Value) internal() internalValue { - var iv internalValue - eface := *(*emptyInterface)(unsafe.Pointer(&v.Internal)) - p := uintptr(unsafe.Pointer(eface.typ)) - iv.typ = toCommonType((*runtime.Type)(unsafe.Pointer(p &^ reflectFlags))) - if iv.typ == nil { - return iv - } - iv.flag = uint32(p & reflectFlags) - iv.word = eface.word - if iv.flag&flagAddr != 0 { - iv.addr = unsafe.Pointer(iv.word) - iv.typ = iv.typ.Elem().common() - if iv.typ.size <= ptrSize { - iv.word = loadIword(iv.addr, iv.typ.size) - } - } else { - if iv.typ.size > ptrSize { - iv.addr = unsafe.Pointer(iv.word) - } - } - iv.kind = iv.typ.Kind() - - // Is this a method? If so, iv describes the receiver. - // Rewrite to describe the method function. - if v.InternalMethod != 0 { - // If this Value is a method value (x.Method(i) for some Value x) - // then we will invoke it using the interface form of the method, - // which always passes the receiver as a single word. - // Record that information. - i := v.InternalMethod - 1 - if iv.kind == Interface { - it := (*interfaceType)(unsafe.Pointer(iv.typ)) - if i < 0 || i >= len(it.methods) { - panic("reflect: broken Value") - } - m := &it.methods[i] - if m.pkgPath != nil { - iv.flag |= flagRO - } - iv.typ = toCommonType(m.typ) - iface := (*nonEmptyInterface)(iv.addr) - if iface.itab == nil { - iv.word = 0 - iv.nilmethod = true - } else { - iv.word = iword(iface.itab.fun[i]) - } - iv.rcvr = iface.word - } else { - ut := iv.typ.uncommon() - if ut == nil || i < 0 || i >= len(ut.methods) { - panic("reflect: broken Value") - } - m := &ut.methods[i] - if m.pkgPath != nil { - iv.flag |= flagRO - } - iv.typ = toCommonType(m.mtyp) - iv.rcvr = iv.word - iv.word = iword(m.ifn) - } - iv.kind = Func - iv.method = true - iv.flag &^= flagAddr - iv.addr = nil - } - - return iv -} - -// packValue returns a Value with the given flag bits, type, and interface word. -func packValue(flag uint32, typ *runtime.Type, word iword) Value { - if typ == nil { - panic("packValue") - } - t := uintptr(unsafe.Pointer(typ)) - t |= uintptr(flag) - eface := emptyInterface{(*runtime.Type)(unsafe.Pointer(t)), word} - return Value{Internal: *(*interface{})(unsafe.Pointer(&eface))} -} - -// valueFromAddr returns a Value using the given type and address. -func valueFromAddr(flag uint32, typ Type, addr unsafe.Pointer) Value { - if flag&flagAddr != 0 { - // Addressable, so the internal value is - // an interface containing a pointer to the real value. - return packValue(flag, PtrTo(typ).runtimeType(), iword(addr)) - } - - var w iword - if n := typ.Size(); n <= ptrSize { - // In line, so the interface word is the actual value. - w = loadIword(addr, n) - } else { - // Not in line: the interface word is the address. - w = iword(addr) - } - return packValue(flag, typ.runtimeType(), w) -} - -// valueFromIword returns a Value using the given type and interface word. -func valueFromIword(flag uint32, typ Type, w iword) Value { - if flag&flagAddr != 0 { - panic("reflect: internal error: valueFromIword addressable") - } - return packValue(flag, typ.runtimeType(), w) -} - -func (iv internalValue) mustBe(want Kind) { - if iv.kind != want { - panic(&ValueError{methodName(), iv.kind}) - } -} - -func (iv internalValue) mustBeExported() { - if iv.kind == 0 { - panic(&ValueError{methodName(), iv.kind}) - } - if iv.flag&flagRO != 0 { - panic(methodName() + " using value obtained using unexported field") - } -} - -func (iv internalValue) mustBeAssignable() { - if iv.kind == 0 { - panic(&ValueError{methodName(), iv.kind}) - } - // Assignable if addressable and not read-only. - if iv.flag&flagRO != 0 { - panic(methodName() + " using value obtained using unexported field") - } - if iv.flag&flagAddr == 0 { - panic(methodName() + " using unaddressable value") - } -} - -// Addr returns a pointer value representing the address of v. -// It panics if CanAddr() returns false. -// Addr is typically used to obtain a pointer to a struct field -// or slice element in order to call a method that requires a -// pointer receiver. -func (v Value) Addr() Value { - iv := v.internal() - if iv.flag&flagAddr == 0 { - panic("reflect.Value.Addr of unaddressable value") - } - return valueFromIword(iv.flag&flagRO, PtrTo(iv.typ.toType()), iword(iv.addr)) -} - -// Bool returns v's underlying value. -// It panics if v's kind is not Bool. -func (v Value) Bool() bool { - iv := v.internal() - iv.mustBe(Bool) - return *(*bool)(unsafe.Pointer(&iv.word)) -} - -// CanAddr returns true if the value's address can be obtained with Addr. -// Such values are called addressable. A value is addressable if it is -// an element of a slice, an element of an addressable array, -// a field of an addressable struct, or the result of dereferencing a pointer. -// If CanAddr returns false, calling Addr will panic. -func (v Value) CanAddr() bool { - iv := v.internal() - return iv.flag&flagAddr != 0 -} - -// CanSet returns true if the value of v can be changed. -// A Value can be changed only if it is addressable and was not -// obtained by the use of unexported struct fields. -// If CanSet returns false, calling Set or any type-specific -// setter (e.g., SetBool, SetInt64) will panic. -func (v Value) CanSet() bool { - iv := v.internal() - return iv.flag&(flagAddr|flagRO) == flagAddr -} - -// Call calls the function v with the input arguments in. -// For example, if len(in) == 3, v.Call(in) represents the Go call v(in[0], in[1], in[2]). -// Call panics if v's Kind is not Func. -// It returns the output results as Values. -// As in Go, each input argument must be assignable to the -// type of the function's corresponding input parameter. -// If v is a variadic function, Call creates the variadic slice parameter -// itself, copying in the corresponding values. -func (v Value) Call(in []Value) []Value { - iv := v.internal() - iv.mustBe(Func) - iv.mustBeExported() - return iv.call("Call", in) -} - -// CallSlice calls the variadic function v with the input arguments in, -// assigning the slice in[len(in)-1] to v's final variadic argument. -// For example, if len(in) == 3, v.Call(in) represents the Go call v(in[0], in[1], in[2]...). -// Call panics if v's Kind is not Func or if v is not variadic. -// It returns the output results as Values. -// As in Go, each input argument must be assignable to the -// type of the function's corresponding input parameter. -func (v Value) CallSlice(in []Value) []Value { - iv := v.internal() - iv.mustBe(Func) - iv.mustBeExported() - return iv.call("CallSlice", in) -} - -func (iv internalValue) call(method string, in []Value) []Value { - if iv.word == 0 { - if iv.nilmethod { - panic("reflect.Value.Call: call of method on nil interface value") - } - panic("reflect.Value.Call: call of nil function") - } - - isSlice := method == "CallSlice" - t := iv.typ - n := t.NumIn() - if isSlice { - if !t.IsVariadic() { - panic("reflect: CallSlice of non-variadic function") - } - if len(in) < n { - panic("reflect: CallSlice with too few input arguments") - } - if len(in) > n { - panic("reflect: CallSlice with too many input arguments") - } - } else { - if t.IsVariadic() { - n-- - } - if len(in) < n { - panic("reflect: Call with too few input arguments") - } - if !t.IsVariadic() && len(in) > n { - panic("reflect: Call with too many input arguments") - } - } - for _, x := range in { - if x.Kind() == Invalid { - panic("reflect: " + method + " using zero Value argument") - } - } - for i := 0; i < n; i++ { - if xt, targ := in[i].Type(), t.In(i); !xt.AssignableTo(targ) { - panic("reflect: " + method + " using " + xt.String() + " as type " + targ.String()) - } - } - if !isSlice && t.IsVariadic() { - // prepare slice for remaining values - m := len(in) - n - slice := MakeSlice(t.In(n), m, m) - elem := t.In(n).Elem() - for i := 0; i < m; i++ { - x := in[n+i] - if xt := x.Type(); !xt.AssignableTo(elem) { - panic("reflect: cannot use " + xt.String() + " as type " + elem.String() + " in " + method) - } - slice.Index(i).Set(x) - } - origIn := in - in = make([]Value, n+1) - copy(in[:n], origIn) - in[n] = slice - } - - nin := len(in) - if nin != t.NumIn() { - panic("reflect.Value.Call: wrong argument count") - } - nout := t.NumOut() - - // Compute arg size & allocate. - // This computation is 5g/6g/8g-dependent - // and probably wrong for gccgo, but so - // is most of this function. - size := uintptr(0) - if iv.method { - // extra word for interface value - size += ptrSize - } - for i := 0; i < nin; i++ { - tv := t.In(i) - a := uintptr(tv.Align()) - size = (size + a - 1) &^ (a - 1) - size += tv.Size() - } - size = (size + ptrSize - 1) &^ (ptrSize - 1) - for i := 0; i < nout; i++ { - tv := t.Out(i) - a := uintptr(tv.Align()) - size = (size + a - 1) &^ (a - 1) - size += tv.Size() - } - - // size must be > 0 in order for &args[0] to be valid. - // the argument copying is going to round it up to - // a multiple of ptrSize anyway, so make it ptrSize to begin with. - if size < ptrSize { - size = ptrSize - } - - // round to pointer size - size = (size + ptrSize - 1) &^ (ptrSize - 1) - - // Copy into args. - // - // TODO(rsc): revisit when reference counting happens. - // The values are holding up the in references for us, - // but something must be done for the out references. - // For now make everything look like a pointer by pretending - // to allocate a []*int. - args := make([]*int, size/ptrSize) - ptr := uintptr(unsafe.Pointer(&args[0])) - off := uintptr(0) - if iv.method { - // Hard-wired first argument. - *(*iword)(unsafe.Pointer(ptr)) = iv.rcvr - off = ptrSize - } - for i, v := range in { - iv := v.internal() - iv.mustBeExported() - targ := t.In(i).(*commonType) - a := uintptr(targ.align) - off = (off + a - 1) &^ (a - 1) - n := targ.size - addr := unsafe.Pointer(ptr + off) - iv = convertForAssignment("reflect.Value.Call", addr, targ, iv) - if iv.addr == nil { - storeIword(addr, iv.word, n) - } else { - memmove(addr, iv.addr, n) - } - off += n - } - off = (off + ptrSize - 1) &^ (ptrSize - 1) - - // Call. - call(unsafe.Pointer(iv.word), unsafe.Pointer(ptr), uint32(size)) - - // Copy return values out of args. - // - // TODO(rsc): revisit like above. - ret := make([]Value, nout) - for i := 0; i < nout; i++ { - tv := t.Out(i) - a := uintptr(tv.Align()) - off = (off + a - 1) &^ (a - 1) - ret[i] = valueFromAddr(0, tv, unsafe.Pointer(ptr+off)) - off += tv.Size() - } - - return ret -} - -// Cap returns v's capacity. -// It panics if v's Kind is not Array, Chan, or Slice. -func (v Value) Cap() int { - iv := v.internal() - switch iv.kind { - case Array: - return iv.typ.Len() - case Chan: - return int(chancap(iv.word)) - case Slice: - return (*SliceHeader)(iv.addr).Cap - } - panic(&ValueError{"reflect.Value.Cap", iv.kind}) -} - -// Close closes the channel v. -// It panics if v's Kind is not Chan. -func (v Value) Close() { - iv := v.internal() - iv.mustBe(Chan) - iv.mustBeExported() - ch := iv.word - chanclose(ch) -} - -// Complex returns v's underlying value, as a complex128. -// It panics if v's Kind is not Complex64 or Complex128 -func (v Value) Complex() complex128 { - iv := v.internal() - switch iv.kind { - case Complex64: - if iv.addr == nil { - return complex128(*(*complex64)(unsafe.Pointer(&iv.word))) - } - return complex128(*(*complex64)(iv.addr)) - case Complex128: - return *(*complex128)(iv.addr) - } - panic(&ValueError{"reflect.Value.Complex", iv.kind}) -} - -// Elem returns the value that the interface v contains -// or that the pointer v points to. -// It panics if v's Kind is not Interface or Ptr. -// It returns the zero Value if v is nil. -func (v Value) Elem() Value { - iv := v.internal() - return iv.Elem() -} - -func (iv internalValue) Elem() Value { - switch iv.kind { - case Interface: - // Empty interface and non-empty interface have different layouts. - // Convert to empty interface. - var eface emptyInterface - if iv.typ.NumMethod() == 0 { - eface = *(*emptyInterface)(iv.addr) - } else { - iface := (*nonEmptyInterface)(iv.addr) - if iface.itab != nil { - eface.typ = iface.itab.typ - } - eface.word = iface.word - } - if eface.typ == nil { - return Value{} - } - return valueFromIword(iv.flag&flagRO, toType(eface.typ), eface.word) - - case Ptr: - // The returned value's address is v's value. - if iv.word == 0 { - return Value{} - } - return valueFromAddr(iv.flag&flagRO|flagAddr, iv.typ.Elem(), unsafe.Pointer(iv.word)) - } - panic(&ValueError{"reflect.Value.Elem", iv.kind}) -} - -// Field returns the i'th field of the struct v. -// It panics if v's Kind is not Struct or i is out of range. -func (v Value) Field(i int) Value { - iv := v.internal() - iv.mustBe(Struct) - t := iv.typ.toType() - if i < 0 || i >= t.NumField() { - panic("reflect: Field index out of range") - } - f := t.Field(i) - - // Inherit permission bits from v. - flag := iv.flag - // Using an unexported field forces flagRO. - if f.PkgPath != "" { - flag |= flagRO - } - return valueFromValueOffset(flag, f.Type, iv, f.Offset) -} - -// valueFromValueOffset returns a sub-value of outer -// (outer is an array or a struct) with the given flag and type -// starting at the given byte offset into outer. -func valueFromValueOffset(flag uint32, typ Type, outer internalValue, offset uintptr) Value { - if outer.addr != nil { - return valueFromAddr(flag, typ, unsafe.Pointer(uintptr(outer.addr)+offset)) - } - - // outer is so tiny it is in line. - // We have to use outer.word and derive - // the new word (it cannot possibly be bigger). - // In line, so not addressable. - if flag&flagAddr != 0 { - panic("reflect: internal error: misuse of valueFromValueOffset") - } - b := *(*[ptrSize]byte)(unsafe.Pointer(&outer.word)) - for i := uintptr(0); i < typ.Size(); i++ { - b[i] = b[offset+i] - } - for i := typ.Size(); i < ptrSize; i++ { - b[i] = 0 - } - w := *(*iword)(unsafe.Pointer(&b)) - return valueFromIword(flag, typ, w) -} - -// FieldByIndex returns the nested field corresponding to index. -// It panics if v's Kind is not struct. -func (v Value) FieldByIndex(index []int) Value { - v.internal().mustBe(Struct) - for i, x := range index { - if i > 0 { - if v.Kind() == Ptr && v.Elem().Kind() == Struct { - v = v.Elem() - } - } - v = v.Field(x) - } - return v -} - -// FieldByName returns the struct field with the given name. -// It returns the zero Value if no field was found. -// It panics if v's Kind is not struct. -func (v Value) FieldByName(name string) Value { - iv := v.internal() - iv.mustBe(Struct) - if f, ok := iv.typ.FieldByName(name); ok { - return v.FieldByIndex(f.Index) - } - return Value{} -} - -// FieldByNameFunc returns the struct field with a name -// that satisfies the match function. -// It panics if v's Kind is not struct. -// It returns the zero Value if no field was found. -func (v Value) FieldByNameFunc(match func(string) bool) Value { - v.internal().mustBe(Struct) - if f, ok := v.Type().FieldByNameFunc(match); ok { - return v.FieldByIndex(f.Index) - } - return Value{} -} - -// Float returns v's underlying value, as an float64. -// It panics if v's Kind is not Float32 or Float64 -func (v Value) Float() float64 { - iv := v.internal() - switch iv.kind { - case Float32: - return float64(*(*float32)(unsafe.Pointer(&iv.word))) - case Float64: - // If the pointer width can fit an entire float64, - // the value is in line when stored in an interface. - if iv.addr == nil { - return *(*float64)(unsafe.Pointer(&iv.word)) - } - // Otherwise we have a pointer. - return *(*float64)(iv.addr) - } - panic(&ValueError{"reflect.Value.Float", iv.kind}) -} - -// Index returns v's i'th element. -// It panics if v's Kind is not Array or Slice or i is out of range. -func (v Value) Index(i int) Value { - iv := v.internal() - switch iv.kind { - default: - panic(&ValueError{"reflect.Value.Index", iv.kind}) - case Array: - flag := iv.flag // element flag same as overall array - t := iv.typ.toType() - if i < 0 || i > t.Len() { - panic("reflect: array index out of range") - } - typ := t.Elem() - return valueFromValueOffset(flag, typ, iv, uintptr(i)*typ.Size()) - - case Slice: - // Element flag same as Elem of Ptr. - // Addressable, possibly read-only. - flag := iv.flag&flagRO | flagAddr - s := (*SliceHeader)(iv.addr) - if i < 0 || i >= s.Len { - panic("reflect: slice index out of range") - } - typ := iv.typ.Elem() - addr := unsafe.Pointer(s.Data + uintptr(i)*typ.Size()) - return valueFromAddr(flag, typ, addr) - } - - panic("not reached") -} - -// Int returns v's underlying value, as an int64. -// It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64. -func (v Value) Int() int64 { - iv := v.internal() - switch iv.kind { - case Int: - return int64(*(*int)(unsafe.Pointer(&iv.word))) - case Int8: - return int64(*(*int8)(unsafe.Pointer(&iv.word))) - case Int16: - return int64(*(*int16)(unsafe.Pointer(&iv.word))) - case Int32: - return int64(*(*int32)(unsafe.Pointer(&iv.word))) - case Int64: - if iv.addr == nil { - return *(*int64)(unsafe.Pointer(&iv.word)) - } - return *(*int64)(iv.addr) - } - panic(&ValueError{"reflect.Value.Int", iv.kind}) -} - -// CanInterface returns true if Interface can be used without panicking. -func (v Value) CanInterface() bool { - iv := v.internal() - if iv.kind == Invalid { - panic(&ValueError{"reflect.Value.CanInterface", iv.kind}) - } - // TODO(rsc): Check flagRO too. Decide what to do about asking for - // interface for a value obtained via an unexported field. - // If the field were of a known type, say chan int or *sync.Mutex, - // the caller could interfere with the data after getting the - // interface. But fmt.Print depends on being able to look. - // Now that reflect is more efficient the special cases in fmt - // might be less important. - return v.InternalMethod == 0 -} - -// Interface returns v's value as an interface{}. -// If v is a method obtained by invoking Value.Method -// (as opposed to Type.Method), Interface cannot return an -// interface value, so it panics. -func (v Value) Interface() interface{} { - return v.internal().Interface() -} - -func (iv internalValue) Interface() interface{} { - if iv.method { - panic("reflect.Value.Interface: cannot create interface value for method with bound receiver") - } - /* - if v.flag()&noExport != 0 { - panic("reflect.Value.Interface: cannot return value obtained from unexported struct field") - } - */ - - if iv.kind == Interface { - // Special case: return the element inside the interface. - // Won't recurse further because an interface cannot contain an interface. - if iv.IsNil() { - return nil - } - return iv.Elem().Interface() - } - - // Non-interface value. - var eface emptyInterface - eface.typ = iv.typ.runtimeType() - eface.word = iv.word - return *(*interface{})(unsafe.Pointer(&eface)) -} - -// InterfaceData returns the interface v's value as a uintptr pair. -// It panics if v's Kind is not Interface. -func (v Value) InterfaceData() [2]uintptr { - iv := v.internal() - iv.mustBe(Interface) - // We treat this as a read operation, so we allow - // it even for unexported data, because the caller - // has to import "unsafe" to turn it into something - // that can be abused. - return *(*[2]uintptr)(iv.addr) -} - -// IsNil returns true if v is a nil value. -// It panics if v's Kind is not Chan, Func, Interface, Map, Ptr, or Slice. -func (v Value) IsNil() bool { - return v.internal().IsNil() -} - -func (iv internalValue) IsNil() bool { - switch iv.kind { - case Chan, Func, Map, Ptr: - if iv.method { - panic("reflect: IsNil of method Value") - } - return iv.word == 0 - case Interface, Slice: - // Both interface and slice are nil if first word is 0. - return *(*uintptr)(iv.addr) == 0 - } - panic(&ValueError{"reflect.Value.IsNil", iv.kind}) -} - -// IsValid returns true if v represents a value. -// It returns false if v is the zero Value. -// If IsValid returns false, all other methods except String panic. -// Most functions and methods never return an invalid value. -// If one does, its documentation states the conditions explicitly. -func (v Value) IsValid() bool { - return v.Internal != nil -} - -// Kind returns v's Kind. -// If v is the zero Value (IsValid returns false), Kind returns Invalid. -func (v Value) Kind() Kind { - return v.internal().kind -} - -// Len returns v's length. -// It panics if v's Kind is not Array, Chan, Map, Slice, or String. -func (v Value) Len() int { - iv := v.internal() - switch iv.kind { - case Array: - return iv.typ.Len() - case Chan: - return int(chanlen(iv.word)) - case Map: - return int(maplen(iv.word)) - case Slice: - return (*SliceHeader)(iv.addr).Len - case String: - return (*StringHeader)(iv.addr).Len - } - panic(&ValueError{"reflect.Value.Len", iv.kind}) -} - -// MapIndex returns the value associated with key in the map v. -// It panics if v's Kind is not Map. -// It returns the zero Value if key is not found in the map or if v represents a nil map. -// As in Go, the key's value must be assignable to the map's key type. -func (v Value) MapIndex(key Value) Value { - iv := v.internal() - iv.mustBe(Map) - typ := iv.typ.toType() - - // Do not require ikey to be exported, so that DeepEqual - // and other programs can use all the keys returned by - // MapKeys as arguments to MapIndex. If either the map - // or the key is unexported, though, the result will be - // considered unexported. - - ikey := key.internal() - ikey = convertForAssignment("reflect.Value.MapIndex", nil, typ.Key(), ikey) - if iv.word == 0 { - return Value{} - } - - flag := (iv.flag | ikey.flag) & flagRO - elemType := typ.Elem() - elemWord, ok := mapaccess(iv.word, ikey.word) - if !ok { - return Value{} - } - return valueFromIword(flag, elemType, elemWord) -} - -// MapKeys returns a slice containing all the keys present in the map, -// in unspecified order. -// It panics if v's Kind is not Map. -// It returns an empty slice if v represents a nil map. -func (v Value) MapKeys() []Value { - iv := v.internal() - iv.mustBe(Map) - keyType := iv.typ.Key() - - flag := iv.flag & flagRO - m := iv.word - mlen := int32(0) - if m != 0 { - mlen = maplen(m) - } - it := mapiterinit(m) - a := make([]Value, mlen) - var i int - for i = 0; i < len(a); i++ { - keyWord, ok := mapiterkey(it) - if !ok { - break - } - a[i] = valueFromIword(flag, keyType, keyWord) - mapiternext(it) - } - return a[:i] -} - -// Method returns a function value corresponding to v's i'th method. -// The arguments to a Call on the returned function should not include -// a receiver; the returned function will always use v as the receiver. -// Method panics if i is out of range. -func (v Value) Method(i int) Value { - iv := v.internal() - if iv.kind == Invalid { - panic(&ValueError{"reflect.Value.Method", Invalid}) - } - if i < 0 || i >= iv.typ.NumMethod() { - panic("reflect: Method index out of range") - } - return Value{v.Internal, i + 1} -} - -// MethodByName returns a function value corresponding to the method -// of v with the given name. -// The arguments to a Call on the returned function should not include -// a receiver; the returned function will always use v as the receiver. -// It returns the zero Value if no method was found. -func (v Value) MethodByName(name string) Value { - iv := v.internal() - if iv.kind == Invalid { - panic(&ValueError{"reflect.Value.MethodByName", Invalid}) - } - m, ok := iv.typ.MethodByName(name) - if ok { - return Value{v.Internal, m.Index + 1} - } - return Value{} -} - -// NumField returns the number of fields in the struct v. -// It panics if v's Kind is not Struct. -func (v Value) NumField() int { - iv := v.internal() - iv.mustBe(Struct) - return iv.typ.NumField() -} - -// OverflowComplex returns true if the complex128 x cannot be represented by v's type. -// It panics if v's Kind is not Complex64 or Complex128. -func (v Value) OverflowComplex(x complex128) bool { - iv := v.internal() - switch iv.kind { - case Complex64: - return overflowFloat32(real(x)) || overflowFloat32(imag(x)) - case Complex128: - return false - } - panic(&ValueError{"reflect.Value.OverflowComplex", iv.kind}) -} - -// OverflowFloat returns true if the float64 x cannot be represented by v's type. -// It panics if v's Kind is not Float32 or Float64. -func (v Value) OverflowFloat(x float64) bool { - iv := v.internal() - switch iv.kind { - case Float32: - return overflowFloat32(x) - case Float64: - return false - } - panic(&ValueError{"reflect.Value.OverflowFloat", iv.kind}) -} - -func overflowFloat32(x float64) bool { - if x < 0 { - x = -x - } - return math.MaxFloat32 <= x && x <= math.MaxFloat64 -} - -// OverflowInt returns true if the int64 x cannot be represented by v's type. -// It panics if v's Kind is not Int, Int8, int16, Int32, or Int64. -func (v Value) OverflowInt(x int64) bool { - iv := v.internal() - switch iv.kind { - case Int, Int8, Int16, Int32, Int64: - bitSize := iv.typ.size * 8 - trunc := (x << (64 - bitSize)) >> (64 - bitSize) - return x != trunc - } - panic(&ValueError{"reflect.Value.OverflowInt", iv.kind}) -} - -// OverflowUint returns true if the uint64 x cannot be represented by v's type. -// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64. -func (v Value) OverflowUint(x uint64) bool { - iv := v.internal() - switch iv.kind { - case Uint, Uintptr, Uint8, Uint16, Uint32, Uint64: - bitSize := iv.typ.size * 8 - trunc := (x << (64 - bitSize)) >> (64 - bitSize) - return x != trunc - } - panic(&ValueError{"reflect.Value.OverflowUint", iv.kind}) -} - -// Pointer returns v's value as a uintptr. -// It returns uintptr instead of unsafe.Pointer so that -// code using reflect cannot obtain unsafe.Pointers -// without importing the unsafe package explicitly. -// It panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or UnsafePointer. -func (v Value) Pointer() uintptr { - iv := v.internal() - switch iv.kind { - case Chan, Func, Map, Ptr, UnsafePointer: - if iv.kind == Func && v.InternalMethod != 0 { - panic("reflect.Value.Pointer of method Value") - } - return uintptr(iv.word) - case Slice: - return (*SliceHeader)(iv.addr).Data - } - panic(&ValueError{"reflect.Value.Pointer", iv.kind}) -} - -// Recv receives and returns a value from the channel v. -// It panics if v's Kind is not Chan. -// The receive blocks until a value is ready. -// The boolean value ok is true if the value x corresponds to a send -// on the channel, false if it is a zero value received because the channel is closed. -func (v Value) Recv() (x Value, ok bool) { - iv := v.internal() - iv.mustBe(Chan) - iv.mustBeExported() - return iv.recv(false) -} - -// internal recv, possibly non-blocking (nb) -func (iv internalValue) recv(nb bool) (val Value, ok bool) { - t := iv.typ.toType() - if t.ChanDir()&RecvDir == 0 { - panic("recv on send-only channel") - } - ch := iv.word - if ch == 0 { - panic("recv on nil channel") - } - valWord, selected, ok := chanrecv(ch, nb) - if selected { - val = valueFromIword(0, t.Elem(), valWord) - } - return -} - -// Send sends x on the channel v. -// It panics if v's kind is not Chan or if x's type is not the same type as v's element type. -// As in Go, x's value must be assignable to the channel's element type. -func (v Value) Send(x Value) { - iv := v.internal() - iv.mustBe(Chan) - iv.mustBeExported() - iv.send(x, false) -} - -// internal send, possibly non-blocking -func (iv internalValue) send(x Value, nb bool) (selected bool) { - t := iv.typ.toType() - if t.ChanDir()&SendDir == 0 { - panic("send on recv-only channel") - } - ix := x.internal() - ix.mustBeExported() // do not let unexported x leak - ix = convertForAssignment("reflect.Value.Send", nil, t.Elem(), ix) - ch := iv.word - if ch == 0 { - panic("send on nil channel") - } - return chansend(ch, ix.word, nb) -} - -// Set assigns x to the value v. -// It panics if CanSet returns false. -// As in Go, x's value must be assignable to v's type. -func (v Value) Set(x Value) { - iv := v.internal() - ix := x.internal() - - iv.mustBeAssignable() - ix.mustBeExported() // do not let unexported x leak - - ix = convertForAssignment("reflect.Set", iv.addr, iv.typ, ix) - - n := ix.typ.size - if n <= ptrSize { - storeIword(iv.addr, ix.word, n) - } else { - memmove(iv.addr, ix.addr, n) - } -} - -// SetBool sets v's underlying value. -// It panics if v's Kind is not Bool or if CanSet() is false. -func (v Value) SetBool(x bool) { - iv := v.internal() - iv.mustBeAssignable() - iv.mustBe(Bool) - *(*bool)(iv.addr) = x -} - -// SetComplex sets v's underlying value to x. -// It panics if v's Kind is not Complex64 or Complex128, or if CanSet() is false. -func (v Value) SetComplex(x complex128) { - iv := v.internal() - iv.mustBeAssignable() - switch iv.kind { - default: - panic(&ValueError{"reflect.Value.SetComplex", iv.kind}) - case Complex64: - *(*complex64)(iv.addr) = complex64(x) - case Complex128: - *(*complex128)(iv.addr) = x - } -} - -// SetFloat sets v's underlying value to x. -// It panics if v's Kind is not Float32 or Float64, or if CanSet() is false. -func (v Value) SetFloat(x float64) { - iv := v.internal() - iv.mustBeAssignable() - switch iv.kind { - default: - panic(&ValueError{"reflect.Value.SetFloat", iv.kind}) - case Float32: - *(*float32)(iv.addr) = float32(x) - case Float64: - *(*float64)(iv.addr) = x - } -} - -// SetInt sets v's underlying value to x. -// It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64, or if CanSet() is false. -func (v Value) SetInt(x int64) { - iv := v.internal() - iv.mustBeAssignable() - switch iv.kind { - default: - panic(&ValueError{"reflect.Value.SetInt", iv.kind}) - case Int: - *(*int)(iv.addr) = int(x) - case Int8: - *(*int8)(iv.addr) = int8(x) - case Int16: - *(*int16)(iv.addr) = int16(x) - case Int32: - *(*int32)(iv.addr) = int32(x) - case Int64: - *(*int64)(iv.addr) = x - } -} - -// SetLen sets v's length to n. -// It panics if v's Kind is not Slice. -func (v Value) SetLen(n int) { - iv := v.internal() - iv.mustBeAssignable() - iv.mustBe(Slice) - s := (*SliceHeader)(iv.addr) - if n < 0 || n > int(s.Cap) { - panic("reflect: slice length out of range in SetLen") - } - s.Len = n -} - -// SetMapIndex sets the value associated with key in the map v to val. -// It panics if v's Kind is not Map. -// If val is the zero Value, SetMapIndex deletes the key from the map. -// As in Go, key's value must be assignable to the map's key type, -// and val's value must be assignable to the map's value type. -func (v Value) SetMapIndex(key, val Value) { - iv := v.internal() - ikey := key.internal() - ival := val.internal() - - iv.mustBe(Map) - iv.mustBeExported() - - ikey.mustBeExported() - ikey = convertForAssignment("reflect.Value.SetMapIndex", nil, iv.typ.Key(), ikey) - - if ival.kind != Invalid { - ival.mustBeExported() - ival = convertForAssignment("reflect.Value.SetMapIndex", nil, iv.typ.Elem(), ival) - } - - mapassign(iv.word, ikey.word, ival.word, ival.kind != Invalid) -} - -// SetUint sets v's underlying value to x. -// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64, or if CanSet() is false. -func (v Value) SetUint(x uint64) { - iv := v.internal() - iv.mustBeAssignable() - switch iv.kind { - default: - panic(&ValueError{"reflect.Value.SetUint", iv.kind}) - case Uint: - *(*uint)(iv.addr) = uint(x) - case Uint8: - *(*uint8)(iv.addr) = uint8(x) - case Uint16: - *(*uint16)(iv.addr) = uint16(x) - case Uint32: - *(*uint32)(iv.addr) = uint32(x) - case Uint64: - *(*uint64)(iv.addr) = x - case Uintptr: - *(*uintptr)(iv.addr) = uintptr(x) - } -} - -// SetPointer sets the unsafe.Pointer value v to x. -// It panics if v's Kind is not UnsafePointer. -func (v Value) SetPointer(x unsafe.Pointer) { - iv := v.internal() - iv.mustBeAssignable() - iv.mustBe(UnsafePointer) - *(*unsafe.Pointer)(iv.addr) = x -} - -// SetString sets v's underlying value to x. -// It panics if v's Kind is not String or if CanSet() is false. -func (v Value) SetString(x string) { - iv := v.internal() - iv.mustBeAssignable() - iv.mustBe(String) - *(*string)(iv.addr) = x -} - -// Slice returns a slice of v. -// It panics if v's Kind is not Array or Slice. -func (v Value) Slice(beg, end int) Value { - iv := v.internal() - if iv.kind != Array && iv.kind != Slice { - panic(&ValueError{"reflect.Value.Slice", iv.kind}) - } - cap := v.Cap() - if beg < 0 || end < beg || end > cap { - panic("reflect.Value.Slice: slice index out of bounds") - } - var typ Type - var base uintptr - switch iv.kind { - case Array: - if iv.flag&flagAddr == 0 { - panic("reflect.Value.Slice: slice of unaddressable array") - } - typ = toType((*arrayType)(unsafe.Pointer(iv.typ)).slice) - base = uintptr(iv.addr) - case Slice: - typ = iv.typ.toType() - base = (*SliceHeader)(iv.addr).Data - } - s := new(SliceHeader) - s.Data = base + uintptr(beg)*typ.Elem().Size() - s.Len = end - beg - s.Cap = cap - beg - return valueFromAddr(iv.flag&flagRO, typ, unsafe.Pointer(s)) -} - -// String returns the string v's underlying value, as a string. -// String is a special case because of Go's String method convention. -// Unlike the other getters, it does not panic if v's Kind is not String. -// Instead, it returns a string of the form "<T value>" where T is v's type. -func (v Value) String() string { - iv := v.internal() - switch iv.kind { - case Invalid: - return "<invalid Value>" - case String: - return *(*string)(iv.addr) - } - return "<" + iv.typ.String() + " Value>" -} - -// TryRecv attempts to receive a value from the channel v but will not block. -// It panics if v's Kind is not Chan. -// If the receive cannot finish without blocking, x is the zero Value. -// The boolean ok is true if the value x corresponds to a send -// on the channel, false if it is a zero value received because the channel is closed. -func (v Value) TryRecv() (x Value, ok bool) { - iv := v.internal() - iv.mustBe(Chan) - iv.mustBeExported() - return iv.recv(true) -} - -// TrySend attempts to send x on the channel v but will not block. -// It panics if v's Kind is not Chan. -// It returns true if the value was sent, false otherwise. -// As in Go, x's value must be assignable to the channel's element type. -func (v Value) TrySend(x Value) bool { - iv := v.internal() - iv.mustBe(Chan) - iv.mustBeExported() - return iv.send(x, true) -} - -// Type returns v's type. -func (v Value) Type() Type { - t := v.internal().typ - if t == nil { - panic(&ValueError{"reflect.Value.Type", Invalid}) - } - return t.toType() -} - -// Uint returns v's underlying value, as a uint64. -// It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64. -func (v Value) Uint() uint64 { - iv := v.internal() - switch iv.kind { - case Uint: - return uint64(*(*uint)(unsafe.Pointer(&iv.word))) - case Uint8: - return uint64(*(*uint8)(unsafe.Pointer(&iv.word))) - case Uint16: - return uint64(*(*uint16)(unsafe.Pointer(&iv.word))) - case Uint32: - return uint64(*(*uint32)(unsafe.Pointer(&iv.word))) - case Uintptr: - return uint64(*(*uintptr)(unsafe.Pointer(&iv.word))) - case Uint64: - if iv.addr == nil { - return *(*uint64)(unsafe.Pointer(&iv.word)) - } - return *(*uint64)(iv.addr) - } - panic(&ValueError{"reflect.Value.Uint", iv.kind}) -} - -// UnsafeAddr returns a pointer to v's data. -// It is for advanced clients that also import the "unsafe" package. -// It panics if v is not addressable. -func (v Value) UnsafeAddr() uintptr { - iv := v.internal() - if iv.kind == Invalid { - panic(&ValueError{"reflect.Value.UnsafeAddr", iv.kind}) - } - if iv.flag&flagAddr == 0 { - panic("reflect.Value.UnsafeAddr of unaddressable value") - } - return uintptr(iv.addr) -} - -// StringHeader is the runtime representation of a string. -// It cannot be used safely or portably. -type StringHeader struct { - Data uintptr - Len int -} - -// SliceHeader is the runtime representation of a slice. -// It cannot be used safely or portably. -type SliceHeader struct { - Data uintptr - Len int - Cap int -} - -func typesMustMatch(what string, t1, t2 Type) { - if t1 != t2 { - panic("reflect: " + what + ": " + t1.String() + " != " + t2.String()) - } -} - -// grow grows the slice s so that it can hold extra more values, allocating -// more capacity if needed. It also returns the old and new slice lengths. -func grow(s Value, extra int) (Value, int, int) { - i0 := s.Len() - i1 := i0 + extra - if i1 < i0 { - panic("reflect.Append: slice overflow") - } - m := s.Cap() - if i1 <= m { - return s.Slice(0, i1), i0, i1 - } - if m == 0 { - m = extra - } else { - for m < i1 { - if i0 < 1024 { - m += m - } else { - m += m / 4 - } - } - } - t := MakeSlice(s.Type(), i1, m) - Copy(t, s) - return t, i0, i1 -} - -// Append appends the values x to a slice s and returns the resulting slice. -// As in Go, each x's value must be assignable to the slice's element type. -func Append(s Value, x ...Value) Value { - s.internal().mustBe(Slice) - s, i0, i1 := grow(s, len(x)) - for i, j := i0, 0; i < i1; i, j = i+1, j+1 { - s.Index(i).Set(x[j]) - } - return s -} - -// AppendSlice appends a slice t to a slice s and returns the resulting slice. -// The slices s and t must have the same element type. -func AppendSlice(s, t Value) Value { - s.internal().mustBe(Slice) - t.internal().mustBe(Slice) - typesMustMatch("reflect.AppendSlice", s.Type().Elem(), t.Type().Elem()) - s, i0, i1 := grow(s, t.Len()) - Copy(s.Slice(i0, i1), t) - return s -} - -// Copy copies the contents of src into dst until either -// dst has been filled or src has been exhausted. -// It returns the number of elements copied. -// Dst and src each must have kind Slice or Array, and -// dst and src must have the same element type. -func Copy(dst, src Value) int { - idst := dst.internal() - isrc := src.internal() - - if idst.kind != Array && idst.kind != Slice { - panic(&ValueError{"reflect.Copy", idst.kind}) - } - if idst.kind == Array { - idst.mustBeAssignable() - } - idst.mustBeExported() - if isrc.kind != Array && isrc.kind != Slice { - panic(&ValueError{"reflect.Copy", isrc.kind}) - } - isrc.mustBeExported() - - de := idst.typ.Elem() - se := isrc.typ.Elem() - typesMustMatch("reflect.Copy", de, se) - - n := dst.Len() - if sn := src.Len(); n > sn { - n = sn - } - - // If sk is an in-line array, cannot take its address. - // Instead, copy element by element. - if isrc.addr == nil { - for i := 0; i < n; i++ { - dst.Index(i).Set(src.Index(i)) - } - return n - } - - // Copy via memmove. - var da, sa unsafe.Pointer - if idst.kind == Array { - da = idst.addr - } else { - da = unsafe.Pointer((*SliceHeader)(idst.addr).Data) - } - if isrc.kind == Array { - sa = isrc.addr - } else { - sa = unsafe.Pointer((*SliceHeader)(isrc.addr).Data) - } - memmove(da, sa, uintptr(n)*de.Size()) - return n -} - -/* - * constructors - */ - -// MakeSlice creates a new zero-initialized slice value -// for the specified slice type, length, and capacity. -func MakeSlice(typ Type, len, cap int) Value { - if typ.Kind() != Slice { - panic("reflect: MakeSlice of non-slice type") - } - s := &SliceHeader{ - Data: uintptr(unsafe.NewArray(typ.Elem(), cap)), - Len: len, - Cap: cap, - } - return valueFromAddr(0, typ, unsafe.Pointer(s)) -} - -// MakeChan creates a new channel with the specified type and buffer size. -func MakeChan(typ Type, buffer int) Value { - if typ.Kind() != Chan { - panic("reflect: MakeChan of non-chan type") - } - if buffer < 0 { - panic("MakeChan: negative buffer size") - } - if typ.ChanDir() != BothDir { - panic("MakeChan: unidirectional channel type") - } - ch := makechan(typ.runtimeType(), uint32(buffer)) - return valueFromIword(0, typ, ch) -} - -// MakeMap creates a new map of the specified type. -func MakeMap(typ Type) Value { - if typ.Kind() != Map { - panic("reflect: MakeMap of non-map type") - } - m := makemap(typ.runtimeType()) - return valueFromIword(0, typ, m) -} - -// Indirect returns the value that v points to. -// If v is a nil pointer, Indirect returns a nil Value. -// If v is not a pointer, Indirect returns v. -func Indirect(v Value) Value { - if v.Kind() != Ptr { - return v - } - return v.Elem() -} - -// ValueOf returns a new Value initialized to the concrete value -// stored in the interface i. ValueOf(nil) returns the zero Value. -func ValueOf(i interface{}) Value { - if i == nil { - return Value{} - } - // For an interface value with the noAddr bit set, - // the representation is identical to an empty interface. - eface := *(*emptyInterface)(unsafe.Pointer(&i)) - return packValue(0, eface.typ, eface.word) -} - -// Zero returns a Value representing a zero value for the specified type. -// The result is different from the zero value of the Value struct, -// which represents no value at all. -// For example, Zero(TypeOf(42)) returns a Value with Kind Int and value 0. -func Zero(typ Type) Value { - if typ == nil { - panic("reflect: Zero(nil)") - } - if typ.Size() <= ptrSize { - return valueFromIword(0, typ, 0) - } - return valueFromAddr(0, typ, unsafe.New(typ)) -} - -// New returns a Value representing a pointer to a new zero value -// for the specified type. That is, the returned Value's Type is PtrTo(t). -func New(typ Type) Value { - if typ == nil { - panic("reflect: New(nil)") - } - ptr := unsafe.New(typ) - return valueFromIword(0, PtrTo(typ), iword(ptr)) -} - -// convertForAssignment -func convertForAssignment(what string, addr unsafe.Pointer, dst Type, iv internalValue) internalValue { - if iv.method { - panic(what + ": cannot assign method value to type " + dst.String()) - } - - dst1 := dst.(*commonType) - if directlyAssignable(dst1, iv.typ) { - // Overwrite type so that they match. - // Same memory layout, so no harm done. - iv.typ = dst1 - return iv - } - if implements(dst1, iv.typ) { - if addr == nil { - addr = unsafe.Pointer(new(interface{})) - } - x := iv.Interface() - if dst.NumMethod() == 0 { - *(*interface{})(addr) = x - } else { - ifaceE2I(dst1.runtimeType(), x, addr) - } - iv.addr = addr - iv.word = iword(addr) - iv.typ = dst1 - return iv - } - - // Failed. - panic(what + ": value of type " + iv.typ.String() + " is not assignable to type " + dst.String()) -} - -// implemented in ../pkg/runtime -func chancap(ch iword) int32 -func chanclose(ch iword) -func chanlen(ch iword) int32 -func chanrecv(ch iword, nb bool) (val iword, selected, received bool) -func chansend(ch iword, val iword, nb bool) bool - -func makechan(typ *runtime.Type, size uint32) (ch iword) -func makemap(t *runtime.Type) iword -func mapaccess(m iword, key iword) (val iword, ok bool) -func mapassign(m iword, key, val iword, ok bool) -func mapiterinit(m iword) *byte -func mapiterkey(it *byte) (key iword, ok bool) -func mapiternext(it *byte) -func maplen(m iword) int32 - -func call(fn, arg unsafe.Pointer, n uint32) -func ifaceE2I(t *runtime.Type, src interface{}, dst unsafe.Pointer) |