1
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) NGINX, Inc.
5 */
6
7 #include <nxt_main.h>
8
9
10 /*
11 * nxt_int_parse() returns size_t value >= 0 on success,
12 * -1 on failure, and -2 on overflow.
13 */
14
15 nxt_int_t
nxt_int_parse(const u_char * p,size_t length)16 nxt_int_parse(const u_char *p, size_t length)
17 {
18 u_char c;
19 nxt_uint_t val;
20
21 static const nxt_uint_t cutoff = NXT_INT_T_MAX / 10;
22 static const nxt_uint_t cutlim = NXT_INT_T_MAX % 10;
23
24 if (nxt_fast_path(length != 0)) {
25
26 val = 0;
27
28 do {
29 c = *p++;
30
31 /* Values below '0' become >= 208. */
32 c = c - '0';
33
34 if (nxt_slow_path(c > 9)) {
35 return -1;
36 }
37
38 if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) {
39 /* An overflow. */
40 return -2;
41 }
42
43 val = val * 10 + c;
44
45 length--;
46
47 } while (length != 0);
48
49 return val;
50 }
51
52 return -1;
53 }
54
55
56 /*
57 * nxt_size_t_parse() returns size_t value >= 0 on success,
58 * -1 on failure, and -2 on overflow.
59 */
60
61 ssize_t
nxt_size_t_parse(const u_char * p,size_t length)62 nxt_size_t_parse(const u_char *p, size_t length)
63 {
64 u_char c;
65 size_t val;
66
67 static const size_t cutoff = NXT_SIZE_T_MAX / 10;
68 static const size_t cutlim = NXT_SIZE_T_MAX % 10;
69
70 if (nxt_fast_path(length != 0)) {
71
72 val = 0;
73
74 do {
75 c = *p++;
76
77 /* Values below '0' become >= 208. */
78 c = c - '0';
79
80 if (nxt_slow_path(c > 9)) {
81 return -1;
82 }
83
84 if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) {
85 /* An overflow. */
86 return -2;
87 }
88
89 val = val * 10 + c;
90
91 length--;
92
93 } while (length != 0);
94
95 return val;
96 }
97
98 return -1;
99 }
100
101
102 /*
103 * nxt_size_parse() parses size string with optional K or M units and
104 * returns size_t value >= 0 on success, -1 on failure, and -2 on overflow.
105 */
106
107 ssize_t
nxt_size_parse(const u_char * p,size_t length)108 nxt_size_parse(const u_char *p, size_t length)
109 {
110 u_char unit;
111 ssize_t val, max;
112 nxt_uint_t shift;
113
114 if (nxt_fast_path(length != 0)) {
115
116 length--;
117
118 /* Upper case. */
119 unit = p[length] & ~0x20;
120
121 switch (unit) {
122
123 case 'G':
124 max = NXT_SIZE_T_MAX >> 30;
125 shift = 30;
126 break;
127
128 case 'M':
129 max = NXT_SIZE_T_MAX >> 20;
130 shift = 20;
131 break;
132
133 case 'K':
134 max = NXT_SIZE_T_MAX >> 10;
135 shift = 10;
136 break;
137
138 default:
139 return nxt_size_t_parse(p, length + 1);
140 }
141
142 val = nxt_size_t_parse(p, length);
143
144 if (nxt_fast_path(val >= 0)) {
145
146 if (nxt_slow_path(val > max)) {
147 /* An overflow. */
148 return -2;
149 }
150
151 val <<= shift;
152 }
153
154 return val;
155 }
156
157 return -1;
158 }
159
160
161 /*
162 * nxt_off_t_parse() returns nxt_off_t value >= 0 on success,
163 * -1 on failure, and -2 on overflow.
164 */
165
166 nxt_off_t
nxt_off_t_parse(const u_char * p,size_t length)167 nxt_off_t_parse(const u_char *p, size_t length)
168 {
169 u_char c;
170 nxt_uoff_t val;
171
172 static const nxt_uoff_t cutoff = NXT_OFF_T_MAX / 10;
173 static const nxt_uoff_t cutlim = NXT_OFF_T_MAX % 10;
174
175 if (nxt_fast_path(length != 0)) {
176
177 val = 0;
178
179 do {
180 c = *p++;
181
182 /* Values below '0' become >= 208. */
183 c = c - '0';
184
185 if (nxt_slow_path(c > 9)) {
186 return -1;
187 }
188
189 if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) {
190 /* An overflow. */
191 return -2;
192 }
193
194 val = val * 10 + c;
195
196 length--;
197
198 } while (length != 0);
199
200 return val;
201 }
202
203 return -1;
204 }
205
206
207 /*
208 * nxt_str_int_parse() returns nxt_int_t value >= 0 on success,
209 * -1 on failure, and -2 on overflow and also updates the 's' argument.
210 */
211
212 nxt_int_t
nxt_str_int_parse(nxt_str_t * s)213 nxt_str_int_parse(nxt_str_t *s)
214 {
215 u_char c, *p;
216 size_t length;
217 nxt_uint_t val;
218
219 static const nxt_uint_t cutoff = NXT_INT_T_MAX / 10;
220 static const nxt_uint_t cutlim = NXT_INT_T_MAX % 10;
221
222 length = s->length;
223
224 if (nxt_slow_path(length == 0)) {
225 return -1;
226 }
227
228 p = s->start;
229 val = 0;
230
231 do {
232 c = *p;
233
234 /* Values below '0' become >= 208. */
235 c = c - '0';
236
237 if (c > 9) {
238 break;
239 }
240
241 if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) {
242 /* An overflow. */
243 return -2;
244 }
245
246 val = val * 10 + c;
247
248 p++;
249 length--;
250
251 } while (length != 0);
252
253 s->length = length;
254 s->start = p;
255
256 return val;
257 }
258
259
260 /*
261 * nxt_number_parse() returns a double value >= 0 and updates the start
262 * argument on success, or returns -1 on failure or -2 on overflow.
263 */
264
265 double
nxt_number_parse(const u_char ** start,const u_char * end)266 nxt_number_parse(const u_char **start, const u_char *end)
267 {
268 u_char c;
269 nxt_bool_t overflow;
270 nxt_uint_t integral, frac, power;
271 const u_char *p;
272
273 static const nxt_uint_t cutoff = NXT_INT_T_MAX / 10;
274 static const nxt_uint_t cutlim = NXT_INT_T_MAX % 10;
275
276 p = *start;
277 integral = 0;
278
279 while (p < end) {
280 c = *p;
281
282 if (c == '.') {
283 goto dot;
284 }
285
286 /* Values below '0' become >= 208. */
287 c = c - '0';
288
289 if (c > 9) {
290 break;
291 }
292
293 overflow = nxt_expect(0, (integral >= cutoff
294 && (integral > cutoff || c > cutlim)));
295
296 if (overflow) {
297 return -2;
298 }
299
300 integral = integral * 10 + c;
301
302 p++;
303 }
304
305 if (nxt_fast_path(p != *start)) {
306 *start = p;
307 return integral;
308 }
309
310 /* No value. */
311 return -1;
312
313 dot:
314
315 if (nxt_slow_path(p == *start)) {
316 /* No leading digit before dot. */
317 return -1;
318 }
319
320 frac = 0;
321 power = 1;
322
323 for (p++; p < end; p++) {
324 c = *p;
325
326 /* Values below '0' become >= 208. */
327 c = c - '0';
328
329 if (c > 9) {
330 break;
331 }
332
333 overflow = nxt_expect(0, (frac >= cutoff && (frac > cutoff
334 || c > cutlim))
335 || power > cutoff);
336
337 if (overflow) {
338 return -2;
339 }
340
341 frac = frac * 10 + c;
342 power *= 10;
343 }
344
345 *start = p;
346
347 return integral + (double) frac / power;
348 }
349