fdo#76294: Properly intern string literals in formula on xls import.

Change-Id: Ib3a442cbb68c23294762561f2911101a087a795e
This commit is contained in:
Kohei Yoshida 2014-04-14 16:57:52 -04:00
parent 2da75ceaca
commit b09426b83c
26 changed files with 114 additions and 61 deletions

View File

@ -801,7 +801,7 @@ FormulaToken* FormulaTokenArray::Add( FormulaToken* t )
}
}
FormulaToken* FormulaTokenArray::AddString( const OUString& rStr )
FormulaToken* FormulaTokenArray::AddString( const svl::SharedString& rStr )
{
return Add( new FormulaStringToken( rStr ) );
}
@ -1369,7 +1369,10 @@ bool FormulaDoubleToken::operator==( const FormulaToken& r ) const
}
FormulaStringToken::FormulaStringToken( const svl::SharedString& r ) :
FormulaToken( svString ), maString( r ) {}
FormulaToken( svString ), maString( r )
{
}
FormulaStringToken::FormulaStringToken( const FormulaStringToken& r ) :
FormulaToken( r ), maString( r.maString ) {}

View File

@ -27,6 +27,12 @@
#include <boost/unordered_set.hpp>
namespace svl {
class SharedString;
}
namespace formula
{
@ -212,7 +218,7 @@ public:
virtual void CheckToken( const FormulaToken& t );
FormulaToken* AddToken( const FormulaToken& );
FormulaToken* AddString( const OUString& rStr );
FormulaToken* AddString( const svl::SharedString& rStr );
FormulaToken* AddDouble( double fVal );
FormulaToken* AddExternal( const sal_Unicode* pStr );
/** Xcl import may play dirty tricks with OpCode!=ocExternal.

View File

@ -40,7 +40,8 @@
#include "editutil.hxx"
#include "tokenarray.hxx"
#include "refupdatecontext.hxx"
#include "svl/sharedstring.hxx"
#include <svl/sharedstring.hxx>
#include <svl/sharedstringpool.hxx>
using namespace formula;
@ -1306,7 +1307,10 @@ ScTokenArray* ScConditionEntry::CreateTokenArry( sal_uInt16 nIndex ) const
{
pRet = new ScTokenArray();
if (bIsStr1)
pRet->AddString( aStrVal1 );
{
svl::SharedStringPool& rSPool = mpDoc->GetSharedStringPool();
pRet->AddString(rSPool.intern(aStrVal1));
}
else
pRet->AddDouble( nVal1 );
}
@ -1319,7 +1323,10 @@ ScTokenArray* ScConditionEntry::CreateTokenArry( sal_uInt16 nIndex ) const
{
pRet = new ScTokenArray();
if (bIsStr2)
pRet->AddString( aStrVal2 );
{
svl::SharedStringPool& rSPool = mpDoc->GetSharedStringPool();
pRet->AddString(rSPool.intern(aStrVal2));
}
else
pRet->AddDouble( nVal2 );
}

View File

@ -714,6 +714,7 @@ bool ScValidationData::GetSelectionFromFormula(
}
bool bHaveEmpty = false;
svl::SharedStringPool& rSPool = pDocument->GetSharedStringPool();
/* XL artificially limits things to a single col or row in the UI but does
* not list the constraint in MOOXml. If a defined name or INDIRECT
@ -749,7 +750,7 @@ bool ScValidationData::GetSelectionFromFormula(
pEntry = new ScTypedStrData( aValStr, 0.0, ScTypedStrData::Standard);
if (!rCell.isEmpty() && rMatch < 0)
aCondTokArr.AddString( aValStr );
aCondTokArr.AddString(rSPool.intern(aValStr));
}
else
{
@ -871,6 +872,7 @@ bool ScValidationData::IsListValid( ScRefCellValue& rCell, const ScAddress& rPos
// *** try if formula is a string list ***
svl::SharedStringPool& rSPool = GetDocument()->GetSharedStringPool();
sal_uInt32 nFormat = lclGetCellFormat( *GetDocument(), rPos );
ScStringTokenIterator aIt( *pTokArr );
for (rtl_uString* pString = aIt.First(); pString && aIt.Ok(); pString = aIt.Next())
@ -886,7 +888,7 @@ bool ScValidationData::IsListValid( ScRefCellValue& rCell, const ScAddress& rPos
if (GetDocument()->GetFormatTable()->IsNumberFormat(aStr, nFormat, fValue))
aCondTokArr.AddDouble( fValue );
else
aCondTokArr.AddString(aStr);
aCondTokArr.AddString(rSPool.intern(aStr));
bIsValid = IsEqualToTokenArray(rCell, rPos, aCondTokArr);
}

View File

@ -367,8 +367,11 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
}
if (pStr)
{
// This is a string cell.
aCode2.AddString(OUString(pStr));
svl::SharedStringPool& rPool = rDoc.GetSharedStringPool();
aCode2.AddString(rPool.intern(OUString(pStr)));
}
else if (rtl::math::isNan(fVal))
// Value of NaN represents an empty cell.
aCode2.AddToken(ScEmptyCellToken(false, false));

View File

@ -181,8 +181,8 @@ void ImportExcel::Formula(
}
ExcelToSc::ExcelToSc( const XclImpRoot& rRoot ) :
ExcelConverterBase( 512 ),
ExcelToSc::ExcelToSc( XclImpRoot& rRoot ) :
ExcelConverterBase(rRoot.GetDocImport().getDoc().GetSharedStringPool(), 512),
XclImpRoot( rRoot ),
maFuncProv( rRoot ),
meBiff( rRoot.GetBiff() )

View File

@ -79,7 +79,7 @@ ExcelToSc8::ExternalTabInfo::ExternalTabInfo() :
{
}
ExcelToSc8::ExcelToSc8( const XclImpRoot& rRoot ) :
ExcelToSc8::ExcelToSc8( XclImpRoot& rRoot ) :
ExcelToSc( rRoot ),
rLinkMan( rRoot.GetLinkManager() )
{

View File

@ -167,7 +167,8 @@ const ScRange* _ScRangeListTabs::Next ()
return &(*maItrCur);
}
ConverterBase::ConverterBase( sal_uInt16 nNewBuffer ) :
ConverterBase::ConverterBase( svl::SharedStringPool& rSPool, sal_uInt16 nNewBuffer ) :
aPool(rSPool),
aEingPos( 0, 0, 0 ),
eStatus( ConvOK ),
nBufferSize( nNewBuffer )
@ -189,8 +190,8 @@ void ConverterBase::Reset()
}
ExcelConverterBase::ExcelConverterBase( sal_uInt16 nNewBuffer ) :
ConverterBase( nNewBuffer )
ExcelConverterBase::ExcelConverterBase( svl::SharedStringPool& rSPool, sal_uInt16 nNewBuffer ) :
ConverterBase(rSPool, nNewBuffer)
{
}
@ -211,8 +212,8 @@ void ExcelConverterBase::Reset()
}
LotusConverterBase::LotusConverterBase( SvStream &rStr, sal_uInt16 nNewBuffer ) :
ConverterBase( nNewBuffer ),
LotusConverterBase::LotusConverterBase( SvStream &rStr, svl::SharedStringPool& rSPool, sal_uInt16 nNewBuffers ) :
ConverterBase(rSPool, nNewBuffers),
aIn( rStr ),
nBytesLeft( 0 )
{

View File

@ -17,14 +17,16 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <string.h>
#include "compiler.hxx"
#include "tokstack.hxx"
#include "compiler.hxx"
#include "global.hxx"
#include "scmatrix.hxx"
#include <svl/sharedstringpool.hxx>
#include <stdio.h>
#include <string.h>
const sal_uInt16 TokenPool::nScTokenOff = 8192;
@ -51,7 +53,8 @@ TokenStack::~TokenStack()
// -> Unterscheidung von anderen Token
TokenPool::TokenPool( void )
TokenPool::TokenPool( svl::SharedStringPool& rSPool ) :
mrStringPool(rSPool)
{
sal_uInt16 nLauf = nScTokenOff;
@ -392,7 +395,7 @@ bool TokenPool::GetElement( const sal_uInt16 nId )
sal_uInt16 n = pElement[ nId ];
OUString* p = ( n < nP_Str )? ppP_Str[ n ] : NULL;
if (p)
pScToken->AddString( *p );
pScToken->AddString(mrStringPool.intern(*p));
else
bRet = false;
}

View File

@ -853,7 +853,7 @@ void XclImpValidationManager::ReadDV( XclImpStream& rStrm )
// process string list of a list validity (convert to list of string tokens)
if( xTokArr1.get() && (eValMode == SC_VALID_LIST) && ::get_flag( nFlags, EXC_DV_STRINGLIST ) )
XclTokenArrayHelper::ConvertStringToList( *xTokArr1, '\n', true );
XclTokenArrayHelper::ConvertStringToList(*xTokArr1, rDoc.GetSharedStringPool(), '\n', true);
maDVItems.push_back(
new DVItem(aScRanges, ScValidationData(eValMode, eCondMode, xTokArr1.get(), xTokArr2.get(), &rDoc, rScRange.aStart)));

View File

@ -28,6 +28,7 @@
#include "xlroot.hxx"
#include <comphelper/string.hxx>
#include <svl/sharedstringpool.hxx>
using namespace ::formula;
@ -854,7 +855,8 @@ bool XclTokenArrayHelper::GetStringList( OUString& rStringList, const ScTokenArr
return bRet;
}
void XclTokenArrayHelper::ConvertStringToList( ScTokenArray& rScTokArr, sal_Unicode cStringSep, bool bTrimLeadingSpaces )
void XclTokenArrayHelper::ConvertStringToList(
ScTokenArray& rScTokArr, svl::SharedStringPool& rSPool, sal_Unicode cStringSep, bool bTrimLeadingSpaces )
{
OUString aString;
if( GetString( aString, rScTokArr ) )
@ -869,7 +871,7 @@ void XclTokenArrayHelper::ConvertStringToList( ScTokenArray& rScTokArr, sal_Unic
aToken = comphelper::string::stripStart(aToken, ' ');
if( nToken > 0 )
rScTokArr.AddOpCode( ocSep );
rScTokArr.AddString( aToken );
rScTokArr.AddString(rSPool.intern(aToken));
}
}
}

View File

@ -159,20 +159,10 @@ private:
virtual bool Read3DTabReference( sal_uInt16 nIxti, SCTAB& rFirstTab, SCTAB& rLastTab, ExternalTabInfo& rExtInfo ) SAL_OVERRIDE;
public:
inline XclImpChTrFmlConverter(
const XclImpRoot& rRoot,
XclImpChangeTrack& rXclChTr );
XclImpChTrFmlConverter( XclImpRoot& rRoot, XclImpChangeTrack& rXclChTr );
virtual ~XclImpChTrFmlConverter();
};
inline XclImpChTrFmlConverter::XclImpChTrFmlConverter(
const XclImpRoot& rRoot,
XclImpChangeTrack& rXclChTr ) :
ExcelToSc8( rRoot ),
rChangeTrack( rXclChTr )
{
}
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@ -49,7 +49,7 @@ protected:
void ExcRelToScRel( sal_uInt16 nRow, sal_uInt8 nCol, ScSingleRefData&, const bool bName );
public:
ExcelToSc( const XclImpRoot& rRoot );
ExcelToSc( XclImpRoot& rRoot );
virtual ~ExcelToSc();
virtual ConvErr Convert( const ScTokenArray*&, XclImpStream& rStrm, sal_Size nFormulaLen,
bool bAllowArrays, const FORMULA_TYPE eFT = FT_CellFormula ) SAL_OVERRIDE;
@ -124,7 +124,7 @@ private:
bool HandleOleLink(sal_uInt16 nXtiIndex, const XclImpExtName& rExtName, ExternalTabInfo& rExtInfo);
public:
ExcelToSc8( const XclImpRoot& rRoot );
ExcelToSc8( XclImpRoot& rRoot );
virtual ~ExcelToSc8();
virtual ConvErr Convert( const ScTokenArray*& rpTokArray, XclImpStream& rStrm, sal_Size nFormulaLen, bool bAllowArrays, const FORMULA_TYPE eFT = FT_CellFormula ) SAL_OVERRIDE;

View File

@ -29,6 +29,12 @@
#include <boost/ptr_container/ptr_map.hpp>
#include <vector>
namespace svl {
class SharedStringPool;
}
class XclImpStream;
class ScTokenArray;
struct ScSingleRefData;
@ -82,7 +88,7 @@ protected:
sal_Char* pBuffer; // universal buffer
sal_uInt16 nBufferSize; // ...and its size
ConverterBase( sal_uInt16 nNewBuffer );
ConverterBase( svl::SharedStringPool& rSPool, sal_uInt16 nNewBuffer );
virtual ~ConverterBase();
void Reset();
@ -91,7 +97,7 @@ protected:
class ExcelConverterBase : public ConverterBase
{
protected:
ExcelConverterBase( sal_uInt16 nNewBuffer );
ExcelConverterBase( svl::SharedStringPool& rSPool, sal_uInt16 nNewBuffer );
virtual ~ExcelConverterBase();
public:
@ -118,7 +124,7 @@ protected:
inline void Read( double& fDouble );
inline void Read( sal_uInt32& nUINT32 );
LotusConverterBase( SvStream& rStr, sal_uInt16 nNewBuffer );
LotusConverterBase( SvStream& rStr, svl::SharedStringPool& rSPool, sal_uInt16 nNewBuffer );
virtual ~LotusConverterBase();
public:

View File

@ -86,7 +86,8 @@ private:
void NegToken( TokenId& rParam );
// ACHTUNG: wie ~, nur wird '-(<rParam>)' gebildet
public:
LotusToSc( SvStream& aStr, rtl_TextEncoding eSrc, bool b );
LotusToSc( SvStream& aStr, svl::SharedStringPool& rSPool, rtl_TextEncoding eSrc, bool b );
virtual ConvErr Convert( const ScTokenArray*& rpErg, sal_Int32& nRest,
const FORMULA_TYPE eFT = FT_CellFormula ) SAL_OVERRIDE;

View File

@ -54,15 +54,15 @@ enum FUNC_TYPE
class QProToSc : public ConverterBase
{
private:
private:
TokenId mnAddToken;
TokenId mnSubToken;
TokenId mn0Token;
SvStream& maIn;
public:
public:
static const size_t nBufSize = 256;
QProToSc( SvStream &aStr, const ScAddress& rRefPos );
QProToSc( SvStream &aStr, svl::SharedStringPool& rSPool, const ScAddress& rRefPos );
virtual ~QProToSc(){ };
ConvErr Convert( const ScTokenArray*& pArray, sal_uInt16 nLen,
const FORMULA_TYPE eFT = FT_CellFormula );

View File

@ -26,6 +26,12 @@
#include <vector>
namespace svl {
class SharedStringPool;
}
typedef OpCode DefTokenId;
// in PRODUCT version: ambiguity between OpCode (being sal_uInt16) and UINT16
// Unfortunately a typedef is just a dumb alias and not a real type ...
@ -76,7 +82,9 @@ class TokenPool
{
// !ACHTUNG!: externe Id-Basis ist 1, interne 0!
// Ausgabe Id = 0 -> Fehlerfall
private:
private:
svl::SharedStringPool& mrStringPool;
OUString** ppP_Str; // Pool fuer Strings
sal_uInt16 nP_Str; // ...mit Groesse
sal_uInt16 nP_StrAkt; // ...und Schreibmarke
@ -182,8 +190,8 @@ class TokenPool
bool GrowMatrix( void );
bool GetElement( const sal_uInt16 nId );
bool GetElementRek( const sal_uInt16 nId );
public:
TokenPool( void );
public:
TokenPool( svl::SharedStringPool& rSPool );
~TokenPool();
inline TokenPool& operator <<( const TokenId nId );
inline TokenPool& operator <<( const DefTokenId eId );

View File

@ -26,6 +26,12 @@
#include "ftools.hxx"
#include <boost/shared_ptr.hpp>
namespace svl {
class SharedStringPool;
}
// Constants ==================================================================
const size_t EXC_TOKARR_MAXLEN = 4096; /// Maximum size of a token array.
@ -520,7 +526,8 @@ public:
@param rScTokArr (in/out-parameter) The token array to modify.
@param cStringSep The separator in the source string.
@param bTrimLeadingSpaces true = remove leading spaces from each token. */
static void ConvertStringToList( ScTokenArray& rScTokArr, sal_Unicode cStringSep, bool bTrimLeadingSpaces );
static void ConvertStringToList(
ScTokenArray& rScTokArr, svl::SharedStringPool& rSPool, sal_Unicode cStringSep, bool bTrimLeadingSpaces );
// multiple operations ----------------------------------------------------

View File

@ -326,8 +326,8 @@ void LotusToSc::Reset( const ScAddress& rEingPos )
}
LotusToSc::LotusToSc( SvStream &rStream, rtl_TextEncoding e, bool b ) :
LotusConverterBase( rStream, 128 )
LotusToSc::LotusToSc( SvStream &rStream, svl::SharedStringPool& rSPool, rtl_TextEncoding e, bool b ) :
LotusConverterBase(rStream, rSPool, 128)
{
eSrcChar = e;
bWK3 = false;

View File

@ -67,7 +67,7 @@ static osl::Mutex aLotImpSemaphore;
ImportLotus::ImportLotus( SvStream& aStream, ScDocument* pDoc, rtl_TextEncoding eQ )
: ImportTyp(pDoc, eQ)
, pIn(&aStream)
, aConv(*pIn, eQ, false)
, aConv(*pIn, pDoc->GetSharedStringPool(), eQ, false)
, nTab(0)
, nExtTab(0)
{

View File

@ -156,7 +156,8 @@ void OP_Formula( SvStream& r, sal_uInt16 /*n*/ )
sal_Int32 nBytesLeft = nFormulaSize;
ScAddress aAddress( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab );
LotusToSc aConv( r, pLotusRoot->eCharsetQ, false );
svl::SharedStringPool& rSPool = pLotusRoot->pDoc->GetSharedStringPool();
LotusToSc aConv(r, rSPool, pLotusRoot->eCharsetQ, false);
aConv.Reset( aAddress );
aConv.Convert( pErg, nBytesLeft );
@ -388,7 +389,8 @@ void OP_Formula123( SvStream& r, sal_uInt16 n )
sal_Int32 nBytesLeft = (n > 12) ? n - 12 : 0;
ScAddress aAddress( nCol, nRow, nTab );
LotusToSc aConv( r, pLotusRoot->eCharsetQ, true );
svl::SharedStringPool& rSPool = pLotusRoot->pDoc->GetSharedStringPool();
LotusToSc aConv(r, rSPool, pLotusRoot->eCharsetQ, true);
aConv.Reset( aAddress );
aConv.Convert( pErg, nBytesLeft );

View File

@ -35,6 +35,7 @@
#include <com/sun/star/table/XCellRange.hpp>
#include <rtl/ustrbuf.hxx>
#include <svl/intitem.hxx>
#include <svl/sharedstringpool.hxx>
#include "oox/helper/attributelist.hxx"
#include "oox/helper/containerhelper.hxx"
#include "oox/helper/propertyset.hxx"
@ -791,7 +792,8 @@ void CondFormatRule::finalizeImport()
{
ScDocument& rDoc = getScDocument();
ScTokenArray aTokenArray;
aTokenArray.AddString(maModel.maText);
svl::SharedStringPool& rSPool = rDoc.GetSharedStringPool();
aTokenArray.AddString(rSPool.intern(maModel.maText));
OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId );
ScCondFormatEntry* pNewEntry = new ScCondFormatEntry( eOperator, &aTokenArray, NULL, &rDoc, aPos, aStyleName );
mpFormat->AddEntry(pNewEntry);

View File

@ -100,13 +100,16 @@ FltError ScQProReader::readSheet( SCTAB nTab, ScDocument* pDoc, ScQProStyle *pSt
}
break;
case 0x0010:{ // Formula cell
case 0x0010:
{
// Formula cell
double nValue;
sal_uInt16 nState, nLen;
mpStream->ReadUChar( nCol ).ReadUChar( nDummy ).ReadUInt16( nRow ).ReadUInt16( nStyle ).ReadDouble( nValue ).ReadUInt16( nState ).ReadUInt16( nLen );
ScAddress aAddr( nCol, nRow, nTab );
const ScTokenArray *pArray;
QProToSc aConv( *mpStream, aAddr );
QProToSc aConv(*mpStream, pDoc->GetSharedStringPool(), aAddr);
if (ConvOK != aConv.Convert( pArray, nLen ))
eRet = eERR_FORMAT;
else
@ -118,8 +121,8 @@ FltError ScQProReader::readSheet( SCTAB nTab, ScDocument* pDoc, ScQProStyle *pSt
pDoc->EnsureTable(nTab);
pDoc->SetFormulaCell(ScAddress(nCol,nRow,nTab), pFormula);
}
}
break;
}
break;
}
}
return eRet;

View File

@ -65,8 +65,8 @@ void QProToSc::ReadSRD( ScSingleRefData& rSRD, sal_Int8 nPage, sal_Int8 nCol, sa
rSRD.SetFlag3D(true);
}
QProToSc::QProToSc( SvStream& rStream, const ScAddress& rRefPos ) :
ConverterBase( 128 ),
QProToSc::QProToSc( SvStream& rStream, svl::SharedStringPool& rSPool, const ScAddress& rRefPos ) :
ConverterBase(rSPool, 128),
maIn( rStream )
{
aEingPos = rRefPos;

View File

@ -500,6 +500,11 @@ void XclImpChangeTrack::Apply()
// class XclImpChTrFmlConverter
XclImpChTrFmlConverter::XclImpChTrFmlConverter(
XclImpRoot& rRoot, XclImpChangeTrack& rXclChTr ) :
ExcelToSc8( rRoot ),
rChangeTrack( rXclChTr ) {}
XclImpChTrFmlConverter::~XclImpChTrFmlConverter()
{
}

View File

@ -20,6 +20,7 @@
#include <cppuhelper/supportsservice.hxx>
#include <sfx2/app.hxx>
#include <svl/itemprop.hxx>
#include <svl/sharedstringpool.hxx>
#include "scitems.hxx"
#include "funcuno.hxx"
@ -526,6 +527,7 @@ uno::Any SAL_CALL ScFunctionAccess::callFunction( const OUString& aName,
long nArgCount = aArguments.getLength();
const uno::Any* pArgArr = aArguments.getConstArray();
svl::SharedStringPool& rSPool = pDoc->GetSharedStringPool();
aTokenArr.AddOpCode(ocOpen);
for (long nPos=0; nPos<nArgCount; nPos++)
{
@ -555,7 +557,7 @@ uno::Any SAL_CALL ScFunctionAccess::callFunction( const OUString& aName,
{
OUString aUStr;
rArg >>= aUStr;
aTokenArr.AddString( aUStr );
aTokenArr.AddString(rSPool.intern(aUStr));
}
else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<sal_Int16> > *)0 ) ) )
{