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