aboutsummaryrefslogtreecommitdiff
path: root/src/encoding
diff options
context:
space:
mode:
Diffstat (limited to 'src/encoding')
-rw-r--r--src/encoding/json/stream.go34
-rw-r--r--src/encoding/json/stream_test.go21
2 files changed, 30 insertions, 25 deletions
diff --git a/src/encoding/json/stream.go b/src/encoding/json/stream.go
index f6b62c4cf6..75a4270df7 100644
--- a/src/encoding/json/stream.go
+++ b/src/encoding/json/stream.go
@@ -12,12 +12,13 @@ import (
// A Decoder reads and decodes JSON values from an input stream.
type Decoder struct {
- r io.Reader
- buf []byte
- d decodeState
- scanp int // start of unread data in buf
- scan scanner
- err error
+ r io.Reader
+ buf []byte
+ d decodeState
+ scanp int // start of unread data in buf
+ scanned int64 // amount of data already scanned
+ scan scanner
+ err error
tokenState int
tokenStack []int
@@ -55,7 +56,7 @@ func (dec *Decoder) Decode(v interface{}) error {
}
if !dec.tokenValueAllowed() {
- return &SyntaxError{msg: "not at beginning of value"}
+ return &SyntaxError{msg: "not at beginning of value", Offset: dec.offset()}
}
// Read whole value into buffer.
@@ -140,6 +141,7 @@ func (dec *Decoder) refill() error {
// Make room to read more into the buffer.
// First slide down data already consumed.
if dec.scanp > 0 {
+ dec.scanned += int64(dec.scanp)
n := copy(dec.buf, dec.buf[dec.scanp:])
dec.buf = dec.buf[:n]
dec.scanp = 0
@@ -306,7 +308,7 @@ func (dec *Decoder) tokenPrepareForDecode() error {
return err
}
if c != ',' {
- return &SyntaxError{"expected comma after array element", 0}
+ return &SyntaxError{"expected comma after array element", dec.offset()}
}
dec.scanp++
dec.tokenState = tokenArrayValue
@@ -316,7 +318,7 @@ func (dec *Decoder) tokenPrepareForDecode() error {
return err
}
if c != ':' {
- return &SyntaxError{"expected colon after object key", 0}
+ return &SyntaxError{"expected colon after object key", dec.offset()}
}
dec.scanp++
dec.tokenState = tokenObjectValue
@@ -433,7 +435,6 @@ func (dec *Decoder) Token() (Token, error) {
err := dec.Decode(&x)
dec.tokenState = old
if err != nil {
- clearOffset(err)
return nil, err
}
dec.tokenState = tokenObjectColon
@@ -447,7 +448,6 @@ func (dec *Decoder) Token() (Token, error) {
}
var x interface{}
if err := dec.Decode(&x); err != nil {
- clearOffset(err)
return nil, err
}
return x, nil
@@ -455,12 +455,6 @@ func (dec *Decoder) Token() (Token, error) {
}
}
-func clearOffset(err error) {
- if s, ok := err.(*SyntaxError); ok {
- s.Offset = 0
- }
-}
-
func (dec *Decoder) tokenError(c byte) (Token, error) {
var context string
switch dec.tokenState {
@@ -477,7 +471,7 @@ func (dec *Decoder) tokenError(c byte) (Token, error) {
case tokenObjectComma:
context = " after object key:value pair"
}
- return nil, &SyntaxError{"invalid character " + quoteChar(c) + " " + context, 0}
+ return nil, &SyntaxError{"invalid character " + quoteChar(c) + " " + context, dec.offset()}
}
// More reports whether there is another element in the
@@ -505,3 +499,7 @@ func (dec *Decoder) peek() (byte, error) {
err = dec.refill()
}
}
+
+func (dec *Decoder) offset() int64 {
+ return dec.scanned + int64(dec.scanp)
+}
diff --git a/src/encoding/json/stream_test.go b/src/encoding/json/stream_test.go
index d0b3ffbce9..83c01d170c 100644
--- a/src/encoding/json/stream_test.go
+++ b/src/encoding/json/stream_test.go
@@ -342,11 +342,18 @@ var tokenStreamCases []tokenStreamCase = []tokenStreamCase{
{json: ` [{"a": 1} {"a": 2}] `, expTokens: []interface{}{
Delim('['),
decodeThis{map[string]interface{}{"a": float64(1)}},
- decodeThis{&SyntaxError{"expected comma after array element", 0}},
+ decodeThis{&SyntaxError{"expected comma after array element", 11}},
}},
- {json: `{ "a" 1 }`, expTokens: []interface{}{
- Delim('{'), "a",
- decodeThis{&SyntaxError{"expected colon after object key", 0}},
+ {json: `{ "` + strings.Repeat("a", 513) + `" 1 }`, expTokens: []interface{}{
+ Delim('{'), strings.Repeat("a", 513),
+ decodeThis{&SyntaxError{"expected colon after object key", 518}},
+ }},
+ {json: `{ "\a" }`, expTokens: []interface{}{
+ Delim('{'),
+ &SyntaxError{"invalid character 'a' in string escape code", 3},
+ }},
+ {json: ` \a`, expTokens: []interface{}{
+ &SyntaxError{"invalid character '\\\\' looking for beginning of value", 1},
}},
}
@@ -367,15 +374,15 @@ func TestDecodeInStream(t *testing.T) {
tk, err = dec.Token()
}
if experr, ok := etk.(error); ok {
- if err == nil || err.Error() != experr.Error() {
- t.Errorf("case %v: Expected error %v in %q, but was %v", ci, experr, tcase.json, err)
+ if err == nil || !reflect.DeepEqual(err, experr) {
+ t.Errorf("case %v: Expected error %#v in %q, but was %#v", ci, experr, tcase.json, err)
}
break
} else if err == io.EOF {
t.Errorf("case %v: Unexpected EOF in %q", ci, tcase.json)
break
} else if err != nil {
- t.Errorf("case %v: Unexpected error '%v' in %q", ci, err, tcase.json)
+ t.Errorf("case %v: Unexpected error '%#v' in %q", ci, err, tcase.json)
break
}
if !reflect.DeepEqual(tk, etk) {