func ParseUint(s string, base int, bitSize int) (uint64, error) {
const fnParseUint = "ParseUint"
- var n uint64
- var cutoff, maxVal uint64
-
if bitSize == 0 {
bitSize = int(IntSize)
}
- i := 0
- switch {
- case len(s) == 0:
+ if len(s) == 0 {
return 0, syntaxError(fnParseUint, s)
+ }
+ s0 := s
+ switch {
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 {
- return 0, syntaxError(fnParseUint, s)
+ return 0, syntaxError(fnParseUint, s0)
}
base = 16
- i = 2
+ s = s[2:]
case s[0] == '0':
base = 8
- i = 1
+ s = s[1:]
default:
base = 10
}
default:
- return 0, baseError(fnParseUint, s, base)
+ return 0, baseError(fnParseUint, s0, base)
}
// Cutoff is the smallest number such that cutoff*base > maxUint64.
// Use compile-time constants for common cases.
+ var cutoff uint64
switch base {
case 10:
cutoff = maxUint64/10 + 1
cutoff = maxUint64/uint64(base) + 1
}
- maxVal = 1<<uint(bitSize) - 1
+ maxVal := uint64(1)<<uint(bitSize) - 1
- for ; i < len(s); i++ {
- var v byte
- d := s[i]
+ var n uint64
+ for _, c := range []byte(s) {
+ var d byte
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
+ case '0' <= c && c <= '9':
+ d = c - '0'
+ case 'a' <= c && c <= 'z':
+ d = c - 'a' + 10
+ case 'A' <= c && c <= 'Z':
+ d = c - 'A' + 10
default:
- return 0, syntaxError(fnParseUint, s)
+ return 0, syntaxError(fnParseUint, s0)
}
- if v >= byte(base) {
- return 0, syntaxError(fnParseUint, s)
+
+ if d >= byte(base) {
+ return 0, syntaxError(fnParseUint, s0)
}
if n >= cutoff {
// n*base overflows
- return maxVal, rangeError(fnParseUint, s)
+ return maxVal, rangeError(fnParseUint, s0)
}
n *= uint64(base)
- n1 := n + uint64(v)
+ n1 := n + uint64(d)
if n1 < n || n1 > maxVal {
// n+v overflows
- return maxVal, rangeError(fnParseUint, s)
+ return maxVal, rangeError(fnParseUint, s0)
}
n = n1
}