value_util.go (5126B)
1 package ini 2 3 import ( 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 11 func 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 49 func 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 isCaselessLitValue(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 77 func 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 85 loop: 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 153 func isDigit(b rune) bool { 154 return b >= '0' && b <= '9' 155 } 156 157 func hasExponent(v []rune) bool { 158 return contains(v, 'e') || contains(v, 'E') 159 } 160 161 func isBinaryByte(b rune) bool { 162 switch b { 163 case '0', '1': 164 return true 165 default: 166 return false 167 } 168 } 169 170 func 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 179 func 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 187 func 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. 217 func 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. 234 func 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 252 func 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 269 func 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 }