iter_skip_sloppy.go 3.2 KB

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