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()
|
||
|
}
|