From cfc9cef1e26e98153eb93229a9c18a674a3ebf11 Mon Sep 17 00:00:00 2001
From: Kohei Yoshida <kohei.yoshida@collabora.com>
Date: Fri, 6 Dec 2013 10:43:38 -0500
Subject: [PATCH 043/109] fdo#69518: Correctly handle the old constraint
syntax.
We apparently support this syntax for ODF-backward compatibility.
To fix this, I resurrected ScDPObject::ParseFilters() which was removed as
unused, adjusted it for the String->OUString change, and changed the filter
data structure to the UNO one rather than using the old one we no longer use
elsewhere.
(cherry picked from commit 1d85c8df2fb9cb25fc524485339ae9f11e8da676)
Conflicts:
sc/inc/dpobject.hxx
sc/source/core/data/dpobject.cxx
sc/source/core/tool/interpr2.cxx
Change-Id: If52b38aaa1e8b208fb0ef9d92a6e853decdf43e3
Reviewed-on: https://gerrit.libreoffice.org/6962
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Eike Rathke <erack@redhat.com>
---
sc/inc/dpobject.hxx | 8 +-
sc/inc/dpoutput.hxx | 21 -----
sc/source/core/data/dpobject.cxx | 163 ++++++++++++++++++++-------------------
sc/source/core/tool/interpr2.cxx | 15 ++++
4 files changed, 103 insertions(+), 104 deletions(-)
diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index 735b033..8505a53 100644
--- a/sc/inc/dpobject.hxx
+++ b/sc/inc/dpobject.hxx
@@ -183,9 +183,11 @@ public:
const OUString& rDataFieldName,
std::vector<com::sun::star::sheet::DataPilotFieldFilter>& rFilters);
- bool ParseFilters( ScDPGetPivotDataField& rTarget,
- std::vector< ScDPGetPivotDataField >& rFilters,
- const OUString& rFilterList );
+ bool ParseFilters(
+ OUString& rDataFieldName,
+ std::vector<com::sun::star::sheet::DataPilotFieldFilter>& rFilters,
+ std::vector<com::sun::star::sheet::GeneralFunction>& rFilterFuncs,
+ const OUString& rFilterList );
void GetMemberResultNames(ScDPUniqueStringSet& rNames, long nDimension);
diff --git a/sc/inc/dpoutput.hxx b/sc/inc/dpoutput.hxx
index 293d937..7b38c7e 100644
--- a/sc/inc/dpoutput.hxx
+++ b/sc/inc/dpoutput.hxx
@@ -41,29 +41,8 @@ namespace com { namespace sun { namespace star { namespace sheet {
class Rectangle;
class ScDocument;
-
struct ScDPOutLevelData;
-
-struct ScDPGetPivotDataField
-{
- OUString maFieldName;
- com::sun::star::sheet::GeneralFunction meFunction;
-
- bool mbValIsStr;
- OUString maValStr;
- double mnValNum;
-
- ScDPGetPivotDataField() :
- meFunction( com::sun::star::sheet::GeneralFunction_NONE ),
- mbValIsStr( false ),
- mnValNum( 0.0 )
- {
- }
-};
-
-
-
class ScDPOutput
{
private:
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 3a45a34..677ccd5 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -1400,25 +1400,27 @@ void ScDPObject::GetMemberResultNames(ScDPUniqueStringSet& rNames, long nDimensi
pOutput->GetMemberResultNames(rNames, nDimension); // used only with table data -> level not needed
}
-static bool lcl_Dequote( const String& rSource, xub_StrLen nStartPos, xub_StrLen& rEndPos, String& rResult )
+namespace {
+
+bool dequote( const OUString& rSource, sal_Int32 nStartPos, sal_Int32& rEndPos, OUString& rResult )
{
// nStartPos has to point to opening quote
bool bRet = false;
const sal_Unicode cQuote = '\'';
- if ( rSource.GetChar(nStartPos) == cQuote )
+ if (rSource[nStartPos] == cQuote)
{
OUStringBuffer aBuffer;
- xub_StrLen nPos = nStartPos + 1;
- const xub_StrLen nLen = rSource.Len();
+ sal_Int32 nPos = nStartPos + 1;
+ const sal_Int32 nLen = rSource.getLength();
while ( nPos < nLen )
{
- const sal_Unicode cNext = rSource.GetChar(nPos);
+ const sal_Unicode cNext = rSource[nPos];
if ( cNext == cQuote )
{
- if ( nPos+1 < nLen && rSource.GetChar(nPos+1) == cQuote )
+ if (nPos+1 < nLen && rSource[nPos+1] == cQuote)
{
// double quote is used for an embedded quote
aBuffer.append( cNext ); // append one quote
@@ -1449,7 +1451,7 @@ struct ScGetPivotDataFunctionEntry
sheet::GeneralFunction eFunc;
};
-static bool lcl_ParseFunction( const String& rList, xub_StrLen nStartPos, xub_StrLen& rEndPos, sheet::GeneralFunction& rFunc )
+bool parseFunction( const OUString& rList, sal_Int32 nStartPos, sal_Int32& rEndPos, sheet::GeneralFunction& rFunc )
{
static const ScGetPivotDataFunctionEntry aFunctions[] =
{
@@ -1471,22 +1473,22 @@ static bool lcl_ParseFunction( const String& rList, xub_StrLen nStartPos, xub_St
{ "StdDevp", sheet::GeneralFunction_STDEVP }
};
- const xub_StrLen nListLen = rList.Len();
- while ( nStartPos < nListLen && rList.GetChar(nStartPos) == ' ' )
+ const sal_Int32 nListLen = rList.getLength();
+ while (nStartPos < nListLen && rList[nStartPos] == ' ')
++nStartPos;
bool bParsed = false;
bool bFound = false;
- String aFuncStr;
- xub_StrLen nFuncEnd = 0;
- if ( nStartPos < nListLen && rList.GetChar(nStartPos) == '\'' )
- bParsed = lcl_Dequote( rList, nStartPos, nFuncEnd, aFuncStr );
+ OUString aFuncStr;
+ sal_Int32 nFuncEnd = 0;
+ if (nStartPos < nListLen && rList[nStartPos] == '\'')
+ bParsed = dequote( rList, nStartPos, nFuncEnd, aFuncStr );
else
{
- nFuncEnd = rList.Search( static_cast<sal_Unicode>(']'), nStartPos );
- if ( nFuncEnd != STRING_NOTFOUND )
+ nFuncEnd = rList.indexOf(']', nStartPos);
+ if (nFuncEnd >= 0)
{
- aFuncStr = rList.Copy( nStartPos, nFuncEnd - nStartPos );
+ aFuncStr = rList.copy(nStartPos, nFuncEnd - nStartPos);
bParsed = true;
}
}
@@ -1498,12 +1500,12 @@ static bool lcl_ParseFunction( const String& rList, xub_StrLen nStartPos, xub_St
const sal_Int32 nFuncCount = sizeof(aFunctions) / sizeof(aFunctions[0]);
for ( sal_Int32 nFunc=0; nFunc<nFuncCount && !bFound; nFunc++ )
{
- if ( aFuncStr.EqualsIgnoreCaseAscii( aFunctions[nFunc].pName ) )
+ if (aFuncStr.equalsIgnoreAsciiCaseAscii(aFunctions[nFunc].pName))
{
rFunc = aFunctions[nFunc].eFunc;
bFound = true;
- while ( nFuncEnd < nListLen && rList.GetChar(nFuncEnd) == ' ' )
+ while (nFuncEnd < nListLen && rList[nFuncEnd] == ' ')
++nFuncEnd;
rEndPos = nFuncEnd;
}
@@ -1513,48 +1515,49 @@ static bool lcl_ParseFunction( const String& rList, xub_StrLen nStartPos, xub_St
return bFound;
}
-static bool lcl_IsAtStart( const String& rList, const String& rSearch, sal_Int32& rMatched,
- bool bAllowBracket, sheet::GeneralFunction* pFunc )
+bool isAtStart(
+ const OUString& rList, const OUString& rSearch, sal_Int32& rMatched,
+ bool bAllowBracket, sheet::GeneralFunction* pFunc )
{
sal_Int32 nMatchList = 0;
sal_Int32 nMatchSearch = 0;
- sal_Unicode cFirst = rList.GetChar(0);
+ sal_Unicode cFirst = rList[0];
if ( cFirst == '\'' || cFirst == '[' )
{
// quoted string or string in brackets must match completely
- String aDequoted;
- xub_StrLen nQuoteEnd = 0;
+ OUString aDequoted;
+ sal_Int32 nQuoteEnd = 0;
bool bParsed = false;
if ( cFirst == '\'' )
- bParsed = lcl_Dequote( rList, 0, nQuoteEnd, aDequoted );
+ bParsed = dequote( rList, 0, nQuoteEnd, aDequoted );
else if ( cFirst == '[' )
{
// skip spaces after the opening bracket
- xub_StrLen nStartPos = 1;
- const xub_StrLen nListLen = rList.Len();
- while ( nStartPos < nListLen && rList.GetChar(nStartPos) == ' ' )
+ sal_Int32 nStartPos = 1;
+ const sal_Int32 nListLen = rList.getLength();
+ while (nStartPos < nListLen && rList[nStartPos] == ' ')
++nStartPos;
- if ( rList.GetChar(nStartPos) == '\'' ) // quoted within the brackets?
+ if (nStartPos < nListLen && rList[nStartPos] == '\'') // quoted within the brackets?
{
- if ( lcl_Dequote( rList, nStartPos, nQuoteEnd, aDequoted ) )
+ if ( dequote( rList, nStartPos, nQuoteEnd, aDequoted ) )
{
// after the quoted string, there must be the closing bracket, optionally preceded by spaces,
// and/or a function name
- while ( nQuoteEnd < nListLen && rList.GetChar(nQuoteEnd) == ' ' )
+ while (nQuoteEnd < nListLen && rList[nQuoteEnd] == ' ')
++nQuoteEnd;
// semicolon separates function name
- if ( nQuoteEnd < nListLen && rList.GetChar(nQuoteEnd) == ';' && pFunc )
+ if (nQuoteEnd < nListLen && rList[nQuoteEnd] == ';' && pFunc)
{
- xub_StrLen nFuncEnd = 0;
- if ( lcl_ParseFunction( rList, nQuoteEnd + 1, nFuncEnd, *pFunc ) )
+ sal_Int32 nFuncEnd = 0;
+ if ( parseFunction( rList, nQuoteEnd + 1, nFuncEnd, *pFunc ) )
nQuoteEnd = nFuncEnd;
}
- if ( nQuoteEnd < nListLen && rList.GetChar(nQuoteEnd) == ']' )
+ if (nQuoteEnd < nListLen && rList[nQuoteEnd] == ']')
{
++nQuoteEnd; // include the closing bracket for the matched length
bParsed = true;
@@ -1565,19 +1568,19 @@ static bool lcl_IsAtStart( const String& rList, const String& rSearch, sal_Int32
{
// implicit quoting to the closing bracket
- xub_StrLen nClosePos = rList.Search( static_cast<sal_Unicode>(']'), nStartPos );
- if ( nClosePos != STRING_NOTFOUND )
+ sal_Int32 nClosePos = rList.indexOf(']', nStartPos);
+ if (nClosePos >= 0)
{
- xub_StrLen nNameEnd = nClosePos;
- xub_StrLen nSemiPos = rList.Search( static_cast<sal_Unicode>(';'), nStartPos );
- if ( nSemiPos != STRING_NOTFOUND && nSemiPos < nClosePos && pFunc )
+ sal_Int32 nNameEnd = nClosePos;
+ sal_Int32 nSemiPos = rList.indexOf(';', nStartPos);
+ if (nSemiPos >= 0 && nSemiPos < nClosePos && pFunc)
{
- xub_StrLen nFuncEnd = 0;
- if ( lcl_ParseFunction( rList, nSemiPos + 1, nFuncEnd, *pFunc ) )
+ sal_Int32 nFuncEnd = 0;
+ if (parseFunction(rList, nSemiPos+1, nFuncEnd, *pFunc))
nNameEnd = nSemiPos;
}
- aDequoted = rList.Copy( nStartPos, nNameEnd - nStartPos );
+ aDequoted = rList.copy(nStartPos, nNameEnd - nStartPos);
// spaces before the closing bracket or semicolon
aDequoted = comphelper::string::stripEnd(aDequoted, ' ');
nQuoteEnd = nClosePos + 1;
@@ -1589,26 +1592,26 @@ static bool lcl_IsAtStart( const String& rList, const String& rSearch, sal_Int32
if ( bParsed && ScGlobal::GetpTransliteration()->isEqual( aDequoted, rSearch ) )
{
nMatchList = nQuoteEnd; // match count in the list string, including quotes
- nMatchSearch = rSearch.Len();
+ nMatchSearch = rSearch.getLength();
}
}
else
{
// otherwise look for search string at the start of rList
- ScGlobal::GetpTransliteration()->equals( rList, 0, rList.Len(), nMatchList,
- rSearch, 0, rSearch.Len(), nMatchSearch );
+ ScGlobal::GetpTransliteration()->equals(
+ rList, 0, rList.getLength(), nMatchList, rSearch, 0, rSearch.getLength(), nMatchSearch);
}
- if ( nMatchSearch == rSearch.Len() )
+ if (nMatchSearch == rSearch.getLength())
{
// search string is at start of rList - look for following space or end of string
bool bValid = false;
- if ( sal::static_int_cast<xub_StrLen>(nMatchList) >= rList.Len() )
+ if ( sal::static_int_cast<sal_Int32>(nMatchList) >= rList.getLength() )
bValid = true;
else
{
- sal_Unicode cNext = rList.GetChar(sal::static_int_cast<xub_StrLen>(nMatchList));
+ sal_Unicode cNext = rList[nMatchList];
if ( cNext == ' ' || ( bAllowBracket && cNext == '[' ) )
bValid = true;
}
@@ -1623,17 +1626,20 @@ static bool lcl_IsAtStart( const String& rList, const String& rSearch, sal_Int32
return false;
}
-bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
- std::vector< ScDPGetPivotDataField >& rFilters,
- const OUString& rFilterList )
+} // anonymous namespace
+
+bool ScDPObject::ParseFilters(
+ OUString& rDataFieldName,
+ std::vector<sheet::DataPilotFieldFilter>& rFilters,
+ std::vector<sheet::GeneralFunction>& rFilterFuncs, const OUString& rFilterList )
{
// parse the string rFilterList into parameters for GetPivotData
CreateObjects(); // create xSource if not already done
- std::vector<String> aDataNames; // data fields (source name)
- std::vector<String> aGivenNames; // data fields (compound name)
- std::vector<String> aFieldNames; // column/row/data fields
+ std::vector<OUString> aDataNames; // data fields (source name)
+ std::vector<OUString> aGivenNames; // data fields (compound name)
+ std::vector<OUString> aFieldNames; // column/row/data fields
std::vector< uno::Sequence<OUString> > aFieldValues;
//
@@ -1691,7 +1697,7 @@ bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
{
uno::Reference<container::XNameAccess> xMembers = xLevSupp->getMembers();
- String aFieldName( xLevNam->getName() );
+ OUString aFieldName( xLevNam->getName() );
uno::Sequence<OUString> aMemberNames( xMembers->getElementNames() );
aFieldNames.push_back( aFieldName );
@@ -1713,8 +1719,8 @@ bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
bool bError = false;
bool bHasData = false;
- String aRemaining(comphelper::string::strip(rFilterList, ' '));
- while ( aRemaining.Len() && !bError )
+ OUString aRemaining(comphelper::string::strip(rFilterList, ' '));
+ while (!aRemaining.isEmpty() && !bError)
{
bool bUsed = false;
@@ -1722,17 +1728,17 @@ bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
for ( SCSIZE nDataPos=0; nDataPos<nDataFields && !bUsed; nDataPos++ )
{
- String aFound;
+ OUString aFound;
sal_Int32 nMatched = 0;
- if ( lcl_IsAtStart( aRemaining, aDataNames[nDataPos], nMatched, false, NULL ) )
+ if (isAtStart(aRemaining, aDataNames[nDataPos], nMatched, false, NULL))
aFound = aDataNames[nDataPos];
- else if ( lcl_IsAtStart( aRemaining, aGivenNames[nDataPos], nMatched, false, NULL ) )
+ else if (isAtStart(aRemaining, aGivenNames[nDataPos], nMatched, false, NULL))
aFound = aGivenNames[nDataPos];
- if ( aFound.Len() )
+ if (!aFound.isEmpty())
{
- rTarget.maFieldName = aFound;
- aRemaining.Erase( 0, sal::static_int_cast<xub_StrLen>(nMatched) );
+ rDataFieldName = aFound;
+ aRemaining = aRemaining.copy(nMatched);
bHasData = true;
bUsed = true;
}
@@ -1740,21 +1746,21 @@ bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
// look for field name
- String aSpecField;
+ OUString aSpecField;
bool bHasFieldName = false;
if ( !bUsed )
{
sal_Int32 nMatched = 0;
for ( SCSIZE nField=0; nField<nFieldCount && !bHasFieldName; nField++ )
{
- if ( lcl_IsAtStart( aRemaining, aFieldNames[nField], nMatched, true, NULL ) )
+ if (isAtStart(aRemaining, aFieldNames[nField], nMatched, true, NULL))
{
aSpecField = aFieldNames[nField];
- aRemaining.Erase( 0, sal::static_int_cast<xub_StrLen>(nMatched) );
+ aRemaining = aRemaining.copy(nMatched);
aRemaining = comphelper::string::stripStart(aRemaining, ' ');
// field name has to be followed by item name in brackets
- if ( aRemaining.GetChar(0) == '[' )
+ if (!aRemaining.isEmpty() && aRemaining[0] == '[')
{
bHasFieldName = true;
// bUsed remains false - still need the item
@@ -1774,8 +1780,8 @@ bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
{
bool bItemFound = false;
sal_Int32 nMatched = 0;
- String aFoundName;
- String aFoundValue;
+ OUString aFoundName;
+ OUString aFoundValue;
sheet::GeneralFunction eFunc = sheet::GeneralFunction_NONE;
sheet::GeneralFunction eFoundFunc = sheet::GeneralFunction_NONE;
@@ -1790,7 +1796,7 @@ bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
const OUString* pItemArr = rItems.getConstArray();
for ( sal_Int32 nItem=0; nItem<nItemCount; nItem++ )
{
- if ( lcl_IsAtStart( aRemaining, pItemArr[nItem], nMatched, false, &eFunc ) )
+ if ( isAtStart( aRemaining, pItemArr[nItem], nMatched, false, &eFunc ) )
{
if ( bItemFound )
bError = true; // duplicate (also across fields)
@@ -1809,15 +1815,12 @@ bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
if ( bItemFound && !bError )
{
- ScDPGetPivotDataField aField;
- aField.maFieldName = aFoundName;
- aField.meFunction = eFoundFunc;
- aField.mbValIsStr = true;
- aField.maValStr = aFoundValue;
- aField.mnValNum = 0.0;
- rFilters.push_back( aField );
-
- aRemaining.Erase( 0, sal::static_int_cast<xub_StrLen>(nMatched) );
+ sheet::DataPilotFieldFilter aField;
+ aField.FieldName = aFoundName;
+ aField.MatchValue = aFoundValue;
+ rFilters.push_back(aField);
+ rFilterFuncs.push_back(eFoundFunc);
+ aRemaining = aRemaining.copy(nMatched);
}
}
@@ -1831,7 +1834,7 @@ bool ScDPObject::ParseFilters( ScDPGetPivotDataField& rTarget,
if ( !bError && !bHasData && aDataNames.size() == 1 )
{
// if there's only one data field, its name need not be specified
- rTarget.maFieldName = aDataNames[0];
+ rDataFieldName = aDataNames[0];
bHasData = true;
}
diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx
index 7cc59de..a0f270d 100644
--- a/sc/source/core/tool/interpr2.cxx
+++ b/sc/source/core/tool/interpr2.cxx
@@ -3005,6 +3005,21 @@ void ScInterpreter::ScGetPivotData()
return;
}
+ if (bOldSyntax)
+ {
+ OUString aFilterStr = aDataFieldName;
+ std::vector<sheet::GeneralFunction> aFilterFuncs;
+ if (!pDPObj->ParseFilters(aDataFieldName, aFilters, aFilterFuncs, aFilterStr))
+ {
+ PushError(errNoRef);
+ return;
+ }
+
+ // TODO : For now, we ignore filter functions since we couldn't find a
+ // live example of how they are supposed to be used. We'll support
+ // this again once we come across a real-world example.
+ }
+
double fVal = pDPObj->GetPivotData(aDataFieldName, aFilters);
if (rtl::math::isNan(fVal))
{
--
1.8.4.2