Remove context for decoding

This commit is contained in:
Masaaki Goshima 2020-05-07 02:37:29 +09:00
parent 82e8cc766f
commit f198ef6517
12 changed files with 159 additions and 200 deletions

View File

@ -23,7 +23,7 @@ type Token interface{}
type Delim rune type Delim rune
type decoder interface { type decoder interface {
decode(*context, uintptr) error decode([]byte, int, uintptr) (int, error)
} }
type Decoder struct { type Decoder struct {
@ -47,17 +47,11 @@ func (m *decoderMap) set(k uintptr, dec decoder) {
} }
var ( var (
ctxPool sync.Pool
cachedDecoder decoderMap cachedDecoder decoderMap
) )
func init() { func init() {
cachedDecoder = decoderMap{} cachedDecoder = decoderMap{}
ctxPool = sync.Pool{
New: func() interface{} {
return newContext()
},
}
} }
// NewDecoder returns a new decoder that reads from r. // NewDecoder returns a new decoder that reads from r.
@ -90,13 +84,9 @@ func (d *Decoder) decode(src []byte, header *interfaceHeader) error {
dec = compiledDec dec = compiledDec
} }
ptr := uintptr(header.ptr) ptr := uintptr(header.ptr)
ctx := ctxPool.Get().(*context) if _, err := dec.decode(src, 0, ptr); err != nil {
ctx.setBuf(src)
if err := dec.decode(ctx, ptr); err != nil {
ctxPool.Put(ctx)
return err return err
} }
ctxPool.Put(ctx)
return nil return nil
} }
@ -133,11 +123,6 @@ func (d *Decoder) Decode(v interface{}) error {
dec = compiledDec dec = compiledDec
} }
ptr := uintptr(header.ptr) ptr := uintptr(header.ptr)
ctx := ctxPool.Get().(*context)
defer ctxPool.Put(ctx)
d.buffered = func() io.Reader {
return bytes.NewReader(ctx.buf[ctx.cursor:])
}
for { for {
buf := make([]byte, 1024) buf := make([]byte, 1024)
n, err := d.r.Read(buf) n, err := d.r.Read(buf)
@ -147,10 +132,13 @@ func (d *Decoder) Decode(v interface{}) error {
if err != nil { if err != nil {
return err return err
} }
ctx.setBuf(buf[:n]) cursor, err := dec.decode(buf[:n], 0, ptr)
if err := dec.decode(ctx, ptr); err != nil { if err != nil {
return err return err
} }
d.buffered = func() io.Reader {
return bytes.NewReader(buf[cursor:])
}
} }
return nil return nil
} }

View File

@ -20,10 +20,8 @@ func newArrayDecoder(dec decoder, elemType *rtype, alen int) *arrayDecoder {
} }
} }
func (d *arrayDecoder) decode(ctx *context, p uintptr) error { func (d *arrayDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
buf := ctx.buf buflen := len(buf)
buflen := ctx.buflen
cursor := ctx.cursor
for ; cursor < buflen; cursor++ { for ; cursor < buflen; cursor++ {
switch buf[cursor] { switch buf[cursor] {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
@ -31,23 +29,25 @@ func (d *arrayDecoder) decode(ctx *context, p uintptr) error {
case '[': case '[':
idx := 0 idx := 0
for { for {
ctx.cursor = cursor + 1 cursor++
if err := d.valueDecoder.decode(ctx, p+uintptr(idx)*d.size); err != nil { c, err := d.valueDecoder.decode(buf, cursor, p+uintptr(idx)*d.size)
return err if err != nil {
return 0, err
} }
cursor = ctx.skipWhiteSpace() cursor = c
cursor = skipWhiteSpace(buf, cursor)
switch buf[cursor] { switch buf[cursor] {
case ']': case ']':
ctx.cursor++ cursor++
return nil return cursor, nil
case ',': case ',':
idx++ idx++
continue continue
default: default:
return errors.New("syntax error array") return 0, errors.New("syntax error array")
} }
} }
} }
} }
return errors.New("unexpected error array") return 0, errors.New("unexpected error array")
} }

View File

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

View File

@ -11,31 +11,13 @@ func init() {
isWhiteSpace['\r'] = true isWhiteSpace['\r'] = true
} }
type context struct { func skipWhiteSpace(buf []byte, cursor int) int {
cursor int buflen := len(buf)
buf []byte for ; cursor < buflen; cursor++ {
buflen int
}
func (c *context) setBuf(buf []byte) {
c.buf = buf
c.buflen = len(buf)
c.cursor = 0
}
func (c *context) skipWhiteSpace() int {
buflen := c.buflen
buf := c.buf
for cursor := c.cursor; cursor < buflen; cursor++ {
if isWhiteSpace[buf[cursor]] { if isWhiteSpace[buf[cursor]] {
continue continue
} }
c.cursor = cursor
return cursor return cursor
} }
return buflen return buflen
} }
func newContext() *context {
return &context{}
}

View File

@ -14,10 +14,8 @@ func newFloatDecoder(op func(uintptr, float64)) *floatDecoder {
return &floatDecoder{op: op} return &floatDecoder{op: op}
} }
func (d *floatDecoder) decodeByte(ctx *context) ([]byte, error) { func (d *floatDecoder) decodeByte(buf []byte, cursor int) ([]byte, int, error) {
buf := ctx.buf buflen := len(buf)
cursor := ctx.cursor
buflen := ctx.buflen
for ; cursor < buflen; cursor++ { for ; cursor < buflen; cursor++ {
switch buf[cursor] { switch buf[cursor] {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
@ -32,24 +30,24 @@ func (d *floatDecoder) decodeByte(ctx *context) ([]byte, error) {
} }
break break
} }
num := ctx.buf[start:cursor] num := buf[start:cursor]
ctx.cursor = cursor return num, cursor, nil
return num, nil
} }
} }
return nil, errors.New("unexpected error number") return nil, 0, errors.New("unexpected error number")
} }
func (d *floatDecoder) decode(ctx *context, p uintptr) error { func (d *floatDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
bytes, err := d.decodeByte(ctx) bytes, c, err := d.decodeByte(buf, cursor)
if err != nil { if err != nil {
return err return 0, err
} }
cursor = c
s := *(*string)(unsafe.Pointer(&bytes)) s := *(*string)(unsafe.Pointer(&bytes))
f64, err := strconv.ParseFloat(s, 64) f64, err := strconv.ParseFloat(s, 64)
if err != nil { if err != nil {
return err return 0, err
} }
d.op(p, f64) d.op(p, f64)
return nil return cursor, nil
} }

View File

@ -38,10 +38,8 @@ func (d *intDecoder) parseInt(b []byte) int64 {
return sum return sum
} }
func (d *intDecoder) decodeByte(ctx *context) ([]byte, error) { func (d *intDecoder) decodeByte(buf []byte, cursor int) ([]byte, int, error) {
buf := ctx.buf buflen := len(buf)
cursor := ctx.cursor
buflen := ctx.buflen
for ; cursor < buflen; cursor++ { for ; cursor < buflen; cursor++ {
switch buf[cursor] { switch buf[cursor] {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
@ -56,19 +54,19 @@ func (d *intDecoder) decodeByte(ctx *context) ([]byte, error) {
} }
break break
} }
num := ctx.buf[start:cursor] num := buf[start:cursor]
ctx.cursor = cursor return num, cursor, nil
return num, nil
} }
} }
return nil, errors.New("unexpected error number") return nil, 0, errors.New("unexpected error number")
} }
func (d *intDecoder) decode(ctx *context, p uintptr) error { func (d *intDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
bytes, err := d.decodeByte(ctx) bytes, c, err := d.decodeByte(buf, cursor)
if err != nil { if err != nil {
return err return 0, err
} }
cursor = c
d.op(p, d.parseInt(bytes)) d.op(p, d.parseInt(bytes))
return nil return cursor, nil
} }

View File

@ -26,57 +26,57 @@ func makemap(*rtype, int) unsafe.Pointer
//go:noescape //go:noescape
func mapassign(t *rtype, m unsafe.Pointer, key, val unsafe.Pointer) func mapassign(t *rtype, m unsafe.Pointer, key, val unsafe.Pointer)
func (d *mapDecoder) setKey(ctx *context, key interface{}) error { func (d *mapDecoder) setKey(buf []byte, cursor int, key interface{}) (int, error) {
header := (*interfaceHeader)(unsafe.Pointer(&key)) header := (*interfaceHeader)(unsafe.Pointer(&key))
return d.keyDecoder.decode(ctx, uintptr(header.ptr)) return d.keyDecoder.decode(buf, cursor, uintptr(header.ptr))
} }
func (d *mapDecoder) setValue(ctx *context, key interface{}) error { func (d *mapDecoder) setValue(buf []byte, cursor int, key interface{}) (int, error) {
header := (*interfaceHeader)(unsafe.Pointer(&key)) header := (*interfaceHeader)(unsafe.Pointer(&key))
return d.valueDecoder.decode(ctx, uintptr(header.ptr)) return d.valueDecoder.decode(buf, cursor, uintptr(header.ptr))
} }
func (d *mapDecoder) decode(ctx *context, p uintptr) error { func (d *mapDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
ctx.skipWhiteSpace() cursor = skipWhiteSpace(buf, cursor)
buf := ctx.buf buflen := len(buf)
buflen := ctx.buflen
cursor := ctx.cursor
if buflen < 2 { if buflen < 2 {
return errors.New("unexpected error {}") return 0, errors.New("unexpected error {}")
} }
if buf[cursor] != '{' { if buf[cursor] != '{' {
return errors.New("unexpected error {") return 0, errors.New("unexpected error {")
} }
cursor++ cursor++
mapValue := makemap(d.mapType, 0) mapValue := makemap(d.mapType, 0)
for ; cursor < buflen; cursor++ { for ; cursor < buflen; cursor++ {
ctx.cursor = cursor
var key interface{} var key interface{}
if err := d.setKey(ctx, &key); err != nil { keyCursor, err := d.setKey(buf, cursor, &key)
return err if err != nil {
return 0, err
} }
cursor = ctx.skipWhiteSpace() cursor = keyCursor
cursor = skipWhiteSpace(buf, cursor)
if buf[cursor] != ':' { if buf[cursor] != ':' {
return errors.New("unexpected error invalid delimiter for object") return 0, errors.New("unexpected error invalid delimiter for object")
} }
cursor++ cursor++
if cursor >= buflen { if cursor >= buflen {
return errors.New("unexpected error missing value") return 0, errors.New("unexpected error missing value")
} }
ctx.cursor = cursor
var value interface{} var value interface{}
if err := d.setValue(ctx, &value); err != nil { valueCursor, err := d.setValue(buf, cursor, &value)
return err if err != nil {
return 0, err
} }
cursor = valueCursor
mapassign(d.mapType, mapValue, unsafe.Pointer(&key), unsafe.Pointer(&value)) mapassign(d.mapType, mapValue, unsafe.Pointer(&key), unsafe.Pointer(&value))
cursor = ctx.skipWhiteSpace() cursor = skipWhiteSpace(buf, valueCursor)
if buf[cursor] == '}' { if buf[cursor] == '}' {
*(*unsafe.Pointer)(unsafe.Pointer(p)) = mapValue *(*unsafe.Pointer)(unsafe.Pointer(p)) = mapValue
return nil return cursor, nil
} }
if buf[cursor] != ',' { if buf[cursor] != ',' {
return errors.New("unexpected error ,") return 0, errors.New("unexpected error ,")
} }
} }
return nil return cursor, nil
} }

View File

@ -16,11 +16,13 @@ func newPtrDecoder(dec decoder, typ *rtype) *ptrDecoder {
//go:linkname unsafe_New reflect.unsafe_New //go:linkname unsafe_New reflect.unsafe_New
func unsafe_New(*rtype) uintptr func unsafe_New(*rtype) uintptr
func (d *ptrDecoder) decode(ctx *context, p uintptr) error { func (d *ptrDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
newptr := unsafe_New(d.typ) newptr := unsafe_New(d.typ)
if err := d.dec.decode(ctx, newptr); err != nil { c, err := d.dec.decode(buf, cursor, newptr)
return err if err != nil {
return 0, err
} }
cursor = c
*(*uintptr)(unsafe.Pointer(p)) = newptr *(*uintptr)(unsafe.Pointer(p)) = newptr
return nil return cursor, nil
} }

View File

@ -26,10 +26,8 @@ func copySlice(elemType *rtype, dst, src reflect.SliceHeader) int
//go:linkname newArray reflect.unsafe_NewArray //go:linkname newArray reflect.unsafe_NewArray
func newArray(*rtype, int) unsafe.Pointer func newArray(*rtype, int) unsafe.Pointer
func (d *sliceDecoder) decode(ctx *context, p uintptr) error { func (d *sliceDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
buf := ctx.buf buflen := len(buf)
buflen := ctx.buflen
cursor := ctx.cursor
for ; cursor < buflen; cursor++ { for ; cursor < buflen; cursor++ {
switch buf[cursor] { switch buf[cursor] {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
@ -39,7 +37,7 @@ func (d *sliceDecoder) decode(ctx *context, p uintptr) error {
cap := 2 cap := 2
data := uintptr(newArray(d.elemType, cap)) data := uintptr(newArray(d.elemType, cap))
for { for {
ctx.cursor = cursor + 1 cursor++
if cap <= idx { if cap <= idx {
src := reflect.SliceHeader{Data: data, Len: idx, Cap: cap} src := reflect.SliceHeader{Data: data, Len: idx, Cap: cap}
cap *= 2 cap *= 2
@ -47,10 +45,12 @@ func (d *sliceDecoder) decode(ctx *context, p uintptr) error {
dst := reflect.SliceHeader{Data: data, Len: idx, Cap: cap} dst := reflect.SliceHeader{Data: data, Len: idx, Cap: cap}
copySlice(d.elemType, dst, src) copySlice(d.elemType, dst, src)
} }
if err := d.valueDecoder.decode(ctx, data+uintptr(idx)*d.size); err != nil { c, err := d.valueDecoder.decode(buf, cursor, data+uintptr(idx)*d.size)
return err if err != nil {
return 0, err
} }
cursor = ctx.skipWhiteSpace() cursor = c
cursor = skipWhiteSpace(buf, cursor)
switch buf[cursor] { switch buf[cursor] {
case ']': case ']':
*(*reflect.SliceHeader)(unsafe.Pointer(p)) = reflect.SliceHeader{ *(*reflect.SliceHeader)(unsafe.Pointer(p)) = reflect.SliceHeader{
@ -58,16 +58,16 @@ func (d *sliceDecoder) decode(ctx *context, p uintptr) error {
Len: idx + 1, Len: idx + 1,
Cap: cap, Cap: cap,
} }
ctx.cursor++ cursor++
return nil return cursor, nil
case ',': case ',':
idx++ idx++
continue continue
default: default:
return errors.New("syntax error slice") return 0, errors.New("syntax error slice")
} }
} }
} }
} }
return errors.New("unexpected error slice") return 0, errors.New("unexpected error slice")
} }

View File

@ -12,19 +12,18 @@ func newStringDecoder() *stringDecoder {
return &stringDecoder{} return &stringDecoder{}
} }
func (d *stringDecoder) decode(ctx *context, p uintptr) error { func (d *stringDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
bytes, err := d.decodeByte(ctx) bytes, c, err := d.decodeByte(buf, cursor)
if err != nil { if err != nil {
return err return 0, err
} }
cursor = c
*(*string)(unsafe.Pointer(p)) = *(*string)(unsafe.Pointer(&bytes)) *(*string)(unsafe.Pointer(p)) = *(*string)(unsafe.Pointer(&bytes))
return nil return cursor, nil
} }
func (d *stringDecoder) decodeByte(ctx *context) ([]byte, error) { func (d *stringDecoder) decodeByte(buf []byte, cursor int) ([]byte, int, error) {
buf := ctx.buf buflen := len(buf)
buflen := ctx.buflen
cursor := ctx.cursor
for ; cursor < buflen; cursor++ { for ; cursor < buflen; cursor++ {
switch buf[cursor] { switch buf[cursor] {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
@ -39,27 +38,26 @@ func (d *stringDecoder) decodeByte(ctx *context) ([]byte, error) {
case '"': case '"':
literal := buf[start:cursor] literal := buf[start:cursor]
cursor++ cursor++
ctx.cursor = cursor return literal, cursor, nil
return literal, nil
} }
} }
return nil, errors.New("unexpected error string") return nil, 0, errors.New("unexpected error string")
case 'n': case 'n':
if cursor+3 >= ctx.buflen { if cursor+3 >= buflen {
return nil, errors.New("unexpected error. invalid bool character") return nil, 0, errors.New("unexpected error. invalid bool character")
} }
if buf[cursor+1] != 'u' { if buf[cursor+1] != 'u' {
return nil, errors.New("unexpected error. invalid bool character") return nil, 0, errors.New("unexpected error. invalid bool character")
} }
if buf[cursor+2] != 'l' { if buf[cursor+2] != 'l' {
return nil, errors.New("unexpected error. invalid bool character") return nil, 0, errors.New("unexpected error. invalid bool character")
} }
if buf[cursor+3] != 'l' { if buf[cursor+3] != 'l' {
return nil, errors.New("unexpected error. invalid bool character") return nil, 0, errors.New("unexpected error. invalid bool character")
} }
ctx.cursor += 5 cursor += 5
return []byte{}, nil return []byte{}, cursor, nil
} }
} }
return nil, errors.New("unexpected error key delimiter") return nil, 0, errors.New("unexpected error key delimiter")
} }

View File

@ -22,13 +22,11 @@ func newStructDecoder(fieldMap map[string]*structFieldSet) *structDecoder {
} }
} }
func (d *structDecoder) skipValue(ctx *context) error { func (d *structDecoder) skipValue(buf []byte, cursor int) (int, error) {
ctx.skipWhiteSpace() cursor = skipWhiteSpace(buf, cursor)
braceCount := 0 braceCount := 0
bracketCount := 0 bracketCount := 0
cursor := ctx.cursor buflen := len(buf)
buf := ctx.buf
buflen := ctx.buflen
for ; cursor < buflen; cursor++ { for ; cursor < buflen; cursor++ {
switch buf[cursor] { switch buf[cursor] {
case '{': case '{':
@ -38,15 +36,13 @@ func (d *structDecoder) skipValue(ctx *context) error {
case '}': case '}':
braceCount-- braceCount--
if braceCount == -1 && bracketCount == 0 { if braceCount == -1 && bracketCount == 0 {
ctx.cursor = cursor return cursor, nil
return nil
} }
case ']': case ']':
bracketCount-- bracketCount--
case ',': case ',':
if bracketCount == 0 && braceCount == 0 { if bracketCount == 0 && braceCount == 0 {
ctx.cursor = cursor return cursor, nil
return nil
} }
case '"': case '"':
cursor++ cursor++
@ -56,8 +52,7 @@ func (d *structDecoder) skipValue(ctx *context) error {
cursor++ cursor++
case '"': case '"':
if bracketCount == 0 && braceCount == 0 { if bracketCount == 0 && braceCount == 0 {
ctx.cursor = cursor + 1 return cursor + 1, nil
return nil
} }
goto QUOTE_END goto QUOTE_END
} }
@ -65,55 +60,56 @@ func (d *structDecoder) skipValue(ctx *context) error {
QUOTE_END: QUOTE_END:
} }
} }
return errors.New("unexpected error value") return cursor, errors.New("unexpected error value")
} }
func (d *structDecoder) decode(ctx *context, p uintptr) error { func (d *structDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
ctx.skipWhiteSpace() buflen := len(buf)
buf := ctx.buf cursor = skipWhiteSpace(buf, cursor)
buflen := ctx.buflen
cursor := ctx.cursor
if buflen < 2 { if buflen < 2 {
return errors.New("unexpected error {}") return 0, errors.New("unexpected error {}")
} }
if buf[cursor] != '{' { if buf[cursor] != '{' {
return errors.New("unexpected error {") return 0, errors.New("unexpected error {")
} }
cursor++ cursor++
for ; cursor < buflen; cursor++ { for ; cursor < buflen; cursor++ {
ctx.cursor = cursor key, c, err := d.keyDecoder.decodeByte(buf, cursor)
key, err := d.keyDecoder.decodeByte(ctx)
if err != nil { if err != nil {
return err return 0, err
} }
cursor = ctx.skipWhiteSpace() cursor = c
cursor = skipWhiteSpace(buf, cursor)
if buf[cursor] != ':' { if buf[cursor] != ':' {
return errors.New("unexpected error invalid delimiter for object") return 0, errors.New("unexpected error invalid delimiter for object")
} }
cursor++ cursor++
if cursor >= buflen { if cursor >= buflen {
return errors.New("unexpected error missing value") return 0, errors.New("unexpected error missing value")
} }
ctx.cursor = cursor
k := *(*string)(unsafe.Pointer(&key)) k := *(*string)(unsafe.Pointer(&key))
field, exists := d.fieldMap[k] field, exists := d.fieldMap[k]
if exists { if exists {
if err := field.dec.decode(ctx, p+field.offset); err != nil { c, err := field.dec.decode(buf, cursor, p+field.offset)
return err if err != nil {
return 0, err
} }
cursor = c
} else { } else {
if err := d.skipValue(ctx); err != nil { c, err := d.skipValue(buf, cursor)
return err if err != nil {
return 0, err
} }
cursor = c
} }
cursor = ctx.skipWhiteSpace() cursor = skipWhiteSpace(buf, cursor)
if buf[cursor] == '}' { if buf[cursor] == '}' {
ctx.cursor++ cursor++
return nil return cursor, nil
} }
if buf[cursor] != ',' { if buf[cursor] != ',' {
return errors.New("unexpected error ,") return 0, errors.New("unexpected error ,")
} }
} }
return nil return cursor, nil
} }

View File

@ -28,10 +28,8 @@ func (d *uintDecoder) parseUint(b []byte) uint64 {
return sum return sum
} }
func (d *uintDecoder) decodeByte(ctx *context) ([]byte, error) { func (d *uintDecoder) decodeByte(buf []byte, cursor int) ([]byte, int, error) {
buf := ctx.buf buflen := len(buf)
buflen := ctx.buflen
cursor := ctx.cursor
for ; cursor < buflen; cursor++ { for ; cursor < buflen; cursor++ {
switch buf[cursor] { switch buf[cursor] {
case ' ', '\n', '\t', '\r': case ' ', '\n', '\t', '\r':
@ -47,18 +45,18 @@ func (d *uintDecoder) decodeByte(ctx *context) ([]byte, error) {
break break
} }
num := buf[start:cursor] num := buf[start:cursor]
ctx.cursor = cursor return num, cursor, nil
return num, nil
} }
} }
return nil, errors.New("unexpected error number") return nil, 0, errors.New("unexpected error number")
} }
func (d *uintDecoder) decode(ctx *context, p uintptr) error { func (d *uintDecoder) decode(buf []byte, cursor int, p uintptr) (int, error) {
bytes, err := d.decodeByte(ctx) bytes, c, err := d.decodeByte(buf, cursor)
if err != nil { if err != nil {
return err return 0, err
} }
cursor = c
d.op(p, d.parseUint(bytes)) d.op(p, d.parseUint(bytes))
return nil return cursor, nil
} }