⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 apr_snprintf.c

📁 Apache V2.0.15 Alpha For Linuxhttpd-2_0_15-alpha.tar.Z
💻 C
📖 第 1 页 / 共 2 页
字号:
    }    *len = s - buf;    return (buf);}/* * Convert num to a base X number where X is a power of 2. nbits determines X. * For example, if nbits is 3, we do base 8 conversion * Return value: *      a pointer to a string containing the number * * The caller provides a buffer for the string: that is the buf_end argument * which is a pointer to the END of the buffer + 1 (i.e. if the buffer * is declared as buf[ 100 ], buf_end should be &buf[ 100 ]) * * As with conv_10, we have a faster version which is used when * the number isn't quad size. */static char *conv_p2(register u_wide_int num, register int nbits,		     char format, char *buf_end, register int *len){    register int mask = (1 << nbits) - 1;    register char *p = buf_end;    static const char low_digits[] = "0123456789abcdef";    static const char upper_digits[] = "0123456789ABCDEF";    register const char *digits = (format == 'X') ? upper_digits : low_digits;    do {	*--p = digits[num & mask];	num >>= nbits;    }    while (num);    *len = buf_end - p;    return (p);}static char *conv_p2_quad(u_widest_int num, register int nbits,		     char format, char *buf_end, register int *len){    register int mask = (1 << nbits) - 1;    register char *p = buf_end;    static const char low_digits[] = "0123456789abcdef";    static const char upper_digits[] = "0123456789ABCDEF";    register const char *digits = (format == 'X') ? upper_digits : low_digits;    if (num <= ULONG_MAX)    	return(conv_p2( (u_wide_int)num, nbits, format, buf_end, len));    do {	*--p = digits[num & mask];	num >>= nbits;    }    while (num);    *len = buf_end - p;    return (p);}/* * Do format conversion placing the output in buffer */APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *),    apr_vformatter_buff_t *vbuff, const char *fmt, va_list ap){    register char *sp;    register char *bep;    register int cc = 0;    register int i;    register char *s = NULL;    char *q;    int s_len;    register int min_width = 0;    int precision = 0;    enum {	LEFT, RIGHT    } adjust;    char pad_char;    char prefix_char;    double fp_num;    widest_int i_quad = (widest_int) 0;    u_widest_int ui_quad;    wide_int i_num = (wide_int) 0;    u_wide_int ui_num;    char num_buf[NUM_BUF_SIZE];    char char_buf[2];		/* for printing %% and %<unknown> */    enum var_type_enum {    	IS_QUAD, IS_LONG, IS_SHORT, IS_INT    };    enum var_type_enum var_type = IS_INT;    /*     * Flag variables     */    boolean_e alternate_form;    boolean_e print_sign;    boolean_e print_blank;    boolean_e adjust_precision;    boolean_e adjust_width;    bool_int is_negative;    sp = vbuff->curpos;    bep = vbuff->endpos;    while (*fmt) {	if (*fmt != '%') {	    INS_CHAR(*fmt, sp, bep, cc);	}	else {	    /*	     * Default variable settings	     */            boolean_e print_something = YES;	    adjust = RIGHT;	    alternate_form = print_sign = print_blank = NO;	    pad_char = ' ';	    prefix_char = NUL;	    fmt++;	    /*	     * Try to avoid checking for flags, width or precision	     */	    if (!apr_islower(*fmt)) {		/*		 * Recognize flags: -, #, BLANK, +		 */		for (;; fmt++) {		    if (*fmt == '-')			adjust = LEFT;		    else if (*fmt == '+')			print_sign = YES;		    else if (*fmt == '#')			alternate_form = YES;		    else if (*fmt == ' ')			print_blank = YES;		    else if (*fmt == '0')			pad_char = '0';		    else			break;		}		/*		 * Check if a width was specified		 */		if (apr_isdigit(*fmt)) {		    STR_TO_DEC(fmt, min_width);		    adjust_width = YES;		}		else if (*fmt == '*') {		    min_width = va_arg(ap, int);		    fmt++;		    adjust_width = YES;		    if (min_width < 0) {			adjust = LEFT;			min_width = -min_width;		    }		}		else		    adjust_width = NO;		/*		 * Check if a precision was specified		 *		 * XXX: an unreasonable amount of precision may be specified		 * resulting in overflow of num_buf. Currently we		 * ignore this possibility.		 */		if (*fmt == '.') {		    adjust_precision = YES;		    fmt++;		    if (apr_isdigit(*fmt)) {			STR_TO_DEC(fmt, precision);		    }		    else if (*fmt == '*') {			precision = va_arg(ap, int);			fmt++;			if (precision < 0)			    precision = 0;		    }		    else			precision = 0;		}		else		    adjust_precision = NO;	    }	    else		adjust_precision = adjust_width = NO;	    /*	     * Modifier check	     */	    if (*fmt == 'q') {		var_type = IS_QUAD;		fmt++;	    }	    else if (*fmt == 'l') {		var_type = IS_LONG;		fmt++;	    }	    else if (*fmt == 'h') {		var_type = IS_SHORT;		fmt++;	    }	    else {		var_type = IS_INT;	    }	    /*	     * Argument extraction and printing.	     * First we determine the argument type.	     * Then, we convert the argument to a string.	     * On exit from the switch, s points to the string that	     * must be printed, s_len has the length of the string	     * The precision requirements, if any, are reflected in s_len.	     *	     * NOTE: pad_char may be set to '0' because of the 0 flag.	     *   It is reset to ' ' by non-numeric formats	     */	    switch (*fmt) {	    case 'u':	    	if (var_type == IS_QUAD) {		    i_quad = va_arg(ap, u_widest_int);		    s = conv_10_quad(i_quad, 1, &is_negative,			    &num_buf[NUM_BUF_SIZE], &s_len);		}		else {		    if (var_type == IS_LONG)			i_num = (wide_int) va_arg(ap, u_wide_int);		    else if (var_type == IS_SHORT)			i_num = (wide_int) (unsigned short) va_arg(ap, unsigned int);		    else			i_num = (wide_int) va_arg(ap, unsigned int);		    s = conv_10(i_num, 1, &is_negative,			    &num_buf[NUM_BUF_SIZE], &s_len);		}		FIX_PRECISION(adjust_precision, precision, s, s_len);		break;	    case 'd':	    case 'i':	    	if (var_type == IS_QUAD) {		    i_quad = va_arg(ap, widest_int);		    s = conv_10_quad(i_quad, 0, &is_negative,			    &num_buf[NUM_BUF_SIZE], &s_len);		}		else {		    if (var_type == IS_LONG)			i_num = (wide_int) va_arg(ap, wide_int);		    else if (var_type == IS_SHORT)			i_num = (wide_int) (short) va_arg(ap, int);		    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) {		    s_len = strlen(s);		    if (adjust_precision && precision < s_len)			s_len = precision;		}		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 = 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 NUL:		    /* if %p ends the string, oh well ignore it */		    continue;		default:		    s = "bogus %p";		    s_len = 8;		    prefix_char = NUL;		    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, size_t len,                                    const char *format, ...){    int cc;    va_list ap;    apr_vformatter_buff_t vbuff;    if (len == 0)	return 0;    /* 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);    *vbuff.curpos = '\0';    return (cc == -1) ? len : cc;}APR_DECLARE(int) apr_vsnprintf(char *buf, size_t len, const char *format,			     va_list ap){    int cc;    apr_vformatter_buff_t vbuff;    if (len == 0)	return 0;    /* save one byte for nul terminator */    vbuff.curpos = buf;    vbuff.endpos = buf + len - 1;    cc = apr_vformatter(snprintf_flush, &vbuff, format, ap);    *vbuff.curpos = '\0';    return (cc == -1) ? len : cc;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -