* gcc.dg/ipa/inlinehint-4.c: Also pass --param inline-unit-growth=20.
[official-gcc.git] / libgo / go / strconv / atoi.go
blobbebed048204fb0eaeac57bf625987c7c2d5a2269
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 (e.g. ErrRange, ErrSyntax, etc.)
22 func (e *NumError) Error() string {
23 return "strconv." + e.Func + ": " + "parsing " + Quote(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 func baseError(fn, str string, base int) *NumError {
35 return &NumError{fn, str, errors.New("invalid base " + Itoa(base))}
38 func bitSizeError(fn, str string, bitSize int) *NumError {
39 return &NumError{fn, str, errors.New("invalid bit size " + Itoa(bitSize))}
42 const intSize = 32 << (^uint(0) >> 63)
44 // IntSize is the size in bits of an int or uint value.
45 const IntSize = intSize
47 const maxUint64 = (1<<64 - 1)
49 // ParseUint is like ParseInt but for unsigned numbers.
50 func ParseUint(s string, base int, bitSize int) (uint64, error) {
51 const fnParseUint = "ParseUint"
53 if len(s) == 0 {
54 return 0, syntaxError(fnParseUint, s)
57 s0 := s
58 switch {
59 case 2 <= base && base <= 36:
60 // valid base; nothing to do
62 case base == 0:
63 // Look for octal, hex prefix.
64 switch {
65 case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
66 if len(s) < 3 {
67 return 0, syntaxError(fnParseUint, s0)
69 base = 16
70 s = s[2:]
71 case s[0] == '0':
72 base = 8
73 s = s[1:]
74 default:
75 base = 10
78 default:
79 return 0, baseError(fnParseUint, s0, base)
82 if bitSize == 0 {
83 bitSize = int(IntSize)
84 } else if bitSize < 0 || bitSize > 64 {
85 return 0, bitSizeError(fnParseUint, s0, bitSize)
88 // Cutoff is the smallest number such that cutoff*base > maxUint64.
89 // Use compile-time constants for common cases.
90 var cutoff uint64
91 switch base {
92 case 10:
93 cutoff = maxUint64/10 + 1
94 case 16:
95 cutoff = maxUint64/16 + 1
96 default:
97 cutoff = maxUint64/uint64(base) + 1
100 maxVal := uint64(1)<<uint(bitSize) - 1
102 var n uint64
103 for _, c := range []byte(s) {
104 var d byte
105 switch {
106 case '0' <= c && c <= '9':
107 d = c - '0'
108 case 'a' <= c && c <= 'z':
109 d = c - 'a' + 10
110 case 'A' <= c && c <= 'Z':
111 d = c - 'A' + 10
112 default:
113 return 0, syntaxError(fnParseUint, s0)
116 if d >= byte(base) {
117 return 0, syntaxError(fnParseUint, s0)
120 if n >= cutoff {
121 // n*base overflows
122 return maxVal, rangeError(fnParseUint, s0)
124 n *= uint64(base)
126 n1 := n + uint64(d)
127 if n1 < n || n1 > maxVal {
128 // n+v overflows
129 return maxVal, rangeError(fnParseUint, s0)
131 n = n1
134 return n, nil
137 // ParseInt interprets a string s in the given base (0, 2 to 36) and
138 // bit size (0 to 64) and returns the corresponding value i.
140 // If base == 0, the base is implied by the string's prefix:
141 // base 16 for "0x", base 8 for "0", and base 10 otherwise.
142 // For bases 1, below 0 or above 36 an error is returned.
144 // The bitSize argument specifies the integer type
145 // that the result must fit into. Bit sizes 0, 8, 16, 32, and 64
146 // correspond to int, int8, int16, int32, and int64.
147 // For a bitSize below 0 or above 64 an error is returned.
149 // The errors that ParseInt returns have concrete type *NumError
150 // and include err.Num = s. If s is empty or contains invalid
151 // digits, err.Err = ErrSyntax and the returned value is 0;
152 // if the value corresponding to s cannot be represented by a
153 // signed integer of the given size, err.Err = ErrRange and the
154 // returned value is the maximum magnitude integer of the
155 // appropriate bitSize and sign.
156 func ParseInt(s string, base int, bitSize int) (i int64, err error) {
157 const fnParseInt = "ParseInt"
159 // Empty string bad.
160 if len(s) == 0 {
161 return 0, syntaxError(fnParseInt, s)
164 // Pick off leading sign.
165 s0 := s
166 neg := false
167 if s[0] == '+' {
168 s = s[1:]
169 } else if s[0] == '-' {
170 neg = true
171 s = s[1:]
174 // Convert unsigned and check range.
175 var un uint64
176 un, err = ParseUint(s, base, bitSize)
177 if err != nil && err.(*NumError).Err != ErrRange {
178 err.(*NumError).Func = fnParseInt
179 err.(*NumError).Num = s0
180 return 0, err
183 if bitSize == 0 {
184 bitSize = int(IntSize)
187 cutoff := uint64(1 << uint(bitSize-1))
188 if !neg && un >= cutoff {
189 return int64(cutoff - 1), rangeError(fnParseInt, s0)
191 if neg && un > cutoff {
192 return -int64(cutoff), rangeError(fnParseInt, s0)
194 n := int64(un)
195 if neg {
196 n = -n
198 return n, nil
201 // Atoi returns the result of ParseInt(s, 10, 0) converted to type int.
202 func Atoi(s string) (int, error) {
203 const fnAtoi = "Atoi"
205 sLen := len(s)
206 if intSize == 32 && (0 < sLen && sLen < 10) ||
207 intSize == 64 && (0 < sLen && sLen < 19) {
208 // Fast path for small integers that fit int type.
209 s0 := s
210 if s[0] == '-' || s[0] == '+' {
211 s = s[1:]
212 if len(s) < 1 {
213 return 0, &NumError{fnAtoi, s0, ErrSyntax}
217 n := 0
218 for _, ch := range []byte(s) {
219 ch -= '0'
220 if ch > 9 {
221 return 0, &NumError{fnAtoi, s0, ErrSyntax}
223 n = n*10 + int(ch)
225 if s0[0] == '-' {
226 n = -n
228 return n, nil
231 // Slow path for invalid or big integers.
232 i64, err := ParseInt(s, 10, 0)
233 if nerr, ok := err.(*NumError); ok {
234 nerr.Func = fnAtoi
236 return int(i64), err