decode_token.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // Copyright 2019 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. "fmt"
  8. "strconv"
  9. )
  10. // Kind represents a token kind expressible in the JSON format.
  11. type Kind uint16
  12. const (
  13. Invalid Kind = (1 << iota) / 2
  14. EOF
  15. Null
  16. Bool
  17. Number
  18. String
  19. Name
  20. ObjectOpen
  21. ObjectClose
  22. ArrayOpen
  23. ArrayClose
  24. // comma is only for parsing in between tokens and
  25. // does not need to be exported.
  26. comma
  27. )
  28. func (k Kind) String() string {
  29. switch k {
  30. case EOF:
  31. return "eof"
  32. case Null:
  33. return "null"
  34. case Bool:
  35. return "bool"
  36. case Number:
  37. return "number"
  38. case String:
  39. return "string"
  40. case ObjectOpen:
  41. return "{"
  42. case ObjectClose:
  43. return "}"
  44. case Name:
  45. return "name"
  46. case ArrayOpen:
  47. return "["
  48. case ArrayClose:
  49. return "]"
  50. case comma:
  51. return ","
  52. }
  53. return "<invalid>"
  54. }
  55. // Token provides a parsed token kind and value.
  56. //
  57. // Values are provided by the difference accessor methods. The accessor methods
  58. // Name, Bool, and ParsedString will panic if called on the wrong kind. There
  59. // are different accessor methods for the Number kind for converting to the
  60. // appropriate Go numeric type and those methods have the ok return value.
  61. type Token struct {
  62. // Token kind.
  63. kind Kind
  64. // pos provides the position of the token in the original input.
  65. pos int
  66. // raw bytes of the serialized token.
  67. // This is a subslice into the original input.
  68. raw []byte
  69. // boo is parsed boolean value.
  70. boo bool
  71. // str is parsed string value.
  72. str string
  73. }
  74. // Kind returns the token kind.
  75. func (t Token) Kind() Kind {
  76. return t.kind
  77. }
  78. // RawString returns the read value in string.
  79. func (t Token) RawString() string {
  80. return string(t.raw)
  81. }
  82. // Pos returns the token position from the input.
  83. func (t Token) Pos() int {
  84. return t.pos
  85. }
  86. // Name returns the object name if token is Name, else it panics.
  87. func (t Token) Name() string {
  88. if t.kind == Name {
  89. return t.str
  90. }
  91. panic(fmt.Sprintf("Token is not a Name: %v", t.RawString()))
  92. }
  93. // Bool returns the bool value if token kind is Bool, else it panics.
  94. func (t Token) Bool() bool {
  95. if t.kind == Bool {
  96. return t.boo
  97. }
  98. panic(fmt.Sprintf("Token is not a Bool: %v", t.RawString()))
  99. }
  100. // ParsedString returns the string value for a JSON string token or the read
  101. // value in string if token is not a string.
  102. func (t Token) ParsedString() string {
  103. if t.kind == String {
  104. return t.str
  105. }
  106. panic(fmt.Sprintf("Token is not a String: %v", t.RawString()))
  107. }
  108. // Float returns the floating-point number if token kind is Number.
  109. //
  110. // The floating-point precision is specified by the bitSize parameter: 32 for
  111. // float32 or 64 for float64. If bitSize=32, the result still has type float64,
  112. // but it will be convertible to float32 without changing its value. It will
  113. // return false if the number exceeds the floating point limits for given
  114. // bitSize.
  115. func (t Token) Float(bitSize int) (float64, bool) {
  116. if t.kind != Number {
  117. return 0, false
  118. }
  119. f, err := strconv.ParseFloat(t.RawString(), bitSize)
  120. if err != nil {
  121. return 0, false
  122. }
  123. return f, true
  124. }
  125. // Int returns the signed integer number if token is Number.
  126. //
  127. // The given bitSize specifies the integer type that the result must fit into.
  128. // It returns false if the number is not an integer value or if the result
  129. // exceeds the limits for given bitSize.
  130. func (t Token) Int(bitSize int) (int64, bool) {
  131. s, ok := t.getIntStr()
  132. if !ok {
  133. return 0, false
  134. }
  135. n, err := strconv.ParseInt(s, 10, bitSize)
  136. if err != nil {
  137. return 0, false
  138. }
  139. return n, true
  140. }
  141. // Uint returns the signed integer number if token is Number.
  142. //
  143. // The given bitSize specifies the unsigned integer type that the result must
  144. // fit into. It returns false if the number is not an unsigned integer value
  145. // or if the result exceeds the limits for given bitSize.
  146. func (t Token) Uint(bitSize int) (uint64, bool) {
  147. s, ok := t.getIntStr()
  148. if !ok {
  149. return 0, false
  150. }
  151. n, err := strconv.ParseUint(s, 10, bitSize)
  152. if err != nil {
  153. return 0, false
  154. }
  155. return n, true
  156. }
  157. func (t Token) getIntStr() (string, bool) {
  158. if t.kind != Number {
  159. return "", false
  160. }
  161. parts, ok := parseNumberParts(t.raw)
  162. if !ok {
  163. return "", false
  164. }
  165. return normalizeToIntString(parts)
  166. }
  167. // TokenEquals returns true if given Tokens are equal, else false.
  168. func TokenEquals(x, y Token) bool {
  169. return x.kind == y.kind &&
  170. x.pos == y.pos &&
  171. bytes.Equal(x.raw, y.raw) &&
  172. x.boo == y.boo &&
  173. x.str == y.str
  174. }