diff options
author | Russ Cox <rsc@golang.org> | 2008-11-18 17:12:07 -0800 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2008-11-18 17:12:07 -0800 |
commit | d81c463bdd945b62b74fea03bc9ad7660891e1e7 (patch) | |
tree | 500b9a192188c7c743f5f6cbbfe5a1cb6fd0e33c /src | |
parent | a4bcb8c18d874d51f348143aa60715ac81bb68ec (diff) | |
download | golang-d81c463bdd945b62b74fea03bc9ad7660891e1e7.tar.gz |
return *os.Error instead of bool from strconv.ato*
R=r
DELTA=137 (56 added, 4 deleted, 77 changed)
OCL=19505
CL=19522
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/strconv/atof.go | 57 | ||||
-rw-r--r-- | src/lib/strconv/atoi.go | 93 |
2 files changed, 100 insertions, 50 deletions
diff --git a/src/lib/strconv/atof.go b/src/lib/strconv/atof.go index c0bb1a61c..5f019d3ec 100644 --- a/src/lib/strconv/atof.go +++ b/src/lib/strconv/atof.go @@ -10,7 +10,10 @@ package strconv -import "strconv" +import ( + "os"; + "strconv"; +) // TODO(rsc): Better truncation handling. func StringToDecimal(s string) (neg bool, d *Decimal, trunc bool, ok bool) { @@ -314,43 +317,49 @@ func DecimalToFloat32(neg bool, d *Decimal, trunc bool) (f float32, ok bool) { // returns f, false, true, where f is the nearest floating point // number rounded using IEEE754 unbiased rounding. // -// If s is not syntactically well-formed, returns ok == false. +// If s is not syntactically well-formed, returns err = os.EINVAL. // // If s is syntactically well-formed but is more than 1/2 ULP // away from the largest floating point number of the given size, -// returns f = ±Inf, overflow = true, ok = true. -export func atof64(s string) (f float64, overflow bool, ok bool) { - neg, d, trunc, ok1 := StringToDecimal(s); - if !ok1 { - return 0, false, false; +// returns f = ±Inf, err = os.ERANGE. +export func atof64(s string) (f float64, err *os.Error) { + neg, d, trunc, ok := StringToDecimal(s); + if !ok { + return 0, os.EINVAL; } if f, ok := DecimalToFloat64(neg, d, trunc); ok { - return f, false, true; + return f, nil; } - b, overflow1 := DecimalToFloatBits(neg, d, trunc, &float64info); - return sys.float64frombits(b), overflow1, true; + b, ovf := DecimalToFloatBits(neg, d, trunc, &float64info); + f = sys.float64frombits(b); + if ovf { + err = os.ERANGE; + } + return f, err } -export func atof32(s string) (f float32, overflow bool, ok bool) { - neg, d, trunc, ok1 := StringToDecimal(s); - if !ok1 { - return 0, false, false; +export func atof32(s string) (f float32, err *os.Error) { + neg, d, trunc, ok := StringToDecimal(s); + if !ok { + return 0, os.EINVAL; } if f, ok := DecimalToFloat32(neg, d, trunc); ok { - return f, false, true; + return f, nil; + } + b, ovf := DecimalToFloatBits(neg, d, trunc, &float32info); + f = sys.float32frombits(uint32(b)); + if ovf { + err = os.ERANGE; } - b, overflow1 := DecimalToFloatBits(neg, d, trunc, &float32info); - return sys.float32frombits(uint32(b)), overflow1, true; + return f, err } -export func atof(s string) (f float, overflow bool, ok bool) { +export func atof(s string) (f float, err *os.Error) { if floatsize == 32 { - var f1 float32; - f1, overflow, ok = atof32(s); - return float(f1), overflow, ok; + f1, err1 := atof32(s); + return float(f1), err1; } - var f1 float64; - f1, overflow, ok = atof64(s); - return float(f1), overflow, ok; + f1, err1 := atof64(s); + return float(f1), err1; } diff --git a/src/lib/strconv/atoi.go b/src/lib/strconv/atoi.go index 7f741c304..cd02df1aa 100644 --- a/src/lib/strconv/atoi.go +++ b/src/lib/strconv/atoi.go @@ -3,42 +3,59 @@ // license that can be found in the LICENSE file. package strconv +import "os" + +func IntSize() uint { + siz := uint(8); + for 1<<siz != 0 { + siz *= 2 + } + return siz +} +var intsize = IntSize(); // Convert decimal string to unsigned integer. -// TODO: Doesn't check for overflow. -export func atoui64(s string) (i uint64, ok bool) { +export func atoui64(s string) (i uint64, err *os.Error) { // empty string bad - if len(s) == 0 { - return 0, false + if len(s) == 0 { + return 0, os.EINVAL } // pick off zero if s == "0" { - return 0, true + return 0, nil } - - // otherwise, leading zero bad + + // otherwise, leading zero bad: + // don't want to take something intended as octal. if s[0] == '0' { - return 0, false + return 0, os.EINVAL } // parse number n := uint64(0); for i := 0; i < len(s); i++ { if s[i] < '0' || s[i] > '9' { - return 0, false + return 0, os.EINVAL + } + if n > (1<<64)/10 { + return 1<<64-1, os.ERANGE } - n = n*10 + uint64(s[i] - '0') + n = n*10; + d := uint64(s[i] - '0'); + if n+d < n { + return 1<<64-1, os.ERANGE + } + n += d; } - return n, true + return n, nil } // Convert decimal string to integer. -// TODO: Doesn't check for overflow. -export func atoi64(s string) (i int64, ok bool) { +export func atoi64(s string) (i int64, err *os.Error) { // empty string bad if len(s) == 0 { - return 0, false + return 0, os.EINVAL } // pick off leading sign @@ -51,25 +68,49 @@ export func atoi64(s string) (i int64, ok bool) { } var un uint64; - un, ok = atoui64(s); - if !ok { - return 0, false + un, err = atoui64(s); + if err != nil && err != os.ERANGE { + return 0, err + } + if !neg && un >= 1<<63 { + return 1<<63-1, os.ERANGE + } + if neg && un > 1<<63 { + return -1<<63, os.ERANGE } n := int64(un); if neg { n = -n } - return n, true + return n, nil } -export func atoui(s string) (i uint, ok bool) { - ii, okok := atoui64(s); - i = uint(ii); - return i, okok +export func atoui(s string) (i uint, err *os.Error) { + i1, e1 := atoui64(s); + if e1 != nil && e1 != os.ERANGE { + return 0, e1 + } + i = uint(i1); + if uint64(i) != i1 { + // TODO: return uint(^0), os.ERANGE. + i1 = 1<<64-1; + return uint(i1), os.ERANGE + } + return i, nil } -export func atoi(s string) (i int, ok bool) { - ii, okok := atoi64(s); - i = int(ii); - return i, okok +export func atoi(s string) (i int, err *os.Error) { + i1, e1 := atoi64(s); + if e1 != nil && e1 != os.ERANGE { + return 0, e1 + } + i = int(i1); + if int64(i) != i1 { + if i1 < 0 { + return -1<<(intsize-1), os.ERANGE + } + return 1<<(intsize-1) - 1, os.ERANGE + } + return i, nil } + |