package strconv
import "os"
type NumError struct {
Num string
Error os.Error
}
func (e *NumError) String() string { return "parsing " + e.Num + ": " + e.Error.String() }
func computeIntsize() uint {
siz := uint(8)
for 1<<siz != 0 {
siz *= 2
}
return siz
}
var IntSize = computeIntsize()
func cutoff64(base int) uint64 {
if base < 2 {
return 0
}
return (1<<64-1)/uint64(base) + 1
}
func Btoui64(s string, b int) (n uint64, err os.Error) {
s0 := s
switch {
case len(s) < 1:
err = os.EINVAL
goto Error
case 2 <= b && b <= 36:
case b == 0:
switch {
case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
b = 16
s = s[2:]
if len(s) < 1 {
err = os.EINVAL
goto Error
}
case s[0] == '0':
b = 8
default:
b = 10
}
default:
err = os.ErrorString("invalid base " + Itoa(b))
goto Error
}
n = 0
cutoff := cutoff64(b)
for i := 0; i < len(s); i++ {
var v byte
d := s[i]
switch {
case '0' <= d && d <= '9':
v = d - '0'
case 'a' <= d && d <= 'z':
v = d - 'a' + 10
case 'A' <= d && d <= 'Z':
v = d - 'A' + 10
default:
n = 0
err = os.EINVAL
goto Error
}
if int(v) >= b {
n = 0
err = os.EINVAL
goto Error
}
if n >= cutoff {
n = 1<<64 - 1
err = os.ERANGE
goto Error
}
n *= uint64(b)
n1 := n + uint64(v)
if n1 < n {
n = 1<<64 - 1
err = os.ERANGE
goto Error
}
n = n1
}
return n, nil
Error:
return n, &NumError{s0, err}
}
func Atoui64(s string) (n uint64, err os.Error) {
return Btoui64(s, 10)
}
func Btoi64(s string, base int) (i int64, err os.Error) {
if len(s) == 0 {
return 0, &NumError{s, os.EINVAL}
}
s0 := s
neg := false
if s[0] == '+' {
s = s[1:]
} else if s[0] == '-' {
neg = true
s = s[1:]
}
var un uint64
un, err = Btoui64(s, base)
if err != nil && err.(*NumError).Error != os.ERANGE {
err.(*NumError).Num = s0
return 0, err
}
if !neg && un >= 1<<63 {
return 1<<63 - 1, &NumError{s0, os.ERANGE}
}
if neg && un > 1<<63 {
return -1 << 63, &NumError{s0, os.ERANGE}
}
n := int64(un)
if neg {
n = -n
}
return n, nil
}
func Atoi64(s string) (i int64, err os.Error) { return Btoi64(s, 10) }
func Atoui(s string) (i uint, err os.Error) {
i1, e1 := Atoui64(s)
if e1 != nil && e1.(*NumError).Error != os.ERANGE {
return 0, e1
}
i = uint(i1)
if uint64(i) != i1 {
return ^uint(0), &NumError{s, os.ERANGE}
}
return i, nil
}
func Atoi(s string) (i int, err os.Error) {
i1, e1 := Atoi64(s)
if e1 != nil && e1.(*NumError).Error != os.ERANGE {
return 0, e1
}
i = int(i1)
if int64(i) != i1 {
if i1 < 0 {
return -1 << (IntSize - 1), &NumError{s, os.ERANGE}
}
return 1<<(IntSize-1) - 1, &NumError{s, os.ERANGE}
}
return i, nil
}