...
1
2
3
4
5 package json
6
7 import (
8 "bytes"
9 "strconv"
10 )
11
12
13
14
15
16 func parseNumber(input []byte) (int, bool) {
17 var n int
18
19 s := input
20 if len(s) == 0 {
21 return 0, false
22 }
23
24
25 if s[0] == '-' {
26 s = s[1:]
27 n++
28 if len(s) == 0 {
29 return 0, false
30 }
31 }
32
33
34 switch {
35 case s[0] == '0':
36 s = s[1:]
37 n++
38
39 case '1' <= s[0] && s[0] <= '9':
40 s = s[1:]
41 n++
42 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
43 s = s[1:]
44 n++
45 }
46
47 default:
48 return 0, false
49 }
50
51
52 if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
53 s = s[2:]
54 n += 2
55 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
56 s = s[1:]
57 n++
58 }
59 }
60
61
62
63 if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
64 s = s[1:]
65 n++
66 if s[0] == '+' || s[0] == '-' {
67 s = s[1:]
68 n++
69 if len(s) == 0 {
70 return 0, false
71 }
72 }
73 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
74 s = s[1:]
75 n++
76 }
77 }
78
79
80 if n < len(input) && isNotDelim(input[n]) {
81 return 0, false
82 }
83
84 return n, true
85 }
86
87
88
89 type numberParts struct {
90 neg bool
91 intp []byte
92 frac []byte
93 exp []byte
94 }
95
96
97
98
99 func parseNumberParts(input []byte) (numberParts, bool) {
100 var neg bool
101 var intp []byte
102 var frac []byte
103 var exp []byte
104
105 s := input
106 if len(s) == 0 {
107 return numberParts{}, false
108 }
109
110
111 if s[0] == '-' {
112 neg = true
113 s = s[1:]
114 if len(s) == 0 {
115 return numberParts{}, false
116 }
117 }
118
119
120 switch {
121 case s[0] == '0':
122
123 s = s[1:]
124
125 case '1' <= s[0] && s[0] <= '9':
126 intp = s
127 n := 1
128 s = s[1:]
129 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
130 s = s[1:]
131 n++
132 }
133 intp = intp[:n]
134
135 default:
136 return numberParts{}, false
137 }
138
139
140 if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
141 frac = s[1:]
142 n := 1
143 s = s[2:]
144 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
145 s = s[1:]
146 n++
147 }
148 frac = frac[:n]
149 }
150
151
152
153 if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
154 s = s[1:]
155 exp = s
156 n := 0
157 if s[0] == '+' || s[0] == '-' {
158 s = s[1:]
159 n++
160 if len(s) == 0 {
161 return numberParts{}, false
162 }
163 }
164 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
165 s = s[1:]
166 n++
167 }
168 exp = exp[:n]
169 }
170
171 return numberParts{
172 neg: neg,
173 intp: intp,
174 frac: bytes.TrimRight(frac, "0"),
175 exp: exp,
176 }, true
177 }
178
179
180
181
182 func normalizeToIntString(n numberParts) (string, bool) {
183 intpSize := len(n.intp)
184 fracSize := len(n.frac)
185
186 if intpSize == 0 && fracSize == 0 {
187 return "0", true
188 }
189
190 var exp int
191 if len(n.exp) > 0 {
192 i, err := strconv.ParseInt(string(n.exp), 10, 32)
193 if err != nil {
194 return "", false
195 }
196 exp = int(i)
197 }
198
199 var num []byte
200 if exp >= 0 {
201
202
203
204
205
206 if fracSize > exp {
207 return "", false
208 }
209
210
211
212
213 const maxDigits = 20
214 if intpSize+exp > maxDigits {
215 return "", false
216 }
217
218
219 num = n.intp[:len(n.intp):len(n.intp)]
220 num = append(num, n.frac...)
221 for i := 0; i < exp-fracSize; i++ {
222 num = append(num, '0')
223 }
224 } else {
225
226
227
228 if fracSize > 0 {
229 return "", false
230 }
231
232
233
234 index := intpSize + exp
235 if index < 0 {
236 return "", false
237 }
238
239 num = n.intp
240
241
242 for i := index; i < intpSize; i++ {
243 if num[i] != '0' {
244 return "", false
245 }
246 }
247 num = num[:index]
248 }
249
250 if n.neg {
251 return "-" + string(num), true
252 }
253 return string(num), true
254 }
255
View as plain text