xref: /unit/src/nxt_parse.c (revision 36:a71e28f0fb03)
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