* config/avr/avr-arch.h
[official-gcc.git] / libgo / go / strconv / atoi.go
blobbdd5d71f875d425b2b602db8d942dcbf8b518917
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.
5 package strconv
7 import "errors"
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 Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat)
18 Num string // the input
19 Err error // the reason the conversion failed (ErrRange, ErrSyntax)
22 func (e *NumError) Error() string {
23 return "strconv." + e.Func + ": " + `parsing "` + e.Num + `": ` + e.Err.Error()
26 func syntaxError(fn, str string) *NumError {
27 return &NumError{fn, str, ErrSyntax}
30 func rangeError(fn, str string) *NumError {
31 return &NumError{fn, str, ErrRange}
34 const intSize = 32 << uint(^uint(0)>>63)
36 const IntSize = intSize // number of bits in int, uint (32 or 64)
38 // Return the first number n such that n*base >= 1<<64.
39 func cutoff64(base int) uint64 {
40 if base < 2 {
41 return 0
43 return (1<<64-1)/uint64(base) + 1
46 // ParseUint is like ParseInt but for unsigned numbers.
47 func ParseUint(s string, base int, bitSize int) (n uint64, err error) {
48 var cutoff, maxVal uint64
50 if bitSize == 0 {
51 bitSize = int(IntSize)
54 s0 := s
55 switch {
56 case len(s) < 1:
57 err = ErrSyntax
58 goto Error
60 case 2 <= base && base <= 36:
61 // valid base; nothing to do
63 case base == 0:
64 // Look for octal, hex prefix.
65 switch {
66 case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
67 base = 16
68 s = s[2:]
69 if len(s) < 1 {
70 err = ErrSyntax
71 goto Error
73 case s[0] == '0':
74 base = 8
75 default:
76 base = 10
79 default:
80 err = errors.New("invalid base " + Itoa(base))
81 goto Error
84 n = 0
85 cutoff = cutoff64(base)
86 maxVal = 1<<uint(bitSize) - 1
88 for i := 0; i < len(s); i++ {
89 var v byte
90 d := s[i]
91 switch {
92 case '0' <= d && d <= '9':
93 v = d - '0'
94 case 'a' <= d && d <= 'z':
95 v = d - 'a' + 10
96 case 'A' <= d && d <= 'Z':
97 v = d - 'A' + 10
98 default:
99 n = 0
100 err = ErrSyntax
101 goto Error
103 if int(v) >= base {
104 n = 0
105 err = ErrSyntax
106 goto Error
109 if n >= cutoff {
110 // n*base overflows
111 n = 1<<64 - 1
112 err = ErrRange
113 goto Error
115 n *= uint64(base)
117 n1 := n + uint64(v)
118 if n1 < n || n1 > maxVal {
119 // n+v overflows
120 n = 1<<64 - 1
121 err = ErrRange
122 goto Error
124 n = n1
127 return n, nil
129 Error:
130 return n, &NumError{"ParseUint", s0, err}
133 // ParseInt interprets a string s in the given base (2 to 36) and
134 // returns the corresponding value i. If base == 0, the base is
135 // implied by the string's prefix: base 16 for "0x", base 8 for
136 // "0", and base 10 otherwise.
138 // The bitSize argument specifies the integer type
139 // that the result must fit into. Bit sizes 0, 8, 16, 32, and 64
140 // correspond to int, int8, int16, int32, and int64.
142 // The errors that ParseInt returns have concrete type *NumError
143 // and include err.Num = s. If s is empty or contains invalid
144 // digits, err.Error = ErrSyntax; if the value corresponding
145 // to s cannot be represented by a signed integer of the
146 // given size, err.Error = ErrRange.
147 func ParseInt(s string, base int, bitSize int) (i int64, err error) {
148 const fnParseInt = "ParseInt"
150 if bitSize == 0 {
151 bitSize = int(IntSize)
154 // Empty string bad.
155 if len(s) == 0 {
156 return 0, syntaxError(fnParseInt, s)
159 // Pick off leading sign.
160 s0 := s
161 neg := false
162 if s[0] == '+' {
163 s = s[1:]
164 } else if s[0] == '-' {
165 neg = true
166 s = s[1:]
169 // Convert unsigned and check range.
170 var un uint64
171 un, err = ParseUint(s, base, bitSize)
172 if err != nil && err.(*NumError).Err != ErrRange {
173 err.(*NumError).Func = fnParseInt
174 err.(*NumError).Num = s0
175 return 0, err
177 cutoff := uint64(1 << uint(bitSize-1))
178 if !neg && un >= cutoff {
179 return int64(cutoff - 1), rangeError(fnParseInt, s0)
181 if neg && un > cutoff {
182 return -int64(cutoff), rangeError(fnParseInt, s0)
184 n := int64(un)
185 if neg {
186 n = -n
188 return n, nil
191 // Atoi is shorthand for ParseInt(s, 10, 0).
192 func Atoi(s string) (i int, err error) {
193 i64, err := ParseInt(s, 10, 0)
194 return int(i64), err