src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

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 }