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

📄 xsnprintf.c

📁 性能优秀的SIP Proxy
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ==================================================================== * $Id: xsnprintf.c,v 1.2 2005/07/01 14:52:33 bogdan_iancu Exp $ * * Copyright (c) 1995-1998 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 "xode.h"#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)#include <stdio.h>#include <ctype.h>#include <sys/types.h>#include <stdarg.h>#include <string.h>#include <stdlib.h>#include <math.h>#ifdef HAVE_GCVT#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;    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 ( isdigit((int)*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 = 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 (isalpha((int)*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 ? '-' : '+';

⌨️ 快捷键说明

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