comparison src/core/ngx_string.c @ 7736:a46fcf101cfc

Core: added format specifiers to output binary data as hex. Now "s", "V", and "v" format specifiers may be prefixed with "x" (lowercase) or "X" (uppercase) to output corresponding data in hexadecimal format. In collaboration with Maxim Dounin.
author Vladimir Homutov <vl@nginx.com>
date Wed, 28 Oct 2020 10:56:11 +0300
parents a42a6dfeb01a
children 5772da03faf8
comparison
equal deleted inserted replaced
7735:908f48bd3c2f 7736:a46fcf101cfc
9 #include <ngx_core.h> 9 #include <ngx_core.h>
10 10
11 11
12 static u_char *ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64, 12 static u_char *ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64,
13 u_char zero, ngx_uint_t hexadecimal, ngx_uint_t width); 13 u_char zero, ngx_uint_t hexadecimal, ngx_uint_t width);
14 static u_char *ngx_sprintf_str(u_char *buf, u_char *last, u_char *src,
15 size_t len, ngx_uint_t hexadecimal);
14 static void ngx_encode_base64_internal(ngx_str_t *dst, ngx_str_t *src, 16 static void ngx_encode_base64_internal(ngx_str_t *dst, ngx_str_t *src,
15 const u_char *basis, ngx_uint_t padding); 17 const u_char *basis, ngx_uint_t padding);
16 static ngx_int_t ngx_decode_base64_internal(ngx_str_t *dst, ngx_str_t *src, 18 static ngx_int_t ngx_decode_base64_internal(ngx_str_t *dst, ngx_str_t *src,
17 const u_char *basis); 19 const u_char *basis);
18 20
99 * %[0][width][.width]f double, max valid number fits to %18.15f 101 * %[0][width][.width]f double, max valid number fits to %18.15f
100 * %P ngx_pid_t 102 * %P ngx_pid_t
101 * %M ngx_msec_t 103 * %M ngx_msec_t
102 * %r rlim_t 104 * %r rlim_t
103 * %p void * 105 * %p void *
104 * %V ngx_str_t * 106 * %[x|X]V ngx_str_t *
105 * %v ngx_variable_value_t * 107 * %[x|X]v ngx_variable_value_t *
106 * %s null-terminated string 108 * %[x|X]s null-terminated string
107 * %*s length and string 109 * %*[x|X]s length and string
108 * %Z '\0' 110 * %Z '\0'
109 * %N '\n' 111 * %N '\n'
110 * %c char 112 * %c char
111 * %% % 113 * %% %
112 * 114 *
163 ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args) 165 ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args)
164 { 166 {
165 u_char *p, zero; 167 u_char *p, zero;
166 int d; 168 int d;
167 double f; 169 double f;
168 size_t len, slen; 170 size_t slen;
169 int64_t i64; 171 int64_t i64;
170 uint64_t ui64, frac; 172 uint64_t ui64, frac;
171 ngx_msec_t ms; 173 ngx_msec_t ms;
172 ngx_uint_t width, sign, hex, max_width, frac_width, scale, n; 174 ngx_uint_t width, sign, hex, max_width, frac_width, scale, n;
173 ngx_str_t *v; 175 ngx_str_t *v;
248 switch (*fmt) { 250 switch (*fmt) {
249 251
250 case 'V': 252 case 'V':
251 v = va_arg(args, ngx_str_t *); 253 v = va_arg(args, ngx_str_t *);
252 254
253 len = ngx_min(((size_t) (last - buf)), v->len); 255 buf = ngx_sprintf_str(buf, last, v->data, v->len, hex);
254 buf = ngx_cpymem(buf, v->data, len);
255 fmt++; 256 fmt++;
256 257
257 continue; 258 continue;
258 259
259 case 'v': 260 case 'v':
260 vv = va_arg(args, ngx_variable_value_t *); 261 vv = va_arg(args, ngx_variable_value_t *);
261 262
262 len = ngx_min(((size_t) (last - buf)), vv->len); 263 buf = ngx_sprintf_str(buf, last, vv->data, vv->len, hex);
263 buf = ngx_cpymem(buf, vv->data, len);
264 fmt++; 264 fmt++;
265 265
266 continue; 266 continue;
267 267
268 case 's': 268 case 's':
269 p = va_arg(args, u_char *); 269 p = va_arg(args, u_char *);
270 270
271 if (slen == (size_t) -1) { 271 buf = ngx_sprintf_str(buf, last, p, slen, hex);
272 while (*p && buf < last) {
273 *buf++ = *p++;
274 }
275
276 } else {
277 len = ngx_min(((size_t) (last - buf)), slen);
278 buf = ngx_cpymem(buf, p, len);
279 }
280
281 fmt++; 272 fmt++;
282 273
283 continue; 274 continue;
284 275
285 case 'O': 276 case 'O':
574 565
575 return ngx_cpymem(buf, p, len); 566 return ngx_cpymem(buf, p, len);
576 } 567 }
577 568
578 569
570 static u_char *
571 ngx_sprintf_str(u_char *buf, u_char *last, u_char *src, size_t len,
572 ngx_uint_t hexadecimal)
573 {
574 static u_char hex[] = "0123456789abcdef";
575 static u_char HEX[] = "0123456789ABCDEF";
576
577 if (hexadecimal == 0) {
578
579 if (len == (size_t) -1) {
580 while (*src && buf < last) {
581 *buf++ = *src++;
582 }
583
584 } else {
585 len = ngx_min((size_t) (last - buf), len);
586 buf = ngx_cpymem(buf, src, len);
587 }
588
589 } else if (hexadecimal == 1) {
590
591 if (len == (size_t) -1) {
592
593 while (*src && buf < last - 1) {
594 *buf++ = hex[*src >> 4];
595 *buf++ = hex[*src++ & 0xf];
596 }
597
598 } else {
599
600 while (len-- && buf < last - 1) {
601 *buf++ = hex[*src >> 4];
602 *buf++ = hex[*src++ & 0xf];
603 }
604 }
605
606 } else { /* hexadecimal == 2 */
607
608 if (len == (size_t) -1) {
609
610 while (*src && buf < last - 1) {
611 *buf++ = HEX[*src >> 4];
612 *buf++ = HEX[*src++ & 0xf];
613 }
614
615 } else {
616
617 while (len-- && buf < last - 1) {
618 *buf++ = HEX[*src >> 4];
619 *buf++ = HEX[*src++ & 0xf];
620 }
621 }
622 }
623
624 return buf;
625 }
626
627
579 /* 628 /*
580 * We use ngx_strcasecmp()/ngx_strncasecmp() for 7-bit ASCII strings only, 629 * We use ngx_strcasecmp()/ngx_strncasecmp() for 7-bit ASCII strings only,
581 * and implement our own ngx_strcasecmp()/ngx_strncasecmp() 630 * and implement our own ngx_strcasecmp()/ngx_strncasecmp()
582 * to avoid libc locale overhead. Besides, we use the ngx_uint_t's 631 * to avoid libc locale overhead. Besides, we use the ngx_uint_t's
583 * instead of the u_char's, because they are slightly faster. 632 * instead of the u_char's, because they are slightly faster.