summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-02-10 15:48:28 -0700
committerLuke Shumaker <lukeshu@lukeshu.com>2023-02-10 21:45:33 -0700
commit1f0abce0bf4061261572f6ed2f815f71647cc7e5 (patch)
tree7920851db4df070c264d38e7b73228f369a3b705
parent0ce1d3e727ea347c3588f96be8a356fa6ea3bc0e (diff)
encode: Begone with encodeTODO
-rw-r--r--borrowed_misc.go43
-rw-r--r--encode.go29
2 files changed, 59 insertions, 13 deletions
diff --git a/borrowed_misc.go b/borrowed_misc.go
index 59c49aa..52f4a12 100644
--- a/borrowed_misc.go
+++ b/borrowed_misc.go
@@ -7,7 +7,10 @@
package lowmemjson
import (
+ "io"
+ "math"
"reflect"
+ "strconv"
)
// isEmptyValue is borrowed from encode.go.
@@ -28,3 +31,43 @@ func isEmptyValue(v reflect.Value) bool {
}
return false
}
+
+// encodeFloat is lightly modified from
+// encode.go:floatEncoder.encode().
+func encodeFloat(w io.Writer, bits int, v reflect.Value) error {
+ var scratch [64]byte
+
+ f := v.Float()
+ if math.IsInf(f, 0) || math.IsNaN(f) {
+ return &EncodeValueError{Value: v, Str: strconv.FormatFloat(f, 'g', -1, bits)}
+ }
+
+ // Convert as if by ES6 number to string conversion.
+ // This matches most other JSON generators.
+ // See golang.org/issue/6384 and golang.org/issue/14135.
+ // Like fmt %g, but the exponent cutoffs are different
+ // and exponents themselves are not padded to two digits.
+ b := scratch[:0]
+ abs := math.Abs(f)
+ fmt := byte('f')
+ // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
+ if abs != 0 {
+ if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
+ fmt = 'e'
+ }
+ }
+ b = strconv.AppendFloat(b, f, fmt, -1, bits)
+ if fmt == 'e' {
+ // clean up e-09 to e-9
+ n := len(b)
+ if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' {
+ b[n-2] = b[n-1]
+ b = b[:n-1]
+ }
+ }
+
+ if _, err := w.Write(b); err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/encode.go b/encode.go
index 2830ace..492b40f 100644
--- a/encode.go
+++ b/encode.go
@@ -246,13 +246,27 @@ func encode(w *ReEncoder, val reflect.Value, escaper BackslashEscaper, quote boo
return err
}
}
- case reflect.Float32, reflect.Float64:
+ case reflect.Float32:
if quote {
if err := w.WriteByte('"'); err != nil {
return err
}
}
- if err := encodeTODO(w, val); err != nil {
+ if err := encodeFloat(w, 32, val); err != nil {
+ return err
+ }
+ if quote {
+ if err := w.WriteByte('"'); err != nil {
+ return err
+ }
+ }
+ case reflect.Float64:
+ if quote {
+ if err := w.WriteByte('"'); err != nil {
+ return err
+ }
+ }
+ if err := encodeFloat(w, 64, val); err != nil {
return err
}
if quote {
@@ -522,14 +536,3 @@ func encodeArray(w *ReEncoder, val reflect.Value, escaper BackslashEscaper, cycl
}
return nil
}
-
-func encodeTODO(w io.Writer, val reflect.Value) error {
- bs, err := json.Marshal(val.Interface())
- if err != nil {
- return err
- }
- if _, err := w.Write(bs); err != nil {
- return err
- }
- return nil
-}