include/rtl/string.hxx | 1 + include/rtl/stringconcat.hxx | 15 +++++++++++++++ include/rtl/ustring.hxx | 1 + sw/source/core/crsr/crstrvl.cxx | 11 ++++------- sw/source/core/fields/authfld.cxx | 4 +--- sw/source/core/text/porglue.cxx | 8 ++------ sw/source/core/text/txttab.cxx | 8 ++------ sw/source/filter/ww8/ww8graf.cxx | 6 +++--- sw/source/filter/ww8/ww8par2.cxx | 5 ++--- sw/source/uibase/docvw/edtwin.cxx | 5 +---- sw/source/writerfilter/dmapper/GraphicImport.cxx | 7 ++----- sw/source/writerfilter/dmapper/StyleSheetTable.cxx | 7 ++----- sw/source/writerfilter/dmapper/TextEffectsHandler.cxx | 7 ++----- 13 files changed, 38 insertions(+), 47 deletions(-)
New commits: commit d1fc7efb90b4a122c0d160295be6a266ad5471a4 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Fri Aug 29 01:49:22 2025 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Fri Aug 29 01:00:26 2025 +0200 Introduce Repeated(U)Char for concatenation of N repeated characters ... and use in sw. Should replace padToLength, where the number of added characters is known in advance. Avoids creation of a string buffer for the task. Change-Id: I90450e37926335d74421c6e38385e4c441e535d9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190341 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/include/rtl/string.hxx b/include/rtl/string.hxx index a39f08dbb4aa..26b4e2515085 100644 --- a/include/rtl/string.hxx +++ b/include/rtl/string.hxx @@ -2734,6 +2734,7 @@ using ::rtl::OStringChar; using ::rtl::Concat2View; using ::rtl::OStringHash; using ::rtl::OStringLiteral; +using RepeatedChar = ::rtl::RepeatedChar_t<char>; #endif #if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) diff --git a/include/rtl/stringconcat.hxx b/include/rtl/stringconcat.hxx index 7009f7e98ccf..209a1394701f 100644 --- a/include/rtl/stringconcat.hxx +++ b/include/rtl/stringconcat.hxx @@ -170,6 +170,21 @@ struct ToStringHelper<OUStringChar_> { return addDataHelper(buffer, &literal.c, 1); } }; +// Output a character specified number of times. If the number is less than 1, do nothing. +template <typename C> struct RepeatedChar_t +{ + C c; + sal_Int32 n; + constexpr RepeatedChar_t(C ch, sal_Int32 num) : c(ch), n(std::max(num, sal_Int32(0))) {} +}; + +template <typename C> struct ToStringHelper<RepeatedChar_t<C>> +{ + static std::size_t length(const RepeatedChar_t<C>& str) { return str.n; } + C* operator()(C* buffer, const RepeatedChar_t<C>& str) const + { return std::fill_n(buffer, str.n, str.c); } +}; + /** @internal diff --git a/include/rtl/ustring.hxx b/include/rtl/ustring.hxx index 99cd213f2a76..8fd6954bee8d 100644 --- a/include/rtl/ustring.hxx +++ b/include/rtl/ustring.hxx @@ -3949,6 +3949,7 @@ using ::rtl::OUStringToOString; using ::rtl::OUStringLiteral; using ::rtl::OUStringChar; using ::rtl::Concat2View; +using RepeatedUChar = ::rtl::RepeatedChar_t<sal_Unicode>; #endif #if defined LIBO_INTERNAL_ONLY && !(defined _MSC_VER && _MSC_VER <= 1929 && defined _MANAGED) diff --git a/sw/source/core/crsr/crstrvl.cxx b/sw/source/core/crsr/crstrvl.cxx index a9df7a9ca480..52ea96a509f3 100644 --- a/sw/source/core/crsr/crstrvl.cxx +++ b/sw/source/core/crsr/crstrvl.cxx @@ -2545,20 +2545,17 @@ bool SwCursorShell::SetShadowCursorPos( const Point& rPt, SwFillMode eFillMode ) case SwFillMode::TabSpace: case SwFillMode::Space: { - OUStringBuffer sInsert; + OUString sInsert; if (aFPos.eMode == SwFillMode::Space) { - comphelper::string::padToLength(sInsert, sInsert.getLength() + aFPos.nSpaceOnlyCnt, ' '); + sInsert = OUString::Concat(RepeatedUChar(' ', aFPos.nSpaceOnlyCnt)); } else { - if (aFPos.nTabCnt) - comphelper::string::padToLength(sInsert, aFPos.nTabCnt, ' '); - if (aFPos.nSpaceCnt) - comphelper::string::padToLength(sInsert, sInsert.getLength() + aFPos.nSpaceCnt, ' '); + sInsert = RepeatedUChar(' ', aFPos.nTabCnt) + RepeatedUChar(' ', aFPos.nSpaceCnt); } if (!sInsert.isEmpty()) - GetDoc()->getIDocumentContentOperations().InsertString( *m_pCurrentCursor, sInsert.makeStringAndClear()); + GetDoc()->getIDocumentContentOperations().InsertString(*m_pCurrentCursor, sInsert); } [[fallthrough]]; // still need to set orientation case SwFillMode::Margin: diff --git a/sw/source/core/fields/authfld.cxx b/sw/source/core/fields/authfld.cxx index 0a3de0e91bb5..b3cb0a2a4147 100644 --- a/sw/source/core/fields/authfld.cxx +++ b/sw/source/core/fields/authfld.cxx @@ -817,9 +817,7 @@ bool SwAuthorityField::PutValue( const Any& rAny, sal_uInt16 /*nWhichId*/ ) if(!(rAny >>= aParam)) return false; - OUStringBuffer sBuf(+(AUTH_FIELD_END - 1)); - comphelper::string::padToLength(sBuf, (AUTH_FIELD_END - 1), TOX_STYLE_DELIMITER); - OUString sToSet(sBuf.makeStringAndClear()); + OUString sToSet = OUString::Concat(RepeatedUChar(TOX_STYLE_DELIMITER, AUTH_FIELD_END - 1)); for (const PropertyValue& rParam : aParam) { const sal_Int32 nFound = lcl_Find(rParam.Name); diff --git a/sw/source/core/text/porglue.cxx b/sw/source/core/text/porglue.cxx index cd5eaf2643b5..3c2ff67a4f3d 100644 --- a/sw/source/core/text/porglue.cxx +++ b/sw/source/core/text/porglue.cxx @@ -54,9 +54,7 @@ bool SwGluePortion::GetExpText( const SwTextSizeInfo &rInf, OUString &rText ) co if( GetLen() && rInf.OnWin() && rInf.GetOpt().IsBlank() && rInf.IsNoSymbol() ) { - OUStringBuffer aBuf(GetLen().get()); - comphelper::string::padToLength(aBuf, sal_Int32(GetLen()), CH_BULLET); - rText = aBuf.makeStringAndClear(); + rText = OUString::Concat(RepeatedUChar(CH_BULLET, GetLen().get())); return true; } return false; @@ -70,9 +68,7 @@ void SwGluePortion::Paint( const SwTextPaintInfo &rInf ) const if( rInf.GetFont()->IsPaintBlank() ) { const sal_Int32 nCount = GetFixWidth() / sal_Int32(GetLen()); - OUStringBuffer aBuf(nCount); - comphelper::string::padToLength(aBuf, nCount, ' '); - OUString aText(aBuf.makeStringAndClear()); + OUString aText(OUString::Concat(RepeatedUChar(' ', nCount))); SwTextPaintInfo aInf( rInf, &aText ); aInf.DrawText(*this, TextFrameIndex(aText.getLength()), true); } diff --git a/sw/source/core/text/txttab.cxx b/sw/source/core/text/txttab.cxx index 8511571ac753..22502f918a6d 100644 --- a/sw/source/core/text/txttab.cxx +++ b/sw/source/core/text/txttab.cxx @@ -628,9 +628,7 @@ void SwTabPortion::Paint( const SwTextPaintInfo &rInf ) const { // Always with kerning, also on printer! sal_Int32 nChar = Width() / nCharWidth; - OUStringBuffer aBuf(nChar); - comphelper::string::padToLength(aBuf, nChar, ' '); - rInf.DrawText(aBuf.makeStringAndClear(), *this, TextFrameIndex(0), + rInf.DrawText(OUString::Concat(RepeatedUChar(' ', nChar)), *this, TextFrameIndex(0), TextFrameIndex(nChar), true); } } @@ -650,9 +648,7 @@ void SwTabPortion::Paint( const SwTextPaintInfo &rInf ) const sal_Int32 nChar = Width() / nCharWidth; if ( m_cFill == '_' ) ++nChar; // to avoid gaps - OUStringBuffer aBuf(nChar); - comphelper::string::padToLength(aBuf, nChar, m_cFill); - rInf.DrawText(aBuf.makeStringAndClear(), *this, TextFrameIndex(0), + rInf.DrawText(OUString::Concat(RepeatedUChar(m_cFill, nChar)), *this, TextFrameIndex(0), TextFrameIndex(nChar), true); } } diff --git a/sw/source/filter/ww8/ww8graf.cxx b/sw/source/filter/ww8/ww8graf.cxx index 981b30248ba8..d8f514b1a1b1 100644 --- a/sw/source/filter/ww8/ww8graf.cxx +++ b/sw/source/filter/ww8/ww8graf.cxx @@ -692,9 +692,9 @@ void SwWW8ImplReader::InsertAttrsAsDrawingAttrs(WW8_CP nStartCp, WW8_CP nEndCp, if (!bBadSelection) { sal_Int32 nCount = nTextStart - nStartReplace; - OUStringBuffer sTemp(nCount); - comphelper::string::padToLength(sTemp, nCount, cReplaceSymbol); - m_pDrawEditEngine->QuickInsertText(sTemp.makeStringAndClear(), aReplaceSel); + m_pDrawEditEngine->QuickInsertText( + OUString::Concat(RepeatedUChar(cReplaceSymbol, nCount)), + aReplaceSel); } } } diff --git a/sw/source/filter/ww8/ww8par2.cxx b/sw/source/filter/ww8/ww8par2.cxx index 9708826f9773..46c493b84425 100644 --- a/sw/source/filter/ww8/ww8par2.cxx +++ b/sw/source/filter/ww8/ww8par2.cxx @@ -624,9 +624,8 @@ void SwWW8ImplReader::SetAnlvStrings(SwNumFormat &rNum, int nLevel, WW8_ANLV con if( bListSymbol ) { // use cBulletChar for correct mapping on MAC - sText.setLength(0); - comphelper::string::padToLength(sText, rAV.cbTextBefore - + rAV.cbTextAfter, cBulletChar); + sText = OUString::Concat( + RepeatedUChar(cBulletChar, rAV.cbTextBefore + rAV.cbTextAfter)); } } } diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx index 5f489158b699..a1e688ae3f13 100644 --- a/sw/source/uibase/docvw/edtwin.cxx +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -2687,10 +2687,7 @@ KEYINPUT_CHECKTABLE_INSDEL: } else { - OUStringBuffer aBuf(m_aInBuffer); - comphelper::string::padToLength(aBuf, - m_aInBuffer.getLength() + aKeyEvent.GetRepeat() + 1, aCh); - m_aInBuffer = aBuf.makeStringAndClear(); + m_aInBuffer += OUString::Concat(RepeatedUChar(aCh, aKeyEvent.GetRepeat() + 1)); bool delayFlush = Application::AnyInput( VclInputFlags::KEYBOARD ); bFlushBuffer = !delayFlush; if( delayFlush ) diff --git a/sw/source/writerfilter/dmapper/GraphicImport.cxx b/sw/source/writerfilter/dmapper/GraphicImport.cxx index 9efa5060217d..93f8c6f99f4e 100644 --- a/sw/source/writerfilter/dmapper/GraphicImport.cxx +++ b/sw/source/writerfilter/dmapper/GraphicImport.cxx @@ -719,11 +719,8 @@ void GraphicImport::lcl_attribute(Id nName, const Value& rValue) case NS_ooxml::LN_CT_Anchor_wp14_anchorId: case NS_ooxml::LN_CT_Inline_wp14_anchorId: { - OUStringBuffer aBuffer = OUString::number(nIntValue, 16); - OUStringBuffer aString; - comphelper::string::padToLength(aString, 8 - aBuffer.getLength(), '0'); - aString.append(aBuffer.getStr()); - m_sAnchorId = aString.makeStringAndClear().toAsciiUpperCase(); + auto aBuffer = OUString::number(nIntValue, 16).toAsciiUpperCase(); + m_sAnchorId = RepeatedUChar('0', 8 - aBuffer.length) + aBuffer; } break; case NS_ooxml::LN_CT_Point2D_x: diff --git a/sw/source/writerfilter/dmapper/StyleSheetTable.cxx b/sw/source/writerfilter/dmapper/StyleSheetTable.cxx index be5e05db987f..b8bbee4efc72 100644 --- a/sw/source/writerfilter/dmapper/StyleSheetTable.cxx +++ b/sw/source/writerfilter/dmapper/StyleSheetTable.cxx @@ -574,13 +574,10 @@ void StyleSheetTable::lcl_sprm(Sprm & rSprm) case NS_ooxml::LN_CT_Style_rsid: { // We want the rsid as a hex string, but always with the length of 8. - OUStringBuffer aBuf = OUString::number(nIntValue, 16); - OUStringBuffer aStr; - comphelper::string::padToLength(aStr, 8 - aBuf.getLength(), '0'); - aStr.append(aBuf.getStr()); + auto aBuf = OUString::number(nIntValue, 16); aValue.Name = "rsid"; - aValue.Value <<= aStr.makeStringAndClear(); + aValue.Value <<= OUString(RepeatedUChar('0', 8 - aBuf.length) + aBuf); } break; case NS_ooxml::LN_CT_Style_qFormat: diff --git a/sw/source/writerfilter/dmapper/TextEffectsHandler.cxx b/sw/source/writerfilter/dmapper/TextEffectsHandler.cxx index 38fddf9ce006..c6b5c250d23f 100644 --- a/sw/source/writerfilter/dmapper/TextEffectsHandler.cxx +++ b/sw/source/writerfilter/dmapper/TextEffectsHandler.cxx @@ -558,11 +558,8 @@ void TextEffectsHandler::lcl_attribute(Id aName, const Value& aValue) break; case NS_ooxml::LN_CT_SRgbColor_val: { - OUString aBuffer = OUString::number(aValue.getInt(), 16); - OUStringBuffer aString; - comphelper::string::padToLength(aString, 6 - aBuffer.getLength(), '0'); - aString.append(aBuffer.getStr()); - mpGrabBagStack->addString(u"val"_ustr, aString.makeStringAndClear().toAsciiUpperCase()); + auto num = OUString::number(aValue.getInt(), 16).toAsciiUpperCase(); + mpGrabBagStack->addString(u"val"_ustr, RepeatedUChar('0', 6 - num.length) + num); } break; case NS_ooxml::LN_CT_Shadow_blurRad: