diff --git a/internal/decoder/array.go b/internal/decoder/array.go index 4283a00..bc8d971 100644 --- a/internal/decoder/array.go +++ b/internal/decoder/array.go @@ -58,8 +58,7 @@ func (d *arrayDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) er } } idx++ - s.skipWhiteSpace() - switch s.char() { + switch s.skipWhiteSpace() { case ']': for idx < d.alen { *(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue diff --git a/internal/decoder/bool.go b/internal/decoder/bool.go index b885ce0..870d3df 100644 --- a/internal/decoder/bool.go +++ b/internal/decoder/bool.go @@ -16,9 +16,9 @@ func newBoolDecoder(structName, fieldName string) *boolDecoder { } func (d *boolDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { - s.skipWhiteSpace() + c := s.skipWhiteSpace() for { - switch s.char() { + switch c { case 't': if err := trueBytes(s); err != nil { return err @@ -38,6 +38,7 @@ func (d *boolDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) err return nil case nul: if s.read() { + c = s.char() continue } goto ERROR diff --git a/internal/decoder/interface.go b/internal/decoder/interface.go index a1bc9b5..9b59455 100644 --- a/internal/decoder/interface.go +++ b/internal/decoder/interface.go @@ -176,9 +176,9 @@ func decodeTextUnmarshaler(buf []byte, cursor, depth int64, unmarshaler encoding } func (d *interfaceDecoder) decodeStreamEmptyInterface(s *Stream, depth int64, p unsafe.Pointer) error { - s.skipWhiteSpace() + c := s.skipWhiteSpace() for { - switch s.char() { + switch c { case '{': var v map[string]interface{} ptr := unsafe.Pointer(&v) @@ -239,6 +239,7 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *Stream, depth int64, p return nil case nul: if s.read() { + c = s.char() continue } } @@ -265,8 +266,7 @@ func (d *interfaceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok { return decodeStreamTextUnmarshaler(s, depth, u, p) } - s.skipWhiteSpace() - if s.char() == 'n' { + if s.skipWhiteSpace() == 'n' { if err := nullBytes(s); err != nil { return err } @@ -285,8 +285,7 @@ func (d *interfaceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr { return d.decodeStreamEmptyInterface(s, depth, p) } - s.skipWhiteSpace() - if s.char() == 'n' { + if s.skipWhiteSpace() == 'n' { if err := nullBytes(s); err != nil { return err } diff --git a/internal/decoder/map.go b/internal/decoder/map.go index 501f009..b1b3437 100644 --- a/internal/decoder/map.go +++ b/internal/decoder/map.go @@ -42,8 +42,7 @@ func (d *mapDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) erro return errors.ErrExceededMaxDepth(s.char(), s.cursor) } - s.skipWhiteSpace() - switch s.char() { + switch s.skipWhiteSpace() { case 'n': if err := nullBytes(s); err != nil { return err @@ -54,7 +53,6 @@ func (d *mapDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) erro default: return errors.ErrExpected("{ character for map value", s.totalOffset()) } - s.skipWhiteSpace() mapValue := *(*unsafe.Pointer)(p) if mapValue == nil { mapValue = makemap(d.mapType, 0) diff --git a/internal/decoder/ptr.go b/internal/decoder/ptr.go index fa8ed03..9eb6014 100644 --- a/internal/decoder/ptr.go +++ b/internal/decoder/ptr.go @@ -35,8 +35,7 @@ func (d *ptrDecoder) contentDecoder() Decoder { func unsafe_New(*runtime.Type) unsafe.Pointer func (d *ptrDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { - s.skipWhiteSpace() - if s.char() == nul { + if s.skipWhiteSpace() == nul { s.read() } if s.char() == 'n' { diff --git a/internal/decoder/slice.go b/internal/decoder/slice.go index 3584f8a..e17b158 100644 --- a/internal/decoder/slice.go +++ b/internal/decoder/slice.go @@ -111,8 +111,7 @@ func (d *sliceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) er return nil case '[': s.cursor++ - s.skipWhiteSpace() - if s.char() == ']' { + if s.skipWhiteSpace() == ']' { dst := (*sliceHeader)(p) if dst.data == nil { dst.data = newArray(d.elemType, 0) diff --git a/internal/decoder/stream.go b/internal/decoder/stream.go index ca68440..b473244 100644 --- a/internal/decoder/stream.go +++ b/internal/decoder/stream.go @@ -90,6 +90,10 @@ func (s *Stream) stat() ([]byte, int64, unsafe.Pointer) { return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data } +func (s *Stream) bufptr() unsafe.Pointer { + return (*sliceHeader)(unsafe.Pointer(&s.buf)).data +} + func (s *Stream) statForRetry() ([]byte, int64, unsafe.Pointer) { s.cursor-- // for retry ( because caller progress cursor position in each loop ) return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data @@ -219,17 +223,21 @@ func (s *Stream) read() bool { return true } -func (s *Stream) skipWhiteSpace() { +func (s *Stream) skipWhiteSpace() byte { + p := s.bufptr() LOOP: - switch s.char() { + c := char(p, s.cursor) + switch c { case ' ', '\n', '\t', '\r': s.cursor++ goto LOOP case nul: if s.read() { + p = s.bufptr() goto LOOP } } + return c } func (s *Stream) skipObject(depth int64) error { diff --git a/internal/decoder/struct.go b/internal/decoder/struct.go index 6fbb0ce..102db78 100644 --- a/internal/decoder/struct.go +++ b/internal/decoder/struct.go @@ -627,23 +627,20 @@ func (d *structDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) e return errors.ErrExceededMaxDepth(s.char(), s.cursor) } - s.skipWhiteSpace() - switch s.char() { + c := s.skipWhiteSpace() + switch c { case 'n': if err := nullBytes(s); err != nil { return err } return nil - case nul: - s.read() default: if s.char() != '{' { return errors.ErrNotAtBeginningOfValue(s.totalOffset()) } } s.cursor++ - s.skipWhiteSpace() - if s.char() == '}' { + if s.skipWhiteSpace() == '}' { s.cursor++ return nil } @@ -653,16 +650,10 @@ func (d *structDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) e if err != nil { return err } - s.skipWhiteSpace() - if s.char() != ':' { + if s.skipWhiteSpace() != ':' { return errors.ErrExpected("colon after object key", s.totalOffset()) } s.cursor++ - if s.char() == nul { - if !s.read() { - return errors.ErrExpected("object value after colon", s.totalOffset()) - } - } if field != nil { if field.err != nil { return field.err @@ -677,8 +668,7 @@ func (d *structDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) e return err } } - s.skipWhiteSpace() - c := s.char() + c := s.skipWhiteSpace() if c == '}' { s.cursor++ return nil