diff options
author | Igor Sysoev <igor@sysoev.ru> | 2017-01-17 20:00:00 +0300 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2017-01-17 20:00:00 +0300 |
commit | 16cbf3c076a0aca6d47adaf3f719493674cf2363 (patch) | |
tree | e6530480020f62a2bdbf249988ec3e2a751d3927 /src/nxt_parse.c | |
download | unit-16cbf3c076a0aca6d47adaf3f719493674cf2363.tar.gz unit-16cbf3c076a0aca6d47adaf3f719493674cf2363.tar.bz2 |
Initial version.
Diffstat (limited to 'src/nxt_parse.c')
-rw-r--r-- | src/nxt_parse.c | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/src/nxt_parse.c b/src/nxt_parse.c new file mode 100644 index 00000000..01dc8aa7 --- /dev/null +++ b/src/nxt_parse.c @@ -0,0 +1,344 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) NGINX, Inc. + */ + +#include <nxt_main.h> + + +/* + * nxt_int_parse() returns size_t value >= 0 on success, + * -1 on failure, and -2 on overflow. + */ + +nxt_int_t +nxt_int_parse(const u_char *p, size_t len) +{ + u_char c; + nxt_uint_t val; + + if (nxt_fast_path(len != 0)) { + + val = 0; + + do { + c = *p++; + + /* Values below '0' become >= 208. */ + c = c - '0'; + + if (nxt_slow_path(c > 9)) { + return -1; + } + + val = val * 10 + c; + + if (nxt_slow_path((nxt_int_t) val < 0)) { + /* An overflow. */ + return -2; + } + + len--; + + } while (len != 0); + + return val; + } + + return -1; +} + + +/* + * nxt_size_t_parse() returns size_t value >= 0 on success, + * -1 on failure, and -2 on overflow. + */ + +ssize_t +nxt_size_t_parse(const u_char *p, size_t len) +{ + u_char c; + size_t val; + + if (nxt_fast_path(len != 0)) { + + val = 0; + + do { + c = *p++; + + /* Values below '0' become >= 208. */ + c = c - '0'; + + if (nxt_slow_path(c > 9)) { + return -1; + } + + val = val * 10 + c; + + if (nxt_slow_path((ssize_t) val < 0)) { + /* An overflow. */ + return -2; + } + + len--; + + } while (len != 0); + + return val; + } + + return -1; +} + + +/* + * nxt_size_parse() parses size string with optional K or M units and + * returns size_t value >= 0 on success, -1 on failure, and -2 on overflow. + */ + +ssize_t +nxt_size_parse(const u_char *p, size_t len) +{ + u_char c, unit; + size_t val, max; + nxt_uint_t shift; + + if (nxt_fast_path(len != 0)) { + + len--; + + /* Upper case. */ + unit = p[len] & ~0x20; + + switch (unit) { + + case 'G': + max = NXT_SIZE_T_MAX >> 30; + shift = 30; + break; + + case 'M': + max = NXT_SIZE_T_MAX >> 20; + shift = 20; + break; + + case 'K': + max = NXT_SIZE_T_MAX >> 10; + shift = 10; + break; + + default: + max = NXT_SIZE_T_MAX; + shift = 0; + len++; + break; + } + + if (nxt_fast_path(len != 0)) { + + val = 0; + + do { + c = *p++; + + /* Values below '0' become >= 208. */ + c = c - '0'; + + if (nxt_slow_path(c > 9)) { + return -1; + } + + val = val * 10 + c; + + if (nxt_slow_path(val > max)) { + /* An overflow. */ + return -2; + } + + len--; + + } while (len != 0); + + return val << shift; + } + } + + return -1; +} + + +/* + * nxt_off_t_parse() returns nxt_off_t value >= 0 on success, + * -1 on failure, and -2 on overflow. + */ + +nxt_off_t +nxt_off_t_parse(const u_char *p, size_t len) +{ + u_char c; + nxt_uoff_t val; + + if (nxt_fast_path(len != 0)) { + + val = 0; + + do { + c = *p++; + + /* Values below '0' become >= 208. */ + c = c - '0'; + + if (nxt_slow_path(c > 9)) { + return -1; + } + + val = val * 10 + c; + + if (nxt_slow_path((nxt_off_t) val < 0)) { + /* An overflow. */ + return -2; + } + + len--; + + } while (len != 0); + + return val; + } + + return -1; +} + + +/* + * nxt_str_int_parse() returns nxt_int_t value >= 0 on success, + * -1 on failure, and -2 on overflow and also updates the 's' argument. + */ + +nxt_int_t +nxt_str_int_parse(nxt_str_t *s) +{ + u_char c, *p; + size_t len; + nxt_uint_t val; + + len = s->len; + + if (nxt_slow_path(len == 0)) { + return -1; + } + + p = s->data; + val = 0; + + do { + c = *p; + + /* Values below '0' become >= 208. */ + c = c - '0'; + + if (c > 9) { + break; + } + + val = val * 10 + c; + + if (nxt_slow_path((nxt_int_t) val < 0)) { + /* An overflow. */ + return -2; + } + + p++; + len--; + + } while (len != 0); + + s->len = len; + s->data = p; + + return val; +} + + +/* + * nxt_number_parse() returns a double value >= 0 and updates the start + * argument on success, or returns -1 on failure or -2 on overflow. + */ + +double +nxt_number_parse(const u_char **start, const u_char *end) +{ + u_char c; + nxt_uint_t integral, frac, power; + const u_char *p; + + p = *start; + integral = 0; + + while (p < end) { + c = *p; + + if (c == '.') { + goto dot; + } + + /* Values below '0' become >= 208. */ + c = c - '0'; + + if (c > 9) { + break; + } + + integral = integral * 10 + c; + + if (nxt_slow_path((nxt_int_t) integral < 0)) { + /* An overflow. */ + return -2; + } + + p++; + } + + if (nxt_fast_path(p != *start)) { + *start = p; + return integral; + } + + /* No value. */ + return -1; + +dot: + + if (nxt_slow_path(p == *start)) { + /* No leading digit before dot. */ + return -1; + } + + frac = 0; + power = 1; + + for (p++; p < end; p++) { + c = *p; + + /* Values below '0' become >= 208. */ + c = c - '0'; + + if (c > 9) { + break; + } + + frac = frac * 10 + c; + power *= 10; + + if (nxt_slow_path((nxt_int_t) frac < 0 || (nxt_int_t) power < 0)) { + /* An overflow. */ + return -2; + } + } + + *start = p; + + return integral + (double) frac / power; +} |