diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2023-02-04 17:50:16 -0700 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2023-02-04 17:50:16 -0700 |
commit | 07d40ba94387eb2420093566cf11087ba66f391f (patch) | |
tree | b9a3e4cdf56bb555a42c88d3f8e1bb833e8c59b9 /reencode.go | |
parent | 4fac0e4475dfcfa5e209467e33d58d0e6beddb31 (diff) | |
parent | 183832b22bf2730645aebffab41211fbfec2e18c (diff) |
Merge branch 'lukeshu/fix'
Diffstat (limited to 'reencode.go')
-rw-r--r-- | reencode.go | 50 |
1 files changed, 34 insertions, 16 deletions
diff --git a/reencode.go b/reencode.go index b135fb8..3e9cf37 100644 --- a/reencode.go +++ b/reencode.go @@ -108,8 +108,13 @@ type ReEncoder struct { expZero bool specu *speculation - // state: .pushBarrier and .popBarrier - stackInputPos []int64 + // state: .pushWriteBarrier and .popWriteBarrier + barriers []barrier +} + +type barrier struct { + inputPos int64 + stackSize int } type speculation struct { @@ -224,15 +229,17 @@ func (enc *ReEncoder) Close() error { } return enc.err } - if err := enc.handleRune(0, internal.RuneTypeError, enc.par.StackSize()); err != nil { - enc.err = &ReEncodeSyntaxError{ - Err: err, - Offset: enc.inputPos, + if len(enc.barriers) == 0 { + if err := enc.handleRune(0, internal.RuneTypeError, enc.stackSize()); err != nil { + enc.err = &ReEncodeSyntaxError{ + Err: err, + Offset: enc.inputPos, + } + return enc.err + } + if enc.AllowMultipleValues { + enc.par.Reset() } - return enc.err - } - if enc.AllowMultipleValues && len(enc.stackInputPos) == 0 { - enc.par.Reset() } return nil } @@ -266,9 +273,9 @@ rehandle: } return enc.written, enc.err } - enc.err = enc.handleRune(c, t, enc.par.StackSize()) + enc.err = enc.handleRune(c, t, enc.stackSize()) if enc.err == nil && t == internal.RuneTypeEOF { - if enc.AllowMultipleValues && len(enc.stackInputPos) == 0 { + if enc.AllowMultipleValues && len(enc.barriers) == 0 { enc.par.Reset() goto rehandle } else { @@ -287,20 +294,31 @@ rehandle: // semi-public API ///////////////////////////////////////////////////////////// func (enc *ReEncoder) pushWriteBarrier() { + enc.barriers = append(enc.barriers, barrier{ + inputPos: enc.inputPos, + stackSize: enc.stackSize(), + }) enc.par.PushWriteBarrier() - enc.stackInputPos = append(enc.stackInputPos, enc.inputPos) enc.inputPos = 0 } func (enc *ReEncoder) popWriteBarrier() { enc.par.PopBarrier() - enc.inputPos += enc.stackInputPos[len(enc.stackInputPos)-1] - enc.stackInputPos = enc.stackInputPos[:len(enc.stackInputPos)-1] + enc.inputPos += enc.barriers[len(enc.barriers)-1].inputPos + enc.barriers = enc.barriers[:len(enc.barriers)-1] enc.lastNonSpace = enc.lastNonSpaceNonEOF } // internal //////////////////////////////////////////////////////////////////// +func (enc *ReEncoder) stackSize() int { + sz := enc.par.StackSize() + for _, barrier := range enc.barriers { + sz += barrier.stackSize + } + return sz +} + func (enc *ReEncoder) handleRune(c rune, t internal.RuneType, stackSize int) error { if enc.CompactIfUnder == 0 || enc.Compact || enc.Indent == "" { return enc.handleRuneNoSpeculation(c, t) @@ -522,7 +540,7 @@ func (enc *ReEncoder) handleRuneMain(c rune, t internal.RuneType) error { case internal.RuneTypeEOF: // EOF implied by the start of the next top-level value enc.wasNumber = enc.lastNonSpace.IsNumber() switch { - case enc.ForceTrailingNewlines && len(enc.stackInputPos) == 0: + case enc.ForceTrailingNewlines && len(enc.barriers) == 0: t = internal.RuneTypeError // enc.lastNonSpace : an NL isn't needed (we already printed one) err = enc.emitByte('\n') default: |