Forráskód Böngészése

#61 read any reuse skip impl

Tao Wen 8 éve
szülő
commit
1ec246d16b
3 módosított fájl, 51 hozzáadás és 124 törlés
  1. 26 118
      feature_any.go
  2. 1 0
      feature_iter.go
  3. 24 6
      feature_iter_skip.go

+ 26 - 118
feature_any.go

@@ -167,137 +167,45 @@ func (iter *Iterator) readAny() Any {
 		return iter.readObjectAny()
 	case '[':
 		return iter.readArrayAny()
+	case '-':
+		return iter.readNumberAny(false)
 	default:
-		return iter.readNumberAny(c)
+		return iter.readNumberAny(true)
 	}
 }
 
-func (iter *Iterator) readNumberAny(firstByte byte) Any {
-	dotFound := false
-	lazyBuf := make([]byte, 1, 8)
-	lazyBuf[0] = firstByte
-	for {
-		for i := iter.head; i < iter.tail; i++ {
-			c := iter.buf[i]
-			if c == '.' {
-				dotFound = true
-				continue
-			}
-			switch c {
-			case ' ', '\n', '\r', '\t', ',', '}', ']':
-				lazyBuf = append(lazyBuf, iter.buf[iter.head:i]...)
-				iter.head = i
-				if dotFound {
-					return &float64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
-				} else {
-					if firstByte == '-' {
-						return &int64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
-					} else {
-						return &uint64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
-					}
-				}
-			}
-		}
-		lazyBuf = append(lazyBuf, iter.buf[iter.head:iter.tail]...)
-		if !iter.loadMore() {
-			iter.head = iter.tail
-			if dotFound {
-				return &float64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
-			} else {
-				if firstByte == '-' {
-					return &int64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
-				} else {
-					return &uint64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
-				}
-			}
+func (iter *Iterator) readNumberAny(positive bool) Any {
+	iter.startCapture(iter.head - 1)
+	dotFound := iter.skipNumberAndTellDotFoundOrNot()
+	lazyBuf := iter.stopCapture()
+	if dotFound {
+		return &float64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
+	} else {
+		if positive {
+			return &uint64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
+		} else {
+			return &int64LazyAny{baseAny{}, iter.cfg, lazyBuf, nil, 0}
 		}
 	}
 }
 
 func (iter *Iterator) readStringAny() Any {
-	lazyBuf := make([]byte, 1, 8)
-	lazyBuf[0] = '"'
-	for {
-		end, escaped := iter.findStringEnd()
-		if end == -1 {
-			lazyBuf = append(lazyBuf, iter.buf[iter.head:iter.tail]...)
-			if !iter.loadMore() {
-				iter.reportError("readStringAny", "incomplete string")
-				return &invalidAny{}
-			}
-			if escaped {
-				iter.head = 1 // skip the first char as last char read is \
-			}
-		} else {
-			lazyBuf = append(lazyBuf, iter.buf[iter.head:end]...)
-			iter.head = end
-			return &stringLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, ""}
-		}
-	}
+	iter.startCapture(iter.head - 1)
+	iter.skipString()
+	lazyBuf := iter.stopCapture()
+	return &stringLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, ""}
 }
 
 func (iter *Iterator) readObjectAny() Any {
-	level := 1
-	lazyBuf := make([]byte, 1, 32)
-	lazyBuf[0] = '{'
-	for {
-		start := iter.head
-		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
-					lazyBuf = append(lazyBuf, iter.buf[start:iter.head]...)
-					return &objectLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, nil, lazyBuf}
-				}
-			}
-		}
-		lazyBuf = append(lazyBuf, iter.buf[iter.head:iter.tail]...)
-		if !iter.loadMore() {
-			iter.reportError("skipObject", "incomplete object")
-			return &invalidAny{}
-		}
-	}
+	iter.startCapture(iter.head - 1)
+	iter.skipObject()
+	lazyBuf := iter.stopCapture()
+	return &objectLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, nil, lazyBuf}
 }
 
 func (iter *Iterator) readArrayAny() Any {
-	level := 1
-	lazyBuf := make([]byte, 1, 32)
-	lazyBuf[0] = '['
-	for {
-		start := iter.head
-		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
-					lazyBuf = append(lazyBuf, iter.buf[start:iter.head]...)
-					return &arrayLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, nil, lazyBuf}
-				}
-			}
-		}
-		lazyBuf = append(lazyBuf, iter.buf[iter.head:iter.tail]...)
-		if !iter.loadMore() {
-			iter.reportError("skipArray", "incomplete array")
-			return &invalidAny{}
-		}
-	}
+	iter.startCapture(iter.head - 1)
+	iter.skipArray()
+	lazyBuf := iter.stopCapture()
+	return &arrayLazyAny{baseAny{}, iter.cfg, lazyBuf, nil, nil, lazyBuf}
 }

+ 1 - 0
feature_iter.go

@@ -210,6 +210,7 @@ func (iter *Iterator) readByte() (ret byte) {
 func (iter *Iterator) loadMore() bool {
 	if iter.reader == nil {
 		if iter.Error == nil {
+			iter.head = iter.tail
 			iter.Error = io.EOF
 		}
 		return false

+ 24 - 6
feature_iter_skip.go

@@ -30,7 +30,7 @@ func (iter *Iterator) ReadBool() (ret bool) {
 }
 
 func (iter *Iterator) SkipAndReturnBytes() []byte {
-	iter.startCapture()
+	iter.startCapture(iter.head)
 	iter.Skip()
 	return iter.stopCapture()
 }
@@ -40,11 +40,11 @@ type captureBuffer struct {
 	captured  []byte
 }
 
-func (iter *Iterator) startCapture() {
+func (iter *Iterator) startCapture(captureStartedAt int) {
 	if iter.captured != nil {
 		panic("already in capture mode")
 	}
-	iter.captureStartedAt = iter.head
+	iter.captureStartedAt = captureStartedAt
 	iter.captured = make([]byte, 0, 32)
 }
 
@@ -75,7 +75,7 @@ func (iter *Iterator) Skip() {
 	case 'f':
 		iter.skipFixedBytes(4) // false
 	case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
-		iter.skipUntilBreak()
+		iter.skipNumber()
 	case '[':
 		iter.skipArray()
 	case '{':
@@ -209,8 +209,7 @@ func (iter *Iterator) skipObject() {
 	}
 }
 
-func (iter *Iterator) skipUntilBreak() {
-	// true, false, null, number
+func (iter *Iterator) skipNumber() {
 	for {
 		for i := iter.head; i < iter.tail; i++ {
 			c := iter.buf[i]
@@ -226,6 +225,25 @@ func (iter *Iterator) skipUntilBreak() {
 	}
 }
 
+func (iter *Iterator) skipNumberAndTellDotFoundOrNot() bool {
+	dotFound := false
+	for {
+		for i := iter.head; i < iter.tail; i++ {
+			c := iter.buf[i]
+			switch c {
+			case ' ', '\n', '\r', '\t', ',', '}', ']':
+				iter.head = i
+				return dotFound
+			case '.':
+				dotFound = true
+			}
+		}
+		if !iter.loadMore() {
+			return dotFound
+		}
+	}
+}
+
 func (iter *Iterator) skipFixedBytes(n int) {
 	iter.head += n
 	if iter.head >= iter.tail {