Support SyntaxError

This commit is contained in:
Masaaki Goshima 2020-05-23 12:51:09 +09:00
parent 12b34f0663
commit 4acc22e0fe
16 changed files with 112 additions and 112 deletions

View File

@ -24,7 +24,7 @@ type Token interface{}
type Delim rune
type decoder interface {
decode([]byte, int, uintptr) (int, error)
decode([]byte, int64, uintptr) (int64, error)
}
type Decoder struct {

View File

@ -1,9 +1,5 @@
package json
import (
"errors"
)
type arrayDecoder struct {
elemType *rtype
size uintptr
@ -20,8 +16,8 @@ func newArrayDecoder(dec decoder, elemType *rtype, alen int) *arrayDecoder {
}
}
func (d *arrayDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
buflen := len(buf)
func (d *arrayDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, error) {
buflen := int64(len(buf))
for ; cursor < buflen; cursor++ {
switch buf[cursor] {
case ' ', '\n', '\t', '\r':
@ -44,10 +40,10 @@ func (d *arrayDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
idx++
continue
default:
return 0, errors.New("syntax error array")
return 0, errInvalidCharacter(buf[cursor], "array", cursor)
}
}
}
}
return 0, errors.New("unexpected error array")
return 0, errUnexpectedEndOfJSON("array", cursor)
}

View File

@ -1,7 +1,6 @@
package json
import (
"errors"
"unsafe"
)
@ -11,40 +10,40 @@ func newBoolDecoder() *boolDecoder {
return &boolDecoder{}
}
func (d *boolDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
buflen := len(buf)
func (d *boolDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, error) {
buflen := int64(len(buf))
cursor = skipWhiteSpace(buf, cursor)
switch buf[cursor] {
case 't':
if cursor+3 >= buflen {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errUnexpectedEndOfJSON("bool(true)", cursor)
}
if buf[cursor+1] != 'r' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+1], "bool(true)", cursor)
}
if buf[cursor+2] != 'u' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+2], "bool(true)", cursor)
}
if buf[cursor+3] != 'e' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+3], "bool(true)", cursor)
}
cursor += 4
*(*bool)(unsafe.Pointer(p)) = true
case 'f':
if cursor+4 >= buflen {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errUnexpectedEndOfJSON("bool(false)", cursor)
}
if buf[cursor+1] != 'a' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+1], "bool(false)", cursor)
}
if buf[cursor+2] != 'l' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+2], "bool(false)", cursor)
}
if buf[cursor+3] != 's' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+3], "bool(false)", cursor)
}
if buf[cursor+4] != 'e' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+4], "bool(false)", cursor)
}
cursor += 5
*(*bool)(unsafe.Pointer(p)) = false

View File

@ -1,9 +1,5 @@
package json
import (
"errors"
)
var (
isWhiteSpace = [256]bool{}
)
@ -15,7 +11,7 @@ func init() {
isWhiteSpace['\r'] = true
}
func skipWhiteSpace(buf []byte, cursor int) int {
func skipWhiteSpace(buf []byte, cursor int64) int64 {
LOOP:
if isWhiteSpace[buf[cursor]] {
cursor++
@ -24,15 +20,15 @@ LOOP:
return cursor
}
func skipValue(buf []byte, cursor int) (int, error) {
func skipValue(buf []byte, cursor int64) (int64, error) {
cursor = skipWhiteSpace(buf, cursor)
braceCount := 0
bracketCount := 0
buflen := len(buf)
buflen := int64(len(buf))
for {
switch buf[cursor] {
case '\000':
return cursor, errors.New("unexpected error value")
return cursor, errUnexpectedEndOfJSON("value of object", cursor)
case '{':
braceCount++
case '[':
@ -79,5 +75,5 @@ func skipValue(buf []byte, cursor int) (int, error) {
}
cursor++
}
return cursor, errors.New("unexpected error value")
return cursor, errUnexpectedEndOfJSON("value of object", cursor)
}

View File

@ -1,7 +1,6 @@
package json
import (
"errors"
"strconv"
"unsafe"
)
@ -14,8 +13,8 @@ func newFloatDecoder(op func(uintptr, float64)) *floatDecoder {
return &floatDecoder{op: op}
}
func (d *floatDecoder) decodeByte(buf []byte, cursor int) ([]byte, int, error) {
buflen := len(buf)
func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
buflen := int64(len(buf))
for ; cursor < buflen; cursor++ {
switch buf[cursor] {
case ' ', '\n', '\t', '\r':
@ -34,10 +33,10 @@ func (d *floatDecoder) decodeByte(buf []byte, cursor int) ([]byte, int, error) {
return num, cursor, nil
}
}
return nil, 0, errors.New("unexpected error number")
return nil, 0, errUnexpectedEndOfJSON("float", cursor)
}
func (d *floatDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
func (d *floatDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, error) {
bytes, c, err := d.decodeByte(buf, cursor)
if err != nil {
return 0, err

View File

@ -1,9 +1,5 @@
package json
import (
"errors"
)
type intDecoder struct {
op func(uintptr, int64)
}
@ -53,7 +49,7 @@ var (
}
)
func (d *intDecoder) decodeByte(buf []byte, cursor int) ([]byte, int, error) {
func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
for {
switch buf[cursor] {
case ' ', '\n', '\t', '\r':
@ -70,14 +66,13 @@ func (d *intDecoder) decodeByte(buf []byte, cursor int) ([]byte, int, error) {
num := buf[start:cursor]
return num, cursor, nil
default:
goto ERROR
return nil, 0, errInvalidCharacter(buf[cursor], "number(integer)", cursor)
}
}
ERROR:
return nil, 0, errors.New("unexpected error number")
return nil, 0, errUnexpectedEndOfJSON("number(integer)", cursor)
}
func (d *intDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
func (d *intDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, error) {
bytes, c, err := d.decodeByte(buf, cursor)
if err != nil {
return 0, err

View File

@ -1,7 +1,6 @@
package json
import (
"errors"
"reflect"
"unsafe"
)
@ -21,7 +20,7 @@ var (
)
)
func (d *interfaceDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
func (d *interfaceDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, error) {
cursor = skipWhiteSpace(buf, cursor)
switch buf[cursor] {
case '{':
@ -63,62 +62,62 @@ func (d *interfaceDecoder) decode(buf []byte, cursor int, p uintptr) (int, error
*(*interface{})(unsafe.Pointer(p)) = *(*string)(unsafe.Pointer(&literal))
return cursor, nil
case '\000':
return 0, errors.New("unexpected error string")
return 0, errUnexpectedEndOfJSON("string", cursor)
}
cursor++
}
return 0, errors.New("unexpected error string")
return 0, errUnexpectedEndOfJSON("string", cursor)
case 't':
if cursor+3 >= len(buf) {
return 0, errors.New("unexpected error. invalid bool character")
if cursor+3 >= int64(len(buf)) {
return 0, errUnexpectedEndOfJSON("bool(true)", cursor)
}
if buf[cursor+1] != 'r' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+1], "bool(true)", cursor)
}
if buf[cursor+2] != 'u' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+2], "bool(true)", cursor)
}
if buf[cursor+3] != 'e' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+3], "bool(true)", cursor)
}
cursor += 4
*(*interface{})(unsafe.Pointer(p)) = true
return cursor, nil
case 'f':
if cursor+4 >= len(buf) {
return 0, errors.New("unexpected error. invalid bool character")
if cursor+4 >= int64(len(buf)) {
return 0, errUnexpectedEndOfJSON("bool(false)", cursor)
}
if buf[cursor+1] != 'a' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+1], "bool(false)", cursor)
}
if buf[cursor+2] != 'l' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+2], "bool(false)", cursor)
}
if buf[cursor+3] != 's' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+3], "bool(false)", cursor)
}
if buf[cursor+4] != 'e' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+4], "bool(false)", cursor)
}
cursor += 5
*(*interface{})(unsafe.Pointer(p)) = false
return cursor, nil
case 'n':
if cursor+3 >= len(buf) {
return 0, errors.New("unexpected error. invalid bool character")
if cursor+3 >= int64(len(buf)) {
return 0, errUnexpectedEndOfJSON("null", cursor)
}
if buf[cursor+1] != 'u' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+1], "null", cursor)
}
if buf[cursor+2] != 'l' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+2], "null", cursor)
}
if buf[cursor+3] != 'l' {
return 0, errors.New("unexpected error. invalid bool character")
return 0, errInvalidCharacter(buf[cursor+3], "null", cursor)
}
cursor += 4
*(*interface{})(unsafe.Pointer(p)) = nil
return cursor, nil
}
return cursor, errors.New("unexpected error value")
return cursor, errNotAtBeginningOfValue(cursor)
}

View File

@ -1,7 +1,6 @@
package json
import (
"errors"
"unsafe"
)
@ -26,24 +25,24 @@ func makemap(*rtype, int) unsafe.Pointer
//go:noescape
func mapassign(t *rtype, m unsafe.Pointer, key, val unsafe.Pointer)
func (d *mapDecoder) setKey(buf []byte, cursor int, key interface{}) (int, error) {
func (d *mapDecoder) setKey(buf []byte, cursor int64, key interface{}) (int64, error) {
header := (*interfaceHeader)(unsafe.Pointer(&key))
return d.keyDecoder.decode(buf, cursor, uintptr(header.ptr))
}
func (d *mapDecoder) setValue(buf []byte, cursor int, key interface{}) (int, error) {
func (d *mapDecoder) setValue(buf []byte, cursor int64, key interface{}) (int64, error) {
header := (*interfaceHeader)(unsafe.Pointer(&key))
return d.valueDecoder.decode(buf, cursor, uintptr(header.ptr))
}
func (d *mapDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
func (d *mapDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, error) {
cursor = skipWhiteSpace(buf, cursor)
buflen := len(buf)
buflen := int64(len(buf))
if buflen < 2 {
return 0, errors.New("unexpected error {}")
return 0, errExpected("{} for map", cursor)
}
if buf[cursor] != '{' {
return 0, errors.New("unexpected error {")
return 0, errExpected("{ character for map value", cursor)
}
cursor++
mapValue := makemap(d.mapType, 0)
@ -56,11 +55,11 @@ func (d *mapDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
cursor = keyCursor
cursor = skipWhiteSpace(buf, cursor)
if buf[cursor] != ':' {
return 0, errors.New("unexpected error invalid delimiter for object")
return 0, errExpected("colon after object key", cursor)
}
cursor++
if cursor >= buflen {
return 0, errors.New("unexpected error missing value")
return 0, errUnexpectedEndOfJSON("map", cursor)
}
var value interface{}
valueCursor, err := d.setValue(buf, cursor, &value)
@ -75,7 +74,7 @@ func (d *mapDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
return cursor, nil
}
if buf[cursor] != ',' {
return 0, errors.New("unexpected error ,")
return 0, errExpected("semicolon after object value", cursor)
}
}
return cursor, nil

View File

@ -16,7 +16,7 @@ func newPtrDecoder(dec decoder, typ *rtype) *ptrDecoder {
//go:linkname unsafe_New reflect.unsafe_New
func unsafe_New(*rtype) uintptr
func (d *ptrDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
func (d *ptrDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, error) {
newptr := unsafe_New(d.typ)
c, err := d.dec.decode(buf, cursor, newptr)
if err != nil {

View File

@ -1,7 +1,6 @@
package json
import (
"errors"
"reflect"
"sync"
"unsafe"
@ -48,8 +47,8 @@ func copySlice(elemType *rtype, dst, src reflect.SliceHeader) int
//go:linkname newArray reflect.unsafe_NewArray
func newArray(*rtype, int) unsafe.Pointer
func (d *sliceDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
buflen := len(buf)
func (d *sliceDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, error) {
buflen := int64(len(buf))
for ; cursor < buflen; cursor++ {
switch buf[cursor] {
case ' ', '\n', '\t', '\r':
@ -97,10 +96,10 @@ func (d *sliceDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
slice.Cap = cap
slice.Data = data
d.releaseSlice(slice)
return 0, errors.New("syntax error slice")
return 0, errInvalidCharacter(buf[cursor], "slice", cursor)
}
}
}
}
return 0, errors.New("unexpected error slice")
return 0, errUnexpectedEndOfJSON("slice", cursor)
}

View File

@ -1,7 +1,6 @@
package json
import (
"errors"
"unsafe"
)
@ -12,7 +11,7 @@ func newStringDecoder() *stringDecoder {
return &stringDecoder{}
}
func (d *stringDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
func (d *stringDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, error) {
bytes, c, err := d.decodeByte(buf, cursor)
if err != nil {
return 0, err
@ -22,7 +21,7 @@ func (d *stringDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
return cursor, nil
}
func (d *stringDecoder) decodeByte(buf []byte, cursor int) ([]byte, int, error) {
func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
for {
switch buf[cursor] {
case ' ', '\n', '\t', '\r':
@ -39,24 +38,24 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int) ([]byte, int, error)
cursor++
return literal, cursor, nil
case '\000':
return nil, 0, errors.New("unexpected error string")
return nil, 0, errUnexpectedEndOfJSON("string", cursor)
}
cursor++
}
return nil, 0, errors.New("unexpected error string")
return nil, 0, errUnexpectedEndOfJSON("string", cursor)
case 'n':
buflen := len(buf)
buflen := int64(len(buf))
if cursor+3 >= buflen {
return nil, 0, errors.New("unexpected error. invalid bool character")
return nil, 0, errUnexpectedEndOfJSON("null", cursor)
}
if buf[cursor+1] != 'u' {
return nil, 0, errors.New("unexpected error. invalid bool character")
return nil, 0, errInvalidCharacter(buf[cursor+1], "null", cursor)
}
if buf[cursor+2] != 'l' {
return nil, 0, errors.New("unexpected error. invalid bool character")
return nil, 0, errInvalidCharacter(buf[cursor+2], "null", cursor)
}
if buf[cursor+3] != 'l' {
return nil, 0, errors.New("unexpected error. invalid bool character")
return nil, 0, errInvalidCharacter(buf[cursor+3], "null", cursor)
}
cursor += 5
return []byte{'n', 'u', 'l', 'l'}, cursor, nil
@ -65,5 +64,5 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int) ([]byte, int, error)
}
}
ERROR:
return nil, 0, errors.New("unexpected error key delimiter")
return nil, 0, errNotAtBeginningOfValue(cursor)
}

View File

@ -1,7 +1,6 @@
package json
import (
"errors"
"unsafe"
)
@ -22,14 +21,14 @@ func newStructDecoder(fieldMap map[string]*structFieldSet) *structDecoder {
}
}
func (d *structDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
buflen := len(buf)
func (d *structDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, error) {
buflen := int64(len(buf))
cursor = skipWhiteSpace(buf, cursor)
if buflen < 2 {
return 0, errors.New("unexpected error {}")
}
if buf[cursor] != '{' {
return 0, errors.New("unexpected error {")
return 0, errNotAtBeginningOfValue(cursor)
}
if buflen < 2 {
return 0, errUnexpectedEndOfJSON("object", cursor)
}
cursor++
for ; cursor < buflen; cursor++ {
@ -40,11 +39,11 @@ func (d *structDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
cursor = c
cursor = skipWhiteSpace(buf, cursor)
if buf[cursor] != ':' {
return 0, errors.New("unexpected error invalid delimiter for object")
return 0, errExpected("colon after object key", cursor)
}
cursor++
if cursor >= buflen {
return 0, errors.New("unexpected error missing value")
return 0, errExpected("object value after colon", cursor)
}
k := *(*string)(unsafe.Pointer(&key))
field, exists := d.fieldMap[k]
@ -67,7 +66,7 @@ func (d *structDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
return cursor, nil
}
if buf[cursor] != ',' {
return 0, errors.New("unexpected error ,")
return 0, errExpected("comma after object element", cursor)
}
}
return cursor, nil

View File

@ -1,9 +1,5 @@
package json
import (
"errors"
)
type uintDecoder struct {
op func(uintptr, uint64)
}
@ -28,8 +24,8 @@ func (d *uintDecoder) parseUint(b []byte) uint64 {
return sum
}
func (d *uintDecoder) decodeByte(buf []byte, cursor int) ([]byte, int, error) {
buflen := len(buf)
func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
buflen := int64(len(buf))
for ; cursor < buflen; cursor++ {
switch buf[cursor] {
case ' ', '\n', '\t', '\r':
@ -46,12 +42,14 @@ func (d *uintDecoder) decodeByte(buf []byte, cursor int) ([]byte, int, error) {
}
num := buf[start:cursor]
return num, cursor, nil
default:
return nil, 0, errInvalidCharacter(buf[cursor], "number(unsigned integer)", cursor)
}
}
return nil, 0, errors.New("unexpected error number")
return nil, 0, errUnexpectedEndOfJSON("number(unsigned integer)", cursor)
}
func (d *uintDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
func (d *uintDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, error) {
bytes, c, err := d.decodeByte(buf, cursor)
if err != nil {
return 0, err

View File

@ -12,7 +12,7 @@ func newUnmarshalJSONDecoder(typ *rtype) *unmarshalJSONDecoder {
return &unmarshalJSONDecoder{typ: typ}
}
func (d *unmarshalJSONDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
func (d *unmarshalJSONDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, error) {
cursor = skipWhiteSpace(buf, cursor)
start := cursor
end, err := skipValue(buf, cursor)

View File

@ -13,7 +13,7 @@ func newUnmarshalTextDecoder(typ *rtype) *unmarshalTextDecoder {
return &unmarshalTextDecoder{typ: typ}
}
func (d *unmarshalTextDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
func (d *unmarshalTextDecoder) decode(buf []byte, cursor int64, p uintptr) (int64, error) {
cursor = skipWhiteSpace(buf, cursor)
start := cursor
end, err := skipValue(buf, cursor)

View File

@ -116,3 +116,25 @@ type UnsupportedValueError struct {
func (e *UnsupportedValueError) Error() string {
return fmt.Sprintf("json: unsupported value: %s", e.Str)
}
func errNotAtBeginningOfValue(cursor int64) *SyntaxError {
return &SyntaxError{msg: "not at beginning of value", Offset: cursor}
}
func errUnexpectedEndOfJSON(msg string, cursor int64) *SyntaxError {
return &SyntaxError{
msg: fmt.Sprintf("unexpected end of JSON input for %s", msg),
Offset: cursor,
}
}
func errExpected(msg string, cursor int64) *SyntaxError {
return &SyntaxError{msg: fmt.Sprintf("expected %s", msg), Offset: cursor}
}
func errInvalidCharacter(c byte, context string, cursor int64) *SyntaxError {
return &SyntaxError{
msg: fmt.Sprintf("invalid character %c as %s", c, context),
Offset: cursor,
}
}