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

📄 apr_snprintf.c

📁 Apache V2.0.15 Alpha For Linuxhttpd-2_0_15-alpha.tar.Z
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. * * 3. The end-user documentation included with the redistribution, *    if any, must include the following acknowledgment: *       "This product includes software developed by the *        Apache Software Foundation (http://www.apache.org/)." *    Alternately, this acknowledgment may appear in the software itself, *    if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must *    not be used to endorse or promote products derived from this *    software without prior written permission. For written *    permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", *    nor may "Apache" appear in their name, without prior written *    permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation.  For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * The apr_vsnprintf/apr_snprintf functions are based on, and used with the * permission of, the  SIO stdio-replacement strx_* functions by Panos * Tsirigotis <panos@alumni.cs.colorado.edu> for xinetd. */#include "apr.h"#include "apr_private.h"#include "apr_lib.h"#include "apr_strings.h"#include "apr_network_io.h"#include <math.h>#if APR_HAVE_CTYPE_H#include <ctype.h>#endif#if APR_HAVE_NETINET_IN_H#include <netinet/in.h>#endif#if APR_HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif#if APR_HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#if APR_HAVE_LIMITS_H#include <limits.h>#endif#if APR_HAVE_STRING_H#include <string.h>#endiftypedef enum {    NO = 0, YES = 1} boolean_e;#ifndef FALSE#define FALSE			0#endif#ifndef TRUE#define TRUE			1#endif#define NUL			'\0'#define WIDE_INT		longtypedef WIDE_INT wide_int;typedef unsigned WIDE_INT u_wide_int;typedef apr_int64_t widest_int;#ifdef __TANDEM/* Although Tandem supports "long long" there is no unsigned variant. */typedef unsigned long       u_widest_int;#elsetypedef apr_uint64_t u_widest_int;#endiftypedef int bool_int;#define S_NULL			"(null)"#define S_NULL_LEN		6#define FLOAT_DIGITS		6#define EXPONENT_LENGTH		10/* * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions * * XXX: this is a magic number; do not decrease it */#define NUM_BUF_SIZE		512/* * cvt.c - IEEE floating point formatting routines for FreeBSD * from GNU libc-4.6.27.  Modified to be thread safe. *//* *    apr_ecvt converts to decimal *      the number of digits is specified by ndigit *      decpt is set to the position of the decimal point *      sign is set to 0 for positive, 1 for negative */#define	NDIG	80/* buf must have at least NDIG bytes */static char *apr_cvt(double arg, int ndigits, int *decpt, int *sign,                      int eflag, char *buf){    register int r2;    double fi, fj;    register char *p, *p1;        if (ndigits >= NDIG - 1)	ndigits = NDIG - 2;    r2 = 0;    *sign = 0;    p = &buf[0];    if (arg < 0) {	*sign = 1;	arg = -arg;    }    arg = modf(arg, &fi);    p1 = &buf[NDIG];    /*     * Do integer part     */    if (fi != 0) {	p1 = &buf[NDIG];	while (fi != 0) {	    fj = modf(fi / 10, &fi);	    *--p1 = (int) ((fj + .03) * 10) + '0';	    r2++;	}	while (p1 < &buf[NDIG])	    *p++ = *p1++;    }    else if (arg > 0) {	while ((fj = arg * 10) < 1) {	    arg = fj;	    r2--;	}    }    p1 = &buf[ndigits];    if (eflag == 0)	p1 += r2;    *decpt = r2;    if (p1 < &buf[0]) {	buf[0] = '\0';	return (buf);    }    while (p <= p1 && p < &buf[NDIG]) {	arg *= 10;	arg = modf(arg, &fj);	*p++ = (int) fj + '0';    }    if (p1 >= &buf[NDIG]) {	buf[NDIG - 1] = '\0';	return (buf);    }    p = p1;    *p1 += 5;    while (*p1 > '9') {	*p1 = '0';	if (p1 > buf)	    ++ * --p1;	else {	    *p1 = '1';	    (*decpt)++;	    if (eflag == 0) {		if (p > buf)		    *p = '0';		p++;	    }	}    }    *p = '\0';    return (buf);}static char *apr_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf){    return (apr_cvt(arg, ndigits, decpt, sign, 1, buf));}static char *apr_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf){    return (apr_cvt(arg, ndigits, decpt, sign, 0, buf));}/* * apr_gcvt  - Floating output conversion to * minimal length string */static char *apr_gcvt(double number, int ndigit, char *buf, boolean_e altform){    int sign, decpt;    register char *p1, *p2;    register int i;    char buf1[NDIG];    p1 = apr_ecvt(number, ndigit, &decpt, &sign, buf1);    p2 = buf;    if (sign)	*p2++ = '-';    for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--)	ndigit--;    if ((decpt >= 0 && decpt - ndigit > 4)	|| (decpt < 0 && decpt < -3)) {		/* use E-style */	decpt--;	*p2++ = *p1++;	*p2++ = '.';	for (i = 1; i < ndigit; i++)	    *p2++ = *p1++;	*p2++ = 'e';	if (decpt < 0) {	    decpt = -decpt;	    *p2++ = '-';	}	else	    *p2++ = '+';	if (decpt / 100 > 0)	    *p2++ = decpt / 100 + '0';	if (decpt / 10 > 0)	    *p2++ = (decpt % 100) / 10 + '0';	*p2++ = decpt % 10 + '0';    }    else {	if (decpt <= 0) {	    if (*p1 != '0')		*p2++ = '.';	    while (decpt < 0) {		decpt++;		*p2++ = '0';	    }	}	for (i = 1; i <= ndigit; i++) {	    *p2++ = *p1++;	    if (i == decpt)		*p2++ = '.';	}	if (ndigit < decpt) {	    while (ndigit++ < decpt)		*p2++ = '0';	    *p2++ = '.';	}    }    if (p2[-1] == '.' && !altform)	p2--;    *p2 = '\0';    return (buf);}/* * The INS_CHAR macro inserts a character in the buffer and writes * the buffer back to disk if necessary * It uses the char pointers sp and bep: *      sp points to the next available character in the buffer *      bep points to the end-of-buffer+1 * While using this macro, note that the nextb pointer is NOT updated. * * NOTE: Evaluation of the c argument should not have any side-effects */#define INS_CHAR(c, sp, bep, cc)				\	    {							\		if (sp >= bep) {				\		    vbuff->curpos = sp;                         \		    if (flush_func(vbuff))			\			return -1;				\		    sp = vbuff->curpos;				\		    bep = vbuff->endpos;			\		} 						\		*sp++ = (c);					\		cc++; 						\	    }#define NUM( c )			( c - '0' )#define STR_TO_DEC( str, num )		\    num = NUM( *str++ ) ;		\    while ( apr_isdigit( *str ) )		\    {					\	num *= 10 ;			\	num += NUM( *str++ ) ;		\    }/* * This macro does zero padding so that the precision * requirement is satisfied. The padding is done by * adding '0's to the left of the string that is going * to be printed. */#define FIX_PRECISION( adjust, precision, s, s_len )	\    if ( adjust )					\	while ( s_len < precision )			\	{						\	    *--s = '0' ;				\	    s_len++ ;					\	}/* * Macro that does padding. The padding is done by printing * the character ch. */#define PAD( width, len, ch )	do		\	{					\	    INS_CHAR( ch, sp, bep, cc ) ;	\	    width-- ;				\	}					\	while ( width > len )/* * Prefix the character ch to the string str * Increase length * Set the has_prefix flag */#define PREFIX( str, length, ch )	 *--str = ch ; length++ ; has_prefix = YES/* * Convert num to its decimal format. * Return value: *   - a pointer to a string containing the number (no sign) *   - len contains the length of the string *   - is_negative is set to TRUE or FALSE depending on the sign *     of the number (always set to FALSE if is_unsigned is TRUE) * * 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 ]) * * Note: we have 2 versions. One is used when we need to use quads * (conv_10_quad), the other when we don't (conv_10). We're assuming the * latter is faster. */static char *conv_10(register wide_int num, register bool_int is_unsigned,		     register bool_int *is_negative, char *buf_end,		     register int *len){    register char *p = buf_end;    register u_wide_int magnitude;    if (is_unsigned) {	magnitude = (u_wide_int) num;	*is_negative = FALSE;    }    else {	*is_negative = (num < 0);	/*	 * On a 2's complement machine, negating the most negative integer 	 * results in a number that cannot be represented as a signed integer.	 * Here is what we do to obtain the number's magnitude:	 *      a. add 1 to the number	 *      b. negate it (becomes positive)	 *      c. convert it to unsigned	 *      d. add 1	 */	if (*is_negative) {	    wide_int t = num + 1;	    magnitude = ((u_wide_int) -t) + 1;	}	else	    magnitude = (u_wide_int) num;    }    /*     * We use a do-while loop so that we write at least 1 digit      */    do {	register u_wide_int new_magnitude = magnitude / 10;	*--p = (char) (magnitude - new_magnitude * 10 + '0');	magnitude = new_magnitude;    }    while (magnitude);    *len = buf_end - p;    return (p);}static char *conv_10_quad(widest_int num, register bool_int is_unsigned,		     register bool_int *is_negative, char *buf_end,		     register int *len){    register char *p = buf_end;    u_widest_int magnitude;    /*     * We see if we can use the faster non-quad version by checking the     * number against the largest long value it can be. If <=, we     * punt to the quicker version.     */    if ((num <= ULONG_MAX && is_unsigned) || (num <= LONG_MAX && !is_unsigned))    	return(conv_10( (wide_int)num, is_unsigned, is_negative,	       buf_end, len));    if (is_unsigned) {	magnitude = (u_widest_int) num;	*is_negative = FALSE;    }    else {	*is_negative = (num < 0);	/*	 * On a 2's complement machine, negating the most negative integer 	 * results in a number that cannot be represented as a signed integer.	 * Here is what we do to obtain the number's magnitude:	 *      a. add 1 to the number	 *      b. negate it (becomes positive)	 *      c. convert it to unsigned	 *      d. add 1	 */	if (*is_negative) {	    widest_int t = num + 1;	    magnitude = ((u_widest_int) -t) + 1;	}	else	    magnitude = (u_widest_int) num;    }    /*     * We use a do-while loop so that we write at least 1 digit      */    do {	u_widest_int new_magnitude = magnitude / 10;	*--p = (char) (magnitude - new_magnitude * 10 + '0');	magnitude = new_magnitude;    }    while (magnitude);    *len = buf_end - p;    return (p);}static char *conv_in_addr(struct in_addr *ia, char *buf_end, int *len){    unsigned addr = ntohl(ia->s_addr);    char *p = buf_end;    bool_int is_negative;    int sub_len;    p = conv_10((addr & 0x000000FF)      , TRUE, &is_negative, p, &sub_len);    *--p = '.';    p = conv_10((addr & 0x0000FF00) >>  8, TRUE, &is_negative, p, &sub_len);    *--p = '.';    p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len);    *--p = '.';    p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len);    *len = buf_end - p;    return (p);}static char *conv_apr_sockaddr(apr_sockaddr_t *sa, char *buf_end, int *len){    char *p = buf_end;    bool_int is_negative;    int sub_len;    char *ipaddr_str;    /* XXX IPv6: this assumes sin_port and sin6_port are at same offset */    p = conv_10(ntohs(sa->sa.sin.sin_port), TRUE, &is_negative, p, &sub_len);    *--p = ':';    apr_sockaddr_ip_get(&ipaddr_str, sa);    sub_len = strlen(ipaddr_str);#if APR_HAVE_IPV6    if (sa->sa.sin.sin_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);}/* * 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, bool_int *is_negative,    char *buf, int *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(strcpy(buf, p));	*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 */	int t_len;	bool_int exponent_is_negative;	*s++ = format;		/* either e or E */	decimal_point--;	if (decimal_point != 0) {	    p = conv_10((wide_int) 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';	}

⌨️ 快捷键说明

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