2008-11-17 13:34:03 -07:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package strconv
|
2008-11-18 18:12:07 -07:00
|
|
|
import "os"
|
|
|
|
|
2009-01-15 18:22:17 -07:00
|
|
|
func computeIntsize() uint {
|
2008-11-18 18:12:07 -07:00
|
|
|
siz := uint(8);
|
|
|
|
for 1<<siz != 0 {
|
|
|
|
siz *= 2
|
|
|
|
}
|
|
|
|
return siz
|
|
|
|
}
|
2009-01-15 18:22:17 -07:00
|
|
|
var intsize = computeIntsize();
|
2008-11-17 13:34:03 -07:00
|
|
|
|
|
|
|
// Convert decimal string to unsigned integer.
|
2009-01-20 15:40:40 -07:00
|
|
|
func Atoui64(s string) (i uint64, err *os.Error) {
|
2008-11-17 13:34:03 -07:00
|
|
|
// empty string bad
|
2008-11-18 18:12:07 -07:00
|
|
|
if len(s) == 0 {
|
|
|
|
return 0, os.EINVAL
|
2008-11-17 13:34:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// pick off zero
|
|
|
|
if s == "0" {
|
2008-11-18 18:12:07 -07:00
|
|
|
return 0, nil
|
2008-11-17 13:34:03 -07:00
|
|
|
}
|
2008-11-18 18:12:07 -07:00
|
|
|
|
|
|
|
// otherwise, leading zero bad:
|
|
|
|
// don't want to take something intended as octal.
|
2008-11-17 13:34:03 -07:00
|
|
|
if s[0] == '0' {
|
2008-11-18 18:12:07 -07:00
|
|
|
return 0, os.EINVAL
|
2008-11-17 13:34:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// parse number
|
|
|
|
n := uint64(0);
|
|
|
|
for i := 0; i < len(s); i++ {
|
|
|
|
if s[i] < '0' || s[i] > '9' {
|
2008-11-18 18:12:07 -07:00
|
|
|
return 0, os.EINVAL
|
|
|
|
}
|
|
|
|
if n > (1<<64)/10 {
|
|
|
|
return 1<<64-1, os.ERANGE
|
2008-11-17 13:34:03 -07:00
|
|
|
}
|
2008-11-18 18:12:07 -07:00
|
|
|
n = n*10;
|
|
|
|
d := uint64(s[i] - '0');
|
|
|
|
if n+d < n {
|
|
|
|
return 1<<64-1, os.ERANGE
|
|
|
|
}
|
|
|
|
n += d;
|
2008-11-17 13:34:03 -07:00
|
|
|
}
|
2008-11-18 18:12:07 -07:00
|
|
|
return n, nil
|
2008-11-17 13:34:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Convert decimal string to integer.
|
2009-01-20 15:40:40 -07:00
|
|
|
func Atoi64(s string) (i int64, err *os.Error) {
|
2008-11-17 13:34:03 -07:00
|
|
|
// empty string bad
|
|
|
|
if len(s) == 0 {
|
2008-11-18 18:12:07 -07:00
|
|
|
return 0, os.EINVAL
|
2008-11-17 13:34:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// pick off leading sign
|
|
|
|
neg := false;
|
|
|
|
if s[0] == '+' {
|
|
|
|
s = s[1:len(s)]
|
|
|
|
} else if s[0] == '-' {
|
|
|
|
neg = true;
|
|
|
|
s = s[1:len(s)]
|
|
|
|
}
|
|
|
|
|
|
|
|
var un uint64;
|
2009-01-15 18:22:17 -07:00
|
|
|
un, err = Atoui64(s);
|
2008-11-18 18:12:07 -07:00
|
|
|
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
|
2008-11-17 13:34:03 -07:00
|
|
|
}
|
|
|
|
n := int64(un);
|
|
|
|
if neg {
|
|
|
|
n = -n
|
|
|
|
}
|
2008-11-18 18:12:07 -07:00
|
|
|
return n, nil
|
2008-11-17 13:34:03 -07:00
|
|
|
}
|
|
|
|
|
2009-01-20 15:40:40 -07:00
|
|
|
func Atoui(s string) (i uint, err *os.Error) {
|
2009-01-15 18:22:17 -07:00
|
|
|
i1, e1 := Atoui64(s);
|
2008-11-18 18:12:07 -07:00
|
|
|
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
|
2008-11-17 13:34:03 -07:00
|
|
|
}
|
|
|
|
|
2009-01-20 15:40:40 -07:00
|
|
|
func Atoi(s string) (i int, err *os.Error) {
|
2009-01-15 18:22:17 -07:00
|
|
|
i1, e1 := Atoi64(s);
|
2008-11-18 18:12:07 -07:00
|
|
|
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
|
2008-11-17 13:34:03 -07:00
|
|
|
}
|
2008-11-18 18:12:07 -07:00
|
|
|
|