literal_tokens.go 6.1 KB

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