apr_snprintf.c

来自「linux网络服务器工具」· C语言 代码 · 共 1,392 行 · 第 1/3 页

C
1,392
字号
#if APR_HAVE_IPV6    if (sa->family == APR_INET6 &&        !IN6_IS_ADDR_V4MAPPED(&sa->sa.sin6.sin6_addr)) {        *(p - 1) = ']';        p -= sub_len + 2;        *p = '[';        memcpy(p + 1, ipaddr_str, sub_len);    }    else#endif    {        p -= sub_len;        memcpy(p, ipaddr_str, sub_len);    }    *len = buf_end - p;    return (p);}#if APR_HAS_THREADSstatic char *conv_os_thread_t(apr_os_thread_t *tid, char *buf_end, apr_size_t *len){    union {        apr_os_thread_t tid;        apr_uint64_t u64;        apr_uint32_t u32;    } u;    int is_negative;    u.tid = *tid;    switch(sizeof(u.tid)) {    case sizeof(apr_int32_t):        return conv_10(u.u32, TRUE, &is_negative, buf_end, len);    case sizeof(apr_int64_t):        return conv_10_quad(u.u64, TRUE, &is_negative, buf_end, len);    default:        /* not implemented; stick 0 in the buffer */        return conv_10(0, TRUE, &is_negative, buf_end, len);    }}#endif/* * Convert a floating point number to a string formats 'f', 'e' or 'E'. * The result is placed in buf, and len denotes the length of the string * The sign is returned in the is_negative argument (and is not placed * in buf). */static char *conv_fp(register char format, register double num,    boolean_e add_dp, int precision, int *is_negative,    char *buf, apr_size_t *len){    register char *s = buf;    register char *p;    int decimal_point;    char buf1[NDIG];    if (format == 'f')        p = apr_fcvt(num, precision, &decimal_point, is_negative, buf1);    else /* either e or E format */        p = apr_ecvt(num, precision + 1, &decimal_point, is_negative, buf1);    /*     * Check for Infinity and NaN     */    if (apr_isalpha(*p)) {        *len = strlen(p);        memcpy(buf, p, *len + 1);        *is_negative = FALSE;        return (buf);    }    if (format == 'f') {        if (decimal_point <= 0) {            *s++ = '0';            if (precision > 0) {                *s++ = '.';                while (decimal_point++ < 0)                    *s++ = '0';            }            else if (add_dp)                *s++ = '.';        }        else {            while (decimal_point-- > 0)                *s++ = *p++;            if (precision > 0 || add_dp)                *s++ = '.';        }    }    else {        *s++ = *p++;        if (precision > 0 || add_dp)            *s++ = '.';    }    /*     * copy the rest of p, the NUL is NOT copied     */    while (*p)        *s++ = *p++;    if (format != 'f') {        char temp[EXPONENT_LENGTH];        /* for exponent conversion */        apr_size_t t_len;        int exponent_is_negative;        *s++ = format;                /* either e or E */        decimal_point--;        if (decimal_point != 0) {            p = conv_10((apr_int32_t) decimal_point, FALSE, &exponent_is_negative,                        &temp[EXPONENT_LENGTH], &t_len);            *s++ = exponent_is_negative ? '-' : '+';            /*             * Make sure the exponent has at least 2 digits             */            if (t_len == 1)                *s++ = '0';            while (t_len--)                *s++ = *p++;        }        else {            *s++ = '+';            *s++ = '0';            *s++ = '0';        }    }    *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 apr_uint32_t num, register int nbits,                     char format, char *buf_end, register apr_size_t *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(apr_uint64_t num, register int nbits,                     char format, char *buf_end, register apr_size_t *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 <= APR_UINT32_MAX)        return(conv_p2((apr_uint32_t)num, nbits, format, buf_end, len));    do {        *--p = digits[num & mask];        num >>= nbits;    }    while (num);    *len = buf_end - p;    return (p);}#if APR_HAS_THREADSstatic char *conv_os_thread_t_hex(apr_os_thread_t *tid, char *buf_end, apr_size_t *len){    union {        apr_os_thread_t tid;        apr_uint64_t u64;        apr_uint32_t u32;    } u;    int is_negative;    u.tid = *tid;    switch(sizeof(u.tid)) {    case sizeof(apr_int32_t):        return conv_p2(u.u32, 4, 'x', buf_end, len);    case sizeof(apr_int64_t):        return conv_p2_quad(u.u64, 4, 'x', buf_end, len);    default:        /* not implemented; stick 0 in the buffer */        return conv_10(0, TRUE, &is_negative, buf_end, len);    }}#endif/* * 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 apr_size_t i;    register char *s = NULL;    char *q;    apr_size_t s_len = 0;    register apr_size_t min_width = 0;    apr_size_t precision = 0;    enum {        LEFT, RIGHT    } adjust;    char pad_char;    char prefix_char;    double fp_num;    apr_int64_t i_quad = 0;    apr_uint64_t ui_quad;    apr_int32_t i_num = 0;    apr_uint32_t 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;    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 == '*') {                    int v = va_arg(ap, int);                    fmt++;                    adjust_width = YES;                    if (v < 0) {                        adjust = LEFT;                        min_width = (apr_size_t)(-v);                    }                    else                        min_width = (apr_size_t)v;                }                else                    adjust_width = NO;                /*                 * Check if a precision was specified                 */                if (*fmt == '.') {                    adjust_precision = YES;                    fmt++;                    if (apr_isdigit(*fmt)) {                        STR_TO_DEC(fmt, precision);                    }                    else if (*fmt == '*') {                        int v = va_arg(ap, int);                        fmt++;                        precision = (v < 0) ? 0 : (apr_size_t)v;                    }                    else                        precision = 0;                }                else                    adjust_precision = NO;            }            else                adjust_precision = adjust_width = NO;            /*             * Modifier check.  Note that if APR_INT64_T_FMT is "d",             * the first if condition is never true.             */            if ((sizeof(APR_INT64_T_FMT) == 4 &&                 fmt[0] == APR_INT64_T_FMT[0] &&                 fmt[1] == APR_INT64_T_FMT[1]) ||                (sizeof(APR_INT64_T_FMT) == 3 &&                 fmt[0] == APR_INT64_T_FMT[0]) ||                (sizeof(APR_INT64_T_FMT) > 4 &&                 strncmp(fmt, APR_INT64_T_FMT,                          sizeof(APR_INT64_T_FMT) - 2) == 0)) {                /* Need to account for trailing 'd' and null in sizeof() */                var_type = IS_QUAD;                fmt += (sizeof(APR_INT64_T_FMT) - 2);            }            else 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, apr_uint64_t);                    s = conv_10_quad(i_quad, 1, &is_negative,                            &num_buf[NUM_BUF_SIZE], &s_len);                }                else {                    if (var_type == IS_LONG)                        i_num = (apr_int32_t) va_arg(ap, apr_uint32_t);                    else if (var_type == IS_SHORT)                        i_num = (apr_int32_t) (unsigned short) va_arg(ap, unsigned int);                    else                        i_num = (apr_int32_t) 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, apr_int64_t);                    s = conv_10_quad(i_quad, 0, &is_negative,                            &num_buf[NUM_BUF_SIZE], &s_len);                }                else {                    if (var_type == IS_LONG)                        i_num = va_arg(ap, apr_int32_t);                    else if (var_type == IS_SHORT)                        i_num = (short) va_arg(ap, int);                    else                        i_num = 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, apr_uint64_t);                    s = conv_p2_quad(ui_quad, 3, *fmt,                            &num_buf[NUM_BUF_SIZE], &s_len);                }                else {                    if (var_type == IS_LONG)                        ui_num = va_arg(ap, apr_uint32_t);                    else if (var_type == IS_SHORT)                        ui_num = (unsigned short) va_arg(ap, unsigned int);                    else                        ui_num = 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':

⌨️ 快捷键说明

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