summaryrefslogtreecommitdiff
path: root/decode_scan.go
diff options
context:
space:
mode:
Diffstat (limited to 'decode_scan.go')
-rw-r--r--decode_scan.go180
1 files changed, 43 insertions, 137 deletions
diff --git a/decode_scan.go b/decode_scan.go
index 387fcea..e233caf 100644
--- a/decode_scan.go
+++ b/decode_scan.go
@@ -5,31 +5,12 @@
package lowmemjson
import (
- "errors"
"io"
"git.lukeshu.com/go/lowmemjson/internal"
)
-type runeTypeScanner interface {
- // The returned error is a *ReadError, a *SyntaxError, or nil.
- // An EOF condition is represented as one of:
- //
- // end of value but not file: (_, >0, RuneTypeEOF, nil)
- // end of both value and file: (_, 0, RuneTypeEOF, nil)
- // end of file in middle of value: (_, 0, RuneTypeError, &DecodeSyntaxError{Offset: offset: Err: io.ErrUnexepctedEOF})
- // end of file at start of value: (_, 0, RuneTypeError, &DecodeSyntaxError{Offset: offset: Err: io.EOF})
- ReadRuneType() (rune, int, internal.RuneType, error)
- // The returned error is a *DecodeReadError, a *DecodeSyntaxError, io.EOF, or nil.
- ReadRune() (rune, int, error)
- UnreadRune() error
- Reset()
- InputOffset() int64
-}
-
-// runeTypeScannerImpl /////////////////////////////////////////////////////////////////////////////
-
-type runeTypeScannerImpl struct {
+type runeTypeScanner struct {
// everything that is not "initialized by constructor" starts
// out as the zero value.
@@ -47,9 +28,7 @@ type runeTypeScannerImpl struct {
rErr error
}
-var _ runeTypeScanner = (*runeTypeScannerImpl)(nil)
-
-func (sc *runeTypeScannerImpl) Reset() {
+func (sc *runeTypeScanner) Reset() {
sc.parser.Reset()
if sc.repeat || (sc.rType == internal.RuneTypeEOF && sc.rSize > 0) {
sc.repeat = false
@@ -69,7 +48,14 @@ func (sc *runeTypeScannerImpl) Reset() {
}
}
-func (sc *runeTypeScannerImpl) ReadRuneType() (rune, int, internal.RuneType, error) {
+// The returned error is a *ReadError, a *SyntaxError, or nil.
+// An EOF condition is represented as one of:
+//
+// end of value but not file: (_, >0, RuneTypeEOF, nil)
+// end of both value and file: (_, 0, RuneTypeEOF, nil)
+// end of file in middle of value: (_, 0, RuneTypeError, &DecodeSyntaxError{Offset: offset: Err: io.ErrUnexepctedEOF})
+// end of file at start of value: (_, 0, RuneTypeError, &DecodeSyntaxError{Offset: offset: Err: io.EOF})
+func (sc *runeTypeScanner) ReadRuneType() (rune, int, internal.RuneType, error) {
switch {
case sc.initialized && (sc.rType == internal.RuneTypeError || sc.rType == internal.RuneTypeEOF):
// do nothing
@@ -77,6 +63,7 @@ func (sc *runeTypeScannerImpl) ReadRuneType() (rune, int, internal.RuneType, err
_, _, _ = sc.inner.ReadRune()
default:
sc.initialized = true
+ again:
var err error
sc.rRune, sc.rSize, err = sc.inner.ReadRune()
sc.offset += int64(sc.rSize)
@@ -91,6 +78,9 @@ func (sc *runeTypeScannerImpl) ReadRuneType() (rune, int, internal.RuneType, err
} else {
sc.rErr = nil
}
+ if sc.rType == internal.RuneTypeSpace {
+ goto again
+ }
case io.EOF:
sc.rType, err = sc.parser.HandleEOF()
if err != nil {
@@ -113,24 +103,12 @@ func (sc *runeTypeScannerImpl) ReadRuneType() (rune, int, internal.RuneType, err
return sc.rRune, sc.rSize, sc.rType, sc.rErr
}
-func (sc *runeTypeScannerImpl) ReadRune() (rune, int, error) {
- r, s, t, e := sc.ReadRuneType()
- switch t {
- case internal.RuneTypeEOF:
- return 0, 0, io.EOF
- case internal.RuneTypeError:
- return 0, 0, e
- default:
- return r, s, nil
- }
-}
-
// UnreadRune undoes a call to .ReadRune() or .ReadRuneType().
//
// If the last call to .ReadRune() or .ReadRuneType() has already been
// unread, or if that call returned a rune with size 0, then
// ErrInvalidUnreadRune is returned. Otherwise, nil is returned.
-func (sc *runeTypeScannerImpl) UnreadRune() error {
+func (sc *runeTypeScanner) UnreadRune() error {
if sc.repeat || sc.rSize == 0 {
return ErrInvalidUnreadRune
}
@@ -139,7 +117,7 @@ func (sc *runeTypeScannerImpl) UnreadRune() error {
return nil
}
-func (sc *runeTypeScannerImpl) InputOffset() int64 {
+func (sc *runeTypeScanner) InputOffset() int64 {
ret := sc.offset
if sc.repeat {
ret -= int64(sc.rSize)
@@ -147,109 +125,37 @@ func (sc *runeTypeScannerImpl) InputOffset() int64 {
return ret
}
-// noWSRuneTypeScanner /////////////////////////////////////////////////////////////////////////////
-
-type noWSRuneTypeScanner struct {
- inner runeTypeScanner
-}
-
-var _ runeTypeScanner = (*noWSRuneTypeScanner)(nil)
-
-func (sc *noWSRuneTypeScanner) ReadRuneType() (rune, int, internal.RuneType, error) {
-again:
- r, s, t, e := sc.inner.ReadRuneType()
- if t == internal.RuneTypeSpace {
- goto again
- }
- return r, s, t, e
-}
-
-func (sc *noWSRuneTypeScanner) ReadRune() (rune, int, error) {
- r, s, t, e := sc.ReadRuneType()
- switch t {
- case internal.RuneTypeEOF:
- return 0, 0, io.EOF
- case internal.RuneTypeError:
- return 0, 0, e
- default:
- return r, s, nil
- }
+func (sc *runeTypeScanner) PushReadBarrier() {
+ sc.parser.PushReadBarrier()
}
-func (sc *noWSRuneTypeScanner) UnreadRune() error { return sc.inner.UnreadRune() }
-func (sc *noWSRuneTypeScanner) Reset() { sc.inner.Reset() }
-func (sc *noWSRuneTypeScanner) InputOffset() int64 { return sc.inner.InputOffset() }
-
-// elemRuneTypeScanner /////////////////////////////////////////////////////////////////////////////
-
-type elemRuneTypeScanner struct {
- inner runeTypeScanner
-
- parser internal.Parser
- repeat bool
- stuck bool
- rType internal.RuneType
- rErr error
-}
-
-var _ runeTypeScanner = (*elemRuneTypeScanner)(nil)
-
-func (sc *elemRuneTypeScanner) ReadRuneType() (rune, int, internal.RuneType, error) {
- // Read it, run it through the parent's parser.
- r, s, t, e := sc.inner.ReadRuneType()
-
- // Run it through our child parser.
- if s > 0 || errors.Is(e, io.ErrUnexpectedEOF) {
- if sc.repeat || sc.stuck {
- sc.repeat = false
- } else {
- var err error
- if s > 0 {
- sc.rType, err = sc.parser.HandleRune(r)
- } else {
- sc.rType, err = sc.parser.HandleEOF()
- }
- if err != nil {
- sc.rErr = &DecodeSyntaxError{
- Offset: sc.inner.InputOffset(),
- Err: err,
- }
- } else {
- sc.rErr = nil
+func (sc *runeTypeScanner) PopReadBarrier() {
+ sc.parser.PopBarrier()
+ if sc.repeat || (sc.rType == internal.RuneTypeEOF && sc.rSize > 0) {
+ // re-figure the rType and rErr
+ var err error
+ sc.rType, err = sc.parser.HandleRune(sc.rRune)
+ if err != nil {
+ sc.rErr = &DecodeSyntaxError{
+ Offset: sc.offset - int64(sc.rSize),
+ Err: err,
}
+ } else {
+ sc.rErr = nil
}
- sc.stuck = sc.rType == internal.RuneTypeEOF || sc.rType == internal.RuneTypeError
- t, e = sc.rType, sc.rErr
- }
-
- // Check if we need to truncate the result.
- if t == internal.RuneTypeEOF {
- if s > 0 {
- _ = sc.inner.UnreadRune()
+ // tell it to use that rType and rErr
+ _ = sc.UnreadRune() // we set it up to always succeed
+ } else if sc.rType == internal.RuneTypeEOF {
+ // re-figure the rType and rErr
+ var err error
+ sc.rType, err = sc.parser.HandleEOF()
+ if err != nil {
+ sc.rErr = &DecodeSyntaxError{
+ Offset: sc.offset,
+ Err: err,
+ }
+ } else {
+ sc.rErr = nil
}
- return 0, 0, internal.RuneTypeEOF, nil
}
-
- return r, s, t, e
}
-
-func (sc *elemRuneTypeScanner) ReadRune() (rune, int, error) {
- r, s, t, e := sc.ReadRuneType()
- switch t {
- case internal.RuneTypeEOF:
- return 0, 0, io.EOF
- case internal.RuneTypeError:
- return 0, 0, e
- default:
- return r, s, nil
- }
-}
-
-func (sc *elemRuneTypeScanner) UnreadRune() error {
- ret := sc.inner.UnreadRune()
- sc.repeat = true
- return ret
-}
-
-func (sc *elemRuneTypeScanner) InputOffset() int64 { return sc.inner.InputOffset() }
-func (sc *elemRuneTypeScanner) Reset() {}