summaryrefslogtreecommitdiff
path: root/src/pkg/json
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-04-28 10:35:15 +0200
committerOndřej Surý <ondrej@sury.org>2011-04-28 10:35:15 +0200
commitc1ba1a0fec4aed430709030f98a3bdb90bfeea16 (patch)
tree3df18657e50a0313ed6defcda30e4474cb28a467 /src/pkg/json
parent7b15ed9ef455b6b66c6b376898a88aef5d6a9970 (diff)
downloadgolang-c1ba1a0fec4aed430709030f98a3bdb90bfeea16.tar.gz
Imported Upstream version 2011.04.27upstream/2011.04.27
Diffstat (limited to 'src/pkg/json')
-rw-r--r--src/pkg/json/decode.go41
-rw-r--r--src/pkg/json/decode_test.go13
-rw-r--r--src/pkg/json/encode.go8
-rw-r--r--src/pkg/json/scanner.go16
-rw-r--r--src/pkg/json/stream.go5
5 files changed, 48 insertions, 35 deletions
diff --git a/src/pkg/json/decode.go b/src/pkg/json/decode.go
index a5fd33912..e78b60ccb 100644
--- a/src/pkg/json/decode.go
+++ b/src/pkg/json/decode.go
@@ -122,11 +122,10 @@ func (d *decodeState) unmarshal(v interface{}) (err os.Error) {
}
}()
- rv := reflect.NewValue(v)
+ rv := reflect.ValueOf(v)
pv := rv
- if pv.Kind() != reflect.Ptr ||
- pv.IsNil() {
- return &InvalidUnmarshalError{reflect.Typeof(v)}
+ if pv.Kind() != reflect.Ptr || pv.IsNil() {
+ return &InvalidUnmarshalError{reflect.TypeOf(v)}
}
d.scan.reset()
@@ -267,17 +266,17 @@ func (d *decodeState) indirect(v reflect.Value, wantptr bool) (Unmarshaler, refl
v = iv.Elem()
continue
}
+
pv := v
if pv.Kind() != reflect.Ptr {
break
}
- if pv.Elem().Kind() != reflect.Ptr &&
- wantptr && !isUnmarshaler {
+ if pv.Elem().Kind() != reflect.Ptr && wantptr && pv.CanSet() && !isUnmarshaler {
return nil, pv
}
if pv.IsNil() {
- pv.Set(reflect.Zero(pv.Type().Elem()).Addr())
+ pv.Set(reflect.New(pv.Type().Elem()))
}
if isUnmarshaler {
// Using v.Interface().(Unmarshaler)
@@ -314,7 +313,7 @@ func (d *decodeState) array(v reflect.Value) {
iv := v
ok := iv.Kind() == reflect.Interface
if ok {
- iv.Set(reflect.NewValue(d.arrayInterface()))
+ iv.Set(reflect.ValueOf(d.arrayInterface()))
return
}
@@ -410,7 +409,7 @@ func (d *decodeState) object(v reflect.Value) {
// Decoding into nil interface? Switch to non-reflect code.
iv := v
if iv.Kind() == reflect.Interface {
- iv.Set(reflect.NewValue(d.objectInterface()))
+ iv.Set(reflect.ValueOf(d.objectInterface()))
return
}
@@ -423,7 +422,7 @@ func (d *decodeState) object(v reflect.Value) {
case reflect.Map:
// map must have string type
t := v.Type()
- if t.Key() != reflect.Typeof("") {
+ if t.Key() != reflect.TypeOf("") {
d.saveError(&UnmarshalTypeError{"object", v.Type()})
break
}
@@ -443,6 +442,8 @@ func (d *decodeState) object(v reflect.Value) {
return
}
+ var mapElem reflect.Value
+
for {
// Read opening " of string key or closing }.
op := d.scanWhile(scanSkipSpace)
@@ -466,7 +467,13 @@ func (d *decodeState) object(v reflect.Value) {
// Figure out field corresponding to key.
var subv reflect.Value
if mv.IsValid() {
- subv = reflect.Zero(mv.Type().Elem())
+ elemType := mv.Type().Elem()
+ if !mapElem.IsValid() {
+ mapElem = reflect.New(elemType).Elem()
+ } else {
+ mapElem.Set(reflect.Zero(elemType))
+ }
+ subv = mapElem
} else {
var f reflect.StructField
var ok bool
@@ -514,7 +521,7 @@ func (d *decodeState) object(v reflect.Value) {
// Write value back to map;
// if using struct, subv points into struct already.
if mv.IsValid() {
- mv.SetMapIndex(reflect.NewValue(key), subv)
+ mv.SetMapIndex(reflect.ValueOf(key), subv)
}
// Next token must be , or }.
@@ -570,7 +577,7 @@ func (d *decodeState) literal(v reflect.Value) {
case reflect.Bool:
v.SetBool(value)
case reflect.Interface:
- v.Set(reflect.NewValue(value))
+ v.Set(reflect.ValueOf(value))
}
case '"': // string
@@ -592,11 +599,11 @@ func (d *decodeState) literal(v reflect.Value) {
d.saveError(err)
break
}
- v.Set(reflect.NewValue(b[0:n]))
+ v.Set(reflect.ValueOf(b[0:n]))
case reflect.String:
v.SetString(string(s))
case reflect.Interface:
- v.Set(reflect.NewValue(string(s)))
+ v.Set(reflect.ValueOf(string(s)))
}
default: // number
@@ -613,7 +620,7 @@ func (d *decodeState) literal(v reflect.Value) {
d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
break
}
- v.Set(reflect.NewValue(n))
+ v.Set(reflect.ValueOf(n))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n, err := strconv.Atoi64(s)
@@ -767,7 +774,7 @@ func (d *decodeState) literalInterface() interface{} {
}
n, err := strconv.Atof64(string(item))
if err != nil {
- d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.Typeof(0.0)})
+ d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.TypeOf(0.0)})
}
return n
}
diff --git a/src/pkg/json/decode_test.go b/src/pkg/json/decode_test.go
index 49135c4bf..bf8bf10bf 100644
--- a/src/pkg/json/decode_test.go
+++ b/src/pkg/json/decode_test.go
@@ -21,7 +21,7 @@ type tx struct {
x int
}
-var txType = reflect.Typeof((*tx)(nil)).Elem()
+var txType = reflect.TypeOf((*tx)(nil)).Elem()
// A type that can unmarshal itself.
@@ -64,14 +64,14 @@ var unmarshalTests = []unmarshalTest{
{`"g-clef: \uD834\uDD1E"`, new(string), "g-clef: \U0001D11E", nil},
{`"invalid: \uD834x\uDD1E"`, new(string), "invalid: \uFFFDx\uFFFD", nil},
{"null", new(interface{}), nil, nil},
- {`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.Typeof("")}},
+ {`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.TypeOf("")}},
{`{"x": 1}`, new(tx), tx{}, &UnmarshalFieldError{"x", txType, txType.Field(0)}},
// skip invalid tags
{`{"X":"a", "y":"b", "Z":"c"}`, new(badTag), badTag{"a", "b", "c"}, nil},
// syntax errors
- {`{"X": "foo", "Y"}`, nil, nil, SyntaxError("invalid character '}' after object key")},
+ {`{"X": "foo", "Y"}`, nil, nil, &SyntaxError{"invalid character '}' after object key", 17}},
// composite tests
{allValueIndent, new(All), allValue, nil},
@@ -125,12 +125,12 @@ func TestMarshalBadUTF8(t *testing.T) {
}
func TestUnmarshal(t *testing.T) {
- var scan scanner
for i, tt := range unmarshalTests {
+ var scan scanner
in := []byte(tt.in)
if err := checkValid(in, &scan); err != nil {
if !reflect.DeepEqual(err, tt.err) {
- t.Errorf("#%d: checkValid: %v", i, err)
+ t.Errorf("#%d: checkValid: %#v", i, err)
continue
}
}
@@ -138,8 +138,7 @@ func TestUnmarshal(t *testing.T) {
continue
}
// v = new(right-type)
- v := reflect.NewValue(tt.ptr)
- v.Set(reflect.Zero(v.Type().Elem()).Addr())
+ v := reflect.New(reflect.TypeOf(tt.ptr).Elem())
if err := Unmarshal([]byte(in), v.Interface()); !reflect.DeepEqual(err, tt.err) {
t.Errorf("#%d: %v want %v", i, err, tt.err)
continue
diff --git a/src/pkg/json/encode.go b/src/pkg/json/encode.go
index dfa3c59da..ec0a14a6a 100644
--- a/src/pkg/json/encode.go
+++ b/src/pkg/json/encode.go
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// The json package implements encoding and decoding of JSON objects as
-// defined in RFC 4627.
+// Package json implements encoding and decoding of JSON objects as defined in
+// RFC 4627.
package json
import (
@@ -172,7 +172,7 @@ func (e *encodeState) marshal(v interface{}) (err os.Error) {
err = r.(os.Error)
}
}()
- e.reflectValue(reflect.NewValue(v))
+ e.reflectValue(reflect.ValueOf(v))
return nil
}
@@ -180,7 +180,7 @@ func (e *encodeState) error(err os.Error) {
panic(err)
}
-var byteSliceType = reflect.Typeof([]byte(nil))
+var byteSliceType = reflect.TypeOf([]byte(nil))
func (e *encodeState) reflectValue(v reflect.Value) {
if !v.IsValid() {
diff --git a/src/pkg/json/scanner.go b/src/pkg/json/scanner.go
index e98ddef5c..49c2edd54 100644
--- a/src/pkg/json/scanner.go
+++ b/src/pkg/json/scanner.go
@@ -23,6 +23,7 @@ import (
func checkValid(data []byte, scan *scanner) os.Error {
scan.reset()
for _, c := range data {
+ scan.bytes++
if scan.step(scan, int(c)) == scanError {
return scan.err
}
@@ -56,10 +57,12 @@ func nextValue(data []byte, scan *scanner) (value, rest []byte, err os.Error) {
}
// A SyntaxError is a description of a JSON syntax error.
-type SyntaxError string
-
-func (e SyntaxError) String() string { return string(e) }
+type SyntaxError struct {
+ msg string // description of error
+ Offset int64 // error occurred after reading Offset bytes
+}
+func (e *SyntaxError) String() string { return e.msg }
// A scanner is a JSON scanning state machine.
// Callers call scan.reset() and then pass bytes in one at a time
@@ -89,6 +92,9 @@ type scanner struct {
// 1-byte redo (see undo method)
redoCode int
redoState func(*scanner, int) int
+
+ // total bytes consumed, updated by decoder.Decode
+ bytes int64
}
// These values are returned by the state transition functions
@@ -148,7 +154,7 @@ func (s *scanner) eof() int {
return scanEnd
}
if s.err == nil {
- s.err = SyntaxError("unexpected end of JSON input")
+ s.err = &SyntaxError{"unexpected end of JSON input", s.bytes}
}
return scanError
}
@@ -581,7 +587,7 @@ func stateError(s *scanner, c int) int {
// error records an error and switches to the error state.
func (s *scanner) error(c int, context string) int {
s.step = stateError
- s.err = SyntaxError("invalid character " + quoteChar(c) + " " + context)
+ s.err = &SyntaxError{"invalid character " + quoteChar(c) + " " + context, s.bytes}
return scanError
}
diff --git a/src/pkg/json/stream.go b/src/pkg/json/stream.go
index cb9b16559..f143b3f0a 100644
--- a/src/pkg/json/stream.go
+++ b/src/pkg/json/stream.go
@@ -23,8 +23,8 @@ func NewDecoder(r io.Reader) *Decoder {
return &Decoder{r: r}
}
-// Decode reads the next JSON-encoded value from the
-// connection and stores it in the value pointed to by v.
+// Decode reads the next JSON-encoded value from its
+// input and stores it in the value pointed to by v.
//
// See the documentation for Unmarshal for details about
// the conversion of JSON into a Go value.
@@ -62,6 +62,7 @@ Input:
for {
// Look in the buffer for a new value.
for i, c := range dec.buf[scanp:] {
+ dec.scan.bytes++
v := dec.scan.step(&dec.scan, int(c))
if v == scanEnd {
scanp += i