number_helper.go (2636B)
1 package ini 2 3 import ( 4 "bytes" 5 "fmt" 6 "strconv" 7 ) 8 9 const ( 10 none = numberFormat(iota) 11 binary 12 octal 13 decimal 14 hex 15 exponent 16 ) 17 18 type numberFormat int 19 20 // numberHelper is used to dictate what format a number is in 21 // and what to do for negative values. Since -1e-4 is a valid 22 // number, we cannot just simply check for duplicate negatives. 23 type numberHelper struct { 24 numberFormat numberFormat 25 26 negative bool 27 negativeExponent bool 28 } 29 30 func (b numberHelper) Exists() bool { 31 return b.numberFormat != none 32 } 33 34 func (b numberHelper) IsNegative() bool { 35 return b.negative || b.negativeExponent 36 } 37 38 func (b *numberHelper) Determine(c rune) error { 39 if b.Exists() { 40 return NewParseError(fmt.Sprintf("multiple number formats: 0%v", string(c))) 41 } 42 43 switch c { 44 case 'b': 45 b.numberFormat = binary 46 case 'o': 47 b.numberFormat = octal 48 case 'x': 49 b.numberFormat = hex 50 case 'e', 'E': 51 b.numberFormat = exponent 52 case '-': 53 if b.numberFormat != exponent { 54 b.negative = true 55 } else { 56 b.negativeExponent = true 57 } 58 case '.': 59 b.numberFormat = decimal 60 default: 61 return NewParseError(fmt.Sprintf("invalid number character: %v", string(c))) 62 } 63 64 return nil 65 } 66 67 func (b numberHelper) CorrectByte(c rune) bool { 68 switch { 69 case b.numberFormat == binary: 70 if !isBinaryByte(c) { 71 return false 72 } 73 case b.numberFormat == octal: 74 if !isOctalByte(c) { 75 return false 76 } 77 case b.numberFormat == hex: 78 if !isHexByte(c) { 79 return false 80 } 81 case b.numberFormat == decimal: 82 if !isDigit(c) { 83 return false 84 } 85 case b.numberFormat == exponent: 86 if !isDigit(c) { 87 return false 88 } 89 case b.negativeExponent: 90 if !isDigit(c) { 91 return false 92 } 93 case b.negative: 94 if !isDigit(c) { 95 return false 96 } 97 default: 98 if !isDigit(c) { 99 return false 100 } 101 } 102 103 return true 104 } 105 106 func (b numberHelper) Base() int { 107 switch b.numberFormat { 108 case binary: 109 return 2 110 case octal: 111 return 8 112 case hex: 113 return 16 114 default: 115 return 10 116 } 117 } 118 119 func (b numberHelper) String() string { 120 buf := bytes.Buffer{} 121 i := 0 122 123 switch b.numberFormat { 124 case binary: 125 i++ 126 buf.WriteString(strconv.Itoa(i) + ": binary format\n") 127 case octal: 128 i++ 129 buf.WriteString(strconv.Itoa(i) + ": octal format\n") 130 case hex: 131 i++ 132 buf.WriteString(strconv.Itoa(i) + ": hex format\n") 133 case exponent: 134 i++ 135 buf.WriteString(strconv.Itoa(i) + ": exponent format\n") 136 default: 137 i++ 138 buf.WriteString(strconv.Itoa(i) + ": integer format\n") 139 } 140 141 if b.negative { 142 i++ 143 buf.WriteString(strconv.Itoa(i) + ": negative format\n") 144 } 145 146 if b.negativeExponent { 147 i++ 148 buf.WriteString(strconv.Itoa(i) + ": negative exponent format\n") 149 } 150 151 return buf.String() 152 }