comparison src/core/ngx_string.c @ 416:b4f69f2ef02c NGINX_0_7_20

nginx 0.7.20 *) Changes in the ngx_http_gzip_filter_module. *) Feature: the ngx_http_limit_req_module. *) Bugfix: worker processes might exit on a SIGBUS signal on sparc and ppc platforms; the bug had appeared in 0.7.3. Thanks to Maxim Dounin. *) Bugfix: the "proxy_pass http://host/some:uri" directives did not work; the bug had appeared in 0.7.12. *) Bugfix: in HTTPS mode requests might fail with the "bad write retry" error. *) Bugfix: the ngx_http_secure_link_module did not work inside locations, whose names are less than 3 characters. *) Bugfix: $server_addr variable might have no value.
author Igor Sysoev <http://sysoev.ru>
date Mon, 10 Nov 2008 00:00:00 +0300
parents 34fb3a573548
children 09f0ef15d544
comparison
equal deleted inserted replaced
415:5410f1e19796 416:b4f69f2ef02c
4 */ 4 */
5 5
6 6
7 #include <ngx_config.h> 7 #include <ngx_config.h>
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9
10
11 static u_char *ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64,
12 u_char zero, ngx_uint_t hexadecimal, ngx_uint_t width);
9 13
10 14
11 void 15 void
12 ngx_strlow(u_char *dst, u_char *src, size_t n) 16 ngx_strlow(u_char *dst, u_char *src, size_t n)
13 { 17 {
65 * %[0][width][u][x|X]l long 69 * %[0][width][u][x|X]l long
66 * %[0][width|m][u][x|X]i ngx_int_t/ngx_uint_t 70 * %[0][width|m][u][x|X]i ngx_int_t/ngx_uint_t
67 * %[0][width][u][x|X]D int32_t/uint32_t 71 * %[0][width][u][x|X]D int32_t/uint32_t
68 * %[0][width][u][x|X]L int64_t/uint64_t 72 * %[0][width][u][x|X]L int64_t/uint64_t
69 * %[0][width|m][u][x|X]A ngx_atomic_int_t/ngx_atomic_uint_t 73 * %[0][width|m][u][x|X]A ngx_atomic_int_t/ngx_atomic_uint_t
74 * %[0][width][.width]f float
70 * %P ngx_pid_t 75 * %P ngx_pid_t
71 * %M ngx_msec_t 76 * %M ngx_msec_t
72 * %r rlim_t 77 * %r rlim_t
73 * %p void * 78 * %p void *
74 * %V ngx_str_t * 79 * %V ngx_str_t *
116 121
117 122
118 u_char * 123 u_char *
119 ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args) 124 ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args)
120 { 125 {
121 u_char *p, zero, *last, temp[NGX_INT64_LEN + 1]; 126 u_char *p, zero, *last;
122 /*
123 * really we need temp[NGX_INT64_LEN] only,
124 * but icc issues the warning
125 */
126 int d; 127 int d;
128 float f, scale;
127 size_t len, slen; 129 size_t len, slen;
128 uint32_t ui32;
129 int64_t i64; 130 int64_t i64;
130 uint64_t ui64; 131 uint64_t ui64;
131 ngx_msec_t ms; 132 ngx_msec_t ms;
132 ngx_uint_t width, sign, hexadecimal, max_width; 133 ngx_uint_t width, sign, hex, max_width, frac_width, i;
133 ngx_str_t *v; 134 ngx_str_t *v;
134 ngx_variable_value_t *vv; 135 ngx_variable_value_t *vv;
135 static u_char hex[] = "0123456789abcdef";
136 static u_char HEX[] = "0123456789ABCDEF";
137 136
138 if (max == 0) { 137 if (max == 0) {
139 return buf; 138 return buf;
140 } 139 }
141 140
154 ui64 = 0; 153 ui64 = 0;
155 154
156 zero = (u_char) ((*++fmt == '0') ? '0' : ' '); 155 zero = (u_char) ((*++fmt == '0') ? '0' : ' ');
157 width = 0; 156 width = 0;
158 sign = 1; 157 sign = 1;
159 hexadecimal = 0; 158 hex = 0;
160 max_width = 0; 159 max_width = 0;
160 frac_width = 0;
161 slen = (size_t) -1; 161 slen = (size_t) -1;
162
163 p = temp + NGX_INT64_LEN;
164 162
165 while (*fmt >= '0' && *fmt <= '9') { 163 while (*fmt >= '0' && *fmt <= '9') {
166 width = width * 10 + *fmt++ - '0'; 164 width = width * 10 + *fmt++ - '0';
167 } 165 }
168 166
179 max_width = 1; 177 max_width = 1;
180 fmt++; 178 fmt++;
181 continue; 179 continue;
182 180
183 case 'X': 181 case 'X':
184 hexadecimal = 2; 182 hex = 2;
185 sign = 0; 183 sign = 0;
186 fmt++; 184 fmt++;
187 continue; 185 continue;
188 186
189 case 'x': 187 case 'x':
190 hexadecimal = 1; 188 hex = 1;
191 sign = 0; 189 sign = 0;
192 fmt++; 190 fmt++;
193 continue; 191 continue;
192
193 case '.':
194 fmt++;
195
196 while (*fmt >= '0' && *fmt <= '9') {
197 frac_width = frac_width * 10 + *fmt++ - '0';
198 }
199
200 break;
194 201
195 case '*': 202 case '*':
196 slen = va_arg(args, size_t); 203 slen = va_arg(args, size_t);
197 fmt++; 204 fmt++;
198 continue; 205 continue;
337 width = NGX_ATOMIC_T_LEN; 344 width = NGX_ATOMIC_T_LEN;
338 } 345 }
339 346
340 break; 347 break;
341 348
349 case 'f':
350 f = (float) va_arg(args, double);
351
352 if (f < 0) {
353 *buf++ = '-';
354 f = -f;
355 }
356
357 ui64 = (int64_t) f;
358
359 buf = ngx_sprintf_num(buf, last, ui64, zero, 0, width);
360
361 if (frac_width) {
362
363 if (buf < last) {
364 *buf++ = '.';
365 }
366
367 scale = 1.0;
368
369 for (i = 0; i < frac_width; i++) {
370 scale *= 10.0;
371 }
372
373 /*
374 * (int64_t) cast is required for msvc6:
375 * it can not convert uint64_t to double
376 */
377 ui64 = (uint64_t) ((f - (int64_t) ui64) * scale);
378
379 buf = ngx_sprintf_num(buf, last, ui64, '0', 0, frac_width);
380 }
381
382 fmt++;
383
384 continue;
385
342 #if !(NGX_WIN32) 386 #if !(NGX_WIN32)
343 case 'r': 387 case 'r':
344 i64 = (int64_t) va_arg(args, rlim_t); 388 i64 = (int64_t) va_arg(args, rlim_t);
345 sign = 1; 389 sign = 1;
346 break; 390 break;
347 #endif 391 #endif
348 392
349 case 'p': 393 case 'p':
350 ui64 = (uintptr_t) va_arg(args, void *); 394 ui64 = (uintptr_t) va_arg(args, void *);
351 hexadecimal = 2; 395 hex = 2;
352 sign = 0; 396 sign = 0;
353 zero = '0'; 397 zero = '0';
354 width = NGX_PTR_SIZE * 2; 398 width = NGX_PTR_SIZE * 2;
355 break; 399 break;
356 400
396 } else { 440 } else {
397 ui64 = (uint64_t) i64; 441 ui64 = (uint64_t) i64;
398 } 442 }
399 } 443 }
400 444
401 if (hexadecimal == 1) { 445 buf = ngx_sprintf_num(buf, last, ui64, zero, hex, width);
402 do {
403
404 /* the "(uint32_t)" cast disables the BCC's warning */
405 *--p = hex[(uint32_t) (ui64 & 0xf)];
406
407 } while (ui64 >>= 4);
408
409 } else if (hexadecimal == 2) {
410 do {
411
412 /* the "(uint32_t)" cast disables the BCC's warning */
413 *--p = HEX[(uint32_t) (ui64 & 0xf)];
414
415 } while (ui64 >>= 4);
416
417 } else if (ui64 <= NGX_MAX_UINT32_VALUE) {
418
419 /*
420 * To divide 64-bit number and to find the remainder
421 * on the x86 platform gcc and icc call the libc functions
422 * [u]divdi3() and [u]moddi3(), they call another function
423 * in its turn. On FreeBSD it is the qdivrem() function,
424 * its source code is about 170 lines of the code.
425 * The glibc counterpart is about 150 lines of the code.
426 *
427 * For 32-bit numbers and some divisors gcc and icc use
428 * the inlined multiplication and shifts. For example,
429 * unsigned "i32 / 10" is compiled to
430 *
431 * (i32 * 0xCCCCCCCD) >> 35
432 */
433
434 ui32 = (uint32_t) ui64;
435
436 do {
437 *--p = (u_char) (ui32 % 10 + '0');
438 } while (ui32 /= 10);
439
440 } else {
441 do {
442 *--p = (u_char) (ui64 % 10 + '0');
443 } while (ui64 /= 10);
444 }
445
446 len = (temp + NGX_INT64_LEN) - p;
447
448 while (len++ < width && buf < last) {
449 *buf++ = zero;
450 }
451
452 len = (temp + NGX_INT64_LEN) - p;
453 if (buf + len > last) {
454 len = last - buf;
455 }
456
457 buf = ngx_cpymem(buf, p, len);
458 446
459 fmt++; 447 fmt++;
460 448
461 } else { 449 } else {
462 *buf++ = *fmt++; 450 *buf++ = *fmt++;
463 } 451 }
464 } 452 }
465 453
466 return buf; 454 return buf;
455 }
456
457
458 static u_char *
459 ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64, u_char zero,
460 ngx_uint_t hexadecimal, ngx_uint_t width)
461 {
462 u_char *p, temp[NGX_INT64_LEN + 1];
463 /*
464 * we need temp[NGX_INT64_LEN] only,
465 * but icc issues the warning
466 */
467 size_t len;
468 uint32_t ui32;
469 static u_char hex[] = "0123456789abcdef";
470 static u_char HEX[] = "0123456789ABCDEF";
471
472 p = temp + NGX_INT64_LEN;
473
474 if (hexadecimal == 0) {
475
476 if (ui64 <= NGX_MAX_UINT32_VALUE) {
477
478 /*
479 * To divide 64-bit numbers and to find remainders
480 * on the x86 platform gcc and icc call the libc functions
481 * [u]divdi3() and [u]moddi3(), they call another function
482 * in its turn. On FreeBSD it is the qdivrem() function,
483 * its source code is about 170 lines of the code.
484 * The glibc counterpart is about 150 lines of the code.
485 *
486 * For 32-bit numbers and some divisors gcc and icc use
487 * a inlined multiplication and shifts. For example,
488 * unsigned "i32 / 10" is compiled to
489 *
490 * (i32 * 0xCCCCCCCD) >> 35
491 */
492
493 ui32 = (uint32_t) ui64;
494
495 do {
496 *--p = (u_char) (ui32 % 10 + '0');
497 } while (ui32 /= 10);
498
499 } else {
500 do {
501 *--p = (u_char) (ui64 % 10 + '0');
502 } while (ui64 /= 10);
503 }
504
505 } else if (hexadecimal == 1) {
506
507 do {
508
509 /* the "(uint32_t)" cast disables the BCC's warning */
510 *--p = hex[(uint32_t) (ui64 & 0xf)];
511
512 } while (ui64 >>= 4);
513
514 } else { /* hexadecimal == 2 */
515
516 do {
517
518 /* the "(uint32_t)" cast disables the BCC's warning */
519 *--p = HEX[(uint32_t) (ui64 & 0xf)];
520
521 } while (ui64 >>= 4);
522 }
523
524 /* zero or space padding */
525
526 len = (temp + NGX_INT64_LEN) - p;
527
528 while (len++ < width && buf < last) {
529 *buf++ = zero;
530 }
531
532 /* number safe copy */
533
534 len = (temp + NGX_INT64_LEN) - p;
535
536 if (buf + len > last) {
537 len = last - buf;
538 }
539
540 return ngx_cpymem(buf, p, len);
467 } 541 }
468 542
469 543
470 /* 544 /*
471 * We use ngx_strcasecmp()/ngx_strncasecmp() for 7-bit ASCII strings only, 545 * We use ngx_strcasecmp()/ngx_strncasecmp() for 7-bit ASCII strings only,