literal_tokens.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. package ini
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. )
  7. var (
  8. runesTrue = []rune("true")
  9. runesFalse = []rune("false")
  10. )
  11. var literalValues = [][]rune{
  12. runesTrue,
  13. runesFalse,
  14. }
  15. func isBoolValue(b []rune) bool {
  16. for _, lv := range literalValues {
  17. if isLitValue(lv, b) {
  18. return true
  19. }
  20. }
  21. return false
  22. }
  23. func isLitValue(want, have []rune) bool {
  24. if len(have) < len(want) {
  25. return false
  26. }
  27. for i := 0; i < len(want); i++ {
  28. if want[i] != have[i] {
  29. return false
  30. }
  31. }
  32. return true
  33. }
  34. // isNumberValue will return whether not the leading characters in
  35. // a byte slice is a number. A number is delimited by whitespace or
  36. // the newline token.
  37. //
  38. // A number is defined to be in a binary, octal, decimal (int | float), hex format,
  39. // or in scientific notation.
  40. func isNumberValue(b []rune) bool {
  41. negativeIndex := 0
  42. helper := numberHelper{}
  43. needDigit := false
  44. for i := 0; i < len(b); i++ {
  45. negativeIndex++
  46. switch b[i] {
  47. case '-':
  48. if helper.IsNegative() || negativeIndex != 1 {
  49. return false
  50. }
  51. helper.Determine(b[i])
  52. needDigit = true
  53. continue
  54. case 'e', 'E':
  55. if err := helper.Determine(b[i]); err != nil {
  56. return false
  57. }
  58. negativeIndex = 0
  59. needDigit = true
  60. continue
  61. case 'b':
  62. if helper.numberFormat == hex {
  63. break
  64. }
  65. fallthrough
  66. case 'o', 'x':
  67. needDigit = true
  68. if i == 0 {
  69. return false
  70. }
  71. fallthrough
  72. case '.':
  73. if err := helper.Determine(b[i]); err != nil {
  74. return false
  75. }
  76. needDigit = true
  77. continue
  78. }
  79. if i > 0 && (isNewline(b[i:]) || isWhitespace(b[i])) {
  80. return !needDigit
  81. }
  82. if !helper.CorrectByte(b[i]) {
  83. return false
  84. }
  85. needDigit = false
  86. }
  87. return !needDigit
  88. }
  89. func isValid(b []rune) (bool, int, error) {
  90. if len(b) == 0 {
  91. // TODO: should probably return an error
  92. return false, 0, nil
  93. }
  94. return isValidRune(b[0]), 1, nil
  95. }
  96. func isValidRune(r rune) bool {
  97. return r != ':' && r != '=' && r != '[' && r != ']' && r != ' ' && r != '\n'
  98. }
  99. // ValueType is an enum that will signify what type
  100. // the Value is
  101. type ValueType int
  102. func (v ValueType) String() string {
  103. switch v {
  104. case NoneType:
  105. return "NONE"
  106. case DecimalType:
  107. return "FLOAT"
  108. case IntegerType:
  109. return "INT"
  110. case StringType:
  111. return "STRING"
  112. case BoolType:
  113. return "BOOL"
  114. }
  115. return ""
  116. }
  117. // ValueType enums
  118. const (
  119. NoneType = ValueType(iota)
  120. DecimalType
  121. IntegerType
  122. StringType
  123. QuotedStringType
  124. BoolType
  125. )
  126. // Value is a union container
  127. type Value struct {
  128. Type ValueType
  129. raw []rune
  130. integer int64
  131. decimal float64
  132. boolean bool
  133. str string
  134. }
  135. func newValue(t ValueType, base int, raw []rune) (Value, error) {
  136. v := Value{
  137. Type: t,
  138. raw: raw,
  139. }
  140. var err error
  141. switch t {
  142. case DecimalType:
  143. v.decimal, err = strconv.ParseFloat(string(raw), 64)
  144. case IntegerType:
  145. if base != 10 {
  146. raw = raw[2:]
  147. }
  148. v.integer, err = strconv.ParseInt(string(raw), base, 64)
  149. case StringType:
  150. v.str = string(raw)
  151. case QuotedStringType:
  152. v.str = string(raw[1 : len(raw)-1])
  153. case BoolType:
  154. v.boolean = runeCompare(v.raw, runesTrue)
  155. }
  156. // issue 2253
  157. //
  158. // if the value trying to be parsed is too large, then we will use
  159. // the 'StringType' and raw value instead.
  160. if nerr, ok := err.(*strconv.NumError); ok && nerr.Err == strconv.ErrRange {
  161. v.Type = StringType
  162. v.str = string(raw)
  163. err = nil
  164. }
  165. return v, err
  166. }
  167. // Append will append values and change the type to a string
  168. // type.
  169. func (v *Value) Append(tok Token) {
  170. r := tok.Raw()
  171. if v.Type != QuotedStringType {
  172. v.Type = StringType
  173. r = tok.raw[1 : len(tok.raw)-1]
  174. }
  175. if tok.Type() != TokenLit {
  176. v.raw = append(v.raw, tok.Raw()...)
  177. } else {
  178. v.raw = append(v.raw, r...)
  179. }
  180. }
  181. func (v Value) String() string {
  182. switch v.Type {
  183. case DecimalType:
  184. return fmt.Sprintf("decimal: %f", v.decimal)
  185. case IntegerType:
  186. return fmt.Sprintf("integer: %d", v.integer)
  187. case StringType:
  188. return fmt.Sprintf("string: %s", string(v.raw))
  189. case QuotedStringType:
  190. return fmt.Sprintf("quoted string: %s", string(v.raw))
  191. case BoolType:
  192. return fmt.Sprintf("bool: %t", v.boolean)
  193. default:
  194. return "union not set"
  195. }
  196. }
  197. func newLitToken(b []rune) (Token, int, error) {
  198. n := 0
  199. var err error
  200. token := Token{}
  201. if b[0] == '"' {
  202. n, err = getStringValue(b)
  203. if err != nil {
  204. return token, n, err
  205. }
  206. token = newToken(TokenLit, b[:n], QuotedStringType)
  207. } else if isNumberValue(b) {
  208. var base int
  209. base, n, err = getNumericalValue(b)
  210. if err != nil {
  211. return token, 0, err
  212. }
  213. value := b[:n]
  214. vType := IntegerType
  215. if contains(value, '.') || hasExponent(value) {
  216. vType = DecimalType
  217. }
  218. token = newToken(TokenLit, value, vType)
  219. token.base = base
  220. } else if isBoolValue(b) {
  221. n, err = getBoolValue(b)
  222. token = newToken(TokenLit, b[:n], BoolType)
  223. } else {
  224. n, err = getValue(b)
  225. token = newToken(TokenLit, b[:n], StringType)
  226. }
  227. return token, n, err
  228. }
  229. // IntValue returns an integer value
  230. func (v Value) IntValue() int64 {
  231. return v.integer
  232. }
  233. // FloatValue returns a float value
  234. func (v Value) FloatValue() float64 {
  235. return v.decimal
  236. }
  237. // BoolValue returns a bool value
  238. func (v Value) BoolValue() bool {
  239. return v.boolean
  240. }
  241. func isTrimmable(r rune) bool {
  242. switch r {
  243. case '\n', ' ':
  244. return true
  245. }
  246. return false
  247. }
  248. // StringValue returns the string value
  249. func (v Value) StringValue() string {
  250. switch v.Type {
  251. case StringType:
  252. return strings.TrimFunc(string(v.raw), isTrimmable)
  253. case QuotedStringType:
  254. // preserve all characters in the quotes
  255. return string(removeEscapedCharacters(v.raw[1 : len(v.raw)-1]))
  256. default:
  257. return strings.TrimFunc(string(v.raw), isTrimmable)
  258. }
  259. }
  260. func contains(runes []rune, c rune) bool {
  261. for i := 0; i < len(runes); i++ {
  262. if runes[i] == c {
  263. return true
  264. }
  265. }
  266. return false
  267. }
  268. func runeCompare(v1 []rune, v2 []rune) bool {
  269. if len(v1) != len(v2) {
  270. return false
  271. }
  272. for i := 0; i < len(v1); i++ {
  273. if v1[i] != v2[i] {
  274. return false
  275. }
  276. }
  277. return true
  278. }