number.go 5.7 KB

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