Commit dd6880d6 authored by Martin Möhrmann's avatar Martin Möhrmann

strconv: unify error creation in ParseUint with ParseInt

Remove goto and use helper functions in ParseUint to create errors.

Change-Id: I1c4677ae1b9980db79065a9f8ca1f2c470249505
Reviewed-on: https://go-review.googlesource.com/55135
Run-TryBot: Martin Möhrmann <moehrmann@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarJoe Tsai <thebrokentoaster@gmail.com>
parent 566f390c
...@@ -16,7 +16,7 @@ var ErrSyntax = errors.New("invalid syntax") ...@@ -16,7 +16,7 @@ var ErrSyntax = errors.New("invalid syntax")
type NumError struct { type NumError struct {
Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat) Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat)
Num string // the input 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 { func (e *NumError) Error() string {
...@@ -31,6 +31,10 @@ func rangeError(fn, str string) *NumError { ...@@ -31,6 +31,10 @@ func rangeError(fn, str string) *NumError {
return &NumError{fn, str, ErrRange} 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) const intSize = 32 << (^uint(0) >> 63)
// IntSize is the size in bits of an int or uint value. // IntSize is the size in bits of an int or uint value.
...@@ -40,8 +44,9 @@ const maxUint64 = (1<<64 - 1) ...@@ -40,8 +44,9 @@ const maxUint64 = (1<<64 - 1)
// ParseUint is like ParseInt but for unsigned numbers. // ParseUint is like ParseInt but for unsigned numbers.
func ParseUint(s string, base int, bitSize int) (uint64, error) { func ParseUint(s string, base int, bitSize int) (uint64, error) {
const fnParseUint = "ParseUint"
var n uint64 var n uint64
var err error
var cutoff, maxVal uint64 var cutoff, maxVal uint64
if bitSize == 0 { if bitSize == 0 {
...@@ -50,9 +55,8 @@ func ParseUint(s string, base int, bitSize int) (uint64, error) { ...@@ -50,9 +55,8 @@ func ParseUint(s string, base int, bitSize int) (uint64, error) {
i := 0 i := 0
switch { switch {
case len(s) < 1: case len(s) == 0:
err = ErrSyntax return 0, syntaxError(fnParseUint, s)
goto Error
case 2 <= base && base <= 36: case 2 <= base && base <= 36:
// valid base; nothing to do // valid base; nothing to do
...@@ -62,8 +66,7 @@ func ParseUint(s string, base int, bitSize int) (uint64, error) { ...@@ -62,8 +66,7 @@ func ParseUint(s string, base int, bitSize int) (uint64, error) {
switch { switch {
case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'): case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
if len(s) < 3 { if len(s) < 3 {
err = ErrSyntax return 0, syntaxError(fnParseUint, s)
goto Error
} }
base = 16 base = 16
i = 2 i = 2
...@@ -75,8 +78,7 @@ func ParseUint(s string, base int, bitSize int) (uint64, error) { ...@@ -75,8 +78,7 @@ func ParseUint(s string, base int, bitSize int) (uint64, error) {
} }
default: default:
err = errors.New("invalid base " + Itoa(base)) return 0, baseError(fnParseUint, s, base)
goto Error
} }
// Cutoff is the smallest number such that cutoff*base > maxUint64. // Cutoff is the smallest number such that cutoff*base > maxUint64.
...@@ -103,38 +105,27 @@ func ParseUint(s string, base int, bitSize int) (uint64, error) { ...@@ -103,38 +105,27 @@ func ParseUint(s string, base int, bitSize int) (uint64, error) {
case 'A' <= d && d <= 'Z': case 'A' <= d && d <= 'Z':
v = d - 'A' + 10 v = d - 'A' + 10
default: default:
n = 0 return 0, syntaxError(fnParseUint, s)
err = ErrSyntax
goto Error
} }
if v >= byte(base) { if v >= byte(base) {
n = 0 return 0, syntaxError(fnParseUint, s)
err = ErrSyntax
goto Error
} }
if n >= cutoff { if n >= cutoff {
// n*base overflows // n*base overflows
n = maxVal return maxVal, rangeError(fnParseUint, s)
err = ErrRange
goto Error
} }
n *= uint64(base) n *= uint64(base)
n1 := n + uint64(v) n1 := n + uint64(v)
if n1 < n || n1 > maxVal { if n1 < n || n1 > maxVal {
// n+v overflows // n+v overflows
n = maxVal return maxVal, rangeError(fnParseUint, s)
err = ErrRange
goto Error
} }
n = n1 n = n1
} }
return n, nil return n, nil
Error:
return n, &NumError{"ParseUint", s, err}
} }
// ParseInt interprets a string s in the given base (2 to 36) and // ParseInt interprets a string s in the given base (2 to 36) and
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment