diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2023-02-15 15:10:00 -0700 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2023-02-16 22:30:29 -0700 |
commit | f823342d5b9c2ca376d038471889176ab74acf1b (patch) | |
tree | f021ae7890922e10a1aa119dcdbd7dd2a587f09e /reencode.go | |
parent | 2b7fff828e29b63ae08a871b4b1e74784fab29e5 (diff) |
reencode: Don't bother tracking the number of bytes written
Diffstat (limited to 'reencode.go')
-rw-r--r-- | reencode.go | 108 |
1 files changed, 41 insertions, 67 deletions
diff --git a/reencode.go b/reencode.go index 4974cb7..f18888c 100644 --- a/reencode.go +++ b/reencode.go @@ -90,14 +90,13 @@ type ReEncoder struct { cfg ReEncoderConfig out fastio.AllWriter - // state: .Write's and .WriteString's utf8-decoding buffer + // state: .Write's/.WriteString's/.WriteRune's utf8-decoding buffer buf [utf8.UTFMax]byte bufLen int - // state: .WriteRune + // state: contract between the public API and .handleRune err error par jsonparse.Parser - written int inputPos int64 // state: .handleRune @@ -166,14 +165,16 @@ func (enc *ReEncoder) Write(p []byte) (int, error) { c, size := utf8.DecodeRune(enc.buf[:]) n += size - enc.bufLen enc.bufLen = 0 - if _, err := enc.WriteRune(c); err != nil { - return 0, err + enc.handleRune(c) + if enc.err != nil { + return 0, enc.err } } for utf8.FullRune(p[n:]) { c, size := utf8.DecodeRune(p[n:]) - if _, err := enc.WriteRune(c); err != nil { - return n, err + enc.handleRune(c) + if enc.err != nil { + return n, enc.err } n += size } @@ -193,18 +194,19 @@ func (enc *ReEncoder) WriteString(p string) (int, error) { c, size := utf8.DecodeRune(enc.buf[:]) n += size - enc.bufLen enc.bufLen = 0 - if _, err := enc.WriteRune(c); err != nil { - return 0, err + enc.handleRune(c) + if enc.err != nil { + return 0, enc.err } } for utf8.FullRuneInString(p[n:]) { c, size := utf8.DecodeRuneInString(p[n:]) - if _, err := enc.WriteRune(c); err != nil { - return n, err + enc.handleRune(c) + if enc.err != nil { + return n, enc.err } n += size } - enc.bufLen = copy(enc.buf[:], p[n:]) return len(p), nil } @@ -213,6 +215,11 @@ func (enc *ReEncoder) WriteByte(b byte) error { return fastio.WriteByte(enc, b) } +// WriteRune does what you'd expect. +func (enc *ReEncoder) WriteRune(c rune) (n int, err error) { + return fastio.WriteRune(enc, c) +} + // Close implements io.Closer; it does what you'd expect, mostly. // // The *ReEncoder may continue to be written to with new JSON values @@ -232,7 +239,7 @@ func (enc *ReEncoder) Close() error { return enc.err } if len(enc.barriers) == 0 { - if err := enc.handleRune(0, jsonparse.RuneTypeError, enc.stackSize()); err != nil { + if err := enc.handleRuneType(0, jsonparse.RuneTypeError, enc.stackSize()); err != nil { enc.err = &ReEncodeWriteError{ Err: err, Offset: enc.inputPos, @@ -246,26 +253,7 @@ func (enc *ReEncoder) Close() error { return nil } -// WriteRune writes a single Unicode code point, returning the number -// of bytes written to the output stream and any error. -// -// Even when there is no error, the number of bytes written may be -// zero (for example, when the rune is whitespace and the ReEncoder is -// minifying the JSON), or it may be substantially longer than one -// code point's worth (for example, when `\uXXXX` escaping a character -// in a string, or when outputing extra whitespace when the ReEncoder -// is prettifying the JSON). -func (enc *ReEncoder) WriteRune(c rune) (n int, err error) { - if enc.err != nil { - return 0, enc.err - } - if enc.bufLen > 0 { - enc.err = fmt.Errorf("lowmemjson.ReEncoder: cannot .WriteRune() when there is a partial rune that has been .Write()en: %q", enc.buf[:enc.bufLen]) - return 0, enc.err - } - - enc.written = 0 - +func (enc *ReEncoder) handleRune(c rune) { rehandle: t, err := enc.par.HandleRune(c) if err != nil { @@ -273,14 +261,14 @@ rehandle: Err: err, Offset: enc.inputPos, } - return enc.written, enc.err + return } - if err := enc.handleRune(c, t, enc.stackSize()); err != nil { + if err := enc.handleRuneType(c, t, enc.stackSize()); err != nil { enc.err = &ReEncodeWriteError{ Err: err, Offset: enc.inputPos, } - return enc.written, enc.err + return } if t == jsonparse.RuneTypeEOF { if enc.cfg.AllowMultipleValues && len(enc.barriers) == 0 { @@ -291,12 +279,11 @@ rehandle: Err: fmt.Errorf("invalid character %q after top-level value", c), Offset: enc.inputPos, } - return enc.written, enc.err + return } } enc.inputPos += int64(utf8.RuneLen(c)) - return enc.written, enc.err } // semi-public API ///////////////////////////////////////////////////////////// @@ -327,7 +314,7 @@ func (enc *ReEncoder) stackSize() int { return sz } -func (enc *ReEncoder) handleRune(c rune, t jsonparse.RuneType, stackSize int) error { +func (enc *ReEncoder) handleRuneType(c rune, t jsonparse.RuneType, stackSize int) error { if enc.cfg.CompactIfUnder == 0 || enc.cfg.Compact || enc.cfg.Indent == "" { return enc.handleRuneNoSpeculation(c, t) } @@ -365,7 +352,7 @@ func (enc *ReEncoder) handleRune(c rune, t jsonparse.RuneType, stackSize int) er t: t, stackSize: stackSize, }) - if err := enc.specu.fmt.handleRune(c, t, stackSize); err != nil { + if err := enc.specu.fmt.handleRuneType(c, t, stackSize); err != nil { return err } switch { @@ -376,7 +363,7 @@ func (enc *ReEncoder) handleRune(c rune, t jsonparse.RuneType, stackSize int) er return err } for _, tuple := range buf[1:] { - if err := enc.handleRune(tuple.c, tuple.t, tuple.stackSize); err != nil { + if err := enc.handleRuneType(tuple.c, tuple.t, tuple.stackSize); err != nil { return err } } @@ -411,11 +398,11 @@ func (enc *ReEncoder) handleRunePre(c rune, t jsonparse.RuneType) (error, bool) if enc.lastNonSpace == jsonparse.RuneTypeEOF { switch { case enc.wasNumber && t.IsNumber(): - if err := enc.emitByte('\n'); err != nil { + if err := enc.out.WriteByte('\n'); err != nil { return err, false } case enc.cfg.Indent != "" && !enc.cfg.Compact: - if err := enc.emitByte('\n'); err != nil { + if err := enc.out.WriteByte('\n'); err != nil { return err, false } } @@ -433,7 +420,7 @@ func (enc *ReEncoder) handleRunePre(c rune, t jsonparse.RuneType) (error, bool) fallthrough default: for enc.fracZeros > 0 { - if err := enc.emitByte('0'); err != nil { + if err := enc.out.WriteByte('0'); err != nil { return err, false } enc.fracZeros-- @@ -449,7 +436,7 @@ func (enc *ReEncoder) handleRunePre(c rune, t jsonparse.RuneType) (error, bool) enc.expZero = false default: if enc.expZero { - if err := enc.emitByte('0'); err != nil { + if err := enc.out.WriteByte('0'); err != nil { return err, false } enc.expZero = false @@ -484,7 +471,7 @@ func (enc *ReEncoder) handleRunePre(c rune, t jsonparse.RuneType) (error, bool) return err, false } case jsonparse.RuneTypeObjectColon: - if err := enc.emitByte(' '); err != nil { + if err := enc.out.WriteByte(' '); err != nil { return err, false } } @@ -508,7 +495,7 @@ func (enc *ReEncoder) handleRuneMain(c rune, t jsonparse.RuneType) error { switch t { case jsonparse.RuneTypeStringChar: - err = enc.emit(jsonstring.WriteStringChar(enc.out, c, escaper(c, BackslashEscapeNone))) + err = jsonstring.WriteStringChar(enc.out, c, escaper(c, BackslashEscapeNone)) case jsonparse.RuneTypeStringEsc, jsonparse.RuneTypeStringEscU: // do nothing case jsonparse.RuneTypeStringEsc1: @@ -528,7 +515,7 @@ func (enc *ReEncoder) handleRuneMain(c rune, t jsonparse.RuneType) error { default: panic(fmt.Errorf("should not happen: rune %q is not a RuneTypeStringEsc1", c)) } - err = enc.emit(jsonstring.WriteStringChar(enc.out, c, escaper(c, BackslashEscapeShort))) + err = jsonstring.WriteStringChar(enc.out, c, escaper(c, BackslashEscapeShort)) case jsonparse.RuneTypeStringEscUA: enc.uhex[0] = byte(c) case jsonparse.RuneTypeStringEscUB: @@ -537,7 +524,7 @@ func (enc *ReEncoder) handleRuneMain(c rune, t jsonparse.RuneType) error { enc.uhex[2] = byte(c) case jsonparse.RuneTypeStringEscUD: c = hexToRune(enc.uhex[0], enc.uhex[1], enc.uhex[2], byte(c)) - err = enc.emit(jsonstring.WriteStringChar(enc.out, c, escaper(c, BackslashEscapeUnicode))) + err = jsonstring.WriteStringChar(enc.out, c, escaper(c, BackslashEscapeUnicode)) case jsonparse.RuneTypeError: // EOF explicitly stated by .Close() fallthrough @@ -546,12 +533,12 @@ func (enc *ReEncoder) handleRuneMain(c rune, t jsonparse.RuneType) error { switch { case enc.cfg.ForceTrailingNewlines && len(enc.barriers) == 0: t = jsonparse.RuneTypeError // enc.lastNonSpace : an NL isn't needed (we already printed one) - err = enc.emitByte('\n') + err = enc.out.WriteByte('\n') default: t = jsonparse.RuneTypeEOF // enc.lastNonSpace : an NL *might* be needed } default: - err = enc.emitByte(byte(c)) + err = enc.out.WriteByte(byte(c)) } if t != jsonparse.RuneTypeSpace { @@ -563,30 +550,17 @@ func (enc *ReEncoder) handleRuneMain(c rune, t jsonparse.RuneType) error { return err } -func (enc *ReEncoder) emitByte(c byte) error { - err := enc.out.WriteByte(c) - if err == nil { - enc.written++ - } - return err -} - -func (enc *ReEncoder) emit(n int, err error) error { - enc.written += n - return err -} - func (enc *ReEncoder) emitNlIndent() error { - if err := enc.emitByte('\n'); err != nil { + if err := enc.out.WriteByte('\n'); err != nil { return err } if enc.cfg.Prefix != "" { - if err := enc.emit(enc.out.WriteString(enc.cfg.Prefix)); err != nil { + if _, err := enc.out.WriteString(enc.cfg.Prefix); err != nil { return err } } for i := 0; i < enc.curIndent; i++ { - if err := enc.emit(enc.out.WriteString(enc.cfg.Indent)); err != nil { + if _, err := enc.out.WriteString(enc.cfg.Indent); err != nil { return err } } |