iter_skip_sloppy.go raw

   1  //+build jsoniter_sloppy
   2  
   3  package jsoniter
   4  
   5  // sloppy but faster implementation, do not validate the input json
   6  
   7  func (iter *Iterator) skipNumber() {
   8  	for {
   9  		for i := iter.head; i < iter.tail; i++ {
  10  			c := iter.buf[i]
  11  			switch c {
  12  			case ' ', '\n', '\r', '\t', ',', '}', ']':
  13  				iter.head = i
  14  				return
  15  			}
  16  		}
  17  		if !iter.loadMore() {
  18  			return
  19  		}
  20  	}
  21  }
  22  
  23  func (iter *Iterator) skipArray() {
  24  	level := 1
  25  	if !iter.incrementDepth() {
  26  		return
  27  	}
  28  	for {
  29  		for i := iter.head; i < iter.tail; i++ {
  30  			switch iter.buf[i] {
  31  			case '"': // If inside string, skip it
  32  				iter.head = i + 1
  33  				iter.skipString()
  34  				i = iter.head - 1 // it will be i++ soon
  35  			case '[': // If open symbol, increase level
  36  				level++
  37  				if !iter.incrementDepth() {
  38  					return
  39  				}
  40  			case ']': // If close symbol, increase level
  41  				level--
  42  				if !iter.decrementDepth() {
  43  					return
  44  				}
  45  
  46  				// If we have returned to the original level, we're done
  47  				if level == 0 {
  48  					iter.head = i + 1
  49  					return
  50  				}
  51  			}
  52  		}
  53  		if !iter.loadMore() {
  54  			iter.ReportError("skipObject", "incomplete array")
  55  			return
  56  		}
  57  	}
  58  }
  59  
  60  func (iter *Iterator) skipObject() {
  61  	level := 1
  62  	if !iter.incrementDepth() {
  63  		return
  64  	}
  65  
  66  	for {
  67  		for i := iter.head; i < iter.tail; i++ {
  68  			switch iter.buf[i] {
  69  			case '"': // If inside string, skip it
  70  				iter.head = i + 1
  71  				iter.skipString()
  72  				i = iter.head - 1 // it will be i++ soon
  73  			case '{': // If open symbol, increase level
  74  				level++
  75  				if !iter.incrementDepth() {
  76  					return
  77  				}
  78  			case '}': // If close symbol, increase level
  79  				level--
  80  				if !iter.decrementDepth() {
  81  					return
  82  				}
  83  
  84  				// If we have returned to the original level, we're done
  85  				if level == 0 {
  86  					iter.head = i + 1
  87  					return
  88  				}
  89  			}
  90  		}
  91  		if !iter.loadMore() {
  92  			iter.ReportError("skipObject", "incomplete object")
  93  			return
  94  		}
  95  	}
  96  }
  97  
  98  func (iter *Iterator) skipString() {
  99  	for {
 100  		end, escaped := iter.findStringEnd()
 101  		if end == -1 {
 102  			if !iter.loadMore() {
 103  				iter.ReportError("skipString", "incomplete string")
 104  				return
 105  			}
 106  			if escaped {
 107  				iter.head = 1 // skip the first char as last char read is \
 108  			}
 109  		} else {
 110  			iter.head = end
 111  			return
 112  		}
 113  	}
 114  }
 115  
 116  // adapted from: https://github.com/buger/jsonparser/blob/master/parser.go
 117  // Tries to find the end of string
 118  // Support if string contains escaped quote symbols.
 119  func (iter *Iterator) findStringEnd() (int, bool) {
 120  	escaped := false
 121  	for i := iter.head; i < iter.tail; i++ {
 122  		c := iter.buf[i]
 123  		if c == '"' {
 124  			if !escaped {
 125  				return i + 1, false
 126  			}
 127  			j := i - 1
 128  			for {
 129  				if j < iter.head || iter.buf[j] != '\\' {
 130  					// even number of backslashes
 131  					// either end of buffer, or " found
 132  					return i + 1, true
 133  				}
 134  				j--
 135  				if j < iter.head || iter.buf[j] != '\\' {
 136  					// odd number of backslashes
 137  					// it is \" or \\\"
 138  					break
 139  				}
 140  				j--
 141  			}
 142  		} else if c == '\\' {
 143  			escaped = true
 144  		}
 145  	}
 146  	j := iter.tail - 1
 147  	for {
 148  		if j < iter.head || iter.buf[j] != '\\' {
 149  			// even number of backslashes
 150  			// either end of buffer, or " found
 151  			return -1, false // do not end with \
 152  		}
 153  		j--
 154  		if j < iter.head || iter.buf[j] != '\\' {
 155  			// odd number of backslashes
 156  			// it is \" or \\\"
 157  			break
 158  		}
 159  		j--
 160  
 161  	}
 162  	return -1, true // end with \
 163  }
 164