value_util.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. package ini
  2. import (
  3. "fmt"
  4. )
  5. // getStringValue will return a quoted string and the amount
  6. // of bytes read
  7. //
  8. // an error will be returned if the string is not properly formatted
  9. func getStringValue(b []rune) (int, error) {
  10. if b[0] != '"' {
  11. return 0, NewParseError("strings must start with '\"'")
  12. }
  13. endQuote := false
  14. i := 1
  15. for ; i < len(b) && !endQuote; i++ {
  16. if escaped := isEscaped(b[:i], b[i]); b[i] == '"' && !escaped {
  17. endQuote = true
  18. break
  19. } else if escaped {
  20. /*c, err := getEscapedByte(b[i])
  21. if err != nil {
  22. return 0, err
  23. }
  24. b[i-1] = c
  25. b = append(b[:i], b[i+1:]...)
  26. i--*/
  27. continue
  28. }
  29. }
  30. if !endQuote {
  31. return 0, NewParseError("missing '\"' in string value")
  32. }
  33. return i + 1, nil
  34. }
  35. // getBoolValue will return a boolean and the amount
  36. // of bytes read
  37. //
  38. // an error will be returned if the boolean is not of a correct
  39. // value
  40. func getBoolValue(b []rune) (int, error) {
  41. if len(b) < 4 {
  42. return 0, NewParseError("invalid boolean value")
  43. }
  44. n := 0
  45. for _, lv := range literalValues {
  46. if len(lv) > len(b) {
  47. continue
  48. }
  49. if isLitValue(lv, b) {
  50. n = len(lv)
  51. }
  52. }
  53. if n == 0 {
  54. return 0, NewParseError("invalid boolean value")
  55. }
  56. return n, nil
  57. }
  58. // getNumericalValue will return a numerical string, the amount
  59. // of bytes read, and the base of the number
  60. //
  61. // an error will be returned if the number is not of a correct
  62. // value
  63. func getNumericalValue(b []rune) (int, int, error) {
  64. if !isDigit(b[0]) {
  65. return 0, 0, NewParseError("invalid digit value")
  66. }
  67. i := 0
  68. helper := numberHelper{}
  69. loop:
  70. for negativeIndex := 0; i < len(b); i++ {
  71. negativeIndex++
  72. if !isDigit(b[i]) {
  73. switch b[i] {
  74. case '-':
  75. if helper.IsNegative() || negativeIndex != 1 {
  76. return 0, 0, NewParseError("parse error '-'")
  77. }
  78. n := getNegativeNumber(b[i:])
  79. i += (n - 1)
  80. helper.Determine(b[i])
  81. continue
  82. case '.':
  83. if err := helper.Determine(b[i]); err != nil {
  84. return 0, 0, err
  85. }
  86. case 'e', 'E':
  87. if err := helper.Determine(b[i]); err != nil {
  88. return 0, 0, err
  89. }
  90. negativeIndex = 0
  91. case 'b':
  92. if helper.numberFormat == hex {
  93. break
  94. }
  95. fallthrough
  96. case 'o', 'x':
  97. if i == 0 && b[i] != '0' {
  98. return 0, 0, NewParseError("incorrect base format, expected leading '0'")
  99. }
  100. if i != 1 {
  101. return 0, 0, NewParseError(fmt.Sprintf("incorrect base format found %s at %d index", string(b[i]), i))
  102. }
  103. if err := helper.Determine(b[i]); err != nil {
  104. return 0, 0, err
  105. }
  106. default:
  107. if isWhitespace(b[i]) {
  108. break loop
  109. }
  110. if isNewline(b[i:]) {
  111. break loop
  112. }
  113. if !(helper.numberFormat == hex && isHexByte(b[i])) {
  114. if i+2 < len(b) && !isNewline(b[i:i+2]) {
  115. return 0, 0, NewParseError("invalid numerical character")
  116. } else if !isNewline([]rune{b[i]}) {
  117. return 0, 0, NewParseError("invalid numerical character")
  118. }
  119. break loop
  120. }
  121. }
  122. }
  123. }
  124. return helper.Base(), i, nil
  125. }
  126. // isDigit will return whether or not something is an integer
  127. func isDigit(b rune) bool {
  128. return b >= '0' && b <= '9'
  129. }
  130. func hasExponent(v []rune) bool {
  131. return contains(v, 'e') || contains(v, 'E')
  132. }
  133. func isBinaryByte(b rune) bool {
  134. switch b {
  135. case '0', '1':
  136. return true
  137. default:
  138. return false
  139. }
  140. }
  141. func isOctalByte(b rune) bool {
  142. switch b {
  143. case '0', '1', '2', '3', '4', '5', '6', '7':
  144. return true
  145. default:
  146. return false
  147. }
  148. }
  149. func isHexByte(b rune) bool {
  150. if isDigit(b) {
  151. return true
  152. }
  153. return (b >= 'A' && b <= 'F') ||
  154. (b >= 'a' && b <= 'f')
  155. }
  156. func getValue(b []rune) (int, error) {
  157. i := 0
  158. for i < len(b) {
  159. if isNewline(b[i:]) {
  160. break
  161. }
  162. if isOp(b[i:]) {
  163. break
  164. }
  165. valid, n, err := isValid(b[i:])
  166. if err != nil {
  167. return 0, err
  168. }
  169. if !valid {
  170. break
  171. }
  172. i += n
  173. }
  174. return i, nil
  175. }
  176. // getNegativeNumber will return a negative number from a
  177. // byte slice. This will iterate through all characters until
  178. // a non-digit has been found.
  179. func getNegativeNumber(b []rune) int {
  180. if b[0] != '-' {
  181. return 0
  182. }
  183. i := 1
  184. for ; i < len(b); i++ {
  185. if !isDigit(b[i]) {
  186. return i
  187. }
  188. }
  189. return i
  190. }
  191. // isEscaped will return whether or not the character is an escaped
  192. // character.
  193. func isEscaped(value []rune, b rune) bool {
  194. if len(value) == 0 {
  195. return false
  196. }
  197. switch b {
  198. case '\'': // single quote
  199. case '"': // quote
  200. case 'n': // newline
  201. case 't': // tab
  202. case '\\': // backslash
  203. default:
  204. return false
  205. }
  206. return value[len(value)-1] == '\\'
  207. }
  208. func getEscapedByte(b rune) (rune, error) {
  209. switch b {
  210. case '\'': // single quote
  211. return '\'', nil
  212. case '"': // quote
  213. return '"', nil
  214. case 'n': // newline
  215. return '\n', nil
  216. case 't': // table
  217. return '\t', nil
  218. case '\\': // backslash
  219. return '\\', nil
  220. default:
  221. return b, NewParseError(fmt.Sprintf("invalid escaped character %c", b))
  222. }
  223. }
  224. func removeEscapedCharacters(b []rune) []rune {
  225. for i := 0; i < len(b); i++ {
  226. if isEscaped(b[:i], b[i]) {
  227. c, err := getEscapedByte(b[i])
  228. if err != nil {
  229. return b
  230. }
  231. b[i-1] = c
  232. b = append(b[:i], b[i+1:]...)
  233. i--
  234. }
  235. }
  236. return b
  237. }