decode_number.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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 text
  5. // parseNumberValue parses a number from the input and returns a Token object.
  6. func (d *Decoder) parseNumberValue() (Token, bool) {
  7. in := d.in
  8. num := parseNumber(in)
  9. if num.size == 0 {
  10. return Token{}, false
  11. }
  12. numAttrs := num.kind
  13. if num.neg {
  14. numAttrs |= isNegative
  15. }
  16. strSize := num.size
  17. last := num.size - 1
  18. if num.kind == numFloat && (d.in[last] == 'f' || d.in[last] == 'F') {
  19. strSize = last
  20. }
  21. tok := Token{
  22. kind: Scalar,
  23. attrs: numberValue,
  24. pos: len(d.orig) - len(d.in),
  25. raw: d.in[:num.size],
  26. str: string(d.in[:strSize]),
  27. numAttrs: numAttrs,
  28. }
  29. d.consume(num.size)
  30. return tok, true
  31. }
  32. const (
  33. numDec uint8 = (1 << iota) / 2
  34. numHex
  35. numOct
  36. numFloat
  37. )
  38. // number is the result of parsing out a valid number from parseNumber. It
  39. // contains data for doing float or integer conversion via the strconv package
  40. // in conjunction with the input bytes.
  41. type number struct {
  42. kind uint8
  43. neg bool
  44. size int
  45. }
  46. // parseNumber constructs a number object from given input. It allows for the
  47. // following patterns:
  48. //
  49. // integer: ^-?([1-9][0-9]*|0[xX][0-9a-fA-F]+|0[0-7]*)
  50. // float: ^-?((0|[1-9][0-9]*)?([.][0-9]*)?([eE][+-]?[0-9]+)?[fF]?)
  51. //
  52. // It also returns the number of parsed bytes for the given number, 0 if it is
  53. // not a number.
  54. func parseNumber(input []byte) number {
  55. kind := numDec
  56. var size int
  57. var neg bool
  58. s := input
  59. if len(s) == 0 {
  60. return number{}
  61. }
  62. // Optional -
  63. if s[0] == '-' {
  64. neg = true
  65. s = s[1:]
  66. size++
  67. if len(s) == 0 {
  68. return number{}
  69. }
  70. }
  71. // C++ allows for whitespace and comments in between the negative sign and
  72. // the rest of the number. This logic currently does not but is consistent
  73. // with v1.
  74. switch {
  75. case s[0] == '0':
  76. if len(s) > 1 {
  77. switch {
  78. case s[1] == 'x' || s[1] == 'X':
  79. // Parse as hex number.
  80. kind = numHex
  81. n := 2
  82. s = s[2:]
  83. for len(s) > 0 && (('0' <= s[0] && s[0] <= '9') ||
  84. ('a' <= s[0] && s[0] <= 'f') ||
  85. ('A' <= s[0] && s[0] <= 'F')) {
  86. s = s[1:]
  87. n++
  88. }
  89. if n == 2 {
  90. return number{}
  91. }
  92. size += n
  93. case '0' <= s[1] && s[1] <= '7':
  94. // Parse as octal number.
  95. kind = numOct
  96. n := 2
  97. s = s[2:]
  98. for len(s) > 0 && '0' <= s[0] && s[0] <= '7' {
  99. s = s[1:]
  100. n++
  101. }
  102. size += n
  103. }
  104. if kind&(numHex|numOct) > 0 {
  105. if len(s) > 0 && !isDelim(s[0]) {
  106. return number{}
  107. }
  108. return number{kind: kind, neg: neg, size: size}
  109. }
  110. }
  111. s = s[1:]
  112. size++
  113. case '1' <= s[0] && s[0] <= '9':
  114. n := 1
  115. s = s[1:]
  116. for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
  117. s = s[1:]
  118. n++
  119. }
  120. size += n
  121. case s[0] == '.':
  122. // Set kind to numFloat to signify the intent to parse as float. And
  123. // that it needs to have other digits after '.'.
  124. kind = numFloat
  125. default:
  126. return number{}
  127. }
  128. // . followed by 0 or more digits.
  129. if len(s) > 0 && s[0] == '.' {
  130. n := 1
  131. s = s[1:]
  132. // If decimal point was before any digits, it should be followed by
  133. // other digits.
  134. if len(s) == 0 && kind == numFloat {
  135. return number{}
  136. }
  137. for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
  138. s = s[1:]
  139. n++
  140. }
  141. size += n
  142. kind = numFloat
  143. }
  144. // e or E followed by an optional - or + and 1 or more digits.
  145. if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
  146. kind = numFloat
  147. s = s[1:]
  148. n := 1
  149. if s[0] == '+' || s[0] == '-' {
  150. s = s[1:]
  151. n++
  152. if len(s) == 0 {
  153. return number{}
  154. }
  155. }
  156. for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
  157. s = s[1:]
  158. n++
  159. }
  160. size += n
  161. }
  162. // Optional suffix f or F for floats.
  163. if len(s) > 0 && (s[0] == 'f' || s[0] == 'F') {
  164. kind = numFloat
  165. s = s[1:]
  166. size++
  167. }
  168. // Check that next byte is a delimiter or it is at the end.
  169. if len(s) > 0 && !isDelim(s[0]) {
  170. return number{}
  171. }
  172. return number{kind: kind, neg: neg, size: size}
  173. }