diff options
Diffstat (limited to 'decode_scan.go')
-rw-r--r-- | decode_scan.go | 180 |
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() {} |