153 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
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()
 | 
						|
}
 |