Explorar el Código

support float

Tao Wen hace 9 años
padre
commit
f96cc49fd4
Se han modificado 3 ficheros con 135 adiciones y 2 borrados
  1. 60 1
      README.md
  2. 39 1
      jsoniter.go
  3. 36 0
      jsoniter_float_test.go

+ 60 - 1
README.md

@@ -47,4 +47,63 @@ func Benchmark_json_int(b *testing.B) {
 }
 ```
 
-3000000	       505 ns/op (8x slower)
+3000000	       505 ns/op (8x slower)
+
+# array
+
+```
+func Benchmark_jsoniter_array(b *testing.B) {
+	for n := 0; n < b.N; n++ {
+		iter := ParseString(`[1,2,3]`)
+		for iter.ReadArray() {
+			iter.ReadUint64()
+		}
+	}
+}
+```
+
+10000000	       189 ns/op
+
+```
+func Benchmark_json_array(b *testing.B) {
+	for n := 0; n < b.N; n++ {
+		result := []interface{}{}
+		json.Unmarshal([]byte(`[1,2,3]`), &result)
+	}
+}
+```
+1000000	      1327 ns/op
+
+# object
+
+```
+func Benchmark_jsoniter_object(b *testing.B) {
+	for n := 0; n < b.N; n++ {
+		iter := ParseString(`{"field1": "1", "field2": 2}`)
+		obj := TestObj{}
+		for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
+			switch field {
+			case "field1":
+				obj.Field1 = iter.ReadString()
+			case "field2":
+				obj.Field2 = iter.ReadUint64()
+			default:
+				iter.ReportError("bind object", "unexpected field")
+			}
+		}
+	}
+}
+```
+
+5000000	       401 ns/op
+
+```
+func Benchmark_json_object(b *testing.B) {
+	for n := 0; n < b.N; n++ {
+		result := TestObj{}
+		json.Unmarshal([]byte(`{"field1": "1", "field2": 2}`), &result)
+	}
+}
+```
+
+1000000	      1318 ns/op

+ 39 - 1
jsoniter.go

@@ -4,6 +4,7 @@ import (
 	"io"
 	"fmt"
 	"unicode/utf16"
+	"strconv"
 )
 
 type Iterator struct {
@@ -391,4 +392,41 @@ func (iter *Iterator) readObjectField() (ret string) {
 	}
 	iter.skipWhitespaces()
 	return field
-}
+}
+
+func (iter *Iterator) ReadFloat64() (ret float64) {
+	str := make([]byte, 0, 10)
+	for c := iter.readByte(); iter.Error == nil; c = iter.readByte() {
+		switch {
+		case c == '+':
+			fallthrough
+		case c == '-':
+			fallthrough
+		case c == '.':
+			fallthrough
+		case c == 'e':
+			fallthrough
+		case c == 'E':
+			fallthrough
+		case c > '0' && c < '9':
+			str = append(str, c)
+		default:
+			iter.unreadByte()
+			val, err := strconv.ParseFloat(string(str), 64)
+			if err != nil {
+				iter.Error = err
+				return
+			}
+			return val
+		}
+	}
+	if iter.Error == io.EOF {
+		val, err := strconv.ParseFloat(string(str), 64)
+		if err != nil {
+			iter.Error = err
+			return
+		}
+		return val
+	}
+	return
+}

+ 36 - 0
jsoniter_float_test.go

@@ -0,0 +1,36 @@
+package jsoniter
+
+import (
+	"testing"
+	"encoding/json"
+)
+
+func Test_float64_0(t *testing.T) {
+	iter := ParseString(`0`)
+	val := iter.ReadFloat64()
+	if val != 0 {
+		t.Fatal(val)
+	}
+}
+
+func Test_float64_1_dot_1(t *testing.T) {
+	iter := ParseString(`1.1`)
+	val := iter.ReadFloat64()
+	if val != 1.1 {
+		t.Fatal(val)
+	}
+}
+
+func Benchmark_jsoniter_float(b *testing.B) {
+	for n := 0; n < b.N; n++ {
+		iter := ParseString(`1.1`)
+		iter.ReadFloat64()
+	}
+}
+
+func Benchmark_json_float(b *testing.B) {
+	for n := 0; n < b.N; n++ {
+		result := float64(0)
+		json.Unmarshal([]byte(`1.1`), &result)
+	}
+}