import (
"json";
"reflect";
+ "strings";
)
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));
}
}
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);
}
}
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));
}
}
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));
}
}
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);
}
}
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);
}
}
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));
}
}
}
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()))
}
}
}
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) }
}
}
}
)
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 =
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);
}
}