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  }