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

📄 apr_snprintf.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as * applicable. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include "apr.h"#include "apr_private.h"#include "apr_lib.h"#include "apr_strings.h"#include "apr_network_io.h"#include "apr_portable.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 * * NOTICE: 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 (p1 > &buf[0] && 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;    if (p1 < &buf[0]) {        *decpt = -ndigits;        buf[0] = '\0';        return (buf);    }    *decpt = r2;    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) {                                       \        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. We don't allow precision to be large * enough that we continue past the start of s. * * NOTE: this makes use of the magic info that s is * always based on num_buf with a size of NUM_BUF_SIZE. */#define FIX_PRECISION(adjust, precision, s, s_len)  \    if (adjust) {                                   \        int p = precision < NUM_BUF_SIZE - 1 ? precision : NUM_BUF_SIZE - 1; \        while (s_len < p)                           \        {                                           \            *--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 && num >= LONG_MIN && !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);

⌨️ 快捷键说明

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