Merge pull request #221 from goccy/feature/refactor-validator

Refactor validator
This commit is contained in:
Masaaki Goshima 2021-05-09 14:44:12 +09:00 committed by GitHub
commit 835c00e18b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 107 additions and 261 deletions

View File

@ -39,10 +39,20 @@ jobs:
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: 1.16 go-version: 1.16
- name: checkout - name: checkout ( feature )
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: run benchmark - name: run benchmark ( feature )
run: cd benchmarks && go test -bench . run: cd benchmarks && go test -bench GoJson | tee $HOME/new.txt
- name: install benchcmp
run: go get -u golang.org/x/tools/cmd/benchcmp
- name: checkout ( master )
uses: actions/checkout@v2
with:
ref: master
- name: run benchmark ( master )
run: cd benchmarks && go test -bench GoJson | tee $HOME/old.txt
- name: compare benchmark results
run: benchcmp $HOME/old.txt $HOME/new.txt
coverage: coverage:
name: Coverage name: Coverage
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -95,24 +95,14 @@ func (d *arrayDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
return 0, errExceededMaxDepth(buf[cursor], cursor) return 0, errExceededMaxDepth(buf[cursor], cursor)
} }
buflen := int64(len(buf)) for {
for ; cursor < buflen; cursor++ {
switch buf[cursor] { switch buf[cursor] {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
cursor++
continue continue
case 'n': case 'n':
buflen := int64(len(buf)) if err := validateNull(buf, cursor); err != nil {
if cursor+3 >= buflen { return 0, err
return 0, errUnexpectedEndOfJSON("null", cursor)
}
if buf[cursor+1] != 'u' {
return 0, errInvalidCharacter(buf[cursor+1], "null", cursor)
}
if buf[cursor+2] != 'l' {
return 0, errInvalidCharacter(buf[cursor+2], "null", cursor)
}
if buf[cursor+3] != 'l' {
return 0, errInvalidCharacter(buf[cursor+3], "null", cursor)
} }
cursor += 4 cursor += 4
return cursor, nil return cursor, nil
@ -149,7 +139,8 @@ func (d *arrayDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
return 0, errInvalidCharacter(buf[cursor], "array", cursor) return 0, errInvalidCharacter(buf[cursor], "array", cursor)
} }
} }
} default:
}
return 0, errUnexpectedEndOfJSON("array", cursor) return 0, errUnexpectedEndOfJSON("array", cursor)
} }
}
}

View File

@ -47,56 +47,25 @@ ERROR:
} }
func (d *boolDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *boolDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
buflen := int64(len(buf))
cursor = skipWhiteSpace(buf, cursor) cursor = skipWhiteSpace(buf, cursor)
switch buf[cursor] { switch buf[cursor] {
case 't': case 't':
if cursor+3 >= buflen { if err := validateTrue(buf, cursor); err != nil {
return 0, errUnexpectedEndOfJSON("bool(true)", cursor) return 0, err
}
if buf[cursor+1] != 'r' {
return 0, errInvalidCharacter(buf[cursor+1], "bool(true)", cursor)
}
if buf[cursor+2] != 'u' {
return 0, errInvalidCharacter(buf[cursor+2], "bool(true)", cursor)
}
if buf[cursor+3] != 'e' {
return 0, errInvalidCharacter(buf[cursor+3], "bool(true)", cursor)
} }
cursor += 4 cursor += 4
**(**bool)(unsafe.Pointer(&p)) = true **(**bool)(unsafe.Pointer(&p)) = true
return cursor, nil return cursor, nil
case 'f': case 'f':
if cursor+4 >= buflen { if err := validateFalse(buf, cursor); err != nil {
return 0, errUnexpectedEndOfJSON("bool(false)", cursor) return 0, err
}
if buf[cursor+1] != 'a' {
return 0, errInvalidCharacter(buf[cursor+1], "bool(false)", cursor)
}
if buf[cursor+2] != 'l' {
return 0, errInvalidCharacter(buf[cursor+2], "bool(false)", cursor)
}
if buf[cursor+3] != 's' {
return 0, errInvalidCharacter(buf[cursor+3], "bool(false)", cursor)
}
if buf[cursor+4] != 'e' {
return 0, errInvalidCharacter(buf[cursor+4], "bool(false)", cursor)
} }
cursor += 5 cursor += 5
**(**bool)(unsafe.Pointer(&p)) = false **(**bool)(unsafe.Pointer(&p)) = false
return cursor, nil return cursor, nil
case 'n': case 'n':
if cursor+3 >= buflen { if err := validateNull(buf, cursor); err != nil {
return 0, errUnexpectedEndOfJSON("null", cursor) return 0, err
}
if buf[cursor+1] != 'u' {
return 0, errInvalidCharacter(buf[cursor+1], "null", cursor)
}
if buf[cursor+2] != 'l' {
return 0, errInvalidCharacter(buf[cursor+2], "null", cursor)
}
if buf[cursor+3] != 'l' {
return 0, errInvalidCharacter(buf[cursor+3], "null", cursor)
} }
cursor += 4 cursor += 4
return cursor, nil return cursor, nil

View File

@ -166,9 +166,7 @@ func (d *bytesDecoder) decodeBinary(buf []byte, cursor, depth int64, p unsafe.Po
cursor += 4 cursor += 4
return nil, cursor, nil return nil, cursor, nil
default: default:
goto ERROR
}
}
ERROR:
return nil, 0, errNotAtBeginningOfValue(cursor) return nil, 0, errNotAtBeginningOfValue(cursor)
} }
}
}

View File

@ -153,37 +153,14 @@ func skipValue(buf []byte, cursor, depth int64) (int64, error) {
} }
return cursor, nil return cursor, nil
case 't': case 't':
buflen := int64(len(buf)) if err := validateTrue(buf, cursor); err != nil {
if cursor+3 >= buflen { return 0, err
return 0, errUnexpectedEndOfJSON("bool of object", cursor)
}
if buf[cursor+1] != 'r' {
return 0, errUnexpectedEndOfJSON("bool of object", cursor)
}
if buf[cursor+2] != 'u' {
return 0, errUnexpectedEndOfJSON("bool of object", cursor)
}
if buf[cursor+3] != 'e' {
return 0, errUnexpectedEndOfJSON("bool of object", cursor)
} }
cursor += 4 cursor += 4
return cursor, nil return cursor, nil
case 'f': case 'f':
buflen := int64(len(buf)) if err := validateFalse(buf, cursor); err != nil {
if cursor+4 >= buflen { return 0, err
return 0, errUnexpectedEndOfJSON("bool of object", cursor)
}
if buf[cursor+1] != 'a' {
return 0, errUnexpectedEndOfJSON("bool of object", cursor)
}
if buf[cursor+2] != 'l' {
return 0, errUnexpectedEndOfJSON("bool of object", cursor)
}
if buf[cursor+3] != 's' {
return 0, errUnexpectedEndOfJSON("bool of object", cursor)
}
if buf[cursor+4] != 'e' {
return 0, errUnexpectedEndOfJSON("bool of object", cursor)
} }
cursor += 5 cursor += 5
return cursor, nil return cursor, nil
@ -199,6 +176,41 @@ func skipValue(buf []byte, cursor, depth int64) (int64, error) {
} }
} }
func validateTrue(buf []byte, cursor int64) error {
if cursor+3 >= int64(len(buf)) {
return errUnexpectedEndOfJSON("true", cursor)
}
if buf[cursor+1] != 'r' {
return errInvalidCharacter(buf[cursor+1], "true", cursor)
}
if buf[cursor+2] != 'u' {
return errInvalidCharacter(buf[cursor+2], "true", cursor)
}
if buf[cursor+3] != 'e' {
return errInvalidCharacter(buf[cursor+3], "true", cursor)
}
return nil
}
func validateFalse(buf []byte, cursor int64) error {
if cursor+4 >= int64(len(buf)) {
return errUnexpectedEndOfJSON("false", cursor)
}
if buf[cursor+1] != 'a' {
return errInvalidCharacter(buf[cursor+1], "false", cursor)
}
if buf[cursor+2] != 'l' {
return errInvalidCharacter(buf[cursor+2], "false", cursor)
}
if buf[cursor+3] != 's' {
return errInvalidCharacter(buf[cursor+3], "false", cursor)
}
if buf[cursor+4] != 'e' {
return errInvalidCharacter(buf[cursor+4], "false", cursor)
}
return nil
}
func validateNull(buf []byte, cursor int64) error { func validateNull(buf []byte, cursor int64) error {
if cursor+3 >= int64(len(buf)) { if cursor+3 >= int64(len(buf)) {
return errUnexpectedEndOfJSON("null", cursor) return errUnexpectedEndOfJSON("null", cursor)

View File

@ -91,34 +91,22 @@ ERROR:
} }
func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
buflen := int64(len(buf)) for {
for ; cursor < buflen; cursor++ {
switch buf[cursor] { switch buf[cursor] {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
cursor++
continue continue
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
start := cursor start := cursor
cursor++ cursor++
for ; cursor < buflen; cursor++ { for floatTable[buf[cursor]] {
if floatTable[buf[cursor]] { cursor++
continue
}
break
} }
num := buf[start:cursor] num := buf[start:cursor]
return num, cursor, nil return num, cursor, nil
case 'n': case 'n':
if cursor+3 >= buflen { if err := validateNull(buf, cursor); err != nil {
return nil, 0, errUnexpectedEndOfJSON("null", cursor) return nil, 0, err
}
if buf[cursor+1] != 'u' {
return nil, 0, errInvalidCharacter(buf[cursor+1], "null", cursor)
}
if buf[cursor+2] != 'l' {
return nil, 0, errInvalidCharacter(buf[cursor+2], "null", cursor)
}
if buf[cursor+3] != 'l' {
return nil, 0, errInvalidCharacter(buf[cursor+3], "null", cursor)
} }
cursor += 4 cursor += 4
return nil, cursor, nil return nil, cursor, nil
@ -126,7 +114,6 @@ func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, erro
return nil, 0, errUnexpectedEndOfJSON("float", cursor) return nil, 0, errUnexpectedEndOfJSON("float", cursor)
} }
} }
return nil, 0, errUnexpectedEndOfJSON("float", cursor)
} }
func (d *floatDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *floatDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {

View File

@ -154,26 +154,14 @@ func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error)
case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9':
start := cursor start := cursor
cursor++ cursor++
LOOP: for numTable[char(b, cursor)] {
if numTable[char(b, cursor)] {
cursor++ cursor++
goto LOOP
} }
num := buf[start:cursor] num := buf[start:cursor]
return num, cursor, nil return num, cursor, nil
case 'n': case 'n':
buflen := int64(len(buf)) if err := validateNull(buf, cursor); err != nil {
if cursor+3 >= buflen { return nil, 0, err
return nil, 0, errUnexpectedEndOfJSON("null", cursor)
}
if buf[cursor+1] != 'u' {
return nil, 0, errInvalidCharacter(buf[cursor+1], "null", cursor)
}
if buf[cursor+2] != 'l' {
return nil, 0, errInvalidCharacter(buf[cursor+2], "null", cursor)
}
if buf[cursor+3] != 'l' {
return nil, 0, errInvalidCharacter(buf[cursor+3], "null", cursor)
} }
cursor += 4 cursor += 4
return nil, cursor, nil return nil, cursor, nil

View File

@ -385,52 +385,22 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64,
**(**interface{})(unsafe.Pointer(&p)) = v **(**interface{})(unsafe.Pointer(&p)) = v
return cursor, nil return cursor, nil
case 't': case 't':
if cursor+3 >= int64(len(buf)) { if err := validateTrue(buf, cursor); err != nil {
return 0, errUnexpectedEndOfJSON("bool(true)", cursor) return 0, err
}
if buf[cursor+1] != 'r' {
return 0, errInvalidCharacter(buf[cursor+1], "bool(true)", cursor)
}
if buf[cursor+2] != 'u' {
return 0, errInvalidCharacter(buf[cursor+2], "bool(true)", cursor)
}
if buf[cursor+3] != 'e' {
return 0, errInvalidCharacter(buf[cursor+3], "bool(true)", cursor)
} }
cursor += 4 cursor += 4
**(**interface{})(unsafe.Pointer(&p)) = true **(**interface{})(unsafe.Pointer(&p)) = true
return cursor, nil return cursor, nil
case 'f': case 'f':
if cursor+4 >= int64(len(buf)) { if err := validateFalse(buf, cursor); err != nil {
return 0, errUnexpectedEndOfJSON("bool(false)", cursor) return 0, err
}
if buf[cursor+1] != 'a' {
return 0, errInvalidCharacter(buf[cursor+1], "bool(false)", cursor)
}
if buf[cursor+2] != 'l' {
return 0, errInvalidCharacter(buf[cursor+2], "bool(false)", cursor)
}
if buf[cursor+3] != 's' {
return 0, errInvalidCharacter(buf[cursor+3], "bool(false)", cursor)
}
if buf[cursor+4] != 'e' {
return 0, errInvalidCharacter(buf[cursor+4], "bool(false)", cursor)
} }
cursor += 5 cursor += 5
**(**interface{})(unsafe.Pointer(&p)) = false **(**interface{})(unsafe.Pointer(&p)) = false
return cursor, nil return cursor, nil
case 'n': case 'n':
if cursor+3 >= int64(len(buf)) { if err := validateNull(buf, cursor); err != nil {
return 0, errUnexpectedEndOfJSON("null", cursor) return 0, err
}
if buf[cursor+1] != 'u' {
return 0, errInvalidCharacter(buf[cursor+1], "null", cursor)
}
if buf[cursor+2] != 'l' {
return 0, errInvalidCharacter(buf[cursor+2], "null", cursor)
}
if buf[cursor+3] != 'l' {
return 0, errInvalidCharacter(buf[cursor+3], "null", cursor)
} }
cursor += 4 cursor += 4
**(**interface{})(unsafe.Pointer(&p)) = nil **(**interface{})(unsafe.Pointer(&p)) = nil

View File

@ -102,17 +102,8 @@ func (d *mapDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (
} }
switch buf[cursor] { switch buf[cursor] {
case 'n': case 'n':
if cursor+3 >= buflen { if err := validateNull(buf, cursor); err != nil {
return 0, errUnexpectedEndOfJSON("null", cursor) return 0, err
}
if buf[cursor+1] != 'u' {
return 0, errInvalidCharacter(buf[cursor+1], "null", cursor)
}
if buf[cursor+2] != 'l' {
return 0, errInvalidCharacter(buf[cursor+2], "null", cursor)
}
if buf[cursor+3] != 'l' {
return 0, errInvalidCharacter(buf[cursor+3], "null", cursor)
} }
cursor += 4 cursor += 4
**(**unsafe.Pointer)(unsafe.Pointer(&p)) = nil **(**unsafe.Pointer)(unsafe.Pointer(&p)) = nil

View File

@ -77,34 +77,22 @@ ERROR:
} }
func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
buflen := int64(len(buf)) for {
for ; cursor < buflen; cursor++ {
switch buf[cursor] { switch buf[cursor] {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
cursor++
continue continue
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
start := cursor start := cursor
cursor++ cursor++
for ; cursor < buflen; cursor++ { for floatTable[buf[cursor]] {
if floatTable[buf[cursor]] { cursor++
continue
}
break
} }
num := buf[start:cursor] num := buf[start:cursor]
return num, cursor, nil return num, cursor, nil
case 'n': case 'n':
if cursor+3 >= buflen { if err := validateNull(buf, cursor); err != nil {
return nil, 0, errUnexpectedEndOfJSON("null", cursor) return nil, 0, err
}
if buf[cursor+1] != 'u' {
return nil, 0, errInvalidCharacter(buf[cursor+1], "null", cursor)
}
if buf[cursor+2] != 'l' {
return nil, 0, errInvalidCharacter(buf[cursor+2], "null", cursor)
}
if buf[cursor+3] != 'l' {
return nil, 0, errInvalidCharacter(buf[cursor+3], "null", cursor)
} }
cursor += 4 cursor += 4
return nil, cursor, nil return nil, cursor, nil
@ -114,5 +102,4 @@ func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
return nil, 0, errUnexpectedEndOfJSON("json.Number", cursor) return nil, 0, errUnexpectedEndOfJSON("json.Number", cursor)
} }
} }
return nil, 0, errUnexpectedEndOfJSON("json.Number", cursor)
} }

View File

@ -60,18 +60,8 @@ func (d *ptrDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) erro
func (d *ptrDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { func (d *ptrDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) {
cursor = skipWhiteSpace(buf, cursor) cursor = skipWhiteSpace(buf, cursor)
if buf[cursor] == 'n' { if buf[cursor] == 'n' {
buflen := int64(len(buf)) if err := validateNull(buf, cursor); err != nil {
if cursor+3 >= buflen { return 0, err
return 0, errUnexpectedEndOfJSON("null", cursor)
}
if buf[cursor+1] != 'u' {
return 0, errInvalidCharacter(buf[cursor+1], "null", cursor)
}
if buf[cursor+2] != 'l' {
return 0, errInvalidCharacter(buf[cursor+2], "null", cursor)
}
if buf[cursor+3] != 'l' {
return 0, errInvalidCharacter(buf[cursor+3], "null", cursor)
} }
if p != nil { if p != nil {
*(*unsafe.Pointer)(p) = nil *(*unsafe.Pointer)(p) = nil

View File

@ -186,24 +186,14 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
return 0, errExceededMaxDepth(buf[cursor], cursor) return 0, errExceededMaxDepth(buf[cursor], cursor)
} }
buflen := int64(len(buf)) for {
for ; cursor < buflen; cursor++ {
switch buf[cursor] { switch buf[cursor] {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
cursor++
continue continue
case 'n': case 'n':
buflen := int64(len(buf)) if err := validateNull(buf, cursor); err != nil {
if cursor+3 >= buflen { return 0, err
return 0, errUnexpectedEndOfJSON("null", cursor)
}
if buf[cursor+1] != 'u' {
return 0, errInvalidCharacter(buf[cursor+1], "null", cursor)
}
if buf[cursor+2] != 'l' {
return 0, errInvalidCharacter(buf[cursor+2], "null", cursor)
}
if buf[cursor+3] != 'l' {
return 0, errInvalidCharacter(buf[cursor+3], "null", cursor)
} }
cursor += 4 cursor += 4
*(*unsafe.Pointer)(p) = nil *(*unsafe.Pointer)(p) = nil
@ -274,9 +264,7 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer)
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return 0, d.errNumber(cursor) return 0, d.errNumber(cursor)
default: default:
goto ERROR
}
}
ERROR:
return 0, errUnexpectedEndOfJSON("slice", cursor) return 0, errUnexpectedEndOfJSON("slice", cursor)
} }
}
}

View File

@ -343,25 +343,13 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err
cursor++ cursor++
} }
case 'n': case 'n':
buflen := int64(len(buf)) if err := validateNull(buf, cursor); err != nil {
if cursor+3 >= buflen { return nil, 0, err
return nil, 0, errUnexpectedEndOfJSON("null", cursor)
}
if buf[cursor+1] != 'u' {
return nil, 0, errInvalidCharacter(buf[cursor+1], "null", cursor)
}
if buf[cursor+2] != 'l' {
return nil, 0, errInvalidCharacter(buf[cursor+2], "null", cursor)
}
if buf[cursor+3] != 'l' {
return nil, 0, errInvalidCharacter(buf[cursor+3], "null", cursor)
} }
cursor += 4 cursor += 4
return nil, cursor, nil return nil, cursor, nil
default: default:
goto ERROR
}
}
ERROR:
return nil, 0, errNotAtBeginningOfValue(cursor) return nil, 0, errNotAtBeginningOfValue(cursor)
} }
}
}

View File

@ -566,17 +566,8 @@ func (d *structDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer
b := (*sliceHeader)(unsafe.Pointer(&buf)).data b := (*sliceHeader)(unsafe.Pointer(&buf)).data
switch char(b, cursor) { switch char(b, cursor) {
case 'n': case 'n':
if cursor+3 >= buflen { if err := validateNull(buf, cursor); err != nil {
return 0, errUnexpectedEndOfJSON("null", cursor) return 0, err
}
if buf[cursor+1] != 'u' {
return 0, errInvalidCharacter(buf[cursor+1], "null", cursor)
}
if buf[cursor+2] != 'l' {
return 0, errInvalidCharacter(buf[cursor+2], "null", cursor)
}
if buf[cursor+3] != 'l' {
return 0, errInvalidCharacter(buf[cursor+3], "null", cursor)
} }
cursor += 4 cursor += 4
return cursor, nil return cursor, nil

View File

@ -1147,7 +1147,7 @@ var unmarshalTests = []unmarshalTest{
{in: `{"B":"true"}`, ptr: new(B), out: B{true}, golden: true}, // 127 {in: `{"B":"true"}`, ptr: new(B), out: B{true}, golden: true}, // 127
{in: `{"B":"false"}`, ptr: new(B), out: B{false}, golden: true}, // 128 {in: `{"B":"false"}`, ptr: new(B), out: B{false}, golden: true}, // 128
{in: `{"B": "maybe"}`, ptr: new(B), err: errors.New(`json: bool unexpected end of JSON input`)}, // 129 {in: `{"B": "maybe"}`, ptr: new(B), err: errors.New(`json: bool unexpected end of JSON input`)}, // 129
{in: `{"B": "tru"}`, ptr: new(B), err: errors.New(`json: invalid character as bool(true)`)}, // 130 {in: `{"B": "tru"}`, ptr: new(B), err: errors.New(`json: invalid character as true`)}, // 130
{in: `{"B": "False"}`, ptr: new(B), err: errors.New(`json: bool unexpected end of JSON input`)}, // 131 {in: `{"B": "False"}`, ptr: new(B), err: errors.New(`json: bool unexpected end of JSON input`)}, // 131
{in: `{"B": "null"}`, ptr: new(B), out: B{false}}, // 132 {in: `{"B": "null"}`, ptr: new(B), out: B{false}}, // 132
{in: `{"B": "nul"}`, ptr: new(B), err: errors.New(`json: invalid character as null`)}, // 133 {in: `{"B": "nul"}`, ptr: new(B), err: errors.New(`json: invalid character as null`)}, // 133

View File

@ -97,10 +97,10 @@ func (d *uintDecoder) decodeStreamByte(s *stream) ([]byte, error) {
} }
func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
buflen := int64(len(buf)) for {
for ; cursor < buflen; cursor++ {
switch buf[cursor] { switch buf[cursor] {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
cursor++
continue continue
case '0': case '0':
cursor++ cursor++
@ -108,27 +108,14 @@ func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error
case '1', '2', '3', '4', '5', '6', '7', '8', '9': case '1', '2', '3', '4', '5', '6', '7', '8', '9':
start := cursor start := cursor
cursor++ cursor++
for ; cursor < buflen; cursor++ { for numTable[buf[cursor]] {
tk := int(buf[cursor]) cursor++
if int('0') <= tk && tk <= int('9') {
continue
}
break
} }
num := buf[start:cursor] num := buf[start:cursor]
return num, cursor, nil return num, cursor, nil
case 'n': case 'n':
if cursor+3 >= buflen { if err := validateNull(buf, cursor); err != nil {
return nil, 0, errUnexpectedEndOfJSON("null", cursor) return nil, 0, err
}
if buf[cursor+1] != 'u' {
return nil, 0, errInvalidCharacter(buf[cursor+1], "null", cursor)
}
if buf[cursor+2] != 'l' {
return nil, 0, errInvalidCharacter(buf[cursor+2], "null", cursor)
}
if buf[cursor+3] != 'l' {
return nil, 0, errInvalidCharacter(buf[cursor+3], "null", cursor)
} }
cursor += 4 cursor += 4
return nil, cursor, nil return nil, cursor, nil
@ -136,7 +123,6 @@ func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error
return nil, 0, d.typeError([]byte{buf[cursor]}, cursor) return nil, 0, d.typeError([]byte{buf[cursor]}, cursor)
} }
} }
return nil, 0, errUnexpectedEndOfJSON("number(unsigned integer)", cursor)
} }
func (d *uintDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { func (d *uintDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {