Tao Wen преди 9 години
родител
ревизия
46d96fb105
променени са 3 файла, в които са добавени 85 реда и са изтрити 83 реда
  1. 53 63
      jsoniter.go
  2. 32 0
      jsoniter_find_end_test.go
  3. 0 20
      jsoniter_skip_test.go

+ 53 - 63
jsoniter.go

@@ -89,6 +89,7 @@ func (iter *Iterator) skipWhitespaces() {
 }
 
 func (iter *Iterator) nextToken() byte {
+	// a variation of skip whitespaces, returning the next non-whitespace token
 	for {
 		for i := iter.head; i < iter.tail; i++ {
 			c := iter.buf[i]
@@ -353,24 +354,6 @@ func (iter *Iterator) findStringEnd() (int, bool) {
 	return -1, true // end with \
 }
 
-
-func (iter *Iterator) skipUntilBreak() {
-	// true, false, null, number
-	for {
-		for i := iter.head; i < iter.tail; i++ {
-			c := iter.buf[i]
-			switch c {
-			case ' ', '\n', '\r', '\t', ',', '}', ']':
-				iter.head = i
-				return
-			}
-		}
-		if (!iter.loadMore()) {
-			return
-		}
-	}
-}
-
 func (iter *Iterator) ReadStringAsBytes() (ret []byte) {
 	c := iter.readByte()
 	if c == 'n' {
@@ -804,64 +787,71 @@ func (iter *Iterator) skipString() {
 }
 
 func (iter *Iterator) skipArray() {
-	c := iter.nextToken()
-	if c == ']' {
-		return
-	} else {
-		iter.unreadByte()
-	}
+	level := 1
 	for {
-		if iter.Error != nil {
-			return
+		for i := iter.head; i < iter.tail; i++ {
+			switch iter.buf[i] {
+			case '"': // If inside string, skip it
+				iter.head = i + 1
+				iter.skipString()
+				i = iter.head - 1 // it will be i++ soon
+			case '[': // If open symbol, increase level
+				level++
+			case ']': // If close symbol, increase level
+				level--
+
+				// If we have returned to the original level, we're done
+				if level == 0 {
+					iter.head = i + 1
+					return
+				}
+			}
 		}
-		iter.Skip()
-		c = iter.nextToken()
-		switch c {
-		case ',':
-			iter.skipWhitespaces()
-			continue
-		case ']':
-			return
-		default:
-			iter.ReportError("skipArray", "expects , or ]")
+		if (!iter.loadMore()) {
 			return
 		}
 	}
 }
 
 func (iter *Iterator) skipObject() {
-	c := iter.nextToken()
-	if c == '}' {
-		return // end of object
-	} else {
-		iter.unreadByte()
-	}
+	level := 1
 	for {
-		c = iter.nextToken()
-		if c != '"' {
-			iter.ReportError("skipObject", `expects "`)
-			return
+		for i := iter.head; i < iter.tail; i++ {
+			switch iter.buf[i] {
+			case '"': // If inside string, skip it
+				iter.head = i + 1
+				iter.skipString()
+				i = iter.head - 1 // it will be i++ soon
+			case '{': // If open symbol, increase level
+				level++
+			case '}': // If close symbol, increase level
+				level--
+
+				// If we have returned to the original level, we're done
+				if level == 0 {
+					iter.head = i + 1
+					return
+				}
+			}
 		}
-		iter.skipString()
-		c = iter.nextToken()
-		if c != ':' {
-			iter.ReportError("skipObject", `expects :`)
+		if (!iter.loadMore()) {
 			return
 		}
-		iter.skipWhitespaces()
-		if iter.Error != nil {
-			return
+	}
+}
+
+func (iter *Iterator) skipUntilBreak() {
+	// true, false, null, number
+	for {
+		for i := iter.head; i < iter.tail; i++ {
+			c := iter.buf[i]
+			switch c {
+			case ' ', '\n', '\r', '\t', ',', '}', ']':
+				iter.head = i
+				return
+			}
 		}
-		iter.Skip()
-		c = iter.nextToken()
-		switch c {
-		case ',':
-			iter.skipWhitespaces()
-			continue
-		case '}':
-			return // end of object
-		default:
-			iter.ReportError("skipObject", "expects , or }")
+		if (!iter.loadMore()) {
 			return
 		}
 	}

+ 32 - 0
jsoniter_find_end_test.go

@@ -136,3 +136,35 @@ func Test_skip_string(t *testing.T) {
 		t.Fatal(iter.head)
 	}
 }
+
+func Test_skip_object(t *testing.T) {
+	iter := ParseString(`}`)
+	iter.skipObject()
+	if iter.head != 1 {
+		t.Fatal(iter.head)
+	}
+	iter = ParseString(`a}`)
+	iter.skipObject()
+	if iter.head != 2 {
+		t.Fatal(iter.head)
+	}
+	iter = ParseString(`{}}a`)
+	iter.skipObject()
+	if iter.head != 3 {
+		t.Fatal(iter.head)
+	}
+	reader := &StagedReader{
+		r1: `{`,
+		r2: `}}a`,
+	}
+	iter = Parse(reader, 4096)
+	iter.skipObject()
+	if iter.head != 2 {
+		t.Fatal(iter.head)
+	}
+	iter = ParseString(`"}"}a`)
+	iter.skipObject()
+	if iter.head != 4 {
+		t.Fatal(iter.head)
+	}
+}

+ 0 - 20
jsoniter_skip_test.go

@@ -66,26 +66,6 @@ func Test_skip_empty_array(t *testing.T) {
 	}
 }
 
-func Test_skip_object(t *testing.T) {
-	iter := ParseString(`[ {"a" : {"b": "c"}, "d": 102 }, "b"]`)
-	iter.ReadArray()
-	iter.Skip()
-	iter.ReadArray()
-	if iter.ReadString() != "b" {
-		t.FailNow()
-	}
-}
-
-func Test_skip_empty_object(t *testing.T) {
-	iter := ParseString(`[ { }, "b"]`)
-	iter.ReadArray()
-	iter.Skip()
-	iter.ReadArray()
-	if iter.ReadString() != "b" {
-		t.FailNow()
-	}
-}
-
 func Test_skip_nested(t *testing.T) {
 	iter := ParseString(`[ {"a" : [{"b": "c"}], "d": 102 }, "b"]`)
 	iter.ReadArray()