Compare commits

...

1 Commits

Author SHA1 Message Date
Masaaki Goshima 5090a4bf5e WIP 2020-12-27 21:25:26 +09:00
4 changed files with 122 additions and 52 deletions

View File

@ -117,8 +117,58 @@ func (d *Decoder) decodeForUnmarshalNoEscape(src []byte, v interface{}) error {
return d.decode(src, header) return d.decode(src, header)
} }
func (d *Decoder) prepareForDecodeArray() error {
for {
switch s.char() {
case ' ', '\t', '\r', '\n':
s.cursor++
continue
case ',', ':':
return errExpected("value in array element", s.totalOffset())
case nul:
if s.read() {
continue
}
return io.EOF
}
break
}
s.context = streamContextTypeArrayDelim
return nil
}
func (d *Decoder) prepareForDecodeArrayDelim() error {
for {
switch s.char() {
case ' ', '\t', '\r', '\n':
s.cursor++
continue
case ',':
s.cursor++
return nil
case ']':
s.cursor++
s.context = streamContextTypeValue
return nil
case nul:
if s.read() {
continue
}
return io.EOF
}
break
}
return nil
}
func (d *Decoder) prepareForDecode() error { func (d *Decoder) prepareForDecode() error {
s := d.s s := d.s
switch s.context {
case streamContextTypeArray:
return d.prepareForDecodeArray()
case streamContextTypeArrayDelim:
return d.prepareForDecodeArrayDelim()
}
for { for {
switch s.char() { switch s.char() {
case ' ', '\t', '\r', '\n': case ' ', '\t', '\r', '\n':
@ -202,8 +252,16 @@ func (d *Decoder) Token() (Token, error) {
switch c { switch c {
case ' ', '\n', '\r', '\t': case ' ', '\n', '\r', '\t':
s.cursor++ s.cursor++
case '{', '[', ']', '}': case ']', '}':
s.cursor++ s.cursor++
d.s.context = streamContextTypeValue
return Delim(c), nil
case '{':
s.cursor++
d.s.context = streamContextTypeObject
return Delim(c), nil
case '[':
d.s.context = streamContextTypeArray
return Delim(c), nil return Delim(c), nil
case ',', ':': case ',', ':':
s.cursor++ s.cursor++

View File

@ -20,8 +20,18 @@ type stream struct {
allRead bool allRead bool
useNumber bool useNumber bool
disallowUnknownFields bool disallowUnknownFields bool
context streamContextType
} }
const (
streamContextTypeValue streamContextType = iota
streamContextTypeArray
streamContextTypeArrayDelim /* expect ',' or ']' */
streamContextTypeObject
streamContextTypeObjectColon /* expect ':' */
streamContextTypeObjectDelim /* expect ',' or '}' */
)
func newStream(r io.Reader) *stream { func newStream(r io.Reader) *stream {
return &stream{ return &stream{
r: r, r: r,

View File

@ -3,6 +3,7 @@ package json
import ( import (
"fmt" "fmt"
"reflect" "reflect"
"runtime"
"strconv" "strconv"
) )
@ -122,6 +123,7 @@ func errNotAtBeginningOfValue(cursor int64) *SyntaxError {
} }
func errUnexpectedEndOfJSON(msg string, cursor int64) *SyntaxError { func errUnexpectedEndOfJSON(msg string, cursor int64) *SyntaxError {
fmt.Println(runtime.Caller(1))
return &SyntaxError{ return &SyntaxError{
msg: fmt.Sprintf("json: %s unexpected end of JSON input", msg), msg: fmt.Sprintf("json: %s unexpected end of JSON input", msg),
Offset: cursor, Offset: cursor,

View File

@ -324,57 +324,59 @@ type decodeThis struct {
var tokenStreamCases = []tokenStreamCase{ var tokenStreamCases = []tokenStreamCase{
// streaming token cases // streaming token cases
{json: `10`, expTokens: []interface{}{float64(10)}}, /*
{json: ` [10] `, expTokens: []interface{}{ {json: `10`, expTokens: []interface{}{float64(10)}},
json.Delim('['), float64(10), json.Delim(']')}}, {json: ` [10] `, expTokens: []interface{}{
{json: ` [false,10,"b"] `, expTokens: []interface{}{ json.Delim('['), float64(10), json.Delim(']')}},
json.Delim('['), false, float64(10), "b", json.Delim(']')}}, {json: ` [false,10,"b"] `, expTokens: []interface{}{
{json: `{ "a": 1 }`, expTokens: []interface{}{ json.Delim('['), false, float64(10), "b", json.Delim(']')}},
json.Delim('{'), "a", float64(1), json.Delim('}')}}, {json: `{ "a": 1 }`, expTokens: []interface{}{
{json: `{"a": 1, "b":"3"}`, expTokens: []interface{}{ json.Delim('{'), "a", float64(1), json.Delim('}')}},
json.Delim('{'), "a", float64(1), "b", "3", json.Delim('}')}}, {json: `{"a": 1, "b":"3"}`, expTokens: []interface{}{
{json: ` [{"a": 1},{"a": 2}] `, expTokens: []interface{}{ json.Delim('{'), "a", float64(1), "b", "3", json.Delim('}')}},
json.Delim('['), {json: ` [{"a": 1},{"a": 2}] `, expTokens: []interface{}{
json.Delim('{'), "a", float64(1), json.Delim('}'), json.Delim('['),
json.Delim('{'), "a", float64(2), json.Delim('}'), json.Delim('{'), "a", float64(1), json.Delim('}'),
json.Delim(']')}}, json.Delim('{'), "a", float64(2), json.Delim('}'),
{json: `{"obj": {"a": 1}}`, expTokens: []interface{}{ json.Delim(']')}},
json.Delim('{'), "obj", json.Delim('{'), "a", float64(1), json.Delim('}'), {json: `{"obj": {"a": 1}}`, expTokens: []interface{}{
json.Delim('}')}}, json.Delim('{'), "obj", json.Delim('{'), "a", float64(1), json.Delim('}'),
{json: `{"obj": [{"a": 1}]}`, expTokens: []interface{}{ json.Delim('}')}},
json.Delim('{'), "obj", json.Delim('['), {json: `{"obj": [{"a": 1}]}`, expTokens: []interface{}{
json.Delim('{'), "a", float64(1), json.Delim('}'), json.Delim('{'), "obj", json.Delim('['),
json.Delim(']'), json.Delim('}')}}, json.Delim('{'), "a", float64(1), json.Delim('}'),
json.Delim(']'), json.Delim('}')}},
// streaming tokens with intermittent Decode() // streaming tokens with intermittent Decode()
{json: `{ "a": 1 }`, expTokens: []interface{}{ {json: `{ "a": 1 }`, expTokens: []interface{}{
json.Delim('{'), "a", json.Delim('{'), "a",
decodeThis{float64(1)}, decodeThis{float64(1)},
json.Delim('}')}}, json.Delim('}')}},
{json: ` [ { "a" : 1 } ] `, expTokens: []interface{}{ {json: ` [ { "a" : 1 } ] `, expTokens: []interface{}{
json.Delim('['), json.Delim('['),
decodeThis{map[string]interface{}{"a": float64(1)}}, decodeThis{map[string]interface{}{"a": float64(1)}},
json.Delim(']')}}, json.Delim(']')}},
{json: ` [{"a": 1},{"a": 2}] `, expTokens: []interface{}{ {json: ` [{"a": 1},{"a": 2}] `, expTokens: []interface{}{
json.Delim('['), json.Delim('['),
decodeThis{map[string]interface{}{"a": float64(1)}}, decodeThis{map[string]interface{}{"a": float64(1)}},
decodeThis{map[string]interface{}{"a": float64(2)}}, decodeThis{map[string]interface{}{"a": float64(2)}},
json.Delim(']')}}, json.Delim(']')}},
{json: `{ "obj" : [ { "a" : 1 } ] }`, expTokens: []interface{}{ {json: `{ "obj" : [ { "a" : 1 } ] }`, expTokens: []interface{}{
json.Delim('{'), "obj", json.Delim('['), json.Delim('{'), "obj", json.Delim('['),
decodeThis{map[string]interface{}{"a": float64(1)}}, decodeThis{map[string]interface{}{"a": float64(1)}},
json.Delim(']'), json.Delim('}')}}, json.Delim(']'), json.Delim('}')}},
{json: `{"obj": {"a": 1}}`, expTokens: []interface{}{ {json: `{"obj": {"a": 1}}`, expTokens: []interface{}{
json.Delim('{'), "obj", json.Delim('{'), "obj",
decodeThis{map[string]interface{}{"a": float64(1)}}, decodeThis{map[string]interface{}{"a": float64(1)}},
json.Delim('}')}}, json.Delim('}')}},
{json: `{"obj": [{"a": 1}]}`, expTokens: []interface{}{ {json: `{"obj": [{"a": 1}]}`, expTokens: []interface{}{
json.Delim('{'), "obj", json.Delim('{'), "obj",
decodeThis{[]interface{}{ decodeThis{[]interface{}{
map[string]interface{}{"a": float64(1)}, map[string]interface{}{"a": float64(1)},
}}, }},
json.Delim('}')}}, json.Delim('}')}},
*/
{json: ` [{"a": 1} {"a": 2}] `, expTokens: []interface{}{ {json: ` [{"a": 1} {"a": 2}] `, expTokens: []interface{}{
json.Delim('['), json.Delim('['),
decodeThis{map[string]interface{}{"a": float64(1)}}, decodeThis{map[string]interface{}{"a": float64(1)}},
@ -393,7 +395,6 @@ var tokenStreamCases = []tokenStreamCase{
}}, }},
} }
/*
func TestDecodeInStream(t *testing.T) { func TestDecodeInStream(t *testing.T) {
for ci, tcase := range tokenStreamCases { for ci, tcase := range tokenStreamCases {
@ -428,7 +429,6 @@ func TestDecodeInStream(t *testing.T) {
} }
} }
} }
*/
// Test from golang.org/issue/11893 // Test from golang.org/issue/11893
func TestHTTPDecoding(t *testing.T) { func TestHTTPDecoding(t *testing.T) {