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

📄 snprintf.c

📁 -
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: snprintf.c,v 1.16.6.1 1999/02/12 19:38:15 wessels Exp $ *//* ==================================================================== * Copyright (c) 1995-1997 The Apache Group.  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. All advertising materials mentioning features or use of this *    software must display the following acknowledgment: *    "This product includes software developed by the Apache Group *    for use in the Apache HTTP server project (http://www.apache.org/)." * * 4. The names "Apache Server" and "Apache Group" must not be used to *    endorse or promote products derived from this software without *    prior written permission. * * 5. Redistributions of any form whatsoever must retain the following *    acknowledgment: *    "This product includes software developed by the Apache Group *    for use in the Apache HTTP server project (http://www.apache.org/)." * * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``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 GROUP 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 Group and was originally based * on public domain software written at the National Center for * Supercomputing Applications, University of Illinois, Urbana-Champaign. * For more information on the Apache Group and the Apache HTTP server * project, please see <http://www.apache.org/>. * * This code is 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 "config.h"#if !HAVE_SNPRINTF || !HAVE_VSNPRINTF#include <stdio.h>#include <ctype.h>#include <sys/types.h>#include <stdarg.h>#include <string.h>#include <stdlib.h>#include <math.h>#include <assert.h>#ifdef HAVE_CVT#define ap_ecvt ecvt#define ap_fcvt fcvt#define ap_gcvt gcvt#else/* * cvt.c - IEEE floating point formatting routines for FreeBSD * from GNU libc-4.6.27 *//* *    ap_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	80static char *ap_cvt(double arg, int ndigits, int *decpt, int *sign, int eflag){    register int r2;    double fi, fj;    register char *p, *p1;    static char buf[NDIG];    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 *ap_ecvt(double arg, int ndigits, int *decpt, int *sign){    return (ap_cvt(arg, ndigits, decpt, sign, 1));}static char *ap_fcvt(double arg, int ndigits, int *decpt, int *sign){    return (ap_cvt(arg, ndigits, decpt, sign, 0));}/* * ap_gcvt  - Floating output conversion to * minimal length string */static char *ap_gcvt(double number, int ndigit, char *buf){    int sign, decpt;    register char *p1, *p2;    register int i;    p1 = ap_ecvt(number, ndigit, &decpt, &sign);    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] == '.')	p2--;    *p2 = '\0';    return (buf);}#endif /* HAVE_CVT */typedef enum {    NO = 0, YES = 1} boolean_e;#define FALSE			0#define TRUE			1#define NUL			'\0'#define INT_NULL		((int *)0)#define WIDE_INT		longtypedef WIDE_INT wide_int;typedef unsigned WIDE_INT u_wide_int;typedef 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/* * Descriptor for buffer area */struct buf_area {    char *buf_end;    char *nextb;		/* pointer to next byte to read/write   */};typedef struct buf_area buffy;/* * 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 )		\		{			\		    *sp++ = c ;		\		    cc++ ;		\		}			\	    }#define NUM( c )			( c - '0' )#define STR_TO_DEC( str, num )		\    num = NUM( *str++ ) ;		\    while ( xisdigit( *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 ]) */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);}/* * 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;    if (format == 'f')	p = ap_fcvt(num, precision, &decimal_point, is_negative);    else			/* either e or E format */	p = ap_ecvt(num, precision + 1, &decimal_point, is_negative);    /*     * Check for Infinity and NaN     */    if (xisalpha(*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++;

⌨️ 快捷键说明

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