VirtualBox

Ignore:
Timestamp:
Sep 9, 2018 1:17:21 PM (6 years ago)
Author:
vboxsync
Message:

IPRT/strformat: Fixed bug formatting INT64_MAX. Cleaned up the integer formatting code to get rid of anachronisms (VAC308).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/string/strformat.cpp

    r69111 r74157  
    2727
    2828/*********************************************************************************************************************************
    29 *   Defined Constants                                                                                                            *
    30 *********************************************************************************************************************************/
    31 #define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
    32 /*#define MAX(a, b)  ((a) >= (b) ? (a) : (b))
    33 #define MIN(a, b)  ((a) < (b) ? (a) : (b)) */
    34 
    35 
    36 /*********************************************************************************************************************************
    3729*   Header Files                                                                                                                 *
    3830*********************************************************************************************************************************/
     
    4739# include <iprt/uni.h>
    4840#endif
     41#include <iprt/ctype.h>
    4942#include <iprt/string.h>
    5043#include <iprt/stdarg.h>
    5144#include "internal/string.h"
    5245
    53 /* Wrappers for converting to iprt facilities. */
    54 #define SSToDS(ptr)     ptr
    55 #define kASSERT         Assert
    56 #define KENDIAN_LITTLE  1
    57 #define KENDIAN         KENDIAN_LITTLE
    58 #define KSIZE           size_t
    59 typedef struct
    60 {
    61     uint32_t    ulLo;
    62     uint32_t    ulHi;
    63 } KSIZE64;
    64 
    65 
    66 /*********************************************************************************************************************************
    67 *   Internal Functions                                                                                                           *
    68 *********************************************************************************************************************************/
    69 static unsigned _strnlen(const char *psz, unsigned cchMax);
    70 static unsigned _strnlenUtf16(PCRTUTF16 pwsz, unsigned cchMax);
    71 static int rtStrFormatNumber(char *psz, KSIZE64 ullValue, unsigned int uiBase, signed int cchWidth, signed int cchPrecision, unsigned int fFlags);
    7246
    7347
     
    140114 * Formats an integer number according to the parameters.
    141115 *
    142  * @returns   Length of the formatted number.
    143  * @param     psz            Pointer to output string buffer of sufficient size.
    144  * @param     u64Value       Value to format.
     116 * @returns   Length of the number.
     117 * @param     psz            Pointer to output string.
     118 * @param     u64Value       Value.
    145119 * @param     uiBase         Number representation base.
    146  * @param     cchWidth       Width.
     120 * @param     cchWidth       Width
    147121 * @param     cchPrecision   Precision.
    148122 * @param     fFlags         Flags (NTFS_*).
     
    151125                              unsigned int fFlags)
    152126{
    153     return rtStrFormatNumber(psz, *(KSIZE64 *)(void *)&u64Value, uiBase, cchWidth, cchPrecision, fFlags);
    154 }
    155 RT_EXPORT_SYMBOL(RTStrFormatNumber);
    156 
    157 
    158 
    159 /**
    160  * Formats an integer number according to the parameters.
    161  *
    162  * @returns   Length of the number.
    163  * @param     psz            Pointer to output string.
    164  * @param     ullValue       Value. Using the high part is optional.
    165  * @param     uiBase         Number representation base.
    166  * @param     cchWidth       Width
    167  * @param     cchPrecision   Precision.
    168  * @param     fFlags         Flags (NTFS_*).
    169  */
    170 static int rtStrFormatNumber(char *psz, KSIZE64 ullValue, unsigned int uiBase, signed int cchWidth, signed int cchPrecision,
    171                              unsigned int fFlags)
    172 {
    173127    const char     *pachDigits = "0123456789abcdef";
    174128    char           *pszStart = psz;
    175129    int             cchMax;
    176130    int             cchValue;
    177     unsigned long   ul;
    178131    int             i;
    179132    int             j;
     133    char            chSign;
    180134
    181135    /*
     
    193147
    194148    /*
    195      * Determine value length
     149     * Determine value length and sign.  Converts the u64Value to unsigned.
    196150     */
    197151    cchValue = 0;
    198     if (ullValue.ulHi || (fFlags & RTSTR_F_64BIT))
    199     {
    200         uint64_t    u64 = *(uint64_t *)(void *)&ullValue;
    201         if ((fFlags & RTSTR_F_VALSIGNED) && (ullValue.ulHi & 0x80000000))
    202             u64 = -(int64_t)u64;
     152    chSign = '\0';
     153    if ((fFlags & RTSTR_F_64BIT) || (u64Value & UINT64_C(0xffffffff00000000)))
     154    {
     155        uint64_t u64;
     156        if (!(fFlags & RTSTR_F_VALSIGNED) || !(u64Value & RT_BIT_64(63)))
     157            u64 = u64Value;
     158        else if (u64Value != RT_BIT_64(63))
     159        {
     160            chSign = '-';
     161            u64 = u64Value = -(int64_t)u64Value;
     162        }
     163        else
     164        {
     165            chSign = '-';
     166            u64 = u64Value = RT_BIT_64(63);
     167        }
    203168        do
    204169        {
     
    209174    else
    210175    {
    211         ul = (fFlags & RTSTR_F_VALSIGNED) && (ullValue.ulLo & 0x80000000) ? -(int32_t)ullValue.ulLo : ullValue.ulLo;
     176        uint32_t u32 = (uint32_t)u64Value;
     177        if (!(fFlags & RTSTR_F_VALSIGNED) || !(u32 & UINT32_C(0x80000000)))
     178        { /* likley */ }
     179        else if (u32 != UINT32_C(0x80000000))
     180        {
     181            chSign = '-';
     182            u64Value = u32 = -(int32_t)u32;
     183        }
     184        else
     185        {
     186            chSign = '-';
     187            u64Value = u32 = UINT32_C(0x80000000);
     188        }
    212189        do
    213190        {
    214191            cchValue++;
    215             ul /= uiBase;
    216         } while (ul);
     192            u32 /= uiBase;
     193        } while (u32);
    217194    }
    218195    if (fFlags & RTSTR_F_THOUSAND_SEP)
     
    230207    if (fFlags & RTSTR_F_VALSIGNED)
    231208    {
    232         if ((ullValue.ulHi || (fFlags & RTSTR_F_64BIT) ? ullValue.ulHi : ullValue.ulLo) & 0x80000000)
    233         {
    234             ullValue.ulLo = -(int32_t)ullValue.ulLo;
    235             if (ullValue.ulHi)
    236                 ullValue.ulHi = ~ullValue.ulHi;
    237             psz[i++] = '-';
    238         }
     209        if (chSign != '\0')
     210            psz[i++] = chSign;
    239211        else if (fFlags & (RTSTR_F_PLUS | RTSTR_F_BLANK))
    240212            psz[i++] = (char)(fFlags & RTSTR_F_PLUS ? '+' : ' ');
     
    289261    psz += cchValue;
    290262    i = -1;
    291     if (ullValue.ulHi || (fFlags & RTSTR_F_64BIT))
    292     {
    293         uint64_t    u64 = *(uint64_t *)(void *)&ullValue;
     263    if ((fFlags & RTSTR_F_64BIT) || (u64Value & UINT64_C(0xffffffff00000000)))
     264    {
     265        uint64_t u64 = u64Value;
    294266        if (fFlags & RTSTR_F_THOUSAND_SEP)
    295267        {
     
    313285    else
    314286    {
    315         ul = (fFlags & RTSTR_F_VALSIGNED) && (ullValue.ulLo & 0x80000000) ? -(int32_t)ullValue.ulLo : ullValue.ulLo;
     287        uint32_t u32 = (uint32_t)u64Value;
    316288        if (fFlags & RTSTR_F_THOUSAND_SEP)
    317289        {
     
    320292                if ((-i - 1) % 4 == 3)
    321293                    psz[i--] = ' ';
    322                 psz[i--] = pachDigits[ul % uiBase];
    323                 ul /= uiBase;
    324             } while (ul);
     294                psz[i--] = pachDigits[u32 % uiBase];
     295                u32 /= uiBase;
     296            } while (u32);
    325297        }
    326298        else
     
    328300            do
    329301            {
    330                 psz[i--] = pachDigits[ul % uiBase];
    331                 ul /= uiBase;
    332             } while (ul);
     302                psz[i--] = pachDigits[u32 % uiBase];
     303                u32 /= uiBase;
     304            } while (u32);
    333305        }
    334306    }
     
    344316    return (unsigned)(psz - pszStart);
    345317}
     318RT_EXPORT_SYMBOL(RTStrFormatNumber);
    346319
    347320
     
    366339    char        szTmp[64]; /* Worker functions assumes 64 byte buffer! Ugly but faster. */
    367340    va_list     args;
    368     KSIZE       cch = 0;
     341    size_t      cch = 0;
    369342    const char *pszStartOutput = pszFormat;
    370343
     
    408381
    409382                /* width */
    410                 if (ISDIGIT(*pszFormat))
     383                if (RT_C_IS_DIGIT(*pszFormat))
    411384                {
    412                     for (cchWidth = 0; ISDIGIT(*pszFormat); pszFormat++)
     385                    for (cchWidth = 0; RT_C_IS_DIGIT(*pszFormat); pszFormat++)
    413386                    {
    414387                        cchWidth *= 10;
     
    433406                {
    434407                    pszFormat++;
    435                     if (ISDIGIT(*pszFormat))
    436                     {
    437                         for (cchPrecision = 0; ISDIGIT(*pszFormat); pszFormat++)
     408                    if (RT_C_IS_DIGIT(*pszFormat))
     409                    {
     410                        for (cchPrecision = 0; RT_C_IS_DIGIT(*pszFormat); pszFormat++)
    438411                        {
    439412                            cchPrecision *= 10;
     
    527500                        szTmp[0] = (char)va_arg(args, int);
    528501                        szTmp[1] = '\0';                     /* Some output functions wants terminated strings. */
    529                         cch += pfnOutput(pvArgOutput, SSToDS(&szTmp[0]), 1);
     502                        cch += pfnOutput(pvArgOutput, &szTmp[0], 1);
    530503
    531504                        while (--cchWidth > 0)
     
    753726                            }
    754727                        }
    755                         cchNum = RTStrFormatNumber((char *)SSToDS(&szTmp), u64Value, uBase, cchWidth, cchPrecision, fFlags);
    756                         cch += pfnOutput(pvArgOutput, (char *)SSToDS(&szTmp), cchNum);
     728                        cchNum = RTStrFormatNumber((char *)&szTmp, u64Value, uBase, cchWidth, cchPrecision, fFlags);
     729                        cch += pfnOutput(pvArgOutput, (char *)&szTmp, cchNum);
    757730                        break;
    758731                    }
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette