decode_number.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. // Copyright 2018 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package json
  5. import (
  6. "bytes"
  7. "strconv"
  8. )
  9. // parseNumber reads the given []byte for a valid JSON number. If it is valid,
  10. // it returns the number of bytes. Parsing logic follows the definition in
  11. // https://tools.ietf.org/html/rfc7159#section-6, and is based off
  12. // encoding/json.isValidNumber function.
  13. func parseNumber(input []byte) (int, bool) {
  14. var n int
  15. s := input
  16. if len(s) == 0 {
  17. return 0, false
  18. }
  19. // Optional -
  20. if s[0] == '-' {
  21. s = s[1:]
  22. n++
  23. if len(s) == 0 {
  24. return 0, false
  25. }
  26. }
  27. // Digits
  28. switch {
  29. case s[0] == '0':
  30. s = s[1:]
  31. n++
  32. case '1' <= s[0] && s[0] <= '9':
  33. s = s[1:]
  34. n++
  35. for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
  36. s = s[1:]
  37. n++
  38. }
  39. default:
  40. return 0, false
  41. }
  42. // . followed by 1 or more digits.
  43. if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
  44. s = s[2:]
  45. n += 2
  46. for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
  47. s = s[1:]
  48. n++
  49. }
  50. }
  51. // e or E followed by an optional - or + and
  52. // 1 or more digits.
  53. if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
  54. s = s[1:]
  55. n++
  56. if s[0] == '+' || s[0] == '-' {
  57. s = s[1:]
  58. n++
  59. if len(s) == 0 {
  60. return 0, false
  61. }
  62. }
  63. for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
  64. s = s[1:]
  65. n++
  66. }
  67. }
  68. // Check that next byte is a delimiter or it is at the end.
  69. if n < len(input) && isNotDelim(input[n]) {
  70. return 0, false
  71. }
  72. return n, true
  73. }
  74. // numberParts is the result of parsing out a valid JSON number. It contains
  75. // the parts of a number. The parts are used for integer conversion.
  76. type numberParts struct {
  77. neg bool
  78. intp []byte
  79. frac []byte
  80. exp []byte
  81. }
  82. // parseNumber constructs numberParts from given []byte. The logic here is
  83. // similar to consumeNumber above with the difference of having to construct
  84. // numberParts. The slice fields in numberParts are subslices of the input.
  85. func parseNumberParts(input []byte) (numberParts, bool) {
  86. var neg bool
  87. var intp []byte
  88. var frac []byte
  89. var exp []byte
  90. s := input
  91. if len(s) == 0 {
  92. return numberParts{}, false
  93. }
  94. // Optional -
  95. if s[0] == '-' {
  96. neg = true
  97. s = s[1:]
  98. if len(s) == 0 {
  99. return numberParts{}, false
  100. }
  101. }
  102. // Digits
  103. switch {
  104. case s[0] == '0':
  105. // Skip first 0 and no need to store.
  106. s = s[1:]
  107. case '1' <= s[0] && s[0] <= '9':
  108. intp = s
  109. n := 1
  110. s = s[1:]
  111. for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
  112. s = s[1:]
  113. n++
  114. }
  115. intp = intp[:n]
  116. default:
  117. return numberParts{}, false
  118. }
  119. // . followed by 1 or more digits.
  120. if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
  121. frac = s[1:]
  122. n := 1
  123. s = s[2:]
  124. for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
  125. s = s[1:]
  126. n++
  127. }
  128. frac = frac[:n]
  129. }
  130. // e or E followed by an optional - or + and
  131. // 1 or more digits.
  132. if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
  133. s = s[1:]
  134. exp = s
  135. n := 0
  136. if s[0] == '+' || s[0] == '-' {
  137. s = s[1:]
  138. n++
  139. if len(s) == 0 {
  140. return numberParts{}, false
  141. }
  142. }
  143. for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
  144. s = s[1:]
  145. n++
  146. }
  147. exp = exp[:n]
  148. }
  149. return numberParts{
  150. neg: neg,
  151. intp: intp,
  152. frac: bytes.TrimRight(frac, "0"), // Remove unnecessary 0s to the right.
  153. exp: exp,
  154. }, true
  155. }
  156. // normalizeToIntString returns an integer string in normal form without the
  157. // E-notation for given numberParts. It will return false if it is not an
  158. // integer or if the exponent exceeds than max/min int value.
  159. func normalizeToIntString(n numberParts) (string, bool) {
  160. intpSize := len(n.intp)
  161. fracSize := len(n.frac)
  162. if intpSize == 0 && fracSize == 0 {
  163. return "0", true
  164. }
  165. var exp int
  166. if len(n.exp) > 0 {
  167. i, err := strconv.ParseInt(string(n.exp), 10, 32)
  168. if err != nil {
  169. return "", false
  170. }
  171. exp = int(i)
  172. }
  173. var num []byte
  174. if exp >= 0 {
  175. // For positive E, shift fraction digits into integer part and also pad
  176. // with zeroes as needed.
  177. // If there are more digits in fraction than the E value, then the
  178. // number is not an integer.
  179. if fracSize > exp {
  180. return "", false
  181. }
  182. // Make sure resulting digits are within max value limit to avoid
  183. // unnecessarily constructing a large byte slice that may simply fail
  184. // later on.
  185. const maxDigits = 20 // Max uint64 value has 20 decimal digits.
  186. if intpSize+exp > maxDigits {
  187. return "", false
  188. }
  189. // Set cap to make a copy of integer part when appended.
  190. num = n.intp[:len(n.intp):len(n.intp)]
  191. num = append(num, n.frac...)
  192. for i := 0; i < exp-fracSize; i++ {
  193. num = append(num, '0')
  194. }
  195. } else {
  196. // For negative E, shift digits in integer part out.
  197. // If there are fractions, then the number is not an integer.
  198. if fracSize > 0 {
  199. return "", false
  200. }
  201. // index is where the decimal point will be after adjusting for negative
  202. // exponent.
  203. index := intpSize + exp
  204. if index < 0 {
  205. return "", false
  206. }
  207. num = n.intp
  208. // If any of the digits being shifted to the right of the decimal point
  209. // is non-zero, then the number is not an integer.
  210. for i := index; i < intpSize; i++ {
  211. if num[i] != '0' {
  212. return "", false
  213. }
  214. }
  215. num = num[:index]
  216. }
  217. if n.neg {
  218. return "-" + string(num), true
  219. }
  220. return string(num), true
  221. }