Kaydet (Commit) 779581fe authored tarafından László Németh's avatar László Németh

tdf#88810 avoid unnecessary massive O(U)String allocations in XLSX export

Using OStringBuffer instead of fixed size character arrays.

Change-Id: I06b705e2159a1ef5990f9eb0ffedd20fe277c616
üst 58a50c3d
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <tools/stream.hxx> #include <tools/stream.hxx>
#include <rtl/ustrbuf.hxx> #include <rtl/ustrbuf.hxx>
#include <rtl/strbuf.hxx>
#include <osl/endian.h> #include <osl/endian.h>
#include <limits> #include <limits>
...@@ -325,6 +326,9 @@ public: ...@@ -325,6 +326,9 @@ public:
ExternalInfo* pExtInfo = NULL, ExternalInfo* pExtInfo = NULL,
const css::uno::Sequence<css::sheet::ExternalLinkInfo>* pExternalLinks = NULL ); const css::uno::Sequence<css::sheet::ExternalLinkInfo>* pExternalLinks = NULL );
SC_DLLPUBLIC bool TryFormat( OStringBuffer& s, sal_uInt16 nFlags = 0,
const ScDocument* pDocument = NULL,
const Details& rDetails = detailsOOOa1) const;
SC_DLLPUBLIC OUString Format( sal_uInt16 nFlags = 0, SC_DLLPUBLIC OUString Format( sal_uInt16 nFlags = 0,
const ScDocument* pDocument = NULL, const ScDocument* pDocument = NULL,
const Details& rDetails = detailsOOOa1) const; const Details& rDetails = detailsOOOa1) const;
...@@ -888,6 +892,8 @@ bool ConvertDoubleRef( ScDocument* pDocument, const OUString& rRefString, ...@@ -888,6 +892,8 @@ bool ConvertDoubleRef( ScDocument* pDocument, const OUString& rRefString,
/// append alpha representation of column to buffer /// append alpha representation of column to buffer
SC_DLLPUBLIC void ScColToAlpha( OUStringBuffer& rBuffer, SCCOL nCol); SC_DLLPUBLIC void ScColToAlpha( OUStringBuffer& rBuffer, SCCOL nCol);
SC_DLLPUBLIC void ScColToAlpha( OStringBuffer& rBuffer, SCCOL nCol);
inline void ScColToAlpha( OUString& rStr, SCCOL nCol) inline void ScColToAlpha( OUString& rStr, SCCOL nCol)
{ {
OUStringBuffer aBuf(2); OUStringBuffer aBuf(2);
......
...@@ -1745,6 +1745,40 @@ static OUString getFileNameFromDoc( const ScDocument* pDoc ) ...@@ -1745,6 +1745,40 @@ static OUString getFileNameFromDoc( const ScDocument* pDoc )
return sFileName; return sFileName;
} }
/** Tries to obtain a simple address without OUString/OString allocation
*
* @returns TRUE at success (it is enough to call OUString Format() at FALSE)
*
*/
bool ScAddress::TryFormat(OStringBuffer& s, sal_uInt16 nFlags, const ScDocument* pDoc,
const Details& rDetails) const
{
if( nFlags & SCA_VALID )
nFlags |= ( SCA_VALID_ROW | SCA_VALID_COL | SCA_VALID_TAB );
if(( pDoc && (nFlags & SCA_VALID_TAB ) && ( nTab >= pDoc->GetTableCount() || ( nFlags & SCA_TAB_3D ))) ||
! (nFlags & SCA_VALID_COL) || ! (nFlags & SCA_VALID_ROW) ||
(nFlags & SCA_COL_ABSOLUTE) != 0 || (nFlags & SCA_ROW_ABSOLUTE) != 0 )
{
return false;
}
switch( rDetails.eConv )
{
default :
case formula::FormulaGrammar::CONV_OOO:
case formula::FormulaGrammar::CONV_XL_A1:
case formula::FormulaGrammar::CONV_XL_OOX:
ScColToAlpha( s, nCol );
s.append( OString::number(nRow+1) );
break;
case formula::FormulaGrammar::CONV_XL_R1C1:
// not used in XLSX export
return false;
}
return true;
}
OUString ScAddress::Format(sal_uInt16 nFlags, const ScDocument* pDoc, OUString ScAddress::Format(sal_uInt16 nFlags, const ScDocument* pDoc,
const Details& rDetails) const const Details& rDetails) const
{ {
...@@ -2102,6 +2136,34 @@ void ScColToAlpha( OUStringBuffer& rBuf, SCCOL nCol ) ...@@ -2102,6 +2136,34 @@ void ScColToAlpha( OUStringBuffer& rBuf, SCCOL nCol )
} }
} }
void ScColToAlpha( OStringBuffer& rBuf, SCCOL nCol )
{
if (nCol < 26*26)
{
if (nCol < 26)
rBuf.append( static_cast<char>( 'A' + nCol ));
else
{
rBuf.append( static_cast<char>( 'A' + nCol / 26 - 1 ));
rBuf.append( static_cast<char>( 'A' + nCol % 26 ));
}
}
else
{
OString aStr;
while (nCol >= 26)
{
SCCOL nC = nCol % 26;
aStr += OString( static_cast<char> ( 'A' + nC ));
nCol = sal::static_int_cast<SCCOL>( nCol - nC );
nCol = nCol / 26 - 1;
}
aStr += OString( static_cast<char> ( 'A' + nCol ));
rBuf.append(comphelper::string::reverseString(aStr));
}
}
bool AlphaToCol( SCCOL& rCol, const OUString& rStr) bool AlphaToCol( SCCOL& rCol, const OUString& rStr)
{ {
SCCOL nResult = 0; SCCOL nResult = 0;
......
...@@ -57,6 +57,7 @@ XclExpRootData::XclExpRootData( XclBiff eBiff, SfxMedium& rMedium, ...@@ -57,6 +57,7 @@ XclExpRootData::XclExpRootData( XclBiff eBiff, SfxMedium& rMedium,
{ {
SvtSaveOptions aSaveOpt; SvtSaveOptions aSaveOpt;
mbRelUrl = mrMedium.IsRemote() ? aSaveOpt.IsSaveRelINet() : aSaveOpt.IsSaveRelFSys(); mbRelUrl = mrMedium.IsRemote() ? aSaveOpt.IsSaveRelINet() : aSaveOpt.IsSaveRelFSys();
maStringBuf = OStringBuffer(10); // for simple addresses, like ABC1000000
} }
XclExpRootData::~XclExpRootData() XclExpRootData::~XclExpRootData()
......
...@@ -718,6 +718,11 @@ OString XclXmlUtils::ToOString( const OUString& s ) ...@@ -718,6 +718,11 @@ OString XclXmlUtils::ToOString( const OUString& s )
return OUStringToOString( s, RTL_TEXTENCODING_UTF8 ); return OUStringToOString( s, RTL_TEXTENCODING_UTF8 );
} }
bool XclXmlUtils::TryToOString( OStringBuffer& s, const ScAddress& rAddress )
{
return rAddress.TryFormat(s, SCA_VALID, NULL, ScAddress::Details( FormulaGrammar::CONV_XL_A1));
}
OString XclXmlUtils::ToOString( const ScAddress& rAddress ) OString XclXmlUtils::ToOString( const ScAddress& rAddress )
{ {
OUString sAddress(rAddress.Format(SCA_VALID, NULL, ScAddress::Details( FormulaGrammar::CONV_XL_A1))); OUString sAddress(rAddress.Format(SCA_VALID, NULL, ScAddress::Details( FormulaGrammar::CONV_XL_A1)));
...@@ -760,6 +765,11 @@ static ScAddress lcl_ToAddress( const XclAddress& rAddress ) ...@@ -760,6 +765,11 @@ static ScAddress lcl_ToAddress( const XclAddress& rAddress )
return aAddress; return aAddress;
} }
bool XclXmlUtils::TryToOString( OStringBuffer& s, const XclAddress& rAddress )
{
return TryToOString( s, lcl_ToAddress( rAddress ));
}
OString XclXmlUtils::ToOString( const XclAddress& rAddress ) OString XclXmlUtils::ToOString( const XclAddress& rAddress )
{ {
return ToOString( lcl_ToAddress( rAddress ) ); return ToOString( lcl_ToAddress( rAddress ) );
......
...@@ -631,8 +631,9 @@ static OString lcl_GetStyleId( XclExpXmlStream& rStrm, const XclExpCellBase& rCe ...@@ -631,8 +631,9 @@ static OString lcl_GetStyleId( XclExpXmlStream& rStrm, const XclExpCellBase& rCe
void XclExpNumberCell::SaveXml( XclExpXmlStream& rStrm ) void XclExpNumberCell::SaveXml( XclExpXmlStream& rStrm )
{ {
sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream(); sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
OStringBuffer rBuf = rStrm.GetRoot().GetStringBuf();
rWorksheet->startElement( XML_c, rWorksheet->startElement( XML_c,
XML_r, XclXmlUtils::ToOString( GetXclPos() ).getStr(), XML_r, XclXmlUtils::TryToOString( rBuf, GetXclPos() ) ? rBuf.getStr() : XclXmlUtils::ToOString( GetXclPos() ).getStr(),
XML_s, lcl_GetStyleId( rStrm, *this ).getStr(), XML_s, lcl_GetStyleId( rStrm, *this ).getStr(),
XML_t, "n", XML_t, "n",
// OOXTODO: XML_cm, XML_vm, XML_ph // OOXTODO: XML_cm, XML_vm, XML_ph
...@@ -923,11 +924,11 @@ void XclExpFormulaCell::SaveXml( XclExpXmlStream& rStrm ) ...@@ -923,11 +924,11 @@ void XclExpFormulaCell::SaveXml( XclExpXmlStream& rStrm )
{ {
const char* sType = NULL; const char* sType = NULL;
OUString sValue; OUString sValue;
XclXmlUtils::GetFormulaTypeAndValue( mrScFmlaCell, sType, sValue ); XclXmlUtils::GetFormulaTypeAndValue( mrScFmlaCell, sType, sValue );
sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream(); sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
OStringBuffer rBuf = rStrm.GetRoot().GetStringBuf();
rWorksheet->startElement( XML_c, rWorksheet->startElement( XML_c,
XML_r, XclXmlUtils::ToOString( GetXclPos() ).getStr(), XML_r, XclXmlUtils::TryToOString( rBuf, GetXclPos() ) ? rBuf.getStr() : XclXmlUtils::ToOString( GetXclPos() ).getStr(),
XML_s, lcl_GetStyleId( rStrm, *this ).getStr(), XML_s, lcl_GetStyleId( rStrm, *this ).getStr(),
XML_t, sType, XML_t, sType,
// OOXTODO: XML_cm, XML_vm, XML_ph // OOXTODO: XML_cm, XML_vm, XML_ph
...@@ -1308,8 +1309,9 @@ bool XclExpRkCell::TryMerge( const XclExpCellBase& rCell ) ...@@ -1308,8 +1309,9 @@ bool XclExpRkCell::TryMerge( const XclExpCellBase& rCell )
void XclExpRkCell::WriteXmlContents( XclExpXmlStream& rStrm, const XclAddress& rAddress, sal_uInt32 nXFId, sal_uInt16 nRelCol ) void XclExpRkCell::WriteXmlContents( XclExpXmlStream& rStrm, const XclAddress& rAddress, sal_uInt32 nXFId, sal_uInt16 nRelCol )
{ {
sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream(); sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
OStringBuffer rBuf = rStrm.GetRoot().GetStringBuf();
rWorksheet->startElement( XML_c, rWorksheet->startElement( XML_c,
XML_r, XclXmlUtils::ToOString( rAddress ).getStr(), XML_r, XclXmlUtils::TryToOString( rBuf, rAddress ) ? rBuf.getStr() : XclXmlUtils::ToOString( rAddress ).getStr(),
XML_s, lcl_GetStyleId( rStrm, nXFId ).getStr(), XML_s, lcl_GetStyleId( rStrm, nXFId ).getStr(),
XML_t, "n", XML_t, "n",
// OOXTODO: XML_cm, XML_vm, XML_ph // OOXTODO: XML_cm, XML_vm, XML_ph
......
...@@ -99,6 +99,8 @@ struct XclExpRootData : public XclRootData ...@@ -99,6 +99,8 @@ struct XclExpRootData : public XclRootData
bool mbRelUrl; /// true = Store URLs relative. bool mbRelUrl; /// true = Store URLs relative.
OStringBuffer maStringBuf; /// buffer to avoid massive OUString allocations
explicit XclExpRootData( XclBiff eBiff, SfxMedium& rMedium, explicit XclExpRootData( XclBiff eBiff, SfxMedium& rMedium,
SotStorageRef xRootStrg, ScDocument& rDoc, rtl_TextEncoding eTextEnc ); SotStorageRef xRootStrg, ScDocument& rDoc, rtl_TextEncoding eTextEnc );
virtual ~XclExpRootData(); virtual ~XclExpRootData();
...@@ -150,6 +152,9 @@ public: ...@@ -150,6 +152,9 @@ public:
/** Returns the differential formatting list */ /** Returns the differential formatting list */
XclExpDxfs& GetDxfs() const; XclExpDxfs& GetDxfs() const;
/** Clean and return the OStringBuffer */
inline OStringBuffer& GetStringBuf() const { mrExpData.maStringBuf.setLength(0); return mrExpData.maStringBuf; }
XclExpXmlPivotTableManager& GetXmlPivotTableManager(); XclExpXmlPivotTableManager& GetXmlPivotTableManager();
/** Is called when export filter starts to create the Excel document (all BIFF versions). */ /** Is called when export filter starts to create the Excel document (all BIFF versions). */
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <map> #include <map>
#include <stack> #include <stack>
#include <string> #include <string>
#include <rtl/strbuf.hxx>
#include <oox/core/xmlfilterbase.hxx> #include <oox/core/xmlfilterbase.hxx>
#include <oox/token/tokens.hxx> #include <oox/token/tokens.hxx>
...@@ -266,9 +267,11 @@ public: ...@@ -266,9 +267,11 @@ public:
static OString ToOString( const Color& rColor ); static OString ToOString( const Color& rColor );
static OString ToOString( const OUString& s ); static OString ToOString( const OUString& s );
static OString ToOString( const ScfUInt16Vec& rBuffer ); static OString ToOString( const ScfUInt16Vec& rBuffer );
static bool TryToOString( OStringBuffer& s, const ScAddress& rRange );
static OString ToOString( const ScAddress& rRange ); static OString ToOString( const ScAddress& rRange );
static OString ToOString( const ScRange& rRange ); static OString ToOString( const ScRange& rRange );
static OString ToOString( const ScRangeList& rRangeList ); static OString ToOString( const ScRangeList& rRangeList );
static bool TryToOString( OStringBuffer& s, const XclAddress& rAddress );
static OString ToOString( const XclAddress& rAddress ); static OString ToOString( const XclAddress& rAddress );
static OString ToOString( const XclExpString& s ); static OString ToOString( const XclExpString& s );
static OString ToOString( const XclRange& rRange ); static OString ToOString( const XclRange& rRange );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment