mirror of
https://github.com/golang/go
synced 2024-11-25 13:57:57 -07:00
strconv: use better errors than os.EINVAL, os.ERANGE
R=golang-dev, adg CC=golang-dev https://golang.org/cl/5327052
This commit is contained in:
parent
01e9a227cc
commit
c1178aae86
@ -52,7 +52,7 @@ var conversionTests = []conversionTest{
|
|||||||
{s: "256", d: &scanuint8, wanterr: `string "256" overflows uint8`},
|
{s: "256", d: &scanuint8, wanterr: `string "256" overflows uint8`},
|
||||||
{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 argument`},
|
{s: "foo", d: &scanint, wanterr: `converting string "foo" to a int: parsing "foo": invalid syntax`},
|
||||||
}
|
}
|
||||||
|
|
||||||
func intValue(intptr interface{}) int64 {
|
func intValue(intptr interface{}) int64 {
|
||||||
|
@ -16,7 +16,7 @@ func Atob(str string) (value bool, err os.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, os.EINVAL}
|
return false, &NumError{str, ErrSyntax}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Btoa returns "true" or "false" according to the value of the boolean argument
|
// Btoa returns "true" or "false" according to the value of the boolean argument
|
||||||
|
@ -17,8 +17,8 @@ type atobTest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var atobtests = []atobTest{
|
var atobtests = []atobTest{
|
||||||
{"", false, os.EINVAL},
|
{"", false, ErrSyntax},
|
||||||
{"asdf", false, os.EINVAL},
|
{"asdf", false, ErrSyntax},
|
||||||
{"0", false, nil},
|
{"0", false, nil},
|
||||||
{"f", false, nil},
|
{"f", false, nil},
|
||||||
{"F", false, nil},
|
{"F", false, nil},
|
||||||
|
@ -350,11 +350,11 @@ func (d *decimal) atof32() (f float32, ok bool) {
|
|||||||
// The errors that Atof32 returns have concrete type *NumError
|
// The errors that Atof32 returns have concrete type *NumError
|
||||||
// and include err.Num = s.
|
// and include err.Num = s.
|
||||||
//
|
//
|
||||||
// If s is not syntactically well-formed, Atof32 returns err.Error = os.EINVAL.
|
// If s is not syntactically well-formed, Atof32 returns err.Error = ErrSyntax.
|
||||||
//
|
//
|
||||||
// If s is syntactically well-formed but is more than 1/2 ULP
|
// If s is syntactically well-formed but is more than 1/2 ULP
|
||||||
// away from the largest floating point number of the given size,
|
// away from the largest floating point number of the given size,
|
||||||
// Atof32 returns f = ±Inf, err.Error = os.ERANGE.
|
// Atof32 returns f = ±Inf, err.Error = ErrRange.
|
||||||
func Atof32(s string) (f float32, err os.Error) {
|
func Atof32(s string) (f float32, err os.Error) {
|
||||||
if val, ok := special(s); ok {
|
if val, ok := special(s); ok {
|
||||||
return float32(val), nil
|
return float32(val), nil
|
||||||
@ -362,7 +362,7 @@ func Atof32(s string) (f float32, err os.Error) {
|
|||||||
|
|
||||||
var d decimal
|
var d decimal
|
||||||
if !d.set(s) {
|
if !d.set(s) {
|
||||||
return 0, &NumError{s, os.EINVAL}
|
return 0, &NumError{s, ErrSyntax}
|
||||||
}
|
}
|
||||||
if optimize {
|
if optimize {
|
||||||
if f, ok := d.atof32(); ok {
|
if f, ok := d.atof32(); ok {
|
||||||
@ -372,7 +372,7 @@ func Atof32(s string) (f float32, err os.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, os.ERANGE}
|
err = &NumError{s, ErrRange}
|
||||||
}
|
}
|
||||||
return f, err
|
return f, err
|
||||||
}
|
}
|
||||||
@ -387,7 +387,7 @@ func Atof64(s string) (f float64, err os.Error) {
|
|||||||
|
|
||||||
var d decimal
|
var d decimal
|
||||||
if !d.set(s) {
|
if !d.set(s) {
|
||||||
return 0, &NumError{s, os.EINVAL}
|
return 0, &NumError{s, ErrSyntax}
|
||||||
}
|
}
|
||||||
if optimize {
|
if optimize {
|
||||||
if f, ok := d.atof64(); ok {
|
if f, ok := d.atof64(); ok {
|
||||||
@ -397,7 +397,7 @@ func Atof64(s string) (f float64, err os.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, os.ERANGE}
|
err = &NumError{s, ErrRange}
|
||||||
}
|
}
|
||||||
return f, err
|
return f, err
|
||||||
}
|
}
|
||||||
|
@ -18,11 +18,11 @@ type atofTest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var atoftests = []atofTest{
|
var atoftests = []atofTest{
|
||||||
{"", "0", os.EINVAL},
|
{"", "0", ErrSyntax},
|
||||||
{"1", "1", nil},
|
{"1", "1", nil},
|
||||||
{"+1", "1", nil},
|
{"+1", "1", nil},
|
||||||
{"1x", "0", os.EINVAL},
|
{"1x", "0", ErrSyntax},
|
||||||
{"1.1.", "0", os.EINVAL},
|
{"1.1.", "0", ErrSyntax},
|
||||||
{"1e23", "1e+23", nil},
|
{"1e23", "1e+23", nil},
|
||||||
{"1E23", "1e+23", nil},
|
{"1E23", "1e+23", nil},
|
||||||
{"100000000000000000000000", "1e+23", nil},
|
{"100000000000000000000000", "1e+23", nil},
|
||||||
@ -56,28 +56,28 @@ var atoftests = []atofTest{
|
|||||||
{"1.7976931348623157e308", "1.7976931348623157e+308", nil},
|
{"1.7976931348623157e308", "1.7976931348623157e+308", nil},
|
||||||
{"-1.7976931348623157e308", "-1.7976931348623157e+308", nil},
|
{"-1.7976931348623157e308", "-1.7976931348623157e+308", nil},
|
||||||
// next float64 - too large
|
// next float64 - too large
|
||||||
{"1.7976931348623159e308", "+Inf", os.ERANGE},
|
{"1.7976931348623159e308", "+Inf", ErrRange},
|
||||||
{"-1.7976931348623159e308", "-Inf", os.ERANGE},
|
{"-1.7976931348623159e308", "-Inf", ErrRange},
|
||||||
// the border is ...158079
|
// the border is ...158079
|
||||||
// borderline - okay
|
// borderline - okay
|
||||||
{"1.7976931348623158e308", "1.7976931348623157e+308", nil},
|
{"1.7976931348623158e308", "1.7976931348623157e+308", nil},
|
||||||
{"-1.7976931348623158e308", "-1.7976931348623157e+308", nil},
|
{"-1.7976931348623158e308", "-1.7976931348623157e+308", nil},
|
||||||
// borderline - too large
|
// borderline - too large
|
||||||
{"1.797693134862315808e308", "+Inf", os.ERANGE},
|
{"1.797693134862315808e308", "+Inf", ErrRange},
|
||||||
{"-1.797693134862315808e308", "-Inf", os.ERANGE},
|
{"-1.797693134862315808e308", "-Inf", ErrRange},
|
||||||
|
|
||||||
// a little too large
|
// a little too large
|
||||||
{"1e308", "1e+308", nil},
|
{"1e308", "1e+308", nil},
|
||||||
{"2e308", "+Inf", os.ERANGE},
|
{"2e308", "+Inf", ErrRange},
|
||||||
{"1e309", "+Inf", os.ERANGE},
|
{"1e309", "+Inf", ErrRange},
|
||||||
|
|
||||||
// way too large
|
// way too large
|
||||||
{"1e310", "+Inf", os.ERANGE},
|
{"1e310", "+Inf", ErrRange},
|
||||||
{"-1e310", "-Inf", os.ERANGE},
|
{"-1e310", "-Inf", ErrRange},
|
||||||
{"1e400", "+Inf", os.ERANGE},
|
{"1e400", "+Inf", ErrRange},
|
||||||
{"-1e400", "-Inf", os.ERANGE},
|
{"-1e400", "-Inf", ErrRange},
|
||||||
{"1e400000", "+Inf", os.ERANGE},
|
{"1e400000", "+Inf", ErrRange},
|
||||||
{"-1e400000", "-Inf", os.ERANGE},
|
{"-1e400000", "-Inf", ErrRange},
|
||||||
|
|
||||||
// denormalized
|
// denormalized
|
||||||
{"1e-305", "1e-305", nil},
|
{"1e-305", "1e-305", nil},
|
||||||
@ -99,14 +99,14 @@ var atoftests = []atofTest{
|
|||||||
|
|
||||||
// try to overflow exponent
|
// try to overflow exponent
|
||||||
{"1e-4294967296", "0", nil},
|
{"1e-4294967296", "0", nil},
|
||||||
{"1e+4294967296", "+Inf", os.ERANGE},
|
{"1e+4294967296", "+Inf", ErrRange},
|
||||||
{"1e-18446744073709551616", "0", nil},
|
{"1e-18446744073709551616", "0", nil},
|
||||||
{"1e+18446744073709551616", "+Inf", os.ERANGE},
|
{"1e+18446744073709551616", "+Inf", ErrRange},
|
||||||
|
|
||||||
// Parse errors
|
// Parse errors
|
||||||
{"1e", "0", os.EINVAL},
|
{"1e", "0", ErrSyntax},
|
||||||
{"1e-", "0", os.EINVAL},
|
{"1e-", "0", ErrSyntax},
|
||||||
{".e-1", "0", os.EINVAL},
|
{".e-1", "0", ErrSyntax},
|
||||||
|
|
||||||
// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
|
// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
|
||||||
{"2.2250738585072012e-308", "2.2250738585072014e-308", nil},
|
{"2.2250738585072012e-308", "2.2250738585072014e-308", nil},
|
||||||
|
@ -6,9 +6,16 @@ package strconv
|
|||||||
|
|
||||||
import "os"
|
import "os"
|
||||||
|
|
||||||
|
// ErrRange indicates that a value is out of range for the target type.
|
||||||
|
var ErrRange = os.NewError("value out of range")
|
||||||
|
|
||||||
|
// ErrSyntax indicates that a value does not have the right syntax for the target type.
|
||||||
|
var ErrSyntax = os.NewError("invalid syntax")
|
||||||
|
|
||||||
|
// A NumError records a failed conversion.
|
||||||
type NumError struct {
|
type NumError struct {
|
||||||
Num string
|
Num string // the input
|
||||||
Error os.Error
|
Error os.Error // the reason the conversion failed (ErrRange, ErrSyntax)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *NumError) String() string { return `parsing "` + e.Num + `": ` + e.Error.String() }
|
func (e *NumError) String() string { return `parsing "` + e.Num + `": ` + e.Error.String() }
|
||||||
@ -38,15 +45,15 @@ func cutoff64(base int) uint64 {
|
|||||||
//
|
//
|
||||||
// The errors that Btoui64 returns have concrete type *NumError
|
// The errors that Btoui64 returns have concrete type *NumError
|
||||||
// and include err.Num = s. If s is empty or contains invalid
|
// and include err.Num = s. If s is empty or contains invalid
|
||||||
// digits, err.Error = os.EINVAL; if the value corresponding
|
// digits, err.Error = ErrSyntax; if the value corresponding
|
||||||
// to s cannot be represented by a uint64, err.Error = os.ERANGE.
|
// to s cannot be represented by a uint64, err.Error = ErrRange.
|
||||||
func Btoui64(s string, b int) (n uint64, err os.Error) {
|
func Btoui64(s string, b int) (n uint64, err os.Error) {
|
||||||
var cutoff uint64
|
var cutoff uint64
|
||||||
|
|
||||||
s0 := s
|
s0 := s
|
||||||
switch {
|
switch {
|
||||||
case len(s) < 1:
|
case len(s) < 1:
|
||||||
err = os.EINVAL
|
err = ErrSyntax
|
||||||
goto Error
|
goto Error
|
||||||
|
|
||||||
case 2 <= b && b <= 36:
|
case 2 <= b && b <= 36:
|
||||||
@ -59,7 +66,7 @@ func Btoui64(s string, b int) (n uint64, err os.Error) {
|
|||||||
b = 16
|
b = 16
|
||||||
s = s[2:]
|
s = s[2:]
|
||||||
if len(s) < 1 {
|
if len(s) < 1 {
|
||||||
err = os.EINVAL
|
err = ErrSyntax
|
||||||
goto Error
|
goto Error
|
||||||
}
|
}
|
||||||
case s[0] == '0':
|
case s[0] == '0':
|
||||||
@ -88,19 +95,19 @@ func Btoui64(s string, b int) (n uint64, err os.Error) {
|
|||||||
v = d - 'A' + 10
|
v = d - 'A' + 10
|
||||||
default:
|
default:
|
||||||
n = 0
|
n = 0
|
||||||
err = os.EINVAL
|
err = ErrSyntax
|
||||||
goto Error
|
goto Error
|
||||||
}
|
}
|
||||||
if int(v) >= b {
|
if int(v) >= b {
|
||||||
n = 0
|
n = 0
|
||||||
err = os.EINVAL
|
err = ErrSyntax
|
||||||
goto Error
|
goto Error
|
||||||
}
|
}
|
||||||
|
|
||||||
if n >= cutoff {
|
if n >= cutoff {
|
||||||
// n*b overflows
|
// n*b overflows
|
||||||
n = 1<<64 - 1
|
n = 1<<64 - 1
|
||||||
err = os.ERANGE
|
err = ErrRange
|
||||||
goto Error
|
goto Error
|
||||||
}
|
}
|
||||||
n *= uint64(b)
|
n *= uint64(b)
|
||||||
@ -109,7 +116,7 @@ func Btoui64(s string, b int) (n uint64, err os.Error) {
|
|||||||
if n1 < n {
|
if n1 < n {
|
||||||
// n+v overflows
|
// n+v overflows
|
||||||
n = 1<<64 - 1
|
n = 1<<64 - 1
|
||||||
err = os.ERANGE
|
err = ErrRange
|
||||||
goto Error
|
goto Error
|
||||||
}
|
}
|
||||||
n = n1
|
n = n1
|
||||||
@ -124,8 +131,8 @@ Error:
|
|||||||
// Atoui64 interprets a string s as a decimal number and
|
// Atoui64 interprets a string s as a decimal number and
|
||||||
// returns the corresponding value n.
|
// returns the corresponding value n.
|
||||||
//
|
//
|
||||||
// Atoui64 returns err == os.EINVAL if s is empty or contains invalid digits.
|
// Atoui64 returns err.Error = ErrSyntax if s is empty or contains invalid digits.
|
||||||
// It returns err == os.ERANGE if s cannot be represented by a uint64.
|
// It returns err.Error = ErrRange if s cannot be represented by a uint64.
|
||||||
func Atoui64(s string) (n uint64, err os.Error) {
|
func Atoui64(s string) (n uint64, err os.Error) {
|
||||||
return Btoui64(s, 10)
|
return Btoui64(s, 10)
|
||||||
}
|
}
|
||||||
@ -135,7 +142,7 @@ func Atoui64(s string) (n uint64, err os.Error) {
|
|||||||
func Btoi64(s string, base int) (i int64, err os.Error) {
|
func Btoi64(s string, base int) (i int64, err os.Error) {
|
||||||
// Empty string bad.
|
// Empty string bad.
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
return 0, &NumError{s, os.EINVAL}
|
return 0, &NumError{s, ErrSyntax}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pick off leading sign.
|
// Pick off leading sign.
|
||||||
@ -151,15 +158,15 @@ func Btoi64(s string, base int) (i int64, err os.Error) {
|
|||||||
// Convert unsigned and check range.
|
// Convert unsigned and check range.
|
||||||
var un uint64
|
var un uint64
|
||||||
un, err = Btoui64(s, base)
|
un, err = Btoui64(s, base)
|
||||||
if err != nil && err.(*NumError).Error != os.ERANGE {
|
if err != nil && err.(*NumError).Error != ErrRange {
|
||||||
err.(*NumError).Num = s0
|
err.(*NumError).Num = s0
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if !neg && un >= 1<<63 {
|
if !neg && un >= 1<<63 {
|
||||||
return 1<<63 - 1, &NumError{s0, os.ERANGE}
|
return 1<<63 - 1, &NumError{s0, ErrRange}
|
||||||
}
|
}
|
||||||
if neg && un > 1<<63 {
|
if neg && un > 1<<63 {
|
||||||
return -1 << 63, &NumError{s0, os.ERANGE}
|
return -1 << 63, &NumError{s0, ErrRange}
|
||||||
}
|
}
|
||||||
n := int64(un)
|
n := int64(un)
|
||||||
if neg {
|
if neg {
|
||||||
@ -175,12 +182,12 @@ func Atoi64(s string) (i int64, err os.Error) { return Btoi64(s, 10) }
|
|||||||
// Atoui is like Atoui64 but returns its result as a uint.
|
// Atoui is like Atoui64 but returns its result as a uint.
|
||||||
func Atoui(s string) (i uint, err os.Error) {
|
func Atoui(s string) (i uint, err os.Error) {
|
||||||
i1, e1 := Atoui64(s)
|
i1, e1 := Atoui64(s)
|
||||||
if e1 != nil && e1.(*NumError).Error != os.ERANGE {
|
if e1 != nil && e1.(*NumError).Error != ErrRange {
|
||||||
return 0, e1
|
return 0, e1
|
||||||
}
|
}
|
||||||
i = uint(i1)
|
i = uint(i1)
|
||||||
if uint64(i) != i1 {
|
if uint64(i) != i1 {
|
||||||
return ^uint(0), &NumError{s, os.ERANGE}
|
return ^uint(0), &NumError{s, ErrRange}
|
||||||
}
|
}
|
||||||
return i, nil
|
return i, nil
|
||||||
}
|
}
|
||||||
@ -188,15 +195,15 @@ func Atoui(s string) (i uint, err os.Error) {
|
|||||||
// Atoi is like Atoi64 but returns its result as an int.
|
// Atoi is like Atoi64 but returns its result as an int.
|
||||||
func Atoi(s string) (i int, err os.Error) {
|
func Atoi(s string) (i int, err os.Error) {
|
||||||
i1, e1 := Atoi64(s)
|
i1, e1 := Atoi64(s)
|
||||||
if e1 != nil && e1.(*NumError).Error != os.ERANGE {
|
if e1 != nil && e1.(*NumError).Error != ErrRange {
|
||||||
return 0, e1
|
return 0, e1
|
||||||
}
|
}
|
||||||
i = int(i1)
|
i = int(i1)
|
||||||
if int64(i) != i1 {
|
if int64(i) != i1 {
|
||||||
if i1 < 0 {
|
if i1 < 0 {
|
||||||
return -1 << (IntSize - 1), &NumError{s, os.ERANGE}
|
return -1 << (IntSize - 1), &NumError{s, ErrRange}
|
||||||
}
|
}
|
||||||
return 1<<(IntSize-1) - 1, &NumError{s, os.ERANGE}
|
return 1<<(IntSize-1) - 1, &NumError{s, ErrRange}
|
||||||
}
|
}
|
||||||
return i, nil
|
return i, nil
|
||||||
}
|
}
|
||||||
|
@ -18,36 +18,36 @@ type atoui64Test struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var atoui64tests = []atoui64Test{
|
var atoui64tests = []atoui64Test{
|
||||||
{"", 0, os.EINVAL},
|
{"", 0, ErrSyntax},
|
||||||
{"0", 0, nil},
|
{"0", 0, nil},
|
||||||
{"1", 1, nil},
|
{"1", 1, nil},
|
||||||
{"12345", 12345, nil},
|
{"12345", 12345, nil},
|
||||||
{"012345", 12345, nil},
|
{"012345", 12345, nil},
|
||||||
{"12345x", 0, os.EINVAL},
|
{"12345x", 0, ErrSyntax},
|
||||||
{"98765432100", 98765432100, nil},
|
{"98765432100", 98765432100, nil},
|
||||||
{"18446744073709551615", 1<<64 - 1, nil},
|
{"18446744073709551615", 1<<64 - 1, nil},
|
||||||
{"18446744073709551616", 1<<64 - 1, os.ERANGE},
|
{"18446744073709551616", 1<<64 - 1, ErrRange},
|
||||||
{"18446744073709551620", 1<<64 - 1, os.ERANGE},
|
{"18446744073709551620", 1<<64 - 1, ErrRange},
|
||||||
}
|
}
|
||||||
|
|
||||||
var btoui64tests = []atoui64Test{
|
var btoui64tests = []atoui64Test{
|
||||||
{"", 0, os.EINVAL},
|
{"", 0, ErrSyntax},
|
||||||
{"0", 0, nil},
|
{"0", 0, nil},
|
||||||
{"1", 1, nil},
|
{"1", 1, nil},
|
||||||
{"12345", 12345, nil},
|
{"12345", 12345, nil},
|
||||||
{"012345", 012345, nil},
|
{"012345", 012345, nil},
|
||||||
{"0x12345", 0x12345, nil},
|
{"0x12345", 0x12345, nil},
|
||||||
{"0X12345", 0x12345, nil},
|
{"0X12345", 0x12345, nil},
|
||||||
{"12345x", 0, os.EINVAL},
|
{"12345x", 0, ErrSyntax},
|
||||||
{"98765432100", 98765432100, nil},
|
{"98765432100", 98765432100, nil},
|
||||||
{"18446744073709551615", 1<<64 - 1, nil},
|
{"18446744073709551615", 1<<64 - 1, nil},
|
||||||
{"18446744073709551616", 1<<64 - 1, os.ERANGE},
|
{"18446744073709551616", 1<<64 - 1, ErrRange},
|
||||||
{"18446744073709551620", 1<<64 - 1, os.ERANGE},
|
{"18446744073709551620", 1<<64 - 1, ErrRange},
|
||||||
{"0xFFFFFFFFFFFFFFFF", 1<<64 - 1, nil},
|
{"0xFFFFFFFFFFFFFFFF", 1<<64 - 1, nil},
|
||||||
{"0x10000000000000000", 1<<64 - 1, os.ERANGE},
|
{"0x10000000000000000", 1<<64 - 1, ErrRange},
|
||||||
{"01777777777777777777777", 1<<64 - 1, nil},
|
{"01777777777777777777777", 1<<64 - 1, nil},
|
||||||
{"01777777777777777777778", 0, os.EINVAL},
|
{"01777777777777777777778", 0, ErrSyntax},
|
||||||
{"02000000000000000000000", 1<<64 - 1, os.ERANGE},
|
{"02000000000000000000000", 1<<64 - 1, ErrRange},
|
||||||
{"0200000000000000000000", 1 << 61, nil},
|
{"0200000000000000000000", 1 << 61, nil},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ type atoi64Test struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var atoi64tests = []atoi64Test{
|
var atoi64tests = []atoi64Test{
|
||||||
{"", 0, os.EINVAL},
|
{"", 0, ErrSyntax},
|
||||||
{"0", 0, nil},
|
{"0", 0, nil},
|
||||||
{"-0", 0, nil},
|
{"-0", 0, nil},
|
||||||
{"1", 1, nil},
|
{"1", 1, nil},
|
||||||
@ -71,14 +71,14 @@ var atoi64tests = []atoi64Test{
|
|||||||
{"-98765432100", -98765432100, nil},
|
{"-98765432100", -98765432100, nil},
|
||||||
{"9223372036854775807", 1<<63 - 1, nil},
|
{"9223372036854775807", 1<<63 - 1, nil},
|
||||||
{"-9223372036854775807", -(1<<63 - 1), nil},
|
{"-9223372036854775807", -(1<<63 - 1), nil},
|
||||||
{"9223372036854775808", 1<<63 - 1, os.ERANGE},
|
{"9223372036854775808", 1<<63 - 1, ErrRange},
|
||||||
{"-9223372036854775808", -1 << 63, nil},
|
{"-9223372036854775808", -1 << 63, nil},
|
||||||
{"9223372036854775809", 1<<63 - 1, os.ERANGE},
|
{"9223372036854775809", 1<<63 - 1, ErrRange},
|
||||||
{"-9223372036854775809", -1 << 63, os.ERANGE},
|
{"-9223372036854775809", -1 << 63, ErrRange},
|
||||||
}
|
}
|
||||||
|
|
||||||
var btoi64tests = []atoi64Test{
|
var btoi64tests = []atoi64Test{
|
||||||
{"", 0, os.EINVAL},
|
{"", 0, ErrSyntax},
|
||||||
{"0", 0, nil},
|
{"0", 0, nil},
|
||||||
{"-0", 0, nil},
|
{"-0", 0, nil},
|
||||||
{"1", 1, nil},
|
{"1", 1, nil},
|
||||||
@ -89,16 +89,16 @@ var btoi64tests = []atoi64Test{
|
|||||||
{"-012345", -012345, nil},
|
{"-012345", -012345, nil},
|
||||||
{"0x12345", 0x12345, nil},
|
{"0x12345", 0x12345, nil},
|
||||||
{"-0X12345", -0x12345, nil},
|
{"-0X12345", -0x12345, nil},
|
||||||
{"12345x", 0, os.EINVAL},
|
{"12345x", 0, ErrSyntax},
|
||||||
{"-12345x", 0, os.EINVAL},
|
{"-12345x", 0, ErrSyntax},
|
||||||
{"98765432100", 98765432100, nil},
|
{"98765432100", 98765432100, nil},
|
||||||
{"-98765432100", -98765432100, nil},
|
{"-98765432100", -98765432100, nil},
|
||||||
{"9223372036854775807", 1<<63 - 1, nil},
|
{"9223372036854775807", 1<<63 - 1, nil},
|
||||||
{"-9223372036854775807", -(1<<63 - 1), nil},
|
{"-9223372036854775807", -(1<<63 - 1), nil},
|
||||||
{"9223372036854775808", 1<<63 - 1, os.ERANGE},
|
{"9223372036854775808", 1<<63 - 1, ErrRange},
|
||||||
{"-9223372036854775808", -1 << 63, nil},
|
{"-9223372036854775808", -1 << 63, nil},
|
||||||
{"9223372036854775809", 1<<63 - 1, os.ERANGE},
|
{"9223372036854775809", 1<<63 - 1, ErrRange},
|
||||||
{"-9223372036854775809", -1 << 63, os.ERANGE},
|
{"-9223372036854775809", -1 << 63, ErrRange},
|
||||||
}
|
}
|
||||||
|
|
||||||
type atoui32Test struct {
|
type atoui32Test struct {
|
||||||
@ -108,15 +108,15 @@ type atoui32Test struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var atoui32tests = []atoui32Test{
|
var atoui32tests = []atoui32Test{
|
||||||
{"", 0, os.EINVAL},
|
{"", 0, ErrSyntax},
|
||||||
{"0", 0, nil},
|
{"0", 0, nil},
|
||||||
{"1", 1, nil},
|
{"1", 1, nil},
|
||||||
{"12345", 12345, nil},
|
{"12345", 12345, nil},
|
||||||
{"012345", 12345, nil},
|
{"012345", 12345, nil},
|
||||||
{"12345x", 0, os.EINVAL},
|
{"12345x", 0, ErrSyntax},
|
||||||
{"987654321", 987654321, nil},
|
{"987654321", 987654321, nil},
|
||||||
{"4294967295", 1<<32 - 1, nil},
|
{"4294967295", 1<<32 - 1, nil},
|
||||||
{"4294967296", 1<<32 - 1, os.ERANGE},
|
{"4294967296", 1<<32 - 1, ErrRange},
|
||||||
}
|
}
|
||||||
|
|
||||||
type atoi32Test struct {
|
type atoi32Test struct {
|
||||||
@ -126,7 +126,7 @@ type atoi32Test struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var atoi32tests = []atoi32Test{
|
var atoi32tests = []atoi32Test{
|
||||||
{"", 0, os.EINVAL},
|
{"", 0, ErrSyntax},
|
||||||
{"0", 0, nil},
|
{"0", 0, nil},
|
||||||
{"-0", 0, nil},
|
{"-0", 0, nil},
|
||||||
{"1", 1, nil},
|
{"1", 1, nil},
|
||||||
@ -135,16 +135,16 @@ var atoi32tests = []atoi32Test{
|
|||||||
{"-12345", -12345, nil},
|
{"-12345", -12345, nil},
|
||||||
{"012345", 12345, nil},
|
{"012345", 12345, nil},
|
||||||
{"-012345", -12345, nil},
|
{"-012345", -12345, nil},
|
||||||
{"12345x", 0, os.EINVAL},
|
{"12345x", 0, ErrSyntax},
|
||||||
{"-12345x", 0, os.EINVAL},
|
{"-12345x", 0, ErrSyntax},
|
||||||
{"987654321", 987654321, nil},
|
{"987654321", 987654321, nil},
|
||||||
{"-987654321", -987654321, nil},
|
{"-987654321", -987654321, nil},
|
||||||
{"2147483647", 1<<31 - 1, nil},
|
{"2147483647", 1<<31 - 1, nil},
|
||||||
{"-2147483647", -(1<<31 - 1), nil},
|
{"-2147483647", -(1<<31 - 1), nil},
|
||||||
{"2147483648", 1<<31 - 1, os.ERANGE},
|
{"2147483648", 1<<31 - 1, ErrRange},
|
||||||
{"-2147483648", -1 << 31, nil},
|
{"-2147483648", -1 << 31, nil},
|
||||||
{"2147483649", 1<<31 - 1, os.ERANGE},
|
{"2147483649", 1<<31 - 1, ErrRange},
|
||||||
{"-2147483649", -1 << 31, os.ERANGE},
|
{"-2147483649", -1 << 31, ErrRange},
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -161,7 +161,7 @@ func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string,
|
|||||||
// easy cases
|
// easy cases
|
||||||
switch c := s[0]; {
|
switch c := s[0]; {
|
||||||
case c == quote && (quote == '\'' || quote == '"'):
|
case c == quote && (quote == '\'' || quote == '"'):
|
||||||
err = os.EINVAL
|
err = ErrSyntax
|
||||||
return
|
return
|
||||||
case c >= utf8.RuneSelf:
|
case c >= utf8.RuneSelf:
|
||||||
r, size := utf8.DecodeRuneInString(s)
|
r, size := utf8.DecodeRuneInString(s)
|
||||||
@ -172,7 +172,7 @@ func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string,
|
|||||||
|
|
||||||
// hard case: c is backslash
|
// hard case: c is backslash
|
||||||
if len(s) <= 1 {
|
if len(s) <= 1 {
|
||||||
err = os.EINVAL
|
err = ErrSyntax
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c := s[1]
|
c := s[1]
|
||||||
@ -205,13 +205,13 @@ func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string,
|
|||||||
}
|
}
|
||||||
var v rune
|
var v rune
|
||||||
if len(s) < n {
|
if len(s) < n {
|
||||||
err = os.EINVAL
|
err = ErrSyntax
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for j := 0; j < n; j++ {
|
for j := 0; j < n; j++ {
|
||||||
x, ok := unhex(s[j])
|
x, ok := unhex(s[j])
|
||||||
if !ok {
|
if !ok {
|
||||||
err = os.EINVAL
|
err = ErrSyntax
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
v = v<<4 | x
|
v = v<<4 | x
|
||||||
@ -223,7 +223,7 @@ func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string,
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if v > unicode.MaxRune {
|
if v > unicode.MaxRune {
|
||||||
err = os.EINVAL
|
err = ErrSyntax
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
value = v
|
value = v
|
||||||
@ -231,7 +231,7 @@ func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string,
|
|||||||
case '0', '1', '2', '3', '4', '5', '6', '7':
|
case '0', '1', '2', '3', '4', '5', '6', '7':
|
||||||
v := rune(c) - '0'
|
v := rune(c) - '0'
|
||||||
if len(s) < 2 {
|
if len(s) < 2 {
|
||||||
err = os.EINVAL
|
err = ErrSyntax
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for j := 0; j < 2; j++ { // one digit already; two more
|
for j := 0; j < 2; j++ { // one digit already; two more
|
||||||
@ -243,7 +243,7 @@ func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string,
|
|||||||
}
|
}
|
||||||
s = s[2:]
|
s = s[2:]
|
||||||
if v > 255 {
|
if v > 255 {
|
||||||
err = os.EINVAL
|
err = ErrSyntax
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
value = v
|
value = v
|
||||||
@ -251,12 +251,12 @@ func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string,
|
|||||||
value = '\\'
|
value = '\\'
|
||||||
case '\'', '"':
|
case '\'', '"':
|
||||||
if c != quote {
|
if c != quote {
|
||||||
err = os.EINVAL
|
err = ErrSyntax
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
value = rune(c)
|
value = rune(c)
|
||||||
default:
|
default:
|
||||||
err = os.EINVAL
|
err = ErrSyntax
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tail = s
|
tail = s
|
||||||
@ -271,25 +271,25 @@ func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string,
|
|||||||
func Unquote(s string) (t string, err os.Error) {
|
func Unquote(s string) (t string, err os.Error) {
|
||||||
n := len(s)
|
n := len(s)
|
||||||
if n < 2 {
|
if n < 2 {
|
||||||
return "", os.EINVAL
|
return "", ErrSyntax
|
||||||
}
|
}
|
||||||
quote := s[0]
|
quote := s[0]
|
||||||
if quote != s[n-1] {
|
if quote != s[n-1] {
|
||||||
return "", os.EINVAL
|
return "", ErrSyntax
|
||||||
}
|
}
|
||||||
s = s[1 : n-1]
|
s = s[1 : n-1]
|
||||||
|
|
||||||
if quote == '`' {
|
if quote == '`' {
|
||||||
if strings.Contains(s, "`") {
|
if strings.Contains(s, "`") {
|
||||||
return "", os.EINVAL
|
return "", ErrSyntax
|
||||||
}
|
}
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
if quote != '"' && quote != '\'' {
|
if quote != '"' && quote != '\'' {
|
||||||
return "", os.EINVAL
|
return "", ErrSyntax
|
||||||
}
|
}
|
||||||
if strings.Index(s, "\n") >= 0 {
|
if strings.Index(s, "\n") >= 0 {
|
||||||
return "", os.EINVAL
|
return "", ErrSyntax
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is it trivial? Avoid allocation.
|
// Is it trivial? Avoid allocation.
|
||||||
@ -319,7 +319,7 @@ func Unquote(s string) (t string, err os.Error) {
|
|||||||
}
|
}
|
||||||
if quote == '\'' && len(s) != 0 {
|
if quote == '\'' && len(s) != 0 {
|
||||||
// single-quoted must be single character
|
// single-quoted must be single character
|
||||||
return "", os.EINVAL
|
return "", ErrSyntax
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return buf.String(), nil
|
return buf.String(), nil
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
package strconv_test
|
package strconv_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
. "strconv"
|
. "strconv"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -210,8 +209,8 @@ func TestUnquote(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range misquoted {
|
for _, s := range misquoted {
|
||||||
if out, err := Unquote(s); out != "" || err != os.EINVAL {
|
if out, err := Unquote(s); out != "" || err != ErrSyntax {
|
||||||
t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", os.EINVAL)
|
t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", ErrSyntax)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user