git.lukeshu.com/go/lowmemjson@v0.3.9-0.20230723050957-72f6d13f6fb2/reencode_compactnum.go (about) 1 // Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com> 2 // 3 // SPDX-License-Identifier: GPL-2.0-or-later 4 5 package lowmemjson 6 7 import ( 8 "git.lukeshu.com/go/lowmemjson/internal/jsonparse" 9 ) 10 11 type reEncodeCompactNum struct { 12 out reEncoderModule 13 14 // state 15 fracFirst bool 16 fracZeros int64 17 expZero bool 18 } 19 20 var _ reEncoderModule = (*reEncodeCompactNum)(nil) 21 22 func (enc *reEncodeCompactNum) PopWriteBarrier() { 23 enc.out.PopWriteBarrier() 24 } 25 26 func (enc *reEncodeCompactNum) HandleRune(c rune, t jsonparse.RuneType, escape BackslashEscapeMode, stackSize int) error { 27 // trim trailing '0's from the fraction-part, but don't remove all digits 28 switch t { 29 case jsonparse.RuneTypeNumberFracDot: 30 enc.fracFirst = true 31 enc.fracZeros = 0 32 case jsonparse.RuneTypeNumberFracDig: 33 if c == '0' && !enc.fracFirst { 34 enc.fracZeros++ 35 return nil 36 } else { 37 for ; enc.fracZeros > 0; enc.fracZeros-- { 38 if err := enc.out.HandleRune('0', jsonparse.RuneTypeNumberFracDig, escape, stackSize); err != nil { 39 return err 40 } 41 } 42 } 43 enc.fracFirst = false 44 } 45 46 // trim leading '0's from the exponent-part, but don't remove all digits 47 switch t { 48 case jsonparse.RuneTypeNumberExpE, jsonparse.RuneTypeNumberExpSign: 49 enc.expZero = true 50 case jsonparse.RuneTypeNumberExpDig: 51 if c == '0' && enc.expZero { 52 return nil 53 } 54 enc.expZero = false 55 default: 56 if enc.expZero { 57 if err := enc.out.HandleRune('0', jsonparse.RuneTypeNumberFracDig, escape, stackSize); err != nil { 58 return err 59 } 60 enc.expZero = false 61 } 62 } 63 64 return enc.out.HandleRune(c, t, escape, stackSize) 65 }