Commit 02f6719d authored by Rob Pike's avatar Rob Pike

strconv: include package and function name in error strings

Fixes #2548.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5484062
parent 6bf84214
...@@ -55,10 +55,10 @@ var conversionTests = []conversionTest{ ...@@ -55,10 +55,10 @@ var conversionTests = []conversionTest{
// Strings to integers // Strings to integers
{s: "255", d: &scanuint8, wantuint: 255}, {s: "255", d: &scanuint8, wantuint: 255},
{s: "256", d: &scanuint8, wanterr: `converting string "256" to a uint8: parsing "256": value out of range`}, {s: "256", d: &scanuint8, wanterr: `converting string "256" to a uint8: strconv.ParseUint: parsing "256": value out of range`},
{s: "256", d: &scanuint16, wantuint: 256}, {s: "256", d: &scanuint16, wantuint: 256},
{s: "-1", d: &scanint, wantint: -1}, {s: "-1", d: &scanint, wantint: -1},
{s: "foo", d: &scanint, wanterr: `converting string "foo" to a int: parsing "foo": invalid syntax`}, {s: "foo", d: &scanint, wanterr: `converting string "foo" to a int: strconv.ParseInt: parsing "foo": invalid syntax`},
// True bools // True bools
{s: true, d: &scanbool, wantbool: true}, {s: true, d: &scanbool, wantbool: true},
......
...@@ -14,7 +14,7 @@ func ParseBool(str string) (value bool, err error) { ...@@ -14,7 +14,7 @@ func ParseBool(str string) (value bool, err error) {
case "0", "f", "F", "false", "FALSE", "False": case "0", "f", "F", "false", "FALSE", "False":
return false, nil return false, nil
} }
return false, &NumError{str, ErrSyntax} return false, syntaxError("ParseBool", str)
} }
// FormatBool returns "true" or "false" according to the value of b // FormatBool returns "true" or "false" according to the value of b
......
...@@ -338,6 +338,8 @@ func (d *decimal) atof32() (f float32, ok bool) { ...@@ -338,6 +338,8 @@ func (d *decimal) atof32() (f float32, ok bool) {
return return
} }
const fnParseFloat = "ParseFloat"
func atof32(s string) (f float32, err error) { func atof32(s string) (f float32, err error) {
if val, ok := special(s); ok { if val, ok := special(s); ok {
return float32(val), nil return float32(val), nil
...@@ -345,7 +347,7 @@ func atof32(s string) (f float32, err error) { ...@@ -345,7 +347,7 @@ func atof32(s string) (f float32, err error) {
var d decimal var d decimal
if !d.set(s) { if !d.set(s) {
return 0, &NumError{s, ErrSyntax} return 0, syntaxError(fnParseFloat, s)
} }
if optimize { if optimize {
if f, ok := d.atof32(); ok { if f, ok := d.atof32(); ok {
...@@ -355,7 +357,7 @@ func atof32(s string) (f float32, err error) { ...@@ -355,7 +357,7 @@ func atof32(s string) (f float32, err error) {
b, ovf := d.floatBits(&float32info) b, ovf := d.floatBits(&float32info)
f = math.Float32frombits(uint32(b)) f = math.Float32frombits(uint32(b))
if ovf { if ovf {
err = &NumError{s, ErrRange} err = rangeError(fnParseFloat, s)
} }
return f, err return f, err
} }
...@@ -367,7 +369,7 @@ func atof64(s string) (f float64, err error) { ...@@ -367,7 +369,7 @@ func atof64(s string) (f float64, err error) {
var d decimal var d decimal
if !d.set(s) { if !d.set(s) {
return 0, &NumError{s, ErrSyntax} return 0, syntaxError(fnParseFloat, s)
} }
if optimize { if optimize {
if f, ok := d.atof64(); ok { if f, ok := d.atof64(); ok {
...@@ -377,7 +379,7 @@ func atof64(s string) (f float64, err error) { ...@@ -377,7 +379,7 @@ func atof64(s string) (f float64, err error) {
b, ovf := d.floatBits(&float64info) b, ovf := d.floatBits(&float64info)
f = math.Float64frombits(b) f = math.Float64frombits(b)
if ovf { if ovf {
err = &NumError{s, ErrRange} err = rangeError(fnParseFloat, s)
} }
return f, err return f, err
} }
......
...@@ -119,7 +119,7 @@ func init() { ...@@ -119,7 +119,7 @@ func init() {
for i := range atoftests { for i := range atoftests {
test := &atoftests[i] test := &atoftests[i]
if test.err != nil { if test.err != nil {
test.err = &NumError{test.in, test.err} test.err = &NumError{"ParseFloat", test.in, test.err}
} }
} }
} }
......
...@@ -14,11 +14,22 @@ var ErrSyntax = errors.New("invalid syntax") ...@@ -14,11 +14,22 @@ var ErrSyntax = errors.New("invalid syntax")
// A NumError records a failed conversion. // A NumError records a failed conversion.
type NumError struct { type NumError struct {
Num string // the input Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat)
Err error // the reason the conversion failed (ErrRange, ErrSyntax) Num string // the input
Err error // the reason the conversion failed (ErrRange, ErrSyntax)
} }
func (e *NumError) Error() string { return `parsing "` + e.Num + `": ` + e.Err.Error() } func (e *NumError) Error() string {
return "strconv." + e.Func + ": " + `parsing "` + e.Num + `": ` + e.Err.Error()
}
func syntaxError(fn, str string) *NumError {
return &NumError{fn, str, ErrSyntax}
}
func rangeError(fn, str string) *NumError {
return &NumError{fn, str, ErrRange}
}
const intSize = 32 << uint(^uint(0)>>63) const intSize = 32 << uint(^uint(0)>>63)
...@@ -116,7 +127,7 @@ func ParseUint(s string, b int, bitSize int) (n uint64, err error) { ...@@ -116,7 +127,7 @@ func ParseUint(s string, b int, bitSize int) (n uint64, err error) {
return n, nil return n, nil
Error: Error:
return n, &NumError{s0, err} return n, &NumError{"ParseUint", s0, 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
...@@ -134,13 +145,15 @@ Error: ...@@ -134,13 +145,15 @@ Error:
// to s cannot be represented by a signed integer of the // to s cannot be represented by a signed integer of the
// given size, err.Error = ErrRange. // given size, err.Error = ErrRange.
func ParseInt(s string, base int, bitSize int) (i int64, err error) { func ParseInt(s string, base int, bitSize int) (i int64, err error) {
const fnParseInt = "ParseInt"
if bitSize == 0 { if bitSize == 0 {
bitSize = int(IntSize) bitSize = int(IntSize)
} }
// Empty string bad. // Empty string bad.
if len(s) == 0 { if len(s) == 0 {
return 0, &NumError{s, ErrSyntax} return 0, syntaxError(fnParseInt, s)
} }
// Pick off leading sign. // Pick off leading sign.
...@@ -157,15 +170,16 @@ func ParseInt(s string, base int, bitSize int) (i int64, err error) { ...@@ -157,15 +170,16 @@ func ParseInt(s string, base int, bitSize int) (i int64, err error) {
var un uint64 var un uint64
un, err = ParseUint(s, base, bitSize) un, err = ParseUint(s, base, bitSize)
if err != nil && err.(*NumError).Err != ErrRange { if err != nil && err.(*NumError).Err != ErrRange {
err.(*NumError).Func = fnParseInt
err.(*NumError).Num = s0 err.(*NumError).Num = s0
return 0, err return 0, err
} }
cutoff := uint64(1 << uint(bitSize-1)) cutoff := uint64(1 << uint(bitSize-1))
if !neg && un >= cutoff { if !neg && un >= cutoff {
return int64(cutoff - 1), &NumError{s0, ErrRange} return int64(cutoff - 1), rangeError(fnParseInt, s0)
} }
if neg && un > cutoff { if neg && un > cutoff {
return -int64(cutoff), &NumError{s0, ErrRange} return -int64(cutoff), rangeError(fnParseInt, s0)
} }
n := int64(un) n := int64(un)
if neg { if neg {
......
...@@ -152,37 +152,37 @@ func init() { ...@@ -152,37 +152,37 @@ func init() {
for i := range atoui64tests { for i := range atoui64tests {
test := &atoui64tests[i] test := &atoui64tests[i]
if test.err != nil { if test.err != nil {
test.err = &NumError{test.in, test.err} test.err = &NumError{"ParseUint", test.in, test.err}
} }
} }
for i := range btoui64tests { for i := range btoui64tests {
test := &btoui64tests[i] test := &btoui64tests[i]
if test.err != nil { if test.err != nil {
test.err = &NumError{test.in, test.err} test.err = &NumError{"ParseUint", test.in, test.err}
} }
} }
for i := range atoi64tests { for i := range atoi64tests {
test := &atoi64tests[i] test := &atoi64tests[i]
if test.err != nil { if test.err != nil {
test.err = &NumError{test.in, test.err} test.err = &NumError{"ParseInt", test.in, test.err}
} }
} }
for i := range btoi64tests { for i := range btoi64tests {
test := &btoi64tests[i] test := &btoi64tests[i]
if test.err != nil { if test.err != nil {
test.err = &NumError{test.in, test.err} test.err = &NumError{"ParseInt", test.in, test.err}
} }
} }
for i := range atoui32tests { for i := range atoui32tests {
test := &atoui32tests[i] test := &atoui32tests[i]
if test.err != nil { if test.err != nil {
test.err = &NumError{test.in, test.err} test.err = &NumError{"ParseUint", test.in, test.err}
} }
} }
for i := range atoi32tests { for i := range atoi32tests {
test := &atoi32tests[i] test := &atoi32tests[i]
if test.err != nil { if test.err != nil {
test.err = &NumError{test.in, test.err} test.err = &NumError{"ParseInt", test.in, test.err}
} }
} }
} }
......
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