1
0
mirror of https://github.com/golang/go synced 2024-10-03 06:21:21 -06:00

json: use new reflect interface (CL 31107)

R=r
DELTA=192  (52 added, 43 deleted, 97 changed)
OCL=31116
CL=31286
This commit is contained in:
Russ Cox 2009-07-07 11:04:18 -07:00
parent 65dbe76532
commit 1b35969871
2 changed files with 134 additions and 125 deletions

View File

@ -10,6 +10,7 @@ package json
import (
"json";
"reflect";
"strings";
)
type _StructBuilder struct {
@ -18,39 +19,51 @@ type _StructBuilder struct {
var nobuilder *_StructBuilder
func isfloat(v reflect.Value) bool {
switch v := v.(type) {
case *reflect.FloatValue:
return true;
case *reflect.Float32Value:
return true;
case *reflect.Float64Value:
return true;
}
return false;
}
func setfloat(v reflect.Value, f float64) {
switch v.Kind() {
case reflect.FloatKind:
v.(reflect.FloatValue).Set(float(f));
case reflect.Float32Kind:
v.(reflect.Float32Value).Set(float32(f));
case reflect.Float64Kind:
v.(reflect.Float64Value).Set(float64(f));
switch v := v.(type) {
case *reflect.FloatValue:
v.Set(float(f));
case *reflect.Float32Value:
v.Set(float32(f));
case *reflect.Float64Value:
v.Set(float64(f));
}
}
func setint(v reflect.Value, i int64) {
switch v.Kind() {
case reflect.IntKind:
v.(reflect.IntValue).Set(int(i));
case reflect.Int8Kind:
v.(reflect.Int8Value).Set(int8(i));
case reflect.Int16Kind:
v.(reflect.Int16Value).Set(int16(i));
case reflect.Int32Kind:
v.(reflect.Int32Value).Set(int32(i));
case reflect.Int64Kind:
v.(reflect.Int64Value).Set(int64(i));
case reflect.UintKind:
v.(reflect.UintValue).Set(uint(i));
case reflect.Uint8Kind:
v.(reflect.Uint8Value).Set(uint8(i));
case reflect.Uint16Kind:
v.(reflect.Uint16Value).Set(uint16(i));
case reflect.Uint32Kind:
v.(reflect.Uint32Value).Set(uint32(i));
case reflect.Uint64Kind:
v.(reflect.Uint64Value).Set(uint64(i));
switch v := v.(type) {
case *reflect.IntValue:
v.Set(int(i));
case *reflect.Int8Value:
v.Set(int8(i));
case *reflect.Int16Value:
v.Set(int16(i));
case *reflect.Int32Value:
v.Set(int32(i));
case *reflect.Int64Value:
v.Set(int64(i));
case *reflect.UintValue:
v.Set(uint(i));
case *reflect.Uint8Value:
v.Set(uint8(i));
case *reflect.Uint16Value:
v.Set(uint16(i));
case *reflect.Uint32Value:
v.Set(uint32(i));
case *reflect.Uint64Value:
v.Set(uint64(i));
}
}
@ -59,10 +72,9 @@ func (b *_StructBuilder) Int64(i int64) {
return
}
v := b.val;
switch v.Kind() {
case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind:
if isfloat(v) {
setfloat(v, float64(i));
default:
} else {
setint(v, i);
}
}
@ -72,10 +84,9 @@ func (b *_StructBuilder) Uint64(i uint64) {
return
}
v := b.val;
switch v.Kind() {
case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind:
if isfloat(v) {
setfloat(v, float64(i));
default:
} else {
setint(v, int64(i));
}
}
@ -85,10 +96,9 @@ func (b *_StructBuilder) Float64(f float64) {
return
}
v := b.val;
switch v.Kind() {
case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind:
if isfloat(v) {
setfloat(v, f);
default:
} else {
setint(v, int64(f));
}
}
@ -100,8 +110,8 @@ func (b *_StructBuilder) String(s string) {
if b == nil {
return
}
if v := b.val; v.Kind() == reflect.StringKind {
v.(reflect.StringValue).Set(s);
if v, ok := b.val.(*reflect.StringValue); ok {
v.Set(s);
}
}
@ -109,8 +119,8 @@ func (b *_StructBuilder) Bool(tf bool) {
if b == nil {
return
}
if v := b.val; v.Kind() == reflect.BoolKind {
v.(reflect.BoolValue).Set(tf);
if v, ok := b.val.(*reflect.BoolValue); ok {
v.Set(tf);
}
}
@ -118,10 +128,9 @@ func (b *_StructBuilder) Array() {
if b == nil {
return
}
if v := b.val; v.Kind() == reflect.ArrayKind {
av := v.(reflect.ArrayValue);
if av.IsSlice() && av.IsNil() {
av.Set(reflect.NewSliceValue(av.Type().(reflect.ArrayType), 0, 8));
if v, ok := b.val.(*reflect.SliceValue); ok {
if v.IsNil() {
v.Set(reflect.MakeSlice(v.Type().(*reflect.SliceType), 0, 8));
}
}
}
@ -130,41 +139,41 @@ func (b *_StructBuilder) Elem(i int) Builder {
if b == nil || i < 0 {
return nobuilder
}
v := b.val;
if v.Kind() != reflect.ArrayKind {
return nobuilder
}
av := v.(reflect.ArrayValue);
if av.IsSlice() && i > av.Cap() {
n := av.Cap();
if n < 8 {
n = 8
switch v := b.val.(type) {
case *reflect.ArrayValue:
if i < v.Len() {
return &_StructBuilder{ v.Elem(i) }
}
for n <= i {
n *= 2
case *reflect.SliceValue:
if i > v.Cap() {
n := v.Cap();
if n < 8 {
n = 8
}
for n <= i {
n *= 2
}
nv := reflect.MakeSlice(v.Type().(*reflect.SliceType), v.Len(), n);
reflect.ArrayCopy(nv, v);
v.Set(nv);
}
if v.Len() <= i && i < v.Cap() {
v.SetLen(i+1);
}
if i < v.Len() {
return &_StructBuilder{ v.Elem(i) }
}
av1 := reflect.NewSliceValue(av.Type().(reflect.ArrayType), av.Len(), n);
av1.CopyFrom(av, av.Len());
av.Set(av1);
}
// Array was grown above, or is fixed size.
if av.Len() <= i && i < av.Cap() {
av.SetLen(i+1);
}
if i < av.Len() {
return &_StructBuilder{ av.Elem(i) }
}
return nobuilder
return nobuilder;
}
func (b *_StructBuilder) Map() {
if b == nil {
return
}
if v := b.val; v.Kind() == reflect.PtrKind {
pv := v.(reflect.PtrValue);
if pv.Get() == nil {
pv.SetSub(reflect.NewZeroValue(pv.Type().(reflect.PtrType).Sub()))
if v, ok := b.val.(*reflect.PtrValue); ok {
if v.IsNil() {
v.PointTo(reflect.MakeZero(v.Type().(*reflect.PtrType).Elem()))
}
}
}
@ -173,17 +182,17 @@ func (b *_StructBuilder) Key(k string) Builder {
if b == nil {
return nobuilder
}
v := b.val;
if v.Kind() == reflect.PtrKind {
v = v.(reflect.PtrValue).Sub();
}
if v.Kind() == reflect.StructKind {
sv := v.(reflect.StructValue);
t := v.Type().(reflect.StructType);
for i := 0; i < t.Len(); i++ {
name, typ, tag, off := t.Field(i);
if k == name {
return &_StructBuilder{ sv.Field(i) }
if v, ok := reflect.Indirect(b.val).(*reflect.StructValue); ok {
t := v.Type().(*reflect.StructType);
for i := 0; i < t.NumField(); i++ {
if t.Field(i).Name == k {
return &_StructBuilder{ v.Field(i) }
}
}
// Again, case-insensitive.
for i := 0; i < t.NumField(); i++ {
if strings.LowerASCII(t.Field(i).Name) == k {
return &_StructBuilder{ v.Field(i) }
}
}
}

View File

@ -10,24 +10,24 @@ import (
)
type _MyStruct struct {
t bool;
f bool;
s string;
i8 int8;
i16 int16;
i32 int32;
i64 int64;
u8 uint8;
u16 uint16;
u32 uint32;
u64 uint64;
i int;
u uint;
fl float;
fl32 float32;
fl64 float64;
a []string;
my *_MyStruct;
T bool;
F bool;
S string;
I8 int8;
I16 int16;
I32 int32;
I64 int64;
U8 uint8;
U16 uint16;
U32 uint32;
U64 uint64;
I int;
U uint;
Fl float;
Fl32 float32;
Fl64 float64;
A []string;
My *_MyStruct;
};
const _Encoded =
@ -48,35 +48,35 @@ func _Check(t *testing.T, ok bool, name string, v interface{}) {
func TestUnmarshal(t *testing.T) {
var m _MyStruct;
m.f = true;
m.F = true;
ok, errtok := Unmarshal(_Encoded, &m);
if !ok {
t.Fatalf("Unmarshal failed near %s", errtok);
}
_Check(t, m.t==true, "t", m.t);
_Check(t, m.f==false, "f", m.f);
_Check(t, m.s=="abc", "s", m.s);
_Check(t, m.i8==1, "i8", m.i8);
_Check(t, m.i16==2, "i16", m.i16);
_Check(t, m.i32==3, "i32", m.i32);
_Check(t, m.i64==4, "i64", m.i64);
_Check(t, m.u8==5, "u8", m.u8);
_Check(t, m.u16==6, "u16", m.u16);
_Check(t, m.u32==7, "u32", m.u32);
_Check(t, m.u64==8, "u64", m.u64);
_Check(t, m.i==-9, "i", m.i);
_Check(t, m.u==10, "u", m.u);
_Check(t, m.fl==11.5, "fl", m.fl);
_Check(t, m.fl32==12.25, "fl32", m.fl32);
_Check(t, m.fl64==13.75, "fl64", m.fl64);
_Check(t, m.a!=nil, "a", m.a);
if m.a != nil {
_Check(t, m.a[0]=="x", "a[0]", m.a[0]);
_Check(t, m.a[1]=="y", "a[1]", m.a[1]);
_Check(t, m.a[2]=="z", "a[2]", m.a[2]);
_Check(t, m.T==true, "t", m.T);
_Check(t, m.F==false, "f", m.F);
_Check(t, m.S=="abc", "s", m.S);
_Check(t, m.I8==1, "i8", m.I8);
_Check(t, m.I16==2, "i16", m.I16);
_Check(t, m.I32==3, "i32", m.I32);
_Check(t, m.I64==4, "i64", m.I64);
_Check(t, m.U8==5, "u8", m.U8);
_Check(t, m.U16==6, "u16", m.U16);
_Check(t, m.U32==7, "u32", m.U32);
_Check(t, m.U64==8, "u64", m.U64);
_Check(t, m.I==-9, "i", m.I);
_Check(t, m.U==10, "u", m.U);
_Check(t, m.Fl==11.5, "fl", m.Fl);
_Check(t, m.Fl32==12.25, "fl32", m.Fl32);
_Check(t, m.Fl64==13.75, "fl64", m.Fl64);
_Check(t, m.A!=nil, "a", m.A);
if m.A != nil {
_Check(t, m.A[0]=="x", "a[0]", m.A[0]);
_Check(t, m.A[1]=="y", "a[1]", m.A[1]);
_Check(t, m.A[2]=="z", "a[2]", m.A[2]);
}
_Check(t, m.my!=nil, "my", m.my);
if m.my != nil {
_Check(t, m.my.s=="subguy", "my.s", m.my.s);
_Check(t, m.My!=nil, "my", m.My);
if m.My != nil {
_Check(t, m.My.S=="subguy", "my.s", m.My.S);
}
}