decode_number.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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. // integer: ^-?([1-9][0-9]*|0[xX][0-9a-fA-F]+|0[0-7]*)
  49. // float: ^-?((0|[1-9][0-9]*)?([.][0-9]*)?([eE][+-]?[0-9]+)?[fF]?)
  50. // It also returns the number of parsed bytes for the given number, 0 if it is
  51. // not a number.
  52. func parseNumber(input []byte) number {
  53. kind := numDec
  54. var size int
  55. var neg bool
  56. s := input
  57. if len(s) == 0 {
  58. return number{}
  59. }
  60. // Optional -
  61. if s[0] == '-' {
  62. neg = true
  63. s = s[1:]
  64. size++
  65. if len(s) == 0 {
  66. return number{}
  67. }
  68. }
  69. // C++ allows for whitespace and comments in between the negative sign and
  70. // the rest of the number. This logic currently does not but is consistent
  71. // with v1.
  72. switch {
  73. case s[0] == '0':
  74. if len(s) > 1 {
  75. switch {
  76. case s[1] == 'x' || s[1] == 'X':
  77. // Parse as hex number.
  78. kind = numHex
  79. n := 2
  80. s = s[2:]
  81. for len(s) > 0 && (('0' <= s[0] && s[0] <= '9') ||
  82. ('a' <= s[0] && s[0] <= 'f') ||
  83. ('A' <= s[0] && s[0] <= 'F')) {
  84. s = s[1:]
  85. n++
  86. }
  87. if n == 2 {
  88. return number{}
  89. }
  90. size += n
  91. case '0' <= s[1] && s[1] <= '7':
  92. // Parse as octal number.
  93. kind = numOct
  94. n := 2
  95. s = s[2:]
  96. for len(s) > 0 && '0' <= s[0] && s[0] <= '7' {
  97. s = s[1:]
  98. n++
  99. }
  100. size += n
  101. }
  102. if kind&(numHex|numOct) > 0 {
  103. if len(s) > 0 && !isDelim(s[0]) {
  104. return number{}
  105. }
  106. return number{kind: kind, neg: neg, size: size}
  107. }
  108. }
  109. s = s[1:]
  110. size++
  111. case '1' <= s[0] && s[0] <= '9':
  112. n := 1
  113. s = s[1:]
  114. for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
  115. s = s[1:]
  116. n++
  117. }
  118. size += n
  119. case s[0] == '.':
  120. // Set kind to numFloat to signify the intent to parse as float. And
  121. // that it needs to have other digits after '.'.
  122. kind = numFloat
  123. default:
  124. return number{}
  125. }
  126. // . followed by 0 or more digits.
  127. if len(s) > 0 && s[0] == '.' {
  128. n := 1
  129. s = s[1:]
  130. // If decimal point was before any digits, it should be followed by
  131. // other digits.
  132. if len(s) == 0 && kind == numFloat {
  133. return number{}
  134. }
  135. for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
  136. s = s[1:]
  137. n++
  138. }
  139. size += n
  140. kind = numFloat
  141. }
  142. // e or E followed by an optional - or + and 1 or more digits.
  143. if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
  144. kind = numFloat
  145. s = s[1:]
  146. n := 1
  147. if s[0] == '+' || s[0] == '-' {
  148. s = s[1:]
  149. n++
  150. if len(s) == 0 {
  151. return number{}
  152. }
  153. }
  154. for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
  155. s = s[1:]
  156. n++
  157. }
  158. size += n
  159. }
  160. // Optional suffix f or F for floats.
  161. if len(s) > 0 && (s[0] == 'f' || s[0] == 'F') {
  162. kind = numFloat
  163. s = s[1:]
  164. size++
  165. }
  166. // Check that next byte is a delimiter or it is at the end.
  167. if len(s) > 0 && !isDelim(s[0]) {
  168. return number{}
  169. }
  170. return number{kind: kind, neg: neg, size: size}
  171. }