fix extension
[nginx.git] / nginx / src / core / ngx_parse.c
1
2 /*
3  * Copyright (C) Igor Sysoev
4  */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9
10
11 ssize_t
12 ngx_parse_size(ngx_str_t *line)
13 {
14     u_char     unit;
15     size_t     len;
16     ssize_t    size;
17     ngx_int_t  scale;
18
19     len = line->len;
20     unit = line->data[len - 1];
21
22     switch (unit) {
23     case 'K':
24     case 'k':
25         len--;
26         scale = 1024;
27         break;
28
29     case 'M':
30     case 'm':
31         len--;
32         scale = 1024 * 1024;
33         break;
34
35     default:
36         scale = 1;
37     }
38
39     size = ngx_atosz(line->data, len);
40     if (size == NGX_ERROR) {
41         return NGX_ERROR;
42     }
43
44     size *= scale;
45
46     return size;
47 }
48
49
50 off_t
51 ngx_parse_offset(ngx_str_t *line)
52 {
53     u_char     unit;
54     off_t      offset;
55     size_t     len;
56     ngx_int_t  scale;
57
58     len = line->len;
59     unit = line->data[len - 1];
60
61     switch (unit) {
62     case 'K':
63     case 'k':
64         len--;
65         scale = 1024;
66         break;
67
68     case 'M':
69     case 'm':
70         len--;
71         scale = 1024 * 1024;
72         break;
73
74     case 'G':
75     case 'g':
76         len--;
77         scale = 1024 * 1024 * 1024;
78         break;
79
80     default:
81         scale = 1;
82     }
83
84     offset = ngx_atoof(line->data, len);
85     if (offset == NGX_ERROR) {
86         return NGX_ERROR;
87     }
88
89     offset *= scale;
90
91     return offset;
92 }
93
94
95 ngx_int_t
96 ngx_parse_time(ngx_str_t *line, ngx_uint_t sec)
97 {
98     u_char      *p, *last;
99     ngx_int_t    value, total, scale;
100     ngx_uint_t   max, valid;
101     enum {
102         st_start = 0,
103         st_year,
104         st_month,
105         st_week,
106         st_day,
107         st_hour,
108         st_min,
109         st_sec,
110         st_msec,
111         st_last
112     } step;
113
114     valid = 0;
115     value = 0;
116     total = 0;
117     step = sec ? st_start : st_month;
118     scale = sec ? 1 : 1000;
119
120     p = line->data;
121     last = p + line->len;
122
123     while (p < last) {
124
125         if (*p >= '0' && *p <= '9') {
126             value = value * 10 + (*p++ - '0');
127             valid = 1;
128             continue;
129         }
130
131         switch (*p++) {
132
133         case 'y':
134             if (step > st_start) {
135                 return NGX_ERROR;
136             }
137             step = st_year;
138             max = 68;
139             scale = 60 * 60 * 24 * 365;
140             break;
141
142         case 'M':
143             if (step > st_year) {
144                 return NGX_ERROR;
145             }
146             step = st_month;
147             max = 828;
148             scale = 60 * 60 * 24 * 30;
149             break;
150
151         case 'w':
152             if (step > st_month) {
153                 return NGX_ERROR;
154             }
155             step = st_week;
156             max = 3550;
157             scale = 60 * 60 * 24 * 7;
158             break;
159
160         case 'd':
161             if (step > st_week) {
162                 return NGX_ERROR;
163             }
164             step = st_day;
165             max = 24855;
166             scale = 60 * 60 * 24;
167             break;
168
169         case 'h':
170             if (step > st_day) {
171                 return NGX_ERROR;
172             }
173             step = st_hour;
174             max = 596523;
175             scale = 60 * 60;
176             break;
177
178         case 'm':
179             if (*p == 's') {
180                 if (sec || step > st_sec) {
181                     return NGX_ERROR;
182                 }
183                 p++;
184                 step = st_msec;
185                 max = 2147483647;
186                 scale = 1;
187                 break;
188             }
189
190             if (step > st_hour) {
191                 return NGX_ERROR;
192             }
193             step = st_min;
194             max = 35791394;
195             scale = 60;
196             break;
197
198         case 's':
199             if (step > st_min) {
200                 return NGX_ERROR;
201             }
202             step = st_sec;
203             max = 2147483647;
204             scale = 1;
205             break;
206
207         case ' ':
208             if (step > st_min) {
209                 return NGX_ERROR;
210             }
211             step = st_last;
212             max = 2147483647;
213             scale = 1;
214             break;
215
216         default:
217             return NGX_ERROR;
218         }
219
220         if (step != st_msec && !sec) {
221             scale *= 1000;
222             max /= 1000;
223         }
224
225         if ((ngx_uint_t) value > max) {
226             return NGX_ERROR;
227         }
228
229         total += value * scale;
230
231         if ((ngx_uint_t) total > 2147483647) {
232             return NGX_ERROR;
233         }
234
235         value = 0;
236         scale = sec ? 1 : 1000;
237
238         while (p < last && *p == ' ') {
239             p++;
240         }
241     }
242
243     if (valid) {
244         return total + value * scale;
245     }
246
247     return NGX_ERROR;
248 }