mirror of
https://github.com/nginx/nginx.git
synced 2025-01-03 12:47:21 -06:00
%f format
This commit is contained in:
parent
698b8cb038
commit
74b7e5fadd
@ -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,63 +442,7 @@ ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args)
|
||||
}
|
||||
}
|
||||
|
||||
if (hexadecimal == 1) {
|
||||
do {
|
||||
|
||||
/* the "(uint32_t)" cast disables the BCC's warning */
|
||||
*--p = hex[(uint32_t) (ui64 & 0xf)];
|
||||
|
||||
} while (ui64 >>= 4);
|
||||
|
||||
} else if (hexadecimal == 2) {
|
||||
do {
|
||||
|
||||
/* the "(uint32_t)" cast disables the BCC's warning */
|
||||
*--p = HEX[(uint32_t) (ui64 & 0xf)];
|
||||
|
||||
} while (ui64 >>= 4);
|
||||
|
||||
} else 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
|
||||
*/
|
||||
|
||||
ui32 = (uint32_t) ui64;
|
||||
|
||||
do {
|
||||
*--p = (u_char) (ui32 % 10 + '0');
|
||||
} while (ui32 /= 10);
|
||||
|
||||
} else {
|
||||
do {
|
||||
*--p = (u_char) (ui64 % 10 + '0');
|
||||
} while (ui64 /= 10);
|
||||
}
|
||||
|
||||
len = (temp + NGX_INT64_LEN) - p;
|
||||
|
||||
while (len++ < width && buf < last) {
|
||||
*buf++ = zero;
|
||||
}
|
||||
|
||||
len = (temp + NGX_INT64_LEN) - p;
|
||||
if (buf + len > last) {
|
||||
len = last - buf;
|
||||
}
|
||||
|
||||
buf = ngx_cpymem(buf, p, len);
|
||||
buf = ngx_sprintf_num(buf, last, ui64, zero, hex, width);
|
||||
|
||||
fmt++;
|
||||
|
||||
@ -467,6 +455,92 @@ ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args)
|
||||
}
|
||||
|
||||
|
||||
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";
|
||||
|
||||
p = temp + NGX_INT64_LEN;
|
||||
|
||||
if (hexadecimal == 0) {
|
||||
|
||||
if (ui64 <= NGX_MAX_UINT32_VALUE) {
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
do {
|
||||
*--p = (u_char) (ui32 % 10 + '0');
|
||||
} while (ui32 /= 10);
|
||||
|
||||
} else {
|
||||
do {
|
||||
*--p = (u_char) (ui64 % 10 + '0');
|
||||
} while (ui64 /= 10);
|
||||
}
|
||||
|
||||
} else if (hexadecimal == 1) {
|
||||
|
||||
do {
|
||||
|
||||
/* the "(uint32_t)" cast disables the BCC's warning */
|
||||
*--p = hex[(uint32_t) (ui64 & 0xf)];
|
||||
|
||||
} while (ui64 >>= 4);
|
||||
|
||||
} else { /* hexadecimal == 2 */
|
||||
|
||||
do {
|
||||
|
||||
/* the "(uint32_t)" cast disables the BCC's warning */
|
||||
*--p = HEX[(uint32_t) (ui64 & 0xf)];
|
||||
|
||||
} while (ui64 >>= 4);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We use ngx_strcasecmp()/ngx_strncasecmp() for 7-bit ASCII strings only,
|
||||
* and implement our own ngx_strcasecmp()/ngx_strncasecmp()
|
||||
|
Loading…
Reference in New Issue
Block a user