diff options
Diffstat (limited to 'src/pkg/json/struct.go')
-rw-r--r-- | src/pkg/json/struct.go | 481 |
1 files changed, 0 insertions, 481 deletions
diff --git a/src/pkg/json/struct.go b/src/pkg/json/struct.go deleted file mode 100644 index 9be89cbd6..000000000 --- a/src/pkg/json/struct.go +++ /dev/null @@ -1,481 +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. - -// Marshalling and unmarshalling of -// JSON data into Go structs using reflection. - -package json - -import ( - "bytes" - "fmt" - "io" - "os" - "reflect" - "strings" -) - -type structBuilder struct { - val reflect.Value - - // if map_ != nil, write val to map_[key] on each change - map_ *reflect.MapValue - key reflect.Value -} - -var nobuilder *structBuilder - -func isfloat(v reflect.Value) bool { - switch v.(type) { - case *reflect.FloatValue, *reflect.Float32Value, *reflect.Float64Value: - return true - } - return false -} - -func setfloat(v reflect.Value, f float64) { - 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 := 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)) - } -} - -// If updating b.val is not enough to update the original, -// copy a changed b.val out to the original. -func (b *structBuilder) Flush() { - if b == nil { - return - } - if b.map_ != nil { - b.map_.SetElem(b.key, b.val) - } -} - -func (b *structBuilder) Int64(i int64) { - if b == nil { - return - } - v := b.val - if isfloat(v) { - setfloat(v, float64(i)) - } else { - setint(v, i) - } -} - -func (b *structBuilder) Uint64(i uint64) { - if b == nil { - return - } - v := b.val - if isfloat(v) { - setfloat(v, float64(i)) - } else { - setint(v, int64(i)) - } -} - -func (b *structBuilder) Float64(f float64) { - if b == nil { - return - } - v := b.val - if isfloat(v) { - setfloat(v, f) - } else { - setint(v, int64(f)) - } -} - -func (b *structBuilder) Null() {} - -func (b *structBuilder) String(s string) { - if b == nil { - return - } - if v, ok := b.val.(*reflect.StringValue); ok { - v.Set(s) - } -} - -func (b *structBuilder) Bool(tf bool) { - if b == nil { - return - } - if v, ok := b.val.(*reflect.BoolValue); ok { - v.Set(tf) - } -} - -func (b *structBuilder) Array() { - if b == nil { - return - } - if v, ok := b.val.(*reflect.SliceValue); ok { - if v.IsNil() { - v.Set(reflect.MakeSlice(v.Type().(*reflect.SliceType), 0, 8)) - } - } -} - -func (b *structBuilder) Elem(i int) Builder { - if b == nil || i < 0 { - return nobuilder - } - switch v := b.val.(type) { - case *reflect.ArrayValue: - if i < v.Len() { - return &structBuilder{val: v.Elem(i)} - } - 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{val: v.Elem(i)} - } - } - return nobuilder -} - -func (b *structBuilder) Map() { - if b == nil { - return - } - if v, ok := b.val.(*reflect.PtrValue); ok && v.IsNil() { - if v.IsNil() { - v.PointTo(reflect.MakeZero(v.Type().(*reflect.PtrType).Elem())) - b.Flush() - } - b.map_ = nil - b.val = v.Elem() - } - if v, ok := b.val.(*reflect.MapValue); ok && v.IsNil() { - v.Set(reflect.MakeMap(v.Type().(*reflect.MapType))) - } -} - -func (b *structBuilder) Key(k string) Builder { - if b == nil { - return nobuilder - } - switch v := reflect.Indirect(b.val).(type) { - case *reflect.StructValue: - t := v.Type().(*reflect.StructType) - // Case-insensitive field lookup. - k = strings.ToLower(k) - for i := 0; i < t.NumField(); i++ { - if strings.ToLower(t.Field(i).Name) == k { - return &structBuilder{val: v.Field(i)} - } - } - case *reflect.MapValue: - t := v.Type().(*reflect.MapType) - if t.Key() != reflect.Typeof(k) { - break - } - key := reflect.NewValue(k) - elem := v.Elem(key) - if elem == nil { - v.SetElem(key, reflect.MakeZero(t.Elem())) - elem = v.Elem(key) - } - return &structBuilder{val: elem, map_: v, key: key} - } - return nobuilder -} - -// Unmarshal parses the JSON syntax string s and fills in -// an arbitrary struct or slice pointed at by val. -// It uses the reflect package to assign to fields -// and arrays embedded in val. Well-formed data that does not fit -// into the struct is discarded. -// -// For example, given these definitions: -// -// type Email struct { -// Where string -// Addr string -// } -// -// type Result struct { -// Name string -// Phone string -// Email []Email -// } -// -// var r = Result{ "name", "phone", nil } -// -// unmarshalling the JSON syntax string -// -// { -// "email": [ -// { -// "where": "home", -// "addr": "gre@example.com" -// }, -// { -// "where": "work", -// "addr": "gre@work.com" -// } -// ], -// "name": "Grace R. Emlin", -// "address": "123 Main Street" -// } -// -// via Unmarshal(s, &r) is equivalent to assigning -// -// r = Result{ -// "Grace R. Emlin", // name -// "phone", // no phone given -// []Email{ -// Email{ "home", "gre@example.com" }, -// Email{ "work", "gre@work.com" }, -// }, -// } -// -// Note that the field r.Phone has not been modified and -// that the JSON field "address" was discarded. -// -// Because Unmarshal uses the reflect package, it can only -// assign to upper case fields. Unmarshal uses a case-insensitive -// comparison to match JSON field names to struct field names. -// -// To unmarshal a top-level JSON array, pass in a pointer to an empty -// slice of the correct type. -// -// On success, Unmarshal returns with ok set to true. -// On a syntax error, it returns with ok set to false and errtok -// set to the offending token. -func Unmarshal(s string, val interface{}) (ok bool, errtok string) { - v := reflect.NewValue(val) - var b *structBuilder - - // If val is a pointer to a slice, we append to the slice. - if ptr, ok := v.(*reflect.PtrValue); ok { - if slice, ok := ptr.Elem().(*reflect.SliceValue); ok { - b = &structBuilder{val: slice} - } - } - - if b == nil { - b = &structBuilder{val: v} - } - - ok, _, errtok = Parse(s, b) - if !ok { - return false, errtok - } - return true, "" -} - -type MarshalError struct { - T reflect.Type -} - -func (e *MarshalError) String() string { - return "json cannot encode value of type " + e.T.String() -} - -type writeState struct { - bytes.Buffer - indent string - newlines bool - depth int -} - -func (s *writeState) descend(bra byte) { - s.depth++ - s.WriteByte(bra) -} - -func (s *writeState) ascend(ket byte) { - s.depth-- - s.writeIndent() - s.WriteByte(ket) -} - -func (s *writeState) writeIndent() { - if s.newlines { - s.WriteByte('\n') - } - for i := 0; i < s.depth; i++ { - s.WriteString(s.indent) - } -} - -func (s *writeState) writeArrayOrSlice(val reflect.ArrayOrSliceValue) { - s.descend('[') - - for i := 0; i < val.Len(); i++ { - s.writeIndent() - s.writeValue(val.Elem(i)) - if i < val.Len()-1 { - s.WriteByte(',') - } - } - - s.ascend(']') -} - -func (s *writeState) writeMap(val *reflect.MapValue) { - key := val.Type().(*reflect.MapType).Key() - if _, ok := key.(*reflect.StringType); !ok { - panic(&MarshalError{val.Type()}) - } - - s.descend('{') - - keys := val.Keys() - for i := 0; i < len(keys); i++ { - s.writeIndent() - fmt.Fprintf(s, "%s:", Quote(keys[i].(*reflect.StringValue).Get())) - s.writeValue(val.Elem(keys[i])) - if i < len(keys)-1 { - s.WriteByte(',') - } - } - - s.ascend('}') -} - -func (s *writeState) writeStruct(val *reflect.StructValue) { - s.descend('{') - - typ := val.Type().(*reflect.StructType) - - for i := 0; i < val.NumField(); i++ { - s.writeIndent() - fmt.Fprintf(s, "%s:", Quote(typ.Field(i).Name)) - s.writeValue(val.Field(i)) - if i < val.NumField()-1 { - s.WriteByte(',') - } - } - - s.ascend('}') -} - -func (s *writeState) writeValue(val reflect.Value) { - if val == nil { - fmt.Fprint(s, "null") - return - } - - switch v := val.(type) { - case *reflect.StringValue: - fmt.Fprint(s, Quote(v.Get())) - case *reflect.ArrayValue: - s.writeArrayOrSlice(v) - case *reflect.SliceValue: - s.writeArrayOrSlice(v) - case *reflect.MapValue: - s.writeMap(v) - case *reflect.StructValue: - s.writeStruct(v) - case *reflect.ChanValue, - *reflect.UnsafePointerValue, - *reflect.FuncValue: - panic(&MarshalError{val.Type()}) - case *reflect.InterfaceValue: - if v.IsNil() { - fmt.Fprint(s, "null") - } else { - s.writeValue(v.Elem()) - } - case *reflect.PtrValue: - if v.IsNil() { - fmt.Fprint(s, "null") - } else { - s.writeValue(v.Elem()) - } - case *reflect.UintptrValue: - fmt.Fprintf(s, "%d", v.Get()) - case *reflect.Uint64Value: - fmt.Fprintf(s, "%d", v.Get()) - case *reflect.Uint32Value: - fmt.Fprintf(s, "%d", v.Get()) - case *reflect.Uint16Value: - fmt.Fprintf(s, "%d", v.Get()) - case *reflect.Uint8Value: - fmt.Fprintf(s, "%d", v.Get()) - default: - value := val.(reflect.Value) - fmt.Fprintf(s, "%#v", value.Interface()) - } -} - -func (s *writeState) marshal(w io.Writer, val interface{}) (err os.Error) { - defer func() { - if e := recover(); e != nil { - err = e.(*MarshalError) - } - }() - s.writeValue(reflect.NewValue(val)) - if s.newlines { - s.WriteByte('\n') - } - _, err = s.WriteTo(w) - return -} - -// Marshal writes the JSON encoding of val to w. -// -// Due to limitations in JSON, val cannot include cyclic data -// structures, channels, functions, or maps. -func Marshal(w io.Writer, val interface{}) os.Error { - s := &writeState{indent: "", newlines: false, depth: 0} - return s.marshal(w, val) -} - -// MarshalIndent writes the JSON encoding of val to w, -// indenting nested values using the indent string. -// -// Due to limitations in JSON, val cannot include cyclic data -// structures, channels, functions, or maps. -func MarshalIndent(w io.Writer, val interface{}, indent string) os.Error { - s := &writeState{indent: indent, newlines: true, depth: 0} - return s.marshal(w, val) -} |