| /* | |
| * Copyright (C) Igor Sysoev | |
| */ | |
| #include <ngx_config.h> | |
| #include <ngx_core.h> | |
| ssize_t | |
| ngx_parse_size(ngx_str_t *line) | |
| { | |
| u_char unit; | |
| size_t len; | |
| ssize_t size; | |
| ngx_int_t scale; | |
| len = line->len; | |
| unit = line->data[len - 1]; | |
| switch (unit) { | |
| case 'K': | |
| case 'k': | |
| len--; | |
| scale = 1024; | |
| break; | |
| case 'M': | |
| case 'm': | |
| len--; | |
| scale = 1024 * 1024; | |
| break; | |
| default: | |
| scale = 1; | |
| } | |
| size = ngx_atosz(line->data, len); | |
| if (size == NGX_ERROR) { | |
| return NGX_ERROR; | |
| } | |
| size *= scale; | |
| return size; | |
| } | |
| off_t | |
| ngx_parse_offset(ngx_str_t *line) | |
| { | |
| u_char unit; | |
| off_t offset; | |
| size_t len; | |
| ngx_int_t scale; | |
| len = line->len; | |
| unit = line->data[len - 1]; | |
| switch (unit) { | |
| case 'K': | |
| case 'k': | |
| len--; | |
| scale = 1024; | |
| break; | |
| case 'M': | |
| case 'm': | |
| len--; | |
| scale = 1024 * 1024; | |
| break; | |
| case 'G': | |
| case 'g': | |
| len--; | |
| scale = 1024 * 1024 * 1024; | |
| break; | |
| default: | |
| scale = 1; | |
| } | |
| offset = ngx_atoof(line->data, len); | |
| if (offset == NGX_ERROR) { | |
| return NGX_ERROR; | |
| } | |
| offset *= scale; | |
| return offset; | |
| } | |
| ngx_int_t | |
| ngx_parse_time(ngx_str_t *line, ngx_uint_t sec) | |
| { | |
| u_char *p, *last; | |
| ngx_int_t value, total, scale; | |
| ngx_uint_t max, valid; | |
| enum { | |
| st_start = 0, | |
| st_year, | |
| st_month, | |
| st_week, | |
| st_day, | |
| st_hour, | |
| st_min, | |
| st_sec, | |
| st_msec, | |
| st_last | |
| } step; | |
| valid = 0; | |
| value = 0; | |
| total = 0; | |
| step = sec ? st_start : st_month; | |
| scale = sec ? 1 : 1000; | |
| p = line->data; | |
| last = p + line->len; | |
| while (p < last) { | |
| if (*p >= '0' && *p <= '9') { | |
| value = value * 10 + (*p++ - '0'); | |
| valid = 1; | |
| continue; | |
| } | |
| switch (*p++) { | |
| case 'y': | |
| if (step > st_start) { | |
| return NGX_ERROR; | |
| } | |
| step = st_year; | |
| max = 68; | |
| scale = 60 * 60 * 24 * 365; | |
| break; | |
| case 'M': | |
| if (step > st_year) { | |
| return NGX_ERROR; | |
| } | |
| step = st_month; | |
| max = 828; | |
| scale = 60 * 60 * 24 * 30; | |
| break; | |
| case 'w': | |
| if (step > st_month) { | |
| return NGX_ERROR; | |
| } | |
| step = st_week; | |
| max = 3550; | |
| scale = 60 * 60 * 24 * 7; | |
| break; | |
| case 'd': | |
| if (step > st_week) { | |
| return NGX_ERROR; | |
| } | |
| step = st_day; | |
| max = 24855; | |
| scale = 60 * 60 * 24; | |
| break; | |
| case 'h': | |
| if (step > st_day) { | |
| return NGX_ERROR; | |
| } | |
| step = st_hour; | |
| max = 596523; | |
| scale = 60 * 60; | |
| break; | |
| case 'm': | |
| if (*p == 's') { | |
| if (sec || step > st_sec) { | |
| return NGX_ERROR; | |
| } | |
| p++; | |
| step = st_msec; | |
| max = 2147483647; | |
| scale = 1; | |
| break; | |
| } | |
| if (step > st_hour) { | |
| return NGX_ERROR; | |
| } | |
| step = st_min; | |
| max = 35791394; | |
| scale = 60; | |
| break; | |
| case 's': | |
| if (step > st_min) { | |
| return NGX_ERROR; | |
| } | |
| step = st_sec; | |
| max = 2147483647; | |
| scale = 1; | |
| break; | |
| case ' ': | |
| if (step > st_min) { | |
| return NGX_ERROR; | |
| } | |
| step = st_last; | |
| max = 2147483647; | |
| scale = 1; | |
| break; | |
| default: | |
| return NGX_ERROR; | |
| } | |
| if (step != st_msec && !sec) { | |
| scale *= 1000; | |
| max /= 1000; | |
| } | |
| if ((ngx_uint_t) value > max) { | |
| return NGX_ERROR; | |
| } | |
| total += value * scale; | |
| if ((ngx_uint_t) total > 2147483647) { | |
| return NGX_ERROR; | |
| } | |
| value = 0; | |
| scale = sec ? 1 : 1000; | |
| while (p < last && *p == ' ') { | |
| p++; | |
| } | |
| } | |
| if (valid) { | |
| return total + value * scale; | |
| } | |
| return NGX_ERROR; | |
| } |