sc/source/core/tool/interpr2.cxx | 144 ++++++++++++++++----------------------- 1 file changed, 61 insertions(+), 83 deletions(-)
New commits: commit 6badee44a10ebb8e9b5b821bd15a12a3bf6b2f22 Author: Mike Kaganski <[email protected]> AuthorDate: Mon Nov 3 16:11:28 2025 +0500 Commit: Mike Kaganski <[email protected]> CommitDate: Sat Nov 8 13:22:31 2025 +0100 Simplify ScBahtText using rtl::math::doubleToString Instead of rounding and converting the number, create a string with all the digits and proper rounding, and parse it from start to end. Avoids insertion to beginning of the buffer; matches the rounding used everywhere (up to 15 significands). Change-Id: I3cdbae0d4fda704edd282c86e85c715c5336e81e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193612 Tested-by: Jenkins Reviewed-by: Mike Kaganski <[email protected]> diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx index 36375d4cc15c..797d863abefb 100644 --- a/sc/source/core/tool/interpr2.cxx +++ b/sc/source/core/tool/interpr2.cxx @@ -3401,22 +3401,21 @@ constexpr std::u16string_view TH_BAHT = u"บาท"; constexpr std::u16string_view TH_SATANG = u"สตางค์"; constexpr std::u16string_view TH_MINUS = u"ลบ"; -/** Appends a digit (0 to 9) to the passed string. */ -void lclAppendDigit( OUStringBuffer& rText, sal_Int32 nDigit ) +/** Appends a digit (1 to 9) to the passed string. */ +void lclAppendDigit( OUStringBuffer& rText, char nDigit ) { + assert(nDigit >= '1' && nDigit <= '9'); switch( nDigit ) { - case 0: rText.append( TH_0 ); break; - case 1: rText.append( TH_1 ); break; - case 2: rText.append( TH_2 ); break; - case 3: rText.append( TH_3 ); break; - case 4: rText.append( TH_4 ); break; - case 5: rText.append( TH_5 ); break; - case 6: rText.append( TH_6 ); break; - case 7: rText.append( TH_7 ); break; - case 8: rText.append( TH_8 ); break; - case 9: rText.append( TH_9 ); break; - default: OSL_FAIL( "lclAppendDigit - illegal digit" ); + case '1': rText.append( TH_1 ); break; + case '2': rText.append( TH_2 ); break; + case '3': rText.append( TH_3 ); break; + case '4': rText.append( TH_4 ); break; + case '5': rText.append( TH_5 ); break; + case '6': rText.append( TH_6 ); break; + case '7': rText.append( TH_7 ); break; + case '8': rText.append( TH_8 ); break; + case '9': rText.append( TH_9 ); break; } } @@ -3424,9 +3423,9 @@ void lclAppendDigit( OUStringBuffer& rText, sal_Int32 nDigit ) @param nDigit A digit in the range from 1 to 9. @param nPow10 A value in the range from 2 to 5. */ -void lclAppendPow10( OUStringBuffer& rText, sal_Int32 nDigit, sal_Int32 nPow10 ) +void lclAppendPow10( OUStringBuffer& rText, char nDigit, sal_Int32 nPow10 ) { - OSL_ENSURE( (1 <= nDigit) && (nDigit <= 9), "lclAppendPow10 - illegal digit" ); + assert(nPow10 >= 2 && nPow10 <= 5); lclAppendDigit( rText, nDigit ); switch( nPow10 ) { @@ -3434,51 +3433,33 @@ void lclAppendPow10( OUStringBuffer& rText, sal_Int32 nDigit, sal_Int32 nPow10 ) case 3: rText.append( TH_1E3 ); break; case 4: rText.append( TH_1E4 ); break; case 5: rText.append( TH_1E5 ); break; - default: OSL_FAIL( "lclAppendPow10 - illegal power" ); } } /** Appends a block of 6 digits (value from 1 to 999,999) to the passed string. */ -void lclAppendBlock( OUStringBuffer& rText, sal_Int32 nValue ) -{ - OSL_ENSURE( (1 <= nValue) && (nValue <= 999999), "lclAppendBlock - illegal value" ); - if( nValue >= 100000 ) - { - lclAppendPow10( rText, nValue / 100000, 5 ); - nValue %= 100000; - } - if( nValue >= 10000 ) - { - lclAppendPow10( rText, nValue / 10000, 4 ); - nValue %= 10000; - } - if( nValue >= 1000 ) - { - lclAppendPow10( rText, nValue / 1000, 3 ); - nValue %= 1000; - } - if( nValue >= 100 ) - { - lclAppendPow10( rText, nValue / 100, 2 ); - nValue %= 100; - } - if( nValue <= 0 ) - return; - - sal_Int32 nTen = nValue / 10; - sal_Int32 nOne = nValue % 10; - if( nTen >= 1 ) - { - if( nTen >= 3 ) - lclAppendDigit( rText, nTen ); - else if( nTen == 2 ) +void lclAppendBlock( OUStringBuffer& rText, std::string_view block ) +{ + assert(block.size() > 0 && block.size() <= 6); + auto it = block.begin(); + for (size_t pow = block.size() - 1; pow >= 2; --pow) + if (char ch = *it++; ch != '0') + lclAppendPow10(rText, ch, pow); + + // Two last characters + char ten = block.size() > 1 ? *it++ : '0'; + char one = *it; + if (ten >= '1') + { + if (ten >= '3') + lclAppendDigit(rText, ten); + else if (ten == '2') rText.append( TH_20 ); rText.append( TH_10 ); } - if( (nTen > 0) && (nOne == 1) ) + if ((ten > '0') && (one == '1')) rText.append( TH_11 ); - else if( nOne > 0 ) - lclAppendDigit( rText, nOne ); + else if( one > '0' ) + lclAppendDigit(rText, one); } } // namespace @@ -3496,56 +3477,53 @@ void ScInterpreter::ScBahtText() return; } - // sign - bool bMinus = fValue < 0.0; - fValue = std::abs( fValue ); - + OString number = rtl::math::doubleToString(std::abs(fValue), rtl_math_StringFormat_F, 2, '.'); + assert(number.getLength() > 3); // At least "0.00" + const sal_Int32 dotPos = number.getLength() - 3; + assert(number[dotPos] == '.'); // split Baht and Satang - double fBaht = 0.0; - sal_Int32 nSatang = std::round(modf(fValue, &fBaht) * 100); - if (nSatang > 99) + std::string_view sBaht(number.subView(0, dotPos)), sSatang(number.subView(dotPos + 1)); + bool noBaht = sBaht == "0", noSatang = sSatang == "00"; + if (noBaht && noSatang) { - nSatang -= 100; - fBaht += 1; + return PushString(OUString::Concat(TH_0) + TH_BAHT + TH_DOT0); } OUStringBuffer aText; + // sign + if (fValue < 0.0) + aText.append(TH_MINUS); // generate text for Baht value - if( fBaht == 0.0 ) - { - if( nSatang == 0 ) - aText.append( TH_0 ); - } - else while( fBaht > 0.0 ) + if (!noBaht) { - OUStringBuffer aBlock; - if (sal_Int32 nBlock = std::round(modf(fBaht / 1.0e6, &fBaht) * 1.0e6)) - lclAppendBlock( aBlock, nBlock ); - // add leading "million", if there will come more blocks - if( fBaht > 0.0 ) - aBlock.insert( 0, TH_1E6 ); - - aText.insert(0, aBlock); + size_t blocksize = sBaht.size() % 6; + if (blocksize == 0) + blocksize = 6; + while (!sBaht.empty()) + { + assert(blocksize <= sBaht.size()); + lclAppendBlock(aText, sBaht.substr(0, blocksize)); + sBaht.remove_prefix(blocksize); + blocksize = 6; + // add "million", if there will come more blocks + if (!sBaht.empty()) + aText.append(TH_1E6); + } + aText.append(TH_BAHT); } - if (!aText.isEmpty()) - aText.append( TH_BAHT ); // generate text for Satang value - if( nSatang == 0 ) + if (noSatang) { aText.append( TH_DOT0 ); } else { - lclAppendBlock( aText, nSatang ); + lclAppendBlock(aText, sSatang); aText.append( TH_SATANG ); } - // add the minus sign - if( bMinus ) - aText.insert( 0, TH_MINUS ); - PushString(aText.makeStringAndClear()); }
