github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/jsoni/iter_skip_sloppy.go (about)

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