}
// Btoui64 interprets a string s in an arbitrary base b (2 to 36)
-// and returns the corresponding value n.
+// and returns the corresponding value n. If b == 0, the base
+// is taken from the string prefix: base 16 for "0x", base 8 for "0",
+// and base 10 otherwise.
//
// The errors that Btoui64 returns have concrete type *NumError
// and include err.Num = s. If s is empty or contains invalid
// digits, err.Error = os.EINVAL; if the value corresponding
// to s cannot be represented by a uint64, err.Error = os.ERANGE.
func Btoui64(s string, b int) (n uint64, err os.Error) {
- if b < 2 || b > 36 {
- err = os.ErrorString("invalid base " + Itoa(b));
- goto Error;
- }
- if len(s) < 1 {
+ s0 := s;
+ switch {
+ case len(s) < 1:
err = os.EINVAL;
goto Error;
+
+ case 2 <= b && b <= 36:
+ // valid base; nothing to do
+
+ case b == 0:
+ // Look for octal, hex prefix.
+ switch {
+ case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
+ b = 16;
+ s = s[2:len(s)];
+ if len(s) < 1 {
+ err = os.EINVAL;
+ goto Error;
+ }
+ case s[0] == '0':
+ b = 8;
+ default:
+ b = 10;
+ }
+
+ default:
+ err = os.ErrorString("invalid base " + Itoa(b));
+ goto Error;
}
n = 0;
return n, nil;
Error:
- return n, &NumError{s, err};
+ return n, &NumError{s0, err};
}
-// Atoui64 interprets a string s as an unsigned decimal, octal, or
-// hexadecimal number and returns the corresponding value n.
-// The default base is decimal. Strings beginning with 0x are
-// hexadecimal; strings beginning with 0 are octal.
+// Atoui64 interprets a string s as a decimal number and
+// returns the corresponding value n.
//
// Atoui64 returns err == os.EINVAL if s is empty or contains invalid digits.
// It returns err == os.ERANGE if s cannot be represented by a uint64.
func Atoui64(s string) (n uint64, err os.Error) {
- // Empty string bad.
- if len(s) == 0 {
- return 0, &NumError{s, os.EINVAL};
- }
-
- // Look for octal, hex prefix.
- switch {
- case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
- n, err = Btoui64(s[2:len(s)], 16);
- case s[0] == '0':
- n, err = Btoui64(s, 8);
- default:
- n, err = Btoui64(s, 10);
- }
-
- if err != nil {
- err.(*NumError).Num = s;
- }
- return;
+ return Btoui64(s, 10);
}
-
-// Atoi64 is like Atoui64 but allows signed numbers and
+// Btoi64 is like Btoui64 but allows signed numbers and
// returns its result in an int64.
-func Atoi64(s string) (i int64, err os.Error) {
+func Btoi64(s string, base int) (i int64, err os.Error) {
// Empty string bad.
if len(s) == 0 {
return 0, &NumError{s, os.EINVAL};
// Convert unsigned and check range.
var un uint64;
- un, err = Atoui64(s);
+ un, err = Btoui64(s, base);
if err != nil && err.(*NumError).Error != os.ERANGE {
err.(*NumError).Num = s0;
return 0, err;
return n, nil;
}
+// Atoi64 is like Atoui64 but allows signed numbers and
+// returns its result in an int64.
+func Atoi64(s string) (i int64, err os.Error) {
+ return Btoi64(s, 10);
+}
+
+
// Atoui is like Atoui64 but returns its result as a uint.
func Atoui(s string) (i uint, err os.Error) {
i1, e1 := Atoui64(s);
}
var atoui64tests = []atoui64Test{
+ atoui64Test{"", 0, os.EINVAL},
+ atoui64Test{"0", 0, nil},
+ atoui64Test{"1", 1, nil},
+ atoui64Test{"12345", 12345, nil},
+ atoui64Test{"012345", 12345, nil},
+ atoui64Test{"12345x", 0, os.EINVAL},
+ atoui64Test{"98765432100", 98765432100, nil},
+ atoui64Test{"18446744073709551615", 1<<64 - 1, nil},
+ atoui64Test{"18446744073709551616", 1<<64 - 1, os.ERANGE},
+ atoui64Test{"18446744073709551620", 1<<64 - 1, os.ERANGE},
+}
+
+var btoui64tests = []atoui64Test{
atoui64Test{"", 0, os.EINVAL},
atoui64Test{"0", 0, nil},
atoui64Test{"1", 1, nil},
}
var atoi64tests = []atoi64Test{
+ atoi64Test{"", 0, os.EINVAL},
+ atoi64Test{"0", 0, nil},
+ atoi64Test{"-0", 0, nil},
+ atoi64Test{"1", 1, nil},
+ atoi64Test{"-1", -1, nil},
+ atoi64Test{"12345", 12345, nil},
+ atoi64Test{"-12345", -12345, nil},
+ atoi64Test{"012345", 12345, nil},
+ atoi64Test{"-012345", -12345, nil},
+ atoi64Test{"98765432100", 98765432100, nil},
+ atoi64Test{"-98765432100", -98765432100, nil},
+ atoi64Test{"9223372036854775807", 1<<63 - 1, nil},
+ atoi64Test{"-9223372036854775807", -(1<<63 - 1), nil},
+ atoi64Test{"9223372036854775808", 1<<63 - 1, os.ERANGE},
+ atoi64Test{"-9223372036854775808", -1 << 63, nil},
+ atoi64Test{"9223372036854775809", 1<<63 - 1, os.ERANGE},
+ atoi64Test{"-9223372036854775809", -1 << 63, os.ERANGE},
+}
+
+var btoi64tests = []atoi64Test{
atoi64Test{"", 0, os.EINVAL},
atoi64Test{"0", 0, nil},
atoi64Test{"-0", 0, nil},
atoui32Test{"0", 0, nil},
atoui32Test{"1", 1, nil},
atoui32Test{"12345", 12345, nil},
- atoui32Test{"012345", 012345, nil},
- atoui32Test{"0x12345", 0x12345, nil},
- atoui32Test{"0X12345", 0x12345, nil},
+ atoui32Test{"012345", 12345, nil},
atoui32Test{"12345x", 0, os.EINVAL},
atoui32Test{"987654321", 987654321, nil},
atoui32Test{"4294967295", 1<<32 - 1, nil},
atoi32Test{"-1", -1, nil},
atoi32Test{"12345", 12345, nil},
atoi32Test{"-12345", -12345, nil},
- atoi32Test{"012345", 012345, nil},
- atoi32Test{"-012345", -012345, nil},
- atoi32Test{"0x12345", 0x12345, nil},
- atoi32Test{"-0X12345", -0x12345, nil},
+ atoi32Test{"012345", 12345, nil},
+ atoi32Test{"-012345", -12345, nil},
atoi32Test{"12345x", 0, os.EINVAL},
atoi32Test{"-12345x", 0, os.EINVAL},
atoi32Test{"987654321", 987654321, nil},
test.err = &NumError{test.in, test.err};
}
}
+ for i := range btoui64tests {
+ test := &btoui64tests[i];
+ if test.err != nil {
+ test.err = &NumError{test.in, test.err};
+ }
+ }
for i := range atoi64tests {
test := &atoi64tests[i];
if test.err != nil {
test.err = &NumError{test.in, test.err};
}
}
+ for i := range btoi64tests {
+ test := &btoi64tests[i];
+ if test.err != nil {
+ test.err = &NumError{test.in, test.err};
+ }
+ }
for i := range atoui32tests {
test := &atoui32tests[i];
if test.err != nil {
}
}
+func TestBtoui64(t *testing.T) {
+ for i := range btoui64tests {
+ test := &btoui64tests[i];
+ out, err := Btoui64(test.in, 0);
+ if test.out != out || !reflect.DeepEqual(test.err, err) {
+ t.Errorf("Btoui64(%q) = %v, %v want %v, %v\n",
+ test.in, out, err, test.out, test.err);
+ }
+ }
+}
+
func TestAtoi64(t *testing.T) {
for i := range atoi64tests {
test := &atoi64tests[i];
}
}
+func TestBtoi64(t *testing.T) {
+ for i := range btoi64tests {
+ test := &btoi64tests[i];
+ out, err := Btoi64(test.in, 0);
+ if test.out != out || !reflect.DeepEqual(test.err, err) {
+ t.Errorf("Btoi64(%q) = %v, %v want %v, %v\n",
+ test.in, out, err, test.out, test.err);
+ }
+ }
+}
+
func TestAtoui(t *testing.T) {
switch IntSize {
case 32: