| package ini |
| |
| import ( |
| "bytes" |
| "fmt" |
| "strconv" |
| ) |
| |
| const ( |
| none = numberFormat(iota) |
| binary |
| octal |
| decimal |
| hex |
| exponent |
| ) |
| |
| type numberFormat int |
| |
| // numberHelper is used to dictate what format a number is in |
| // and what to do for negative values. Since -1e-4 is a valid |
| // number, we cannot just simply check for duplicate negatives. |
| type numberHelper struct { |
| numberFormat numberFormat |
| |
| negative bool |
| negativeExponent bool |
| } |
| |
| func (b numberHelper) Exists() bool { |
| return b.numberFormat != none |
| } |
| |
| func (b numberHelper) IsNegative() bool { |
| return b.negative || b.negativeExponent |
| } |
| |
| func (b *numberHelper) Determine(c rune) error { |
| if b.Exists() { |
| return NewParseError(fmt.Sprintf("multiple number formats: 0%v", string(c))) |
| } |
| |
| switch c { |
| case 'b': |
| b.numberFormat = binary |
| case 'o': |
| b.numberFormat = octal |
| case 'x': |
| b.numberFormat = hex |
| case 'e', 'E': |
| b.numberFormat = exponent |
| case '-': |
| if b.numberFormat != exponent { |
| b.negative = true |
| } else { |
| b.negativeExponent = true |
| } |
| case '.': |
| b.numberFormat = decimal |
| default: |
| return NewParseError(fmt.Sprintf("invalid number character: %v", string(c))) |
| } |
| |
| return nil |
| } |
| |
| func (b numberHelper) CorrectByte(c rune) bool { |
| switch { |
| case b.numberFormat == binary: |
| if !isBinaryByte(c) { |
| return false |
| } |
| case b.numberFormat == octal: |
| if !isOctalByte(c) { |
| return false |
| } |
| case b.numberFormat == hex: |
| if !isHexByte(c) { |
| return false |
| } |
| case b.numberFormat == decimal: |
| if !isDigit(c) { |
| return false |
| } |
| case b.numberFormat == exponent: |
| if !isDigit(c) { |
| return false |
| } |
| case b.negativeExponent: |
| if !isDigit(c) { |
| return false |
| } |
| case b.negative: |
| if !isDigit(c) { |
| return false |
| } |
| default: |
| if !isDigit(c) { |
| return false |
| } |
| } |
| |
| return true |
| } |
| |
| func (b numberHelper) Base() int { |
| switch b.numberFormat { |
| case binary: |
| return 2 |
| case octal: |
| return 8 |
| case hex: |
| return 16 |
| default: |
| return 10 |
| } |
| } |
| |
| func (b numberHelper) String() string { |
| buf := bytes.Buffer{} |
| i := 0 |
| |
| switch b.numberFormat { |
| case binary: |
| i++ |
| buf.WriteString(strconv.Itoa(i) + ": binary format\n") |
| case octal: |
| i++ |
| buf.WriteString(strconv.Itoa(i) + ": octal format\n") |
| case hex: |
| i++ |
| buf.WriteString(strconv.Itoa(i) + ": hex format\n") |
| case exponent: |
| i++ |
| buf.WriteString(strconv.Itoa(i) + ": exponent format\n") |
| default: |
| i++ |
| buf.WriteString(strconv.Itoa(i) + ": integer format\n") |
| } |
| |
| if b.negative { |
| i++ |
| buf.WriteString(strconv.Itoa(i) + ": negative format\n") |
| } |
| |
| if b.negativeExponent { |
| i++ |
| buf.WriteString(strconv.Itoa(i) + ": negative exponent format\n") |
| } |
| |
| return buf.String() |
| } |