VirtualBox

Ignore:
Timestamp:
Mar 15, 2022 10:34:28 PM (3 years ago)
Author:
vboxsync
Message:

IPRT/RTStrFormatR80[u2]: A little overhaul to better deal with special values and using the RTSTR_F_SPECIAL flag to show more data for these when applicable. bugref:9898

File:
1 edited

Legend:

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

    r93115 r94255  
    236236
    237237
     238/**
     239 * Helper for rtStrFormatR80Worker that copies out the resulting string.
     240 */
     241static ssize_t rtStrFormatR80CopyOutStr(char *pszBuf, size_t cbBuf, const char *pszSrc, size_t cchSrc)
     242{
     243    if (cchSrc < cbBuf)
     244    {
     245        memcpy(pszBuf, pszSrc, cchSrc);
     246        pszBuf[cchSrc] = '\0';
     247        return cchSrc;
     248    }
     249    if (cbBuf)
     250    {
     251        memcpy(pszBuf, pszSrc, cbBuf - 1);
     252        pszBuf[cbBuf - 1] = '\0';
     253    }
     254    return VERR_BUFFER_OVERFLOW;
     255}
     256
     257
     258/**
     259 * Common worker for RTStrFormatR80 and RTStrFormatR80u2.
     260 */
     261static ssize_t rtStrFormatR80Worker(char *pszBuf, size_t cbBuf, bool const fSign, bool const fInteger,
     262                                    uint64_t const uFraction, uint16_t const uExponent, uint32_t fFlags)
     263{
     264    char szTmp[160];
     265
     266    /*
     267     * Output sign first.
     268     */
     269    char *pszTmp = szTmp;
     270    if (fSign)
     271        *pszTmp++ = '-';
     272    else
     273        *pszTmp++ = '+';
     274
     275    /*
     276     * Then check for special numbers (indicated by expontent).
     277     */
     278    bool fDenormal = false;
     279    if (uExponent == 0)
     280    {
     281        /* Zero? */
     282        if (   !uFraction
     283            && !fInteger)
     284            return fSign
     285                 ? rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("+0"))
     286                 : rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("-0"));
     287        fDenormal = true;
     288    }
     289    else if (uExponent == UINT16_C(0x7fff))
     290    {
     291        if (!fInteger)
     292        {
     293            if (!uFraction)
     294                return fSign
     295                     ? rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("+PseudoInf"))
     296                     : rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("-PseudoInf"));
     297            if (!(fFlags & RTSTR_F_SPECIAL))
     298                return fSign
     299                     ? rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("+PseudoNan"))
     300                     : rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("-PseudoNan"));
     301            pszTmp = (char *)memcpy(pszTmp, RT_STR_TUPLE("PseudoNan[")) + 10;
     302        }
     303        else if (!(uFraction & RT_BIT_64(62)))
     304        {
     305            if (!(uFraction & (RT_BIT_64(62) - 1)))
     306                return fSign
     307                     ? rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("+Inf"))
     308                     : rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("-Inf"));
     309            if (!(fFlags & RTSTR_F_SPECIAL))
     310                return rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("Nan"));
     311            pszTmp = (char *)memcpy(pszTmp, RT_STR_TUPLE("Nan[")) + 4;
     312        }
     313        else
     314        {
     315            if (!(uFraction & (RT_BIT_64(62) - 1)))
     316                return fSign
     317                     ? rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("+Ind"))
     318                     : rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("-Ind"));
     319            if (!(fFlags & RTSTR_F_SPECIAL))
     320                return rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("QNan"));
     321            pszTmp = (char *)memcpy(pszTmp, RT_STR_TUPLE("QNan[")) + 4;
     322        }
     323        pszTmp += RTStrFormatNumber(pszTmp, uFraction, 16, 2 + 16, 0,
     324                                    RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
     325        *pszTmp++ = ']';
     326        return rtStrFormatR80CopyOutStr(pszBuf, cbBuf, szTmp, pszTmp - &szTmp[0]);
     327    }
     328
     329    /*
     330     * Format the mantissa and exponent.
     331     */
     332    *pszTmp++ = fInteger ? '1' : '0';
     333    *pszTmp++ = 'm';
     334    pszTmp += RTStrFormatNumber(pszTmp, uFraction, 16, 2+16, 0,
     335                                RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
     336
     337    *pszTmp++ = '^';
     338    pszTmp += RTStrFormatNumber(pszTmp, (int32_t)uExponent - 16383, 10, 0, 0,
     339                                RTSTR_F_ZEROPAD | RTSTR_F_32BIT | RTSTR_F_VALSIGNED);
     340    if (fDenormal && (fFlags & RTSTR_F_SPECIAL))
     341    {
     342        if (fInteger)
     343            pszTmp = (char *)memcpy(pszTmp, RT_STR_TUPLE("[PDn]")) + 5;
     344        else
     345            pszTmp = (char *)memcpy(pszTmp, RT_STR_TUPLE("[Den]")) + 5;
     346    }
     347    return rtStrFormatR80CopyOutStr(pszBuf, cbBuf, szTmp, pszTmp - &szTmp[0]);
     348}
     349
     350
    238351RTDECL(ssize_t) RTStrFormatR80u2(char *pszBuf, size_t cbBuf, PCRTFLOAT80U2 pr80Value, signed int cchWidth,
    239352                                 signed int cchPrecision, uint32_t fFlags)
    240353{
    241     NOREF(cchWidth); NOREF(cchPrecision); NOREF(fFlags);
    242     char szTmp[160];
    243 
    244     char *pszTmp = szTmp;
    245     if (pr80Value->s.fSign)
    246         *pszTmp++ = '-';
    247     else
    248         *pszTmp++ = '+';
    249 
    250     if (pr80Value->s.uExponent == 0)
    251     {
     354    RT_NOREF(cchWidth, cchPrecision);
    252355#ifdef RT_COMPILER_GROKS_64BIT_BITFIELDS
    253         if (   !pr80Value->sj64.u63Fraction
    254             && pr80Value->sj64.fInteger)
     356    return rtStrFormatR80Worker(pszBuf, cbBuf, pr80Value->sj64.fSign, pr80Value->sj64.fInteger,
     357                                pr80Value->sj64.u63Fraction, pr80Value->sj64.uExponent, fFlags);
    255358#else
    256         if (   !pr80Value->sj.u32FractionLow
    257             && !pr80Value->sj.u31FractionHigh
    258             && pr80Value->sj.fInteger)
     359    return rtStrFormatR80Worker(pszBuf, cbBuf, pr80Value->sj.fSign, pr80Value->sj.fInteger,
     360                                RT_MAKE_U64(pr80Value->sj.u32FractionLow, pr80Value->sj.u31FractionHigh),
     361                                pr80Value->sj.uExponent, fFlags);
    259362#endif
    260             *pszTmp++ = '0';
    261         /* else: Denormal, handled way below. */
    262     }
    263 #ifdef RT_COMPILER_GROKS_64BIT_BITFIELDS
    264     else if (pr80Value->sj64.uExponent == UINT16_C(0x7fff))
    265 #else
    266     else if (pr80Value->sj.uExponent == UINT16_C(0x7fff))
    267 #endif
    268     {
    269         /** @todo Figure out Pseudo inf/nan... */
    270 #ifdef RT_COMPILER_GROKS_64BIT_BITFIELDS
    271         if (pr80Value->sj64.fInteger)
    272 #else
    273         if (pr80Value->sj.fInteger)
    274 #endif
    275             *pszTmp++ = 'P';
    276 #ifdef RT_COMPILER_GROKS_64BIT_BITFIELDS
    277         if (pr80Value->sj64.u63Fraction == 0)
    278 #else
    279         if (   pr80Value->sj.u32FractionLow == 0
    280             && pr80Value->sj.u31FractionHigh == 0)
    281 #endif
    282         {
    283             *pszTmp++ = 'I';
    284             *pszTmp++ = 'n';
    285             *pszTmp++ = 'f';
    286         }
    287         else
    288         {
    289             *pszTmp++ = 'N';
    290             *pszTmp++ = 'a';
    291             *pszTmp++ = 'N';
    292         }
    293     }
    294     if (pszTmp != &szTmp[1])
    295         *pszTmp = '\0';
    296     else
    297     {
    298 #ifdef RT_COMPILER_GROKS_64BIT_BITFIELDS
    299         *pszTmp++ = pr80Value->sj64.fInteger ? '1' : '0';
    300 #else
    301         *pszTmp++ = pr80Value->sj.fInteger ? '1' : '0';
    302 #endif
    303         *pszTmp++ = 'm';
    304 #ifdef RT_COMPILER_GROKS_64BIT_BITFIELDS
    305         pszTmp += RTStrFormatNumber(pszTmp, pr80Value->sj64.u63Fraction, 16, 2+16, 0,
    306                                     RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
    307 #else
    308         pszTmp += RTStrFormatNumber(pszTmp, RT_MAKE_U64(pr80Value->sj.u32FractionLow, pr80Value->sj.u31FractionHigh), 16, 2+16, 0,
    309                                     RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
    310 #endif
    311 
    312         *pszTmp++ = 'e';
    313 #ifdef RT_COMPILER_GROKS_64BIT_BITFIELDS
    314         pszTmp += RTStrFormatNumber(pszTmp, (int32_t)pr80Value->sj64.uExponent - 16383, 10, 0, 0,
    315                                     RTSTR_F_ZEROPAD | RTSTR_F_32BIT | RTSTR_F_VALSIGNED);
    316 #else
    317         pszTmp += RTStrFormatNumber(pszTmp, (int32_t)pr80Value->sj.uExponent - 16383, 10, 0, 0,
    318                                     RTSTR_F_ZEROPAD | RTSTR_F_32BIT | RTSTR_F_VALSIGNED);
    319 #endif
    320     }
    321 
    322     /*
    323      * Copy out the result.
    324      */
    325     ssize_t cchRet = pszTmp - &szTmp[0];
    326     if ((size_t)cchRet < cbBuf)
    327         memcpy(pszBuf, szTmp, cchRet + 1);
    328     else
    329     {
    330         if (cbBuf)
    331         {
    332             memcpy(pszBuf, szTmp, cbBuf - 1);
    333             pszBuf[cbBuf - 1] = '\0';
    334         }
    335         cchRet = VERR_BUFFER_OVERFLOW;
    336     }
    337     return cchRet;
    338363}
    339364
     
    342367                               signed int cchPrecision, uint32_t fFlags)
    343368{
    344     RTFLOAT80U2 r80ValueU2;
    345     RT_ZERO(r80ValueU2);
    346     r80ValueU2.s.fSign       = pr80Value->s.fSign;
    347     r80ValueU2.s.uExponent   = pr80Value->s.uExponent;
    348     r80ValueU2.s.u64Mantissa = pr80Value->s.u64Mantissa;
    349     return RTStrFormatR80u2(pszBuf, cbBuf, &r80ValueU2, cchWidth, cchPrecision, fFlags);
    350 }
    351 
     369    RT_NOREF(cchWidth, cchPrecision);
     370    return rtStrFormatR80Worker(pszBuf, cbBuf, pr80Value->s.fSign, pr80Value->s.u64Mantissa >> 63,
     371                                pr80Value->s.u64Mantissa & (RT_BIT_64(63) - 1), pr80Value->s.uExponent, fFlags);
     372}
     373
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