diff options
author | Igor Sysoev <igor@sysoev.ru> | 2008-11-10 18:20:59 +0300 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2008-11-10 18:20:59 +0300 |
commit | 74b7e5fadd33804eefa37ff86764b512e2de379b (patch) | |
tree | 26db12eb0ca18484a660e6eb566fb640924072e8 /src/core/ngx_string.c | |
parent | 698b8cb03862606e94a08dff6be55c6526773e74 (diff) |
%f format
Diffstat (limited to 'src/core/ngx_string.c')
-rw-r--r-- | src/core/ngx_string.c | 200 |
1 files changed, 137 insertions, 63 deletions
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index 203cd3e37..0ad594f82 100644 --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -8,6 +8,10 @@ #include <ngx_core.h> +static u_char *ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64, + u_char zero, ngx_uint_t hexadecimal, ngx_uint_t width); + + void ngx_strlow(u_char *dst, u_char *src, size_t n) { @@ -67,6 +71,7 @@ ngx_pstrdup(ngx_pool_t *pool, ngx_str_t *src) * %[0][width][u][x|X]D int32_t/uint32_t * %[0][width][u][x|X]L int64_t/uint64_t * %[0][width|m][u][x|X]A ngx_atomic_int_t/ngx_atomic_uint_t + * %[0][width][.width]f float * %P ngx_pid_t * %M ngx_msec_t * %r rlim_t @@ -118,22 +123,16 @@ ngx_snprintf(u_char *buf, size_t max, const char *fmt, ...) u_char * ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args) { - u_char *p, zero, *last, temp[NGX_INT64_LEN + 1]; - /* - * really we need temp[NGX_INT64_LEN] only, - * but icc issues the warning - */ + u_char *p, zero, *last; int d; + float f, scale; size_t len, slen; - uint32_t ui32; int64_t i64; uint64_t ui64; ngx_msec_t ms; - ngx_uint_t width, sign, hexadecimal, max_width; + ngx_uint_t width, sign, hex, max_width, frac_width, i; ngx_str_t *v; ngx_variable_value_t *vv; - static u_char hex[] = "0123456789abcdef"; - static u_char HEX[] = "0123456789ABCDEF"; if (max == 0) { return buf; @@ -156,12 +155,11 @@ ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args) zero = (u_char) ((*++fmt == '0') ? '0' : ' '); width = 0; sign = 1; - hexadecimal = 0; + hex = 0; max_width = 0; + frac_width = 0; slen = (size_t) -1; - p = temp + NGX_INT64_LEN; - while (*fmt >= '0' && *fmt <= '9') { width = width * 10 + *fmt++ - '0'; } @@ -181,17 +179,26 @@ ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args) continue; case 'X': - hexadecimal = 2; + hex = 2; sign = 0; fmt++; continue; case 'x': - hexadecimal = 1; + hex = 1; sign = 0; fmt++; continue; + case '.': + fmt++; + + while (*fmt >= '0' && *fmt <= '9') { + frac_width = frac_width * 10 + *fmt++ - '0'; + } + + break; + case '*': slen = va_arg(args, size_t); fmt++; @@ -339,6 +346,43 @@ ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args) break; + case 'f': + f = (float) va_arg(args, double); + + if (f < 0) { + *buf++ = '-'; + f = -f; + } + + ui64 = (int64_t) f; + + buf = ngx_sprintf_num(buf, last, ui64, zero, 0, width); + + if (frac_width) { + + if (buf < last) { + *buf++ = '.'; + } + + scale = 1.0; + + for (i = 0; i < frac_width; i++) { + scale *= 10.0; + } + + /* + * (int64_t) cast is required for msvc6: + * it can not convert uint64_t to double + */ + ui64 = (uint64_t) ((f - (int64_t) ui64) * scale); + + buf = ngx_sprintf_num(buf, last, ui64, '0', 0, frac_width); + } + + fmt++; + + continue; + #if !(NGX_WIN32) case 'r': i64 = (int64_t) va_arg(args, rlim_t); @@ -348,7 +392,7 @@ ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args) case 'p': ui64 = (uintptr_t) va_arg(args, void *); - hexadecimal = 2; + hex = 2; sign = 0; zero = '0'; width = NGX_PTR_SIZE * 2; @@ -398,72 +442,102 @@ ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args) } } - if (hexadecimal == 1) { - do { + buf = ngx_sprintf_num(buf, last, ui64, zero, hex, width); + + fmt++; + + } else { + *buf++ = *fmt++; + } + } - /* the "(uint32_t)" cast disables the BCC's warning */ - *--p = hex[(uint32_t) (ui64 & 0xf)]; + return buf; +} - } while (ui64 >>= 4); - } else if (hexadecimal == 2) { - do { +static u_char * +ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64, u_char zero, + ngx_uint_t hexadecimal, ngx_uint_t width) +{ + u_char *p, temp[NGX_INT64_LEN + 1]; + /* + * we need temp[NGX_INT64_LEN] only, + * but icc issues the warning + */ + size_t len; + uint32_t ui32; + static u_char hex[] = "0123456789abcdef"; + static u_char HEX[] = "0123456789ABCDEF"; - /* the "(uint32_t)" cast disables the BCC's warning */ - *--p = HEX[(uint32_t) (ui64 & 0xf)]; + p = temp + NGX_INT64_LEN; - } while (ui64 >>= 4); + if (hexadecimal == 0) { - } else if (ui64 <= NGX_MAX_UINT32_VALUE) { + if (ui64 <= NGX_MAX_UINT32_VALUE) { - /* - * To divide 64-bit number and to find the remainder - * on the x86 platform gcc and icc call the libc functions - * [u]divdi3() and [u]moddi3(), they call another function - * in its turn. On FreeBSD it is the qdivrem() function, - * its source code is about 170 lines of the code. - * The glibc counterpart is about 150 lines of the code. - * - * For 32-bit numbers and some divisors gcc and icc use - * the inlined multiplication and shifts. For example, - * unsigned "i32 / 10" is compiled to - * - * (i32 * 0xCCCCCCCD) >> 35 - */ + /* + * To divide 64-bit numbers and to find remainders + * on the x86 platform gcc and icc call the libc functions + * [u]divdi3() and [u]moddi3(), they call another function + * in its turn. On FreeBSD it is the qdivrem() function, + * its source code is about 170 lines of the code. + * The glibc counterpart is about 150 lines of the code. + * + * For 32-bit numbers and some divisors gcc and icc use + * a inlined multiplication and shifts. For example, + * unsigned "i32 / 10" is compiled to + * + * (i32 * 0xCCCCCCCD) >> 35 + */ - ui32 = (uint32_t) ui64; + ui32 = (uint32_t) ui64; - do { - *--p = (u_char) (ui32 % 10 + '0'); - } while (ui32 /= 10); + do { + *--p = (u_char) (ui32 % 10 + '0'); + } while (ui32 /= 10); - } else { - do { - *--p = (u_char) (ui64 % 10 + '0'); - } while (ui64 /= 10); - } + } else { + do { + *--p = (u_char) (ui64 % 10 + '0'); + } while (ui64 /= 10); + } - len = (temp + NGX_INT64_LEN) - p; + } else if (hexadecimal == 1) { - while (len++ < width && buf < last) { - *buf++ = zero; - } + do { - len = (temp + NGX_INT64_LEN) - p; - if (buf + len > last) { - len = last - buf; - } + /* the "(uint32_t)" cast disables the BCC's warning */ + *--p = hex[(uint32_t) (ui64 & 0xf)]; - buf = ngx_cpymem(buf, p, len); + } while (ui64 >>= 4); - fmt++; + } else { /* hexadecimal == 2 */ - } else { - *buf++ = *fmt++; - } + do { + + /* the "(uint32_t)" cast disables the BCC's warning */ + *--p = HEX[(uint32_t) (ui64 & 0xf)]; + + } while (ui64 >>= 4); } - return buf; + /* zero or space padding */ + + len = (temp + NGX_INT64_LEN) - p; + + while (len++ < width && buf < last) { + *buf++ = zero; + } + + /* number safe copy */ + + len = (temp + NGX_INT64_LEN) - p; + + if (buf + len > last) { + len = last - buf; + } + + return ngx_cpymem(buf, p, len); } |