Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2008-11-10 18:20:59 +0300
committerIgor Sysoev <igor@sysoev.ru>2008-11-10 18:20:59 +0300
commit74b7e5fadd33804eefa37ff86764b512e2de379b (patch)
tree26db12eb0ca18484a660e6eb566fb640924072e8 /src/core/ngx_string.c
parent698b8cb03862606e94a08dff6be55c6526773e74 (diff)
%f format
Diffstat (limited to 'src/core/ngx_string.c')
-rw-r--r--src/core/ngx_string.c200
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);
}