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