Mercurial > hg > nginx-vendor-1-0
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, |