Browse Source

#21 #22 marshal float precisely by default

Tao Wen 8 năm trước cách đây
mục cha
commit
5fbe4e387d

+ 21 - 0
feature_stream_float.go

@@ -2,6 +2,7 @@ package jsoniter
 
 
 import (
 import (
 	"strconv"
 	"strconv"
+	"unsafe"
 )
 )
 
 
 var POW10 []uint64
 var POW10 []uint64
@@ -11,6 +12,10 @@ func init() {
 }
 }
 
 
 func (stream *Stream) WriteFloat32(val float32) {
 func (stream *Stream) WriteFloat32(val float32) {
+	stream.WriteRaw(strconv.FormatFloat(float64(val), 'f', -1, 32))
+}
+
+func (stream *Stream) WriteFloat32Lossy(val float32) {
 	if val < 0 {
 	if val < 0 {
 		stream.writeByte('-')
 		stream.writeByte('-')
 		val = -val
 		val = -val
@@ -41,6 +46,10 @@ func (stream *Stream) WriteFloat32(val float32) {
 }
 }
 
 
 func (stream *Stream) WriteFloat64(val float64) {
 func (stream *Stream) WriteFloat64(val float64) {
+	stream.WriteRaw(strconv.FormatFloat(float64(val), 'f', -1, 64))
+}
+
+func (stream *Stream) WriteFloat64Lossy(val float64) {
 	if val < 0 {
 	if val < 0 {
 		stream.writeByte('-')
 		stream.writeByte('-')
 		val = -val
 		val = -val
@@ -68,4 +77,16 @@ func (stream *Stream) WriteFloat64(val float64) {
 	for stream.buf[stream.n - 1] == '0' {
 	for stream.buf[stream.n - 1] == '0' {
 		stream.n--
 		stream.n--
 	}
 	}
+}
+
+func EnableLossyFloatMarshalling() {
+	// for better performance
+	RegisterTypeEncoder("float32", func(ptr unsafe.Pointer, stream *Stream) {
+		val := *((*float32)(ptr))
+		stream.WriteFloat32Lossy(val)
+	})
+	RegisterTypeEncoder("float64", func(ptr unsafe.Pointer, stream *Stream) {
+		val := *((*float64)(ptr))
+		stream.WriteFloat64Lossy(val)
+	})
 }
 }

+ 9 - 0
jsoniter_customize_test.go

@@ -56,6 +56,15 @@ func Test_customize_byte_array_encoder(t *testing.T) {
 	should.Equal(`"abc"`, str)
 	should.Equal(`"abc"`, str)
 }
 }
 
 
+func Test_customize_float_marshal(t *testing.T) {
+	should := require.New(t)
+	EnableLossyFloatMarshalling()
+	defer CleanEncoders()
+	str, err := MarshalToString(float32(1.23456789))
+	should.Nil(err)
+	should.Equal("1.234568", str)
+}
+
 type Tom struct {
 type Tom struct {
 	field1 string
 	field1 string
 }
 }

+ 4 - 4
jsoniter_float_test.go

@@ -75,7 +75,7 @@ func Test_write_float32(t *testing.T) {
 			should := require.New(t)
 			should := require.New(t)
 			buf := &bytes.Buffer{}
 			buf := &bytes.Buffer{}
 			stream := NewStream(buf, 4096)
 			stream := NewStream(buf, 4096)
-			stream.WriteFloat32(val)
+			stream.WriteFloat32Lossy(val)
 			stream.Flush()
 			stream.Flush()
 			should.Nil(stream.Error)
 			should.Nil(stream.Error)
 			should.Equal(strconv.FormatFloat(float64(val), 'f', -1, 32), buf.String())
 			should.Equal(strconv.FormatFloat(float64(val), 'f', -1, 32), buf.String())
@@ -94,7 +94,7 @@ func Test_write_float32(t *testing.T) {
 	buf := &bytes.Buffer{}
 	buf := &bytes.Buffer{}
 	stream := NewStream(buf, 10)
 	stream := NewStream(buf, 10)
 	stream.WriteRaw("abcdefg")
 	stream.WriteRaw("abcdefg")
-	stream.WriteFloat32(1.123456)
+	stream.WriteFloat32Lossy(1.123456)
 	stream.Flush()
 	stream.Flush()
 	should.Nil(stream.Error)
 	should.Nil(stream.Error)
 	should.Equal("abcdefg1.123456", buf.String())
 	should.Equal("abcdefg1.123456", buf.String())
@@ -108,7 +108,7 @@ func Test_write_float64(t *testing.T) {
 			should := require.New(t)
 			should := require.New(t)
 			buf := &bytes.Buffer{}
 			buf := &bytes.Buffer{}
 			stream := NewStream(buf, 4096)
 			stream := NewStream(buf, 4096)
-			stream.WriteFloat64(val)
+			stream.WriteFloat64Lossy(val)
 			stream.Flush()
 			stream.Flush()
 			should.Nil(stream.Error)
 			should.Nil(stream.Error)
 			should.Equal(strconv.FormatFloat(val, 'f', -1, 64), buf.String())
 			should.Equal(strconv.FormatFloat(val, 'f', -1, 64), buf.String())
@@ -127,7 +127,7 @@ func Test_write_float64(t *testing.T) {
 	buf := &bytes.Buffer{}
 	buf := &bytes.Buffer{}
 	stream := NewStream(buf, 10)
 	stream := NewStream(buf, 10)
 	stream.WriteRaw("abcdefg")
 	stream.WriteRaw("abcdefg")
-	stream.WriteFloat64(1.123456)
+	stream.WriteFloat64Lossy(1.123456)
 	stream.Flush()
 	stream.Flush()
 	should.Nil(stream.Error)
 	should.Nil(stream.Error)
 	should.Equal("abcdefg1.123456", buf.String())
 	should.Equal("abcdefg1.123456", buf.String())