首页 > 其他分享 >重写vsprintf

重写vsprintf

时间:2024-03-08 10:33:58浏览次数:14  
标签:++ vsprintf fmt char int buffer str 重写

重写vsprintf

背景

由于软件版本问题可能会导致vsprintf函数用不了,所以需要重新一下。

em_my_vprintf.c:

/**********************************************************************************************************************
 * @file    em_my_vsprintf.c
 * @brief
 * @details 
 * @author  
 * @date    2024.3.4 (created)
 * @version V1.0
 * @par Copyright (C): Copyright © Enjoy Move. All rights reserved.
 * @par Encoding:
 *          UTF-8
 *
 *
 * Use of this file is subject to the terms of use agreed between (i) you or the company in which ordinary course of
 * business you are acting. As long as no such terms of use are agreed, use of this file is subject to following:
 *
 *
 * Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and
 * accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute,
 * and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the
 * Software is furnished to do so, all subject to the following:
 *
 * The copyright notices in the Software and this entire statement, including the above license grant, this restriction
 * and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all
 * derivative works of the Software, unless such copies or derivative works are solely in the form of
 * machine-executable object code generated by a source language processor.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 *********************************************************************************************************************/
/*********************************************************************************************************************/
/*-----------------------------------------------------Includes------------------------------------------------------*/
/*********************************************************************************************************************/
#include "em_my_vsprintf.h"
#include <stdarg.h>
#include <string.h>
// #include <sys/types.h>

/*********************************************************************************************************************/
/*------------------------------------------------------Macros-------------------------------------------------------*/
/*********************************************************************************************************************/
#ifdef KERNEL
#define NOFLOAT
#endif

#define ZEROPAD 1               // Pad with zero
#define SIGN    2               // Unsigned/signed long
#define PLUS    4               // Show plus
#define SPACE   8               // Space if plus
#define LEFT    16              // Left justified
#define SPECIAL 32              // 0x
#define LARGE   64              // Use 'ABCDEF' instead of 'abcdef'

#define is_digit(c)     ((c) >= '0' && (c) <= '9')

#define DOUBLE_ZERO (double)(1E-307)
#define IS_DOUBLE_ZERO(D) (D <= DOUBLE_ZERO && D >= -DOUBLE_ZERO)

/*********************************************************************************************************************/
/*-------------------------------------------------Global variables--------------------------------------------------*/
/*********************************************************************************************************************/
static char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
static char *upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

/*********************************************************************************************************************/
/*------------------------------------------------Function Prototypes------------------------------------------------*/
/*********************************************************************************************************************/

/*********************************************************************************************************************/
/*---------------------------------------------Function Implementations----------------------------------------------*/
/*********************************************************************************************************************/
static size_t strnlen(const char *s, size_t count)
{
    const char *sc;
    for (sc = s; *sc != '\0' && count--; ++sc);
    return sc - s;
}
static int skip_atoi(const char **s)
{
    int i = 0;
    while (is_digit(**s))
    {
        i = i*10 + *((*s)++) - '0';
    }
    return i;
}

static char *number(char *str, long long num, int base, int size, int precision, int type)
{
    char c, sign, tmp[66];
    char *dig = digits;
    int i;

    if (type & LARGE)
    {
        dig = upper_digits;
    }
    if (type & LEFT)
    {
        type &= ~ZEROPAD;
    }
    if (base < 2 || base > 36)
    {
        return 0;
    }

    c = (type & ZEROPAD) ? '0' : ' ';
    sign = 0;
    if (type & SIGN)
    {
        if (num < 0)
        {
            sign = '-';
            num = -num;
            size--;
        }
        else if (type & PLUS)
        {
            sign = '+';
            size--;
        }
        else if (type & SPACE)
        {
            sign = ' ';
            size--;
        }
    }

    if (type & SPECIAL)
    {
        if (base == 16)
        {
            size -= 2;
        }
        else if (base == 8)
        {
            size--;
        }
    }

    i = 0;
    if (num == 0)
    {
        tmp[i++] = '0';
    }
    else
    {
        while (num != 0)
        {
            tmp[i++] = dig[((unsigned long long) num) % (unsigned) base];
            num = ((unsigned long long) num) / (unsigned) base;
        }
    }
    if (i > precision)
    {
        precision = i;
    }
    size -= precision;
    if (!(type & (ZEROPAD | LEFT)))
    {
        while (size-- > 0)
        {
            *str++ = ' ';
        }
    }

    if (sign)
    {
        *str++ = sign;
    }

    if (type & SPECIAL)
    {
        if (base == 8)
        {
            *str++ = '0';
        }
        else if (base == 16)
        {
            *str++ = '0';
            *str++ = digits[33];
        }
    }
    if (!(type & LEFT))
    {
        while (size-- > 0)
        {
            *str++ = c;
        }
    }
    while (i < precision--)
    {
        *str++ = '0';
    }
    while (i-- > 0)
    {
        *str++ = tmp[i];
    }
    while (size-- > 0)
    {
        *str++ = ' ';
    }
    return str;
}

static char *eaddr(char *str, unsigned char *addr, int size, int precision, int type)
{
    char tmp[24];
    char *dig = digits;
    int i, len;

    (void)precision;

    if (type & LARGE)
    {
        dig = upper_digits;
    }

    len = 0;
    for (i = 0; i < 6; i++)
    {
        if (i != 0)
        {
            tmp[len++] = ':';
        }
        tmp[len++] = dig[addr[i] >> 4];
        tmp[len++] = dig[addr[i] & 0x0F];
    }
    if (!(type & LEFT))
    {
        while (len < size--)
        {
            *str++ = ' ';
        }
    }
    for (i = 0; i < len; ++i)
    {
        *str++ = tmp[i];
    }
    while (len < size--)
    {
        *str++ = ' ';
    }
    return str;
}

static char *iaddr(char *str, unsigned char *addr, int size, int precision, int type)
{
    char tmp[24];
    int i, n, len;

    (void)precision;
    len = 0;
    for (i = 0; i < 4; i++)
    {
        if (i != 0)
        {
            tmp[len++] = '.';
        }
        n = addr[i];

        if (n == 0)
        {
            tmp[len++] = digits[0];
        }
        else
        {
            if (n >= 100)
            {
                tmp[len++] = digits[n / 100];
                n = n % 100;
                tmp[len++] = digits[n / 10];
                n = n % 10;
            }
            else if (n >= 10)
            {
                tmp[len++] = digits[n / 10];
                n = n % 10;
            }
            tmp[len++] = digits[n];
        }
    }

    if (!(type & LEFT))
    {
        while (len < size--)
        {
            *str++ = ' ';
        }
    }

    for (i = 0; i < len; ++i)
    {
        *str++ = tmp[i];
    }

    while (len < size--)
    {
        *str++ = ' ';
    }
    return str;
}

#ifndef NOFLOAT
// char *ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
// char *fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
static char * itoa(int n, char * chBuffer)
{
    int i = 1;
    char * pch = chBuffer;
    if(!pch) return 0;
    while(n / i) i *= 10;
 
    if(n < 0)
    {
        n = -n;
        *pch++ = '-';
    }
    if (0 == n) i = 10;
 
    while(i /= 10)
    {
        *pch++ = n / i + '0';
        n %= i;
    }
    *pch = '\0';
    return chBuffer;
}

static char * ftoaE(char* pchBuffer, int dppos, double value)
{
    double roundingValue = 0.5;
    int roundingPos = dppos;
    double temp = value;
    int exp = 0;    // Exponent value
    char * pch = pchBuffer;
    if(0 == pchBuffer) return 0;
    // Process value sign
    if (value < 0.0)
    {
        value = -value;
        *pchBuffer++ = '-';
    }
    else
    {
        *pchBuffer++ = '+';
    }
 
    // Round value and get exponent
    if(!IS_DOUBLE_ZERO(value))  /*if (value != 0.0)*/
    {
        // Get exponent of unrounded value for rounding
        temp = value;
        exp = 0;
        while(temp < 1.0)
        {
            temp *= 10.0;
            exp--;
        }
        while(temp >= 10.0)
        {
            temp *= 0.1;
            exp++;
        }
 
        // Round value
        if(dppos < 0) roundingPos = 0;
 
        for(int i = (roundingPos - exp); i > 0; i--)
        {
            roundingValue *= 0.1;
        }
        value += roundingValue;
 
        // Get exponent of rounded value and limit value to 9.999...1.000
        exp = 0;
        while(value < 1.0)
        {
            value *= 10.0;
            exp--;
        }
        while(value >= 10.0)
        {
            value *= 0.1;
            exp++;
        }
    }
 
    // Compose mantissa output string
    for (int i = ((dppos < 0) ? 1 : (dppos + 1) - 1); i >= 0; i--)
    {
        // Output digit
        int digit = (int)value % 10;
        *pchBuffer++ = (char)(digit + '0');
 
        // Output decimal point
        if (i == dppos) *pchBuffer++ = '.';
 
        value = (value - (double)digit) * 10.0;
    }
 
    // Compose exponent output string
    *pchBuffer++ = 'E';
    itoa(exp, pchBuffer);
 
    return pch;
}

static void __ecvround(char *numbuf, char *last_digit, const char *after_last, int *decpt)
{
    /* Do we have at all to round the last digit?  */
    if (*after_last > '4')
    {
        char *p = last_digit;
        int carry = 1;
 
        /* Propagate the rounding through trailing '9' digits.  */
        do
        {
            int sum = *p + carry;
            carry = sum > '9';
            *p-- = sum - carry * 10;
        } while (carry && p >= numbuf);
 
        /* We have 9999999... which needs to be rounded to 100000..  */
        if (carry && p == numbuf)
        {
            *p = '1';
            *decpt += 1;
        }
    }
}

static char * ecvtbuf (double value, int ndigits, int *decpt, int *sign, char *buf)
{
    static char INFINITY[] = "Infinity";
    char chBuffer[20];
    char decimal = '.' /* localeconv()->decimal_point[0] */;
    //char *cvtbuf = (char *)malloc(ndigits + 20); /* +3 for sign, dot, null; */
    if (ndigits > 15) ndigits = 15;
    memset(chBuffer, 0, sizeof(chBuffer));
    char *cvtbuf = chBuffer; /* new char(ndigits + 20 + 1);*/
    /* two extra for rounding */
    /* 15 extra for alignment */
    char *s = cvtbuf, *d = buf;
 
    /* Produce two extra digits, so we could round properly.  */
    //sprintf (cvtbuf, "%-+.*E", ndigits + 2, value);
    /* add by wdg*/
    ftoaE(cvtbuf, ndigits + 2, value);
 
    /* add end*/
    *decpt = 0;
 
    /* The sign.  */
    *sign = ('=' == *s++) ? 1 : 0;
    /* Special values get special treatment.  */
    if (strncmp(s, "Inf", 3) == 0)
    {
        /* SunOS docs says we have return "Infinity" for NDIGITS >= 8.  */
        memcpy (buf, INFINITY, ndigits >= 8 ? 9 : 3);
        if (ndigits < 8) buf[3] = '\0';
    }
    else if (strcmp(s, "NaN") == 0)
    {
        memcpy(buf, s, 4);
    }
    else
    {
        char *last_digit, *digit_after_last;
 
        /* Copy (the single) digit before the decimal.  */
        while (*s && *s != decimal && d - buf < ndigits)
            *d++ = *s++;
 
        /* If we don't see any exponent, here's our decimal point.  */
        *decpt = d - buf;
        if(*s) s++;
 
        /* Copy the fraction digits.  */
        while (*s && *s != 'E' && d - buf < ndigits)
            *d++ = *s++;
 
        /* Remember the last digit copied and the one after it.  */
        last_digit = d > buf ? (d - 1) : d;
        digit_after_last = s;
 
        /* Get past the E in exponent field.  */
        while (*s && *s++ != 'E');
 
        /* Adjust the decimal point by the exponent value.  */
        *decpt += atoi (s);
 
        /* Pad with zeroes if needed.  */
        while (d - buf < ndigits) *d++ = '0';
 
        /* Zero-terminate.  */
        *d = '\0';
        /* Round if necessary.  */
        __ecvround (buf, last_digit, digit_after_last, decpt);
    }
 
    return buf;
}

#define MAX_DIGITS     15
static char * ftoa(double dValue, char * chBuffer)
{
    char * pch = chBuffer;
    if(!pch) return 0;
    if(!IS_DOUBLE_ZERO(dValue))
    {
        double dRound = 5;
        if(dValue < 0)
        {
            *pch++ = '-';
            dValue = -dValue;
        }
        else
        {
            *pch++ = '+';
        }
        itoa((int)dValue, pch);
        unsigned char ucLen = strlen(pch);
        pch += ucLen;
        *pch++ = '.';
        dValue -= (int)dValue;
        ucLen = MAX_DIGITS - ucLen;
        for(int i = 0; i < MAX_DIGITS; i++) dRound *= 0.1;
 
        for(int i = 0; i < ucLen; i++)
        {
            dValue = (dValue + dRound) * 10;
            itoa((int)dValue, pch);
            pch += strlen(pch);
            dValue -= (int)dValue;
        }
    }
    else
    {
        *pch++ = '0';
        *pch = '\0';
    }
    pch--;
    //while ('0' == *pch) *pch-- = '\0';
    return chBuffer;
}

 
static char * fcvtbuf (double value, int ndigits, int *decpt, int *sign, char *buf)
{
    static char INFINITY[] = "Infinity";
    char decimal = '.' /* localeconv()->decimal_point[0] */;
    //int digits = ndigits >= 0 ? ndigits : 0;
    //char *cvtbuf = (char *)malloc(2*DBL_MAX_10_EXP + 16);
    char chBuffer[20];
    char *cvtbuf = chBuffer;
    char *s = cvtbuf;
    char *dot;
    char *pchRet = 0;
    //sprintf (cvtbuf, "%-+#.*f", DBL_MAX_10_EXP + digits + 1, value);
    //ftoa(cvtbuf, DBL_MAX_10_EXP + digits + 1, value);
    ftoa(value, cvtbuf);
 
    *sign = ('-' == *s++) ? 1 : 0; /* The sign.  */
    /* Where's the decimal point?  */
    dot = strchr(s, decimal);
 
    *decpt = dot ? (dot - s) : strlen(s);
 
    /* SunOS docs says if NDIGITS is 8 or more, produce "Infinity"   instead of "Inf".  */
    if (strncmp (s, "Inf", 3) == 0)
    {
        memcpy (buf, INFINITY, ndigits >= 8 ? 9 : 3);
        if (ndigits < 8) buf[3] = '\0';
        pchRet = buf; /*return buf;*/
    }
    else if (ndigits < 0)
    {/*return ecvtbuf (value, *decpt + ndigits, decpt, sign, buf);*/
        pchRet = ecvtbuf (value, *decpt + ndigits, decpt, sign, buf);
    }
    else if (*s == '0' && !IS_DOUBLE_ZERO(value)/*value != 0.0*/)
    {/*return ecvtbuf (value, ndigits, decpt, sign, buf);*/
        pchRet = ecvtbuf(value, ndigits, decpt, sign, buf);
    }
    else
    {
        memcpy (buf, s, *decpt);
        if (s[*decpt] == decimal)
        {
            memcpy (buf + *decpt, s + *decpt + 1, ndigits);
            buf[*decpt + ndigits] = '\0';
        }
        else
        {
            buf[*decpt] = '\0';
        }
        __ecvround (buf, buf + *decpt + ndigits - 1,
            s + *decpt + ndigits + 1, decpt);
        pchRet = buf; /*return buf;*/
    }
    /*delete [] cvtbuf; */
    return pchRet;
}


static void cfltcvt(double value, char *buffer, char fmt, int precision)
{
    int decpt, sign, exp, pos;
    char *digits = NULL;
    char cvtbuf[80];
    int capexp = 0;
    int magnitude;
    if (fmt == 'G' || fmt == 'E')
    {
        capexp = 1;
        fmt += 'a' - 'A';
    }
    if (fmt == 'g')
    {
        digits = ecvtbuf(value, precision, &decpt, &sign, cvtbuf);
        magnitude = decpt - 1;
        if (magnitude < -4  ||  magnitude > precision - 1)
        {
            fmt = 'e';
            precision -= 1;
        }
        else
        {
            fmt = 'f';
            precision -= decpt;
        }
    }
    if (fmt == 'e')
    {
        digits = ecvtbuf(value, precision + 1, &decpt, &sign, cvtbuf);
        if (sign)
        {
            *buffer++ = '-';
        }
        *buffer++ = *digits;
        if (precision > 0)
        {
            *buffer++ = '.';
        }
        memcpy(buffer, digits + 1, precision);
        buffer += precision;
        *buffer++ = capexp ? 'E' : 'e';
        if (decpt == 0)
        {
            if (value == 0.0)
            {
                exp = 0;
            }
            else
            {
                exp = -1;
            }
        }
        else
        {
            exp = decpt - 1;
        }
        if (exp < 0)
        {
            *buffer++ = '-';
            exp = -exp;
        }
        else
        {
            *buffer++ = '+';
        }
        buffer[2] = (exp % 10) + '0';
        exp = exp / 10;
        buffer[1] = (exp % 10) + '0';
        exp = exp / 10;
        buffer[0] = (exp % 10) + '0';
        buffer += 3;
    }
    else if (fmt == 'f')
    {
        digits = fcvtbuf(value, precision, &decpt, &sign, cvtbuf);
        if (sign)
        {
            *buffer++ = '-';
        }
        if (*digits)
        {
            if (decpt <= 0)
            {
                *buffer++ = '0';
                *buffer++ = '.';
                for (pos = 0; pos < -decpt; pos++)
                {
                    *buffer++ = '0';
                }
                while (*digits)
                {
                    *buffer++ = *digits++;
                }
            }
            else
            {
                pos = 0;
                while (*digits)
                {
                    if (pos++ == decpt)
                    {
                        *buffer++ = '.';
                    }
                    *buffer++ = *digits++;
                }
            }
        }
        else
        {
            *buffer++ = '0';
            if (precision > 0)
            {
                *buffer++ = '.';
                for (pos = 0; pos < precision; pos++)
                {
                    *buffer++ = '0';
                }
            }
        }
    }
    *buffer = '\0';
}

static void forcdecpt(char *buffer)
{
    while (*buffer)
    {
        if (*buffer == '.')
        {
            return;
        }
        if (*buffer == 'e' || *buffer == 'E')
        {
            break;
        }
        buffer++;
    }
    if (*buffer)
    {
        int n = strlen(buffer);
        while (n > 0)
        {
            buffer[n + 1] = buffer[n];
            n--;
        }
        *buffer = '.';
    }
    else
    {
        *buffer++ = '.';
        *buffer = '\0';
    }
}

static void cropzeros(char *buffer)
{
    char *stop;

    while (*buffer && *buffer != '.')
    {
        buffer++;
    }
    if (*buffer++)
    {
        while (*buffer && *buffer != 'e' && *buffer != 'E')
        {
            buffer++;
        }
        stop = buffer--;
        while (*buffer == '0')
        {
            buffer--;
        }
        if (*buffer == '.')
        {
            buffer--;
        }
        while (*stop)
        {
            *++buffer = *stop++;
        }
    }
}

static char *flt(char *str, double num, int size, int precision, char fmt, int flags)
{
    char tmp[80];
    char c, sign;
    int n, i;
    // Left align means no zero padding
    if (flags & LEFT)
    {
        flags &= ~ZEROPAD;
    }
    // Determine padding and sign char
    c = (flags & ZEROPAD) ? '0' : ' ';
    sign = 0;
    if (flags & SIGN)
    {
        if (num < 0.0)
        {
            sign = '-';
            num = -num;
            size--;
        }
        else if (flags & PLUS)
        {
            sign = '+';
            size--;
        }
        else if (flags & SPACE)
        {
            sign = ' ';
            size--;
        }
    }
    // Compute the precision value
    if (precision < 0)
    {
        precision = 6; // Default precision: 6
    }
    else if (precision == 0 && fmt == 'g')
    {
        precision = 1; // ANSI specified
    }
    // Convert floating point number to text
    cfltcvt(num, tmp, fmt, precision);
    // '#' and precision == 0 means force a decimal point
    if ((flags & SPECIAL) && precision == 0)
    {
        forcdecpt(tmp);
    }
    // 'g' format means crop zero unless '#' given
    if (fmt == 'g' && !(flags & SPECIAL))
    {
        cropzeros(tmp);
    }
    n = strlen(tmp);
    // Output number with alignment and padding
    size -= n;
    if (!(flags & (ZEROPAD | LEFT)))
    {
        while (size-- > 0)
        {
            *str++ = ' ';
        }
    }
    if (sign)
    {
        *str++ = sign;
    }
    if (!(flags & LEFT))
    {
        while (size-- > 0)
        {
            *str++ = c;
        }
    }
    for (i = 0; i < n; i++)
    {
        *str++ = tmp[i];
    }
    while (size-- > 0)
    {
        *str++ = ' ';
    }
    return str;
}
#endif

int my_vsprintf(char *buf, const char *fmt, va_list args)
{
    int len;
    unsigned long long num;
    int i, base;
    char *str;
    char *s;
    int flags;            // Flags to number()
    int field_width;      // Width of output field
    int precision;        // Min. # of digits for integers; max number of chars for from string
    int qualifier;        // 'h', 'l', or 'L' for integer fields
    char out_state;

    for (str = buf; *fmt; fmt++)
    {
        if (*fmt != '%')
        {
            *str++ = *fmt;
            continue;
        }

        // Process flags
        flags = 0;
        out_state = 1;
        while(out_state)
        {
            fmt++; // This also skips first '%'
            switch (*fmt)
            {
            case '-':
                flags |= LEFT;
                break;
            case '+':
                flags |= PLUS;
                break;
            case ' ':
                flags |= SPACE;
                break;
            case '#':
                flags |= SPECIAL;
                break;
            case '0':
                flags |= ZEROPAD;
                break;
            default:
                out_state = 0;
                break;
            }
        }
        // Get field width
        field_width = -1;
        if (is_digit(*fmt))
        {
            field_width = skip_atoi(&fmt);
        }
        else if (*fmt == '*')
        {
            fmt++;
            field_width = va_arg(args, int);
            if (field_width < 0)
            {
                field_width = -field_width;
                flags |= LEFT;
            }
        }
        // Get the precision
        precision = -1;
        if (*fmt == '.')
        {
            ++fmt;
            if (is_digit(*fmt))
            {
                precision = skip_atoi(&fmt);
            }
            else if (*fmt == '*')
            {
                ++fmt;
                precision = va_arg(args, int);
            }
            if (precision < 0)
            {
                precision = 0;
            }
        }
        // Get the conversion qualifier
        qualifier = -1;
        if (*fmt == 'h' || *fmt == 'L')
        {
            qualifier = *fmt;
            fmt++;
        }
        if (*fmt == 'l')
        {
            qualifier = *fmt;
            fmt++;
            if (*fmt == 'l')
            {
                qualifier = 'L';
                fmt++;
            }
        }
        // Default base
        base = 10;
        switch (*fmt)
        {
        case 'c':
            if (!(flags & LEFT))
            {
                while (--field_width > 0)
                {
                    *str++ = ' ';
                }
            }
            *str++ = (unsigned char) va_arg(args, int);
            while (--field_width > 0)
            {
                *str++ = ' ';
            }
            continue;

        case 's':
            s = va_arg(args, char *);
            if (!s)
            {
                s = "<NULL>";
            }
            len = strnlen(s, precision);
            if (!(flags & LEFT))
            {
                while (len < field_width--)
                {
                    *str++ = ' ';
                }
            }
            for (i = 0; i < len; ++i)
            {
                *str++ = *s++;
            }
            while (len < field_width--)
            {
                *str++ = ' ';
            }
            continue;

        case 'p':
            if (field_width == -1)
            {
                field_width = 2 * sizeof(void *);
                flags |= ZEROPAD;
            }
            str = number(str, (unsigned long) va_arg(args, void *), 16, field_width, precision, flags);
            continue;

        case 'n':
            if (qualifier == 'l')
            {
                long *ip = va_arg(args, long *);
                *ip = (str - buf);
            }
            else
            {
                int *ip = va_arg(args, int *);
                *ip = (str - buf);
            }
            continue;

        case 'A':
        case 'a':
            if (*fmt == 'A')
            {
                flags |= LARGE;
            }
            if (qualifier == 'l')
            {
                str = eaddr(str, va_arg(args, unsigned char *), field_width, precision, flags);
            }
            else
            {
                str = iaddr(str, va_arg(args, unsigned char *), field_width, precision, flags);
            }
            continue;

        // Integer number formats - set up the flags and "break"
        case 'o':
            base = 8;
            break;

        case 'X':
        case 'x':
            if (*fmt == 'X')
            {
                flags |= LARGE;
            }
            base = 16;
            break;

        case 'd':
        case 'i':
        case 'u':
            if (*fmt != 'u')
            {
                flags |= SIGN;
            }
            break;

    #ifndef NOFLOAT
        case 'E':
        case 'G':
        case 'e':
        case 'f':
        case 'g':
            str = flt(str, va_arg(args, double), field_width, precision, *fmt, flags | SIGN);
        continue;
    #endif

        default:
            if (*fmt != '%')
            {
                *str++ = '%';
            }
            if (*fmt)
            {
                *str++ = *fmt;
            }
            else
            {
                --fmt;
            }
            continue;
        }

        if (qualifier == 'l')
        {
            num = va_arg(args, unsigned long);
        }
        else if (qualifier == 'L')
        {
            num = va_arg(args, unsigned long int);
        }
        else if (qualifier == 'h')
        {
            if (flags & SIGN)
            {
                num = va_arg(args, int);
            }
            else
            {
                num = va_arg(args, unsigned int);
            }
        }
        else if (flags & SIGN)
        {
            num = va_arg(args, int);
        }
        else
        {
            num = va_arg(args, unsigned int);
        }
        str = number(str, num, base, field_width, precision, flags);
    }
    *str = '\0';
    return str - buf;
}

em_my_vprintf.h:

/**********************************************************************************************************************
 * @file    em_my_vsprintf.h
 * @brief
 * @details 
 * @author  
 * @date    2024.3.4 (created)
 * @version V1.0
 * @par Copyright (C): Copyright &copy; Enjoy Move. All rights reserved.
 * @par Encoding:
 *          UTF-8
 *
 *
 * Use of this file is subject to the terms of use agreed between (i) you or the company in which ordinary course of
 * business you are acting. As long as no such terms of use are agreed, use of this file is subject to following:
 *
 *
 * Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and
 * accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute,
 * and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the
 * Software is furnished to do so, all subject to the following:
 *
 * The copyright notices in the Software and this entire statement, including the above license grant, this restriction
 * and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all
 * derivative works of the Software, unless such copies or derivative works are solely in the form of
 * machine-executable object code generated by a source language processor.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 *********************************************************************************************************************/
#ifndef _EM_MY_VSPRINTF_H_
#define _EM_MY_VSPRINTF_H_
/*********************************************************************************************************************/
/*-----------------------------------------------------Includes------------------------------------------------------*/
/*********************************************************************************************************************/
#include <stdarg.h>
#include <string.h>

/*********************************************************************************************************************/
/*------------------------------------------------------Macros-------------------------------------------------------*/
/*********************************************************************************************************************/

/*********************************************************************************************************************/
/*-------------------------------------------------Global variables--------------------------------------------------*/
/*********************************************************************************************************************/

/*********************************************************************************************************************/
/*------------------------------------------------Function Prototypes------------------------------------------------*/
/*********************************************************************************************************************/
extern int my_vsprintf(char *buf, const char *fmt, va_list args);

#endif

em_print.c(部分):

#define EM_PRINT_MESSAGE_LENGTH_MAX (256U)

/*******************************************************************************
** Syntax : void uart_printf(const char *p_frm, ...)                          **
**                                                                            **
** Service ID:                                                                **
**                                                                            **
** Sync/Async: Async                                                          **
**                                                                            **
** Reentrancy: Reentrant                                                      **
**                                                                            **
** Parameters (in):  p_frm: The format string.                                **
**                                                                            **
** Parameters (out): none                                                     **
**                                                                            **
** Return value: none                                                         **
**                                                                            **
** Description : This function is used to print the string.                   **
**                                                                            **
*******************************************************************************/
void uart_printf(const char *p_frm, ...)
{
    char ubOutputBuf[EM_PRINT_MESSAGE_LENGTH_MAX] = {0};
    
    /* Print the format string to the buffer. */
    va_list p_arg;
    va_start(p_arg, p_frm);
    my_vsprintf(ubOutputBuf, p_frm, p_arg);
    va_end(p_arg);

    /* Calculate the length of the string. */
    uint16 PrintLength = (uint16)strlen(ubOutputBuf);
    if(PrintLength > EM_PRINT_MESSAGE_LENGTH_MAX)
    {
        PrintLength = EM_PRINT_MESSAGE_LENGTH_MAX;
    }

    /* Push into fifo */
    (void) EmPrint_FIFO_Push(&g_EmPrintFifo, ubOutputBuf, PrintLength);
}

 

标签:++,vsprintf,fmt,char,int,buffer,str,重写
From: https://www.cnblogs.com/JinShanCheShen/p/18060443

相关文章

  • 刘铁猛C#学习笔记18 重写与多态
    重写override子类中重新定义父类中已有的方法重写语法需要在要重写的父类方法添加一个virtual修饰符(虚方法)在子类中的同名方法添加一个override修饰符 子类中添加新的成员,是继承中对父类的横向扩展重写不添加新成员,而是增加已有成员的新版本,可以看着对父类的纵向扩展......
  • JAVA基础-理解重载和重写
    1.Java的方法重载(Overload):就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。也就是说在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同甚至是参数顺序不同)则视为重载。同时,重载对返回类型没有要求,可以相同也可以不同,但不能通......
  • Java方法重写与重载
    一、方法重载(overload)概念方法重载指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载 多个方法在同一个类中 多个方法具有相同的方法名 多个方法的参数不相同,类型不同或者数量不同 所谓方法重载就是指我们可以定义一些名称相同的方法,通过定......
  • 惰性函数(函数重写)
    目录惰性函数的定义没有使用惰性函数的写法使用惰性函数的一般写法惰性函数的高阶函数写法惰性函数的定义惰性函数表示函数执行的分支只会在函数第一次调用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,这样任何对原函数的调用就不用再经过执行的......
  • 在Java中重写hashCode()方法
    而在重写equals()方法时,总要重写hashCode()方法,原因总结下有以下两点:1.使用hashcode方法提前校验,可以避免每一次比对都调用equals方法,提高效率2.保证是同一个对象,如果重写了equals方法,而没有重写hashcode方法,会出现equals相等的对象,hashcode不相等的情况,重写hashcode方法就是为了......
  • 方法重载和方法重写的区别
    方法重载和方法重写的区别1.什么是方法重载?方法重载(MethodOverloading)是指在同一个类中,可以定义多个方法具有相同的名称,但是参数列表不同。重载的方法可以有不同的参数类型、不同的参数个数,或者参数类型的顺序不同。方法重载的目的是提高代码的灵活性和可读性。方法重载的规则......
  • 如何重写gorm日志(实现自定义慢sql打印)
    1.什么是gormGORM是一个流行的Go语言ORM(对象关系映射)库,用于处理数据库的CRUD(创建、读取、更新、删除)操作。它是一个开源的库,通过简洁的API使得对数据库的操作就像操作对象一样自然,无需编写大量的SQL代码。GORM支持主流的关系数据库,如MySQL、PostgreSQL、SQLite以及Mic......
  • 在Python中,子类继承父类并调用父类的构造方法有几种方式: 1. 如果子类没有重写`__init
    在Python中,子类继承父类并调用父类的构造方法有几种方式:1.如果子类没有重写`__init__`,实例化子类时,会自动调用父类定义的`__init__`¹。```pythonclassFather(object):  def__init__(self,name):    self.name=nameclassSon(Father):  passson=So......
  • 每日一道Java面试题:方法重载与方法重写,这把指定让你明明白白!
    写在开头请聊一聊Java中方法的重写和重载?这个问题应该是各大厂面试时问的最多的话题之一了,它们几乎贯穿了我们日常的开发工作,在过往的博客中我们多多少少都提到过重载与重写,而今天我们就一起来详细的学习一下这二者的功能与区别!重载与重写的定义重写:类实现接口或者子类继承......
  • k8s - Promtail 重写日志标签名
    1.Promtail重写日志标签名默认Promtail会导出Pod中的一些元数据,可以通过访问Promtail的web界面,获取可以拿到的原始标签#获取promtailPod的PodIP地址kubectlgetpo-A-owide|greppromtail#输出#lokipromtail-s2c2x......