Source file src/pkg/strconv/atoi.go
1
2
3
4
5 package strconv
6
7 import "errors"
8
9
10 var ErrRange = errors.New("value out of range")
11
12
13 var ErrSyntax = errors.New("invalid syntax")
14
15
16 type NumError struct {
17 Func string
18 Num string
19 Err error
20 }
21
22 func (e *NumError) Error() string {
23 return "strconv." + e.Func + ": " + "parsing " + Quote(e.Num) + ": " + e.Err.Error()
24 }
25
26 func syntaxError(fn, str string) *NumError {
27 return &NumError{fn, str, ErrSyntax}
28 }
29
30 func rangeError(fn, str string) *NumError {
31 return &NumError{fn, str, ErrRange}
32 }
33
34 const intSize = 32 << uint(^uint(0)>>63)
35
36 const IntSize = intSize
37
38
39 func cutoff64(base int) uint64 {
40 if base < 2 {
41 return 0
42 }
43 return (1<<64-1)/uint64(base) + 1
44 }
45
46
47 func ParseUint(s string, base int, bitSize int) (n uint64, err error) {
48 var cutoff, maxVal uint64
49
50 if bitSize == 0 {
51 bitSize = int(IntSize)
52 }
53
54 s0 := s
55 switch {
56 case len(s) < 1:
57 err = ErrSyntax
58 goto Error
59
60 case 2 <= base && base <= 36:
61
62
63 case base == 0:
64
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
72 }
73 case s[0] == '0':
74 base = 8
75 default:
76 base = 10
77 }
78
79 default:
80 err = errors.New("invalid base " + Itoa(base))
81 goto Error
82 }
83
84 n = 0
85 cutoff = cutoff64(base)
86 maxVal = 1<<uint(bitSize) - 1
87
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
102 }
103 if int(v) >= base {
104 n = 0
105 err = ErrSyntax
106 goto Error
107 }
108
109 if n >= cutoff {
110
111 n = 1<<64 - 1
112 err = ErrRange
113 goto Error
114 }
115 n *= uint64(base)
116
117 n1 := n + uint64(v)
118 if n1 < n || n1 > maxVal {
119
120 n = 1<<64 - 1
121 err = ErrRange
122 goto Error
123 }
124 n = n1
125 }
126
127 return n, nil
128
129 Error:
130 return n, &NumError{"ParseUint", s0, err}
131 }
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147 func ParseInt(s string, base int, bitSize int) (i int64, err error) {
148 const fnParseInt = "ParseInt"
149
150 if bitSize == 0 {
151 bitSize = int(IntSize)
152 }
153
154
155 if len(s) == 0 {
156 return 0, syntaxError(fnParseInt, s)
157 }
158
159
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:]
167 }
168
169
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
176 }
177 cutoff := uint64(1 << uint(bitSize-1))
178 if !neg && un >= cutoff {
179 return int64(cutoff - 1), rangeError(fnParseInt, s0)
180 }
181 if neg && un > cutoff {
182 return -int64(cutoff), rangeError(fnParseInt, s0)
183 }
184 n := int64(un)
185 if neg {
186 n = -n
187 }
188 return n, nil
189 }
190
191
192 func Atoi(s string) (i int, err error) {
193 i64, err := ParseInt(s, 10, 0)
194 return int(i64), err
195 }
View as plain text