diff options
| author | Ondřej Surý <ondrej@sury.org> | 2011-04-20 15:44:41 +0200 | 
|---|---|---|
| committer | Ondřej Surý <ondrej@sury.org> | 2011-04-20 15:44:41 +0200 | 
| commit | 50104cc32a498f7517a51c8dc93106c51c7a54b4 (patch) | |
| tree | 47af80be259cc7c45d0eaec7d42e61fa38c8e4fb /src/pkg/json/decode.go | |
| parent | c072558b90f1bbedc2022b0f30c8b1ac4712538e (diff) | |
| download | golang-50104cc32a498f7517a51c8dc93106c51c7a54b4.tar.gz | |
Imported Upstream version 2011.03.07.1upstream/2011.03.07.1
Diffstat (limited to 'src/pkg/json/decode.go')
| -rw-r--r-- | src/pkg/json/decode.go | 72 | 
1 files changed, 59 insertions, 13 deletions
| diff --git a/src/pkg/json/decode.go b/src/pkg/json/decode.go index ff91dd83c..501230c0c 100644 --- a/src/pkg/json/decode.go +++ b/src/pkg/json/decode.go @@ -9,6 +9,7 @@ package json  import (  	"container/vector" +	"encoding/base64"  	"os"  	"reflect"  	"runtime" @@ -466,13 +467,15 @@ func (d *decodeState) object(v reflect.Value) {  		} else {  			var f reflect.StructField  			var ok bool -			// First try for field with that tag.  			st := sv.Type().(*reflect.StructType) -			for i := 0; i < sv.NumField(); i++ { -				f = st.Field(i) -				if f.Tag == key { -					ok = true -					break +			// First try for field with that tag. +			if isValidTag(key) { +				for i := 0; i < sv.NumField(); i++ { +					f = st.Field(i) +					if f.Tag == key { +						ok = true +						break +					}  				}  			}  			if !ok { @@ -568,17 +571,29 @@ func (d *decodeState) literal(v reflect.Value) {  		}  	case '"': // string -		s, ok := unquote(item) +		s, ok := unquoteBytes(item)  		if !ok {  			d.error(errPhase)  		}  		switch v := v.(type) {  		default:  			d.saveError(&UnmarshalTypeError{"string", v.Type()}) +		case *reflect.SliceValue: +			if v.Type() != byteSliceType { +				d.saveError(&UnmarshalTypeError{"string", v.Type()}) +				break +			} +			b := make([]byte, base64.StdEncoding.DecodedLen(len(s))) +			n, err := base64.StdEncoding.Decode(b, s) +			if err != nil { +				d.saveError(err) +				break +			} +			v.Set(reflect.NewValue(b[0:n]).(*reflect.SliceValue))  		case *reflect.StringValue: -			v.Set(s) +			v.Set(string(s))  		case *reflect.InterfaceValue: -			v.Set(reflect.NewValue(s)) +			v.Set(reflect.NewValue(string(s)))  		}  	default: // number @@ -772,12 +787,43 @@ func getu4(s []byte) int {  // unquote converts a quoted JSON string literal s into an actual string t.  // The rules are different than for Go, so cannot use strconv.Unquote.  func unquote(s []byte) (t string, ok bool) { +	s, ok = unquoteBytes(s) +	t = string(s) +	return +} + +func unquoteBytes(s []byte) (t []byte, ok bool) {  	if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {  		return  	} +	s = s[1 : len(s)-1] + +	// Check for unusual characters. If there are none, +	// then no unquoting is needed, so return a slice of the +	// original bytes. +	r := 0 +	for r < len(s) { +		c := s[r] +		if c == '\\' || c == '"' || c < ' ' { +			break +		} +		if c < utf8.RuneSelf { +			r++ +			continue +		} +		rune, size := utf8.DecodeRune(s[r:]) +		if rune == utf8.RuneError && size == 1 { +			break +		} +		r += size +	} +	if r == len(s) { +		return s, true +	} +  	b := make([]byte, len(s)+2*utf8.UTFMax) -	w := 0 -	for r := 1; r < len(s)-1; { +	w := copy(b, s[0:r]) +	for r < len(s) {  		// Out of room?  Can only happen if s is full of  		// malformed UTF-8 and we're replacing each  		// byte with RuneError. @@ -789,7 +835,7 @@ func unquote(s []byte) (t string, ok bool) {  		switch c := s[r]; {  		case c == '\\':  			r++ -			if r >= len(s)-1 { +			if r >= len(s) {  				return  			}  			switch s[r] { @@ -857,5 +903,5 @@ func unquote(s []byte) (t string, ok bool) {  			w += utf8.EncodeRune(b[w:], rune)  		}  	} -	return string(b[0:w]), true +	return b[0:w], true  } | 
