type NumError struct {
Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat)
Num string // the input
- Err error // the reason the conversion failed (ErrRange, ErrSyntax)
+ Err error // the reason the conversion failed (e.g. ErrRange, ErrSyntax, etc.)
}
func (e *NumError) Error() string {
return &NumError{fn, str, ErrRange}
}
+func baseError(fn, str string, base int) *NumError {
+ return &NumError{fn, str, errors.New("invalid base " + Itoa(base))}
+}
+
const intSize = 32 << (^uint(0) >> 63)
// IntSize is the size in bits of an int or uint value.
// ParseUint is like ParseInt but for unsigned numbers.
func ParseUint(s string, base int, bitSize int) (uint64, error) {
+ const fnParseUint = "ParseUint"
+
var n uint64
- var err error
var cutoff, maxVal uint64
if bitSize == 0 {
i := 0
switch {
- case len(s) < 1:
- err = ErrSyntax
- goto Error
+ case len(s) == 0:
+ return 0, syntaxError(fnParseUint, s)
case 2 <= base && base <= 36:
// valid base; nothing to do
switch {
case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
if len(s) < 3 {
- err = ErrSyntax
- goto Error
+ return 0, syntaxError(fnParseUint, s)
}
base = 16
i = 2
}
default:
- err = errors.New("invalid base " + Itoa(base))
- goto Error
+ return 0, baseError(fnParseUint, s, base)
}
// Cutoff is the smallest number such that cutoff*base > maxUint64.
case 'A' <= d && d <= 'Z':
v = d - 'A' + 10
default:
- n = 0
- err = ErrSyntax
- goto Error
+ return 0, syntaxError(fnParseUint, s)
}
if v >= byte(base) {
- n = 0
- err = ErrSyntax
- goto Error
+ return 0, syntaxError(fnParseUint, s)
}
if n >= cutoff {
// n*base overflows
- n = maxVal
- err = ErrRange
- goto Error
+ return maxVal, rangeError(fnParseUint, s)
}
n *= uint64(base)
n1 := n + uint64(v)
if n1 < n || n1 > maxVal {
// n+v overflows
- n = maxVal
- err = ErrRange
- goto Error
+ return maxVal, rangeError(fnParseUint, s)
}
n = n1
}
return n, nil
-
-Error:
- return n, &NumError{"ParseUint", s, err}
}
// ParseInt interprets a string s in the given base (2 to 36) and