📄 apr_snprintf.c
字号:
else i_num = (wide_int) va_arg(ap, int); s = conv_10(i_num, 0, &is_negative, &num_buf[NUM_BUF_SIZE], &s_len); } FIX_PRECISION(adjust_precision, precision, s, s_len); if (is_negative) prefix_char = '-'; else if (print_sign) prefix_char = '+'; else if (print_blank) prefix_char = ' '; break; case 'o': if (var_type == IS_QUAD) { ui_quad = va_arg(ap, u_widest_int); s = conv_p2_quad(ui_quad, 3, *fmt, &num_buf[NUM_BUF_SIZE], &s_len); } else { if (var_type == IS_LONG) ui_num = (u_wide_int) va_arg(ap, u_wide_int); else if (var_type == IS_SHORT) ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int); else ui_num = (u_wide_int) va_arg(ap, unsigned int); s = conv_p2(ui_num, 3, *fmt, &num_buf[NUM_BUF_SIZE], &s_len); } FIX_PRECISION(adjust_precision, precision, s, s_len); if (alternate_form && *s != '0') { *--s = '0'; s_len++; } break; case 'x': case 'X': if (var_type == IS_QUAD) { ui_quad = va_arg(ap, u_widest_int); s = conv_p2_quad(ui_quad, 4, *fmt, &num_buf[NUM_BUF_SIZE], &s_len); } else { if (var_type == IS_LONG) ui_num = (u_wide_int) va_arg(ap, u_wide_int); else if (var_type == IS_SHORT) ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int); else ui_num = (u_wide_int) va_arg(ap, unsigned int); s = conv_p2(ui_num, 4, *fmt, &num_buf[NUM_BUF_SIZE], &s_len); } FIX_PRECISION(adjust_precision, precision, s, s_len); if (alternate_form && i_num != 0) { *--s = *fmt; /* 'x' or 'X' */ *--s = '0'; s_len += 2; } break; case 's': s = va_arg(ap, char *); if (s != NULL) { if (!adjust_precision) { s_len = strlen(s); } else { /* From the C library standard in section 7.9.6.1: * ...if the precision is specified, no more then * that many characters are written. If the * precision is not specified or is greater * than the size of the array, the array shall * contain a null character. * * My reading is is precision is specified and * is less then or equal to the size of the * array, no null character is required. So * we can't do a strlen. * * This figures out the length of the string * up to the precision. Once it's long enough * for the specified precision, we don't care * anymore. * * NOTE: you must do the length comparison * before the check for the null character. * Otherwise, you'll check one beyond the * last valid character. */ const char *walk; for (walk = s, s_len = 0; (s_len < precision) && (*walk != '\0'); ++walk, ++s_len); } } else { s = S_NULL; s_len = S_NULL_LEN; } pad_char = ' '; break; case 'f': case 'e': case 'E': fp_num = va_arg(ap, double); /* * We use &num_buf[ 1 ], so that we have room for the sign */ s = NULL;#ifdef HAVE_ISNAN if (isnan(fp_num)) { s = "nan"; s_len = 3; }#endif#ifdef HAVE_ISINF if (!s && isinf(fp_num)) { s = "inf"; s_len = 3; }#endif if (!s) { s = conv_fp(*fmt, fp_num, alternate_form, (adjust_precision == NO) ? FLOAT_DIGITS : precision, &is_negative, &num_buf[1], &s_len); if (is_negative) prefix_char = '-'; else if (print_sign) prefix_char = '+'; else if (print_blank) prefix_char = ' '; } break; case 'g': case 'G': if (adjust_precision == NO) precision = FLOAT_DIGITS; else if (precision == 0) precision = 1; /* * * We use &num_buf[ 1 ], so that we have room for the sign */ s = apr_gcvt(va_arg(ap, double), precision, &num_buf[1], alternate_form); if (*s == '-') prefix_char = *s++; else if (print_sign) prefix_char = '+'; else if (print_blank) prefix_char = ' '; s_len = strlen(s); if (alternate_form && (q = strchr(s, '.')) == NULL) { s[s_len++] = '.'; s[s_len] = '\0'; /* delimit for following strchr() */ } if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL) *q = 'E'; break; case 'c': char_buf[0] = (char) (va_arg(ap, int)); s = &char_buf[0]; s_len = 1; pad_char = ' '; break; case '%': char_buf[0] = '%'; s = &char_buf[0]; s_len = 1; pad_char = ' '; break; case 'n': if (var_type == IS_QUAD) *(va_arg(ap, widest_int *)) = cc; else if (var_type == IS_LONG) *(va_arg(ap, long *)) = cc; else if (var_type == IS_SHORT) *(va_arg(ap, short *)) = cc; else *(va_arg(ap, int *)) = cc; print_something = NO; break; /* * This is where we extend the printf format, with a second * type specifier */ case 'p': switch(*++fmt) { /* * If the pointer size is equal to or smaller than the size * of the largest unsigned int, we convert the pointer to a * hex number, otherwise we print "%p" to indicate that we * don't handle "%p". */ case 'p':#ifdef APR_VOID_P_IS_QUAD if (sizeof(void *) <= sizeof(u_widest_int)) { ui_quad = (u_widest_int) va_arg(ap, void *); s = conv_p2_quad(ui_quad, 4, 'x', &num_buf[NUM_BUF_SIZE], &s_len); }#else if (sizeof(void *) <= sizeof(u_wide_int)) { ui_num = (u_wide_int) va_arg(ap, void *); s = conv_p2(ui_num, 4, 'x', &num_buf[NUM_BUF_SIZE], &s_len); }#endif else { s = "%p"; s_len = 2; prefix_char = NUL; } pad_char = ' '; break; /* print an apr_sockaddr_t as a.b.c.d:port */ case 'I': { apr_sockaddr_t *sa; sa = va_arg(ap, apr_sockaddr_t *); if (sa != NULL) { s = conv_apr_sockaddr(sa, &num_buf[NUM_BUF_SIZE], &s_len); if (adjust_precision && precision < s_len) s_len = precision; } else { s = S_NULL; s_len = S_NULL_LEN; } pad_char = ' '; } break; /* print a struct in_addr as a.b.c.d */ case 'A': { struct in_addr *ia; ia = va_arg(ap, struct in_addr *); if (ia != NULL) { s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len); if (adjust_precision && precision < s_len) s_len = precision; } else { s = S_NULL; s_len = S_NULL_LEN; } pad_char = ' '; } break; case 'T':#if APR_HAS_THREADS { apr_os_thread_t *tid; tid = va_arg(ap, apr_os_thread_t *); if (tid != NULL) { s = conv_os_thread_t(tid, &num_buf[NUM_BUF_SIZE], &s_len); if (adjust_precision && precision < s_len) s_len = precision; } else { s = S_NULL; s_len = S_NULL_LEN; } pad_char = ' '; }#else char_buf[0] = '0'; s = &char_buf[0]; s_len = 1; pad_char = ' ';#endif break; case NUL: /* if %p ends the string, oh well ignore it */ continue; default: s = "bogus %p"; s_len = 8; prefix_char = NUL; (void)va_arg(ap, void *); /* skip the bogus argument on the stack */ break; } break; case NUL: /* * The last character of the format string was %. * We ignore it. */ continue; /* * The default case is for unrecognized %'s. * We print %<char> to help the user identify what * option is not understood. * This is also useful in case the user wants to pass * the output of format_converter to another function * that understands some other %<char> (like syslog). * Note that we can't point s inside fmt because the * unknown <char> could be preceded by width etc. */ default: char_buf[0] = '%'; char_buf[1] = *fmt; s = char_buf; s_len = 2; pad_char = ' '; break; } if (prefix_char != NUL && s != S_NULL && s != char_buf) { *--s = prefix_char; s_len++; } if (adjust_width && adjust == RIGHT && min_width > s_len) { if (pad_char == '0' && prefix_char != NUL) { INS_CHAR(*s, sp, bep, cc); s++; s_len--; min_width--; } PAD(min_width, s_len, pad_char); } /* * Print the string s. */ if (print_something == YES) { for (i = s_len; i != 0; i--) { INS_CHAR(*s, sp, bep, cc); s++; } } if (adjust_width && adjust == LEFT && min_width > s_len) PAD(min_width, s_len, pad_char); } fmt++; } vbuff->curpos = sp; return cc;}static int snprintf_flush(apr_vformatter_buff_t *vbuff){ /* if the buffer fills we have to abort immediately, there is no way * to "flush" an apr_snprintf... there's nowhere to flush it to. */ return -1;}APR_DECLARE_NONSTD(int) apr_snprintf(char *buf, apr_size_t len, const char *format, ...){ int cc; va_list ap; apr_vformatter_buff_t vbuff; if (len == 0) { /* NOTE: This is a special case; we just want to return the number * of chars that would be written (minus \0) if the buffer * size was infinite. We leverage the fact that INS_CHAR * just does actual inserts iff the buffer pointer is non-NULL. * In this case, we don't care what buf is; it can be NULL, since * we don't touch it at all. */ vbuff.curpos = NULL; vbuff.endpos = NULL; } else { /* save one byte for nul terminator */ vbuff.curpos = buf; vbuff.endpos = buf + len - 1; } va_start(ap, format); cc = apr_vformatter(snprintf_flush, &vbuff, format, ap); va_end(ap); if (len != 0) { *vbuff.curpos = '\0'; } return (cc == -1) ? (int)len : cc;}APR_DECLARE(int) apr_vsnprintf(char *buf, apr_size_t len, const char *format, va_list ap){ int cc; apr_vformatter_buff_t vbuff; if (len == 0) { /* See above note */ vbuff.curpos = NULL; vbuff.endpos = NULL; } else { /* save one byte for nul terminator */ vbuff.curpos = buf; vbuff.endpos = buf + len - 1; } cc = apr_vformatter(snprintf_flush, &vbuff, format, ap); if (len != 0) { *vbuff.curpos = '\0'; } return (cc == -1) ? (int)len : cc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -