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:

Reply via email to