소스 검색

support cb

Tao Wen 9 년 전
부모
커밋
e5e9a13f2e
2개의 변경된 파일75개의 추가작업 그리고 18개의 파일을 삭제
  1. 36 8
      jsoniter.go
  2. 39 10
      jsoniter_object_test.go

+ 36 - 8
jsoniter.go

@@ -538,7 +538,7 @@ func (iter *Iterator) ReadArrayCB(cb func()) {
 		return // null
 	}
 	if c != '[' {
-		iter.ReportError("ReadArray", "expect [ or n")
+		iter.ReportError("ReadArrayCB", "expect [ or n")
 		return
 	}
 	c = iter.nextToken()
@@ -557,13 +557,47 @@ func (iter *Iterator) ReadArrayCB(cb func()) {
 			return
 		}
 		if c != ',' {
-			iter.ReportError("ReadArray", "expect , or ]")
+			iter.ReportError("ReadArrayCB", "expect , or ]")
 			return
 		}
 		iter.skipWhitespaces()
 	}
 }
 
+func (iter *Iterator) ReadObjectCB(cb func(string)) {
+	c := iter.nextToken()
+	if c == 'n' {
+		iter.skipNull()
+		return // null
+	}
+	if c != '{' {
+		iter.ReportError("ReadObjectCB", "expect { or n")
+		return
+	}
+	c = iter.nextToken()
+	if c == '}' {
+		return // []
+	} else {
+		iter.unreadByte()
+	}
+	for {
+		iter.skipWhitespaces()
+		field := iter.readObjectField()
+		if iter.Error != nil {
+			return
+		}
+		cb(field)
+		c = iter.nextToken()
+		if c == '}' {
+			return // end of object
+		}
+		if c != ',' {
+			iter.ReportError("ReadObjectCB", `expect ,`)
+			return
+		}
+	}
+}
+
 func (iter *Iterator) ReadObject() (ret string) {
 	c := iter.nextToken()
 	if iter.Error != nil {
@@ -607,13 +641,7 @@ func (iter *Iterator) ReadObject() (ret string) {
 func (iter *Iterator) readObjectField() (ret string) {
 	str := iter.ReadStringAsBytes()
 	field := *(*string)(unsafe.Pointer(&str))
-	if iter.Error != nil {
-		return
-	}
 	c := iter.nextToken()
-	if iter.Error != nil {
-		return
-	}
 	if c != ':' {
 		iter.ReportError("ReadObject", "expect : after object field")
 		return

+ 39 - 10
jsoniter_object_test.go

@@ -66,6 +66,18 @@ func Test_two_field(t *testing.T) {
 	}
 }
 
+func Test_cb(t *testing.T) {
+	iter := ParseString(`{ "a": "b" , "c": "d" }`)
+	count := 0
+	iter.ReadObjectCB(func(field string) {
+		iter.Skip()
+		count += 1
+	})
+	if count != 2 {
+		t.Fatal(count)
+	}
+}
+
 type TestObj struct {
 	Field1 string
 	Field2 uint64
@@ -73,18 +85,35 @@ type TestObj struct {
 
 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")
+		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")
+			}
+		}
 	}
 }
+
+func Benchmark_jsoniter_cb(b *testing.B) {
+	for n := 0; n < b.N; n++ {
+		iter := ParseString(`{"field1": "1", "field2": 2}`)
+		obj := TestObj{}
+		iter.ReadObjectCB(func(field string) {
+			switch field {
+			case "field1":
+				obj.Field1 = iter.ReadString()
+			case "field2":
+				obj.Field2 = iter.ReadUint64()
+			default:
+				iter.ReportError("bind object", "unexpected field")
+			}
+		})
 	}
 }