| |
| /* |
| * Copyright (C) Igor Sysoev |
| */ |
| |
| |
| #include <ngx_config.h> |
| #include <ngx_core.h> |
| |
| |
| ssize_t |
| ngx_parse_size(ngx_str_t *line) |
| { |
| u_char last; |
| size_t len; |
| ssize_t size; |
| ngx_int_t scale; |
| |
| len = line->len; |
| last = line->data[len - 1]; |
| |
| switch (last) { |
| 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 last; |
| off_t offset; |
| size_t len; |
| ngx_int_t scale; |
| |
| len = line->len; |
| last = line->data[len - 1]; |
| |
| switch (last) { |
| 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_int_t sec) |
| { |
| size_t len; |
| u_char *start, last; |
| ngx_int_t value, total, scale; |
| ngx_uint_t max, i; |
| enum { |
| st_start = 0, |
| st_year, |
| st_month, |
| st_week, |
| st_day, |
| st_hour, |
| st_min, |
| st_sec, |
| st_msec, |
| st_last |
| } step; |
| |
| |
| start = line->data; |
| len = 0; |
| total = 0; |
| step = sec ? st_start : st_month; |
| |
| for (i = 0; /* void */ ; i++) { |
| |
| if (i < line->len) { |
| if (line->data[i] != ' ') { |
| len++; |
| continue; |
| } |
| |
| if (line->data[i] == ' ' && len == 0) { |
| start = &line->data[i + 1]; |
| continue; |
| } |
| } |
| |
| if (len == 0) { |
| break; |
| } |
| |
| last = line->data[i - 1]; |
| |
| switch (last) { |
| case 'y': |
| if (step > st_start) { |
| return NGX_ERROR; |
| } |
| step = st_year; |
| len--; |
| max = 68; |
| scale = 60 * 60 * 24 * 365; |
| break; |
| |
| case 'M': |
| if (step > st_year) { |
| return NGX_ERROR; |
| } |
| step = st_month; |
| len--; |
| max = 828; |
| scale = 60 * 60 * 24 * 30; |
| break; |
| |
| case 'w': |
| if (step > st_month) { |
| return NGX_ERROR; |
| } |
| step = st_week; |
| len--; |
| max = 3550; |
| scale = 60 * 60 * 24 * 7; |
| break; |
| |
| case 'd': |
| if (step > st_week) { |
| return NGX_ERROR; |
| } |
| step = st_day; |
| len--; |
| max = 24855; |
| scale = 60 * 60 * 24; |
| break; |
| |
| case 'h': |
| if (step > st_day) { |
| return NGX_ERROR; |
| } |
| step = st_hour; |
| len--; |
| max = 596523; |
| scale = 60 * 60; |
| break; |
| |
| case 'm': |
| if (step > st_hour) { |
| return NGX_ERROR; |
| } |
| step = st_min; |
| len--; |
| max = 35791394; |
| scale = 60; |
| break; |
| |
| case 's': |
| len--; |
| |
| if (line->data[i - 2] == 'm') { |
| if (sec || step > st_sec) { |
| return NGX_ERROR; |
| } |
| step = st_msec; |
| len--; |
| max = 2147483647; |
| scale = 1; |
| break; |
| } |
| |
| if (step > st_min) { |
| return NGX_ERROR; |
| } |
| |
| step = st_sec; |
| max = 2147483647; |
| scale = 1; |
| break; |
| |
| default: |
| step = st_last; |
| max = 2147483647; |
| scale = 1; |
| } |
| |
| value = ngx_atoi(start, len); |
| if (value == NGX_ERROR) { |
| return NGX_ERROR; |
| } |
| |
| if (step != st_msec && !sec) { |
| scale *= 1000; |
| max /= 1000; |
| } |
| |
| if ((u_int) value > max) { |
| return NGX_PARSE_LARGE_TIME; |
| } |
| |
| total += value * scale; |
| |
| if ((u_int) total > 2147483647) { |
| return NGX_PARSE_LARGE_TIME; |
| } |
| |
| if (i >= line->len) { |
| break; |
| } |
| |
| len = 0; |
| start = &line->data[i + 1]; |
| } |
| |
| return total; |
| } |