diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2022-07-31 01:36:16 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2022-07-31 01:40:36 -0600 |
commit | 326319cff84557e522b2ea8b21755b22764e85af (patch) | |
tree | be2fd3eafaa17ebbfeb184974e28b9626dfe514f /lib | |
parent | 128959707364340c942399283b15b5025d9aaa70 (diff) |
have reencoder.WriteRune return the number of bytes written to output
Diffstat (limited to 'lib')
-rw-r--r-- | lib/lowmemjson/encode.go | 2 | ||||
-rw-r--r-- | lib/lowmemjson/misc.go | 15 | ||||
-rw-r--r-- | lib/lowmemjson/reencode.go | 110 |
3 files changed, 68 insertions, 59 deletions
diff --git a/lib/lowmemjson/encode.go b/lib/lowmemjson/encode.go index 3f671ea..329f6c2 100644 --- a/lib/lowmemjson/encode.go +++ b/lib/lowmemjson/encode.go @@ -282,7 +282,7 @@ func encodeString[T interface{ ~[]byte | ~string }](w io.Writer, str T) { encodeWriteByte(w, '"') for i := 0; i < len(str); { c, size := decodeRune(str[i:]) - if err := writeStringChar(w, c, false, nil); err != nil { + if _, err := writeStringChar(w, c, false, nil); err != nil { panic(encodeError{err}) } i += size diff --git a/lib/lowmemjson/misc.go b/lib/lowmemjson/misc.go index d1f8f25..b9dbb9b 100644 --- a/lib/lowmemjson/misc.go +++ b/lib/lowmemjson/misc.go @@ -82,7 +82,7 @@ func UnicodeEscapeDefault(c rune, wasEscaped bool) bool { } } -func writeStringUnicodeEscape(w io.Writer, c rune) error { +func writeStringUnicodeEscape(w io.Writer, c rune) (int, error) { buf := [6]byte{ '\\', 'u', @@ -91,15 +91,13 @@ func writeStringUnicodeEscape(w io.Writer, c rune) error { hex[(c>>4)&0xf], hex[(c>>0)&0xf], } - _, err := w.Write(buf[:]) - return err + return w.Write(buf[:]) } -func writeStringShortEscape(w io.Writer, c byte) error { +func writeStringShortEscape(w io.Writer, c byte) (int, error) { buf := [2]byte{'\\', c} - _, err := w.Write(buf[:]) - return err + return w.Write(buf[:]) } -func writeStringChar(w io.Writer, c rune, wasEscaped bool, escaper func(rune, bool) bool) error { +func writeStringChar(w io.Writer, c rune, wasEscaped bool, escaper func(rune, bool) bool) (int, error) { if escaper == nil { escaper = UnicodeEscapeDefault } @@ -124,7 +122,6 @@ func writeStringChar(w io.Writer, c rune, wasEscaped bool, escaper func(rune, bo return writeStringUnicodeEscape(w, c) } default: - _, err := writeRune(w, c) - return err + return writeRune(w, c) } } diff --git a/lib/lowmemjson/reencode.go b/lib/lowmemjson/reencode.go index 721b0b9..836c5f6 100644 --- a/lib/lowmemjson/reencode.go +++ b/lib/lowmemjson/reencode.go @@ -37,6 +37,7 @@ type ReEncoder struct { // state: .WriteRune err error + written int stack []reencodeState stack0IsNumber bool curIndent int @@ -57,13 +58,13 @@ 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 { + if _, err := enc.WriteRune(c); err != nil { return 0, err } } for utf8.FullRune(p[n:]) { c, size := utf8.DecodeRune(p[n:]) - if err := enc.WriteRune(c); err != nil { + if _, err := enc.WriteRune(c); err != nil { return n, err } n += size @@ -90,37 +91,48 @@ func (enc *ReEncoder) Flush() error { } } -func (enc *ReEncoder) WriteRune(c rune) (err error) { +func (enc *ReEncoder) WriteRune(c rune) (n int, err error) { if enc.err != nil { - return enc.err + return 0, enc.err } - defer func() { - if err != nil { - enc.err = err - } - }() if enc.bufLen != 0 { - return errors.New("lowmemjson.ReEncoder: cannot .WriteRune() when there is a partial rune that has been .Write()n") + enc.err = errors.New("lowmemjson.ReEncoder: cannot .WriteRune() when there is a partial rune that has been .Write()n") + return 0, enc.err } - return enc.state(c) + enc.written = 0 + enc.err = enc.state(c) + return enc.written, enc.err } // io helpers ////////////////////////////////////////////////////////////////// +func (enc *ReEncoder) emitByte(c byte) error { + err := writeByte(enc.Out, 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) nlIndent() error { if enc.Compact || enc.Indent == "" { return nil } - if err := writeByte(enc.Out, '\n'); err != nil { + if err := enc.emitByte('\n'); err != nil { return err } if enc.prefix != "" { - if _, err := io.WriteString(enc.Out, enc.prefix); err != nil { + if err := enc.emit(io.WriteString(enc.Out, enc.prefix)); err != nil { return err } } for i := 0; i < enc.curIndent; i++ { - if _, err := io.WriteString(enc.Out, enc.Indent); err != nil { + if err := enc.emit(io.WriteString(enc.Out, enc.Indent)); err != nil { return err } } @@ -186,7 +198,7 @@ func (enc *ReEncoder) stateAny(c rune) error { default: return fmt.Errorf("decode value: unexpected character: %c", c) } - return writeByte(enc.Out, byte(c)) + return enc.emitByte(byte(c)) } // object ////////////////////////////////////////////////////////////////////////////////////////// @@ -216,7 +228,7 @@ func (enc *ReEncoder) _stateInObject(c rune, nonempty bool) error { default: return fmt.Errorf("decode object: unexpected character: %c", c) } - return writeByte(enc.Out, byte(c)) + return enc.emitByte(byte(c)) } func (enc *ReEncoder) stateInKV(c rune) error { switch c { @@ -224,15 +236,15 @@ func (enc *ReEncoder) stateInKV(c rune) error { if enc.Compact || enc.Indent != "" { return nil } - return writeByte(enc.Out, byte(c)) + return enc.emitByte(byte(c)) case ':': enc.replaceState(enc.stateAfterV, false) enc.pushState(enc.stateAny, false) - if err := writeByte(enc.Out, byte(c)); err != nil { + if err := enc.emitByte(byte(c)); err != nil { return err } if !enc.Compact && enc.Indent != "" { - return writeByte(enc.Out, ' ') + return enc.emitByte(' ') } return nil default: @@ -256,7 +268,7 @@ func (enc *ReEncoder) stateAfterV(c rune) error { default: return fmt.Errorf("decode object member: unexpected character: %c", c) } - return writeByte(enc.Out, byte(c)) + return enc.emitByte(byte(c)) } // array /////////////////////////////////////////////////////////////////////////////////////////// @@ -285,7 +297,7 @@ func (enc *ReEncoder) _stateInArray(c rune, nonempty bool) error { enc.pushState(enc.stateAny, false) return enc.state(c) } - return writeByte(enc.Out, byte(c)) + return enc.emitByte(byte(c)) } func (enc *ReEncoder) stateAfterItem(c rune) error { switch c { @@ -304,7 +316,7 @@ func (enc *ReEncoder) stateAfterItem(c rune) error { default: return fmt.Errorf("decode array: unexpected character: %c", c) } - return writeByte(enc.Out, byte(c)) + return enc.emitByte(byte(c)) } // string ////////////////////////////////////////////////////////////////////////////////////////// @@ -316,9 +328,9 @@ func (enc *ReEncoder) stateInString(c rune) error { return nil case c == '"': enc.popState() - return writeByte(enc.Out, byte(c)) + return enc.emitByte(byte(c)) case 0x0020 <= c && c <= 0x10FFFF: - return writeStringChar(enc.Out, c, false, enc.UnicodeEscape) + return enc.emit(writeStringChar(enc.Out, c, false, enc.UnicodeEscape)) default: return fmt.Errorf("decode string: unexpected character: %c", c) } @@ -327,25 +339,25 @@ func (enc *ReEncoder) stateInBackslash(c rune) error { switch c { case '"': enc.replaceState(enc.stateInString, false) - return writeStringChar(enc.Out, '"', false, enc.UnicodeEscape) + return enc.emit(writeStringChar(enc.Out, '"', false, enc.UnicodeEscape)) case '\\': enc.replaceState(enc.stateInString, false) - return writeStringChar(enc.Out, '\\', false, enc.UnicodeEscape) + return enc.emit(writeStringChar(enc.Out, '\\', false, enc.UnicodeEscape)) case 'b': enc.replaceState(enc.stateInString, false) - return writeStringChar(enc.Out, '\b', false, enc.UnicodeEscape) + return enc.emit(writeStringChar(enc.Out, '\b', false, enc.UnicodeEscape)) case 'f': enc.replaceState(enc.stateInString, false) - return writeStringChar(enc.Out, '\f', false, enc.UnicodeEscape) + return enc.emit(writeStringChar(enc.Out, '\f', false, enc.UnicodeEscape)) case 'n': enc.replaceState(enc.stateInString, false) - return writeStringChar(enc.Out, '\n', false, enc.UnicodeEscape) + return enc.emit(writeStringChar(enc.Out, '\n', false, enc.UnicodeEscape)) case 'r': enc.replaceState(enc.stateInString, false) - return writeStringChar(enc.Out, '\r', false, enc.UnicodeEscape) + return enc.emit(writeStringChar(enc.Out, '\r', false, enc.UnicodeEscape)) case 't': enc.replaceState(enc.stateInString, false) - return writeStringChar(enc.Out, '\t', false, enc.UnicodeEscape) + return enc.emit(writeStringChar(enc.Out, '\t', false, enc.UnicodeEscape)) case 'u': enc.replaceState(enc.stateInUnicode, false) return nil @@ -372,7 +384,7 @@ func (enc *ReEncoder) stateInUnicode(c rune) error { rune(enc.stateBuf[2])<<4 | rune(enc.stateBuf[3])<<0 enc.stateBuf = enc.stateBuf[:0] - return writeStringChar(enc.Out, c, true, enc.UnicodeEscape) + return enc.emit(writeStringChar(enc.Out, c, true, enc.UnicodeEscape)) } return nil } @@ -430,7 +442,7 @@ func (enc *ReEncoder) stateNumberA(c rune) error { // start default: return fmt.Errorf("decode number: unexpected character: %c", c) } - return writeByte(enc.Out, byte(c)) + return enc.emitByte(byte(c)) } func (enc *ReEncoder) stateNumberB(c rune) error { // got a leading "-" switch c { @@ -441,17 +453,17 @@ func (enc *ReEncoder) stateNumberB(c rune) error { // got a leading "-" default: return fmt.Errorf("decode number: unexpected character: %c", c) } - return writeByte(enc.Out, byte(c)) + return enc.emitByte(byte(c)) } func (enc *ReEncoder) stateNumberC(c rune) error { // ready for the fraction or exponent part to start switch c { case '.': enc.replaceState(enc.stateNumberE, true) - return writeByte(enc.Out, '.') + return enc.emitByte('.') case 'e', 'E': enc.replaceState(enc.stateNumberG, true) enc.stateBuf = append(enc.stateBuf[:0], 0) - return writeByte(enc.Out, 'e') + return enc.emitByte('e') default: enc.popState() return enc.state(c) @@ -460,14 +472,14 @@ func (enc *ReEncoder) stateNumberC(c rune) error { // ready for the fraction or func (enc *ReEncoder) stateNumberD(c rune) error { // in the integer part switch c { case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - return writeByte(enc.Out, byte(c)) + return enc.emitByte(byte(c)) case '.': enc.replaceState(enc.stateNumberE, true) - return writeByte(enc.Out, '.') + return enc.emitByte('.') case 'e', 'E': enc.replaceState(enc.stateNumberG, true) enc.stateBuf = append(enc.stateBuf[:0], 0) - return writeByte(enc.Out, 'e') + return enc.emitByte('e') default: enc.popState() return enc.state(c) @@ -479,7 +491,7 @@ func (enc *ReEncoder) stateNumberE(c rune) error { // got a ".", ready to read a switch c { case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': enc.replaceState(enc.stateNumberF, true) - return writeByte(enc.Out, byte(c)) + return enc.emitByte(byte(c)) default: return fmt.Errorf("decode number: unexpected character: %c", c) } @@ -495,7 +507,7 @@ func (enc *ReEncoder) stateNumberF(c rune) error { // in the fraction part return nil case '1', '2', '3', '4', '5', '6', '7', '8', '9': for len(enc.stateBuf) > 0 { - if err := writeByte(enc.Out, '0'); err != nil { + if err := enc.emitByte('0'); err != nil { return err } if enc.stateBuf[len(enc.stateBuf)-1] == 1 { @@ -504,11 +516,11 @@ func (enc *ReEncoder) stateNumberF(c rune) error { // in the fraction part enc.stateBuf[len(enc.stateBuf)-1]-- } } - return writeByte(enc.Out, byte(c)) + return enc.emitByte(byte(c)) case 'e', 'E': enc.replaceState(enc.stateNumberG, true) enc.stateBuf = append(enc.stateBuf[:0], 0) - return writeByte(enc.Out, 'e') + return enc.emitByte('e') default: enc.stateBuf = enc.stateBuf[:0] enc.popState() @@ -521,14 +533,14 @@ func (enc *ReEncoder) stateNumberG(c rune) error { // got a leading "e" switch c { case '-', '+': enc.replaceState(enc.stateNumberH, true) - return writeByte(enc.Out, byte(c)) + return enc.emitByte(byte(c)) case '0': enc.replaceState(enc.stateNumberH, true) return nil case '1', '2', '3', '4', '5', '6', '7', '8', '9': enc.replaceState(enc.stateNumberH, true) enc.stateBuf[0] = 1 - return writeByte(enc.Out, byte(c)) + return enc.emitByte(byte(c)) default: enc.stateBuf = enc.stateBuf[:0] return fmt.Errorf("decode number: unexpected character: %c", c) @@ -540,13 +552,13 @@ func (enc *ReEncoder) stateNumberH(c rune) error { // in the exponent's number p if enc.stateBuf[0] == 0 { return nil } - return writeByte(enc.Out, '0') + return enc.emitByte('0') case '1', '2', '3', '4', '5', '6', '7', '8', '9': enc.stateBuf[0] = 1 - return writeByte(enc.Out, byte(c)) + return enc.emitByte(byte(c)) default: if enc.stateBuf[0] == 0 { - if err := writeByte(enc.Out, '0'); err != nil { + if err := enc.emitByte('0'); err != nil { return err } } @@ -569,5 +581,5 @@ func (enc *ReEncoder) _stateInLiteral(c rune, full string) error { if len(enc.stateBuf) == len(full) { enc.popState() } - return writeByte(enc.Out, byte(c)) + return enc.emitByte(byte(c)) } |