1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
9 // ErrRange indicates that a value is out of range for the target type.
10 var ErrRange = errors.New("value out of range")
12 // ErrSyntax indicates that a value does not have the right syntax for the target type.
13 var ErrSyntax = errors.New("invalid syntax")
15 // A NumError records a failed conversion.
16 type NumError struct {
17 Num string // the input
18 Err error // the reason the conversion failed (ErrRange, ErrSyntax)
21 func (e *NumError) Error() string { return `parsing "` + e.Num + `": ` + e.Err.Error() }
23 func computeIntsize() uint {
31 var IntSize = computeIntsize()
33 // Return the first number n such that n*base >= 1<<64.
34 func cutoff64(base int) uint64 {
38 return (1<<64-1)/uint64(base) + 1
41 // Btoui64 interprets a string s in an arbitrary base b (2 to 36)
42 // and returns the corresponding value n. If b == 0, the base
43 // is taken from the string prefix: base 16 for "0x", base 8 for "0",
44 // and base 10 otherwise.
46 // The errors that Btoui64 returns have concrete type *NumError
47 // and include err.Num = s. If s is empty or contains invalid
48 // digits, err.Error = ErrSyntax; if the value corresponding
49 // to s cannot be represented by a uint64, err.Error = ErrRange.
50 func Btoui64(s string, b int) (n uint64, err error) {
59 case 2 <= b && b <= 36:
60 // valid base; nothing to do
63 // Look for octal, hex prefix.
65 case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
79 err = errors.New("invalid base " + Itoa(b))
86 for i := 0; i < len(s); i++ {
90 case '0' <= d && d <= '9':
92 case 'a' <= d && d <= 'z':
94 case 'A' <= d && d <= 'Z':
128 return n, &NumError{s0, err}
131 // Atoui64 interprets a string s as a decimal number and
132 // returns the corresponding value n.
134 // Atoui64 returns err.Error = ErrSyntax if s is empty or contains invalid digits.
135 // It returns err.Error = ErrRange if s cannot be represented by a uint64.
136 func Atoui64(s string) (n uint64, err error) {
137 return Btoui64(s, 10)
140 // Btoi64 is like Btoui64 but allows signed numbers and
141 // returns its result in an int64.
142 func Btoi64(s string, base int) (i int64, err error) {
145 return 0, &NumError{s, ErrSyntax}
148 // Pick off leading sign.
153 } else if s[0] == '-' {
158 // Convert unsigned and check range.
160 un, err = Btoui64(s, base)
161 if err != nil && err.(*NumError).Err != ErrRange {
162 err.(*NumError).Num = s0
165 if !neg && un >= 1<<63 {
166 return 1<<63 - 1, &NumError{s0, ErrRange}
168 if neg && un > 1<<63 {
169 return -1 << 63, &NumError{s0, ErrRange}
178 // Atoi64 is like Atoui64 but allows signed numbers and
179 // returns its result in an int64.
180 func Atoi64(s string) (i int64, err error) { return Btoi64(s, 10) }
182 // Atoui is like Atoui64 but returns its result as a uint.
183 func Atoui(s string) (i uint, err error) {
185 if e1 != nil && e1.(*NumError).Err != ErrRange {
190 return ^uint(0), &NumError{s, ErrRange}
195 // Atoi is like Atoi64 but returns its result as an int.
196 func Atoi(s string) (i int, err error) {
198 if e1 != nil && e1.(*NumError).Err != ErrRange {
204 return -1 << (IntSize - 1), &NumError{s, ErrRange}
206 return 1<<(IntSize-1) - 1, &NumError{s, ErrRange}