Prepare search code for other functions than MATCH and XLOOKUP.

Purpose is to use one set of code for all similar lookup functions, as
they now each have their own code, which is largely identical.
Next steps will be to make the code used by XLOOKUP and MATCH work with
each similar lookup function.
This patch just changes the interface to accomodate other functions.

Change-Id: I6950aa69404f3eb8acbf2d55e247058f3e798814
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163230
Tested-by: Jenkins
Reviewed-by: Balazs Varga <balazs.varga.extern@allotropia.de>
This commit is contained in:
Winfried Donkers
2024-02-16 11:01:17 +01:00
committed by Balazs Varga
parent b508e4f081
commit 88ba9fab08
4 changed files with 42 additions and 34 deletions
+4 -4
View File
@@ -183,7 +183,7 @@ protected:
sal_uInt8 nSortedBinarySearch;
bool bAdvanceQuery;
bool bIgnoreMismatchOnLeadingStrings;
bool bXLookUp;
sal_uInt16 nSearchOpCode;
SCCOL nBestFitCol;
SCROW nBestFitRow;
@@ -276,8 +276,8 @@ public:
nSearchbAscd : (nSearchMode == -2 ? nSearchbDesc : nBinarySearchDisabled));
}
void SetXlookupMode( bool bVal )
{ bXLookUp = bVal; }
void SetLookupMode( sal_uInt16 nVal )
{ nSearchOpCode = nVal; }
};
@@ -325,7 +325,7 @@ class ScQueryCellIterator
using Base::getThisResult;
using Base::nBestFitCol;
using Base::nBestFitRow;
using Base::bXLookUp;
using Base::nSearchOpCode;
bool GetThis();
+17 -10
View File
@@ -67,7 +67,7 @@ ScQueryCellIteratorBase< accessType, queryType >::ScQueryCellIteratorBase(ScDocu
, nSortedBinarySearch( nBinarySearchDisabled )
, bAdvanceQuery( false )
, bIgnoreMismatchOnLeadingStrings( false )
, bXLookUp( false )
, nSearchOpCode( SC_OPCODE_NONE )
, nBestFitCol(SCCOL_MAX)
, nBestFitRow(SCROW_MAX)
{
@@ -207,7 +207,8 @@ void ScQueryCellIteratorBase< accessType, queryType >::PerformQuery()
return;
// XLookUp: Forward/asc/backward/desc search for best fit value, except if we have an exact match
if (bXLookUp && (rEntry.eOp == SC_LESS_EQUAL || rEntry.eOp == SC_GREATER_EQUAL) &&
if (nSearchOpCode == SC_OPCODE_X_LOOKUP &&
(rEntry.eOp == SC_LESS_EQUAL || rEntry.eOp == SC_GREATER_EQUAL) &&
(nBestFitCol != nCol || nBestFitRow != nRow))
{
bool bNumSearch = rItem.meType == ScQueryEntry::ByValue && aCell.hasNumeric();
@@ -315,7 +316,7 @@ void ScQueryCellIteratorBase< accessType, queryType >::InitPos()
// is the one after it.
lastRow = nRow;
// BinarySearch() looks for the first match for XLOOKUP
if (!bXLookUp)
if (nSearchOpCode != SC_OPCODE_X_LOOKUP)
{
ScQueryOp saveOp = op;
op = SC_LESS;
@@ -341,7 +342,7 @@ void ScQueryCellIteratorBase< accessType, queryType >::InitPos()
if( BinarySearch( nCol ))
lastRow = nRow;
}
AccessBase::InitPosFinish(beforeRow, lastRow, bXLookUp);
AccessBase::InitPosFinish(beforeRow, lastRow, (nSearchOpCode == SC_OPCODE_X_LOOKUP));
}
}
@@ -545,7 +546,9 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch( SCCOL col,
{
if (fLastInRangeValue <= nCellVal)
{
if (bXLookUp && nSortedBinarySearch != nSearchbDesc && fLastInRangeValue == nCellVal && aIndexer.getLowIndex() != i)
if (nSearchOpCode == SC_OPCODE_X_LOOKUP &&
nSortedBinarySearch != nSearchbDesc &&
fLastInRangeValue == nCellVal && aIndexer.getLowIndex() != i)
bDone = true;
else
{
@@ -593,7 +596,9 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch( SCCOL col,
aCellStr);
if (nTmp <= 0)
{
if (bXLookUp && nSortedBinarySearch != nSearchbDesc && nTmp == 0 && aIndexer.getLowIndex() != i)
if (nSearchOpCode == SC_OPCODE_X_LOOKUP &&
nSortedBinarySearch != nSearchbDesc &&
nTmp == 0 && aIndexer.getLowIndex() != i)
bDone = true;
else
{
@@ -667,7 +672,8 @@ bool ScQueryCellIteratorBase< accessType, queryType >::BinarySearch( SCCOL col,
{
found = i;
nLastInRange = i;
if (bXLookUp && (nSortedBinarySearch == nSearchbAscd && (rEntry.eOp == SC_LESS_EQUAL || rEntry.eOp == SC_EQUAL)))
if (nSearchOpCode == SC_OPCODE_X_LOOKUP && (nSortedBinarySearch == nSearchbAscd &&
(rEntry.eOp == SC_LESS_EQUAL || rEntry.eOp == SC_EQUAL)))
bDone = true;
else // But keep searching to find the last matching one.
nLo = nMid + 1;
@@ -747,7 +753,7 @@ bool ScQueryCellIterator< accessType >::FindEqualOrSortedLastInRange( SCCOL& nFo
nFoundCol = rDoc.MaxCol()+1;
nFoundRow = rDoc.MaxRow()+1;
if (bXLookUp && nSortedBinarySearch == nBinarySearchDisabled)
if (nSearchOpCode == SC_OPCODE_X_LOOKUP && nSortedBinarySearch == nBinarySearchDisabled)
SetStopOnMismatch( false ); // assume not sorted keys for XLookup
else
SetStopOnMismatch( true ); // assume sorted keys
@@ -762,7 +768,8 @@ bool ScQueryCellIterator< accessType >::FindEqualOrSortedLastInRange( SCCOL& nFo
(maParam.GetEntry(0).eOp == SC_LESS_EQUAL || maParam.GetEntry(0).eOp == SC_GREATER_EQUAL);
// assume not sorted properly if we are using XLookup with forward or backward search
if (bBinary && bXLookUp && nSortedBinarySearch == nBinarySearchDisabled)
if (bBinary && nSearchOpCode == SC_OPCODE_X_LOOKUP &&
nSortedBinarySearch == nBinarySearchDisabled)
bBinary = false;
bool bFound = false;
@@ -855,7 +862,7 @@ bool ScQueryCellIterator< accessType >::FindEqualOrSortedLastInRange( SCCOL& nFo
}
}
}
if ( IsEqualConditionFulfilled() && !bXLookUp )
if ( IsEqualConditionFulfilled() && nSearchOpCode != SC_OPCODE_X_LOOKUP )
{
// Position on last equal entry, except for XLOOKUP,
// which looking for the first equal entry
+3 -3
View File
@@ -61,8 +61,8 @@ enum SearchMode{ searchfwd=1, searchrev=-1, searchbasc=2, searchbdesc=-2 };
struct VectorSearchArguments
{
// struct contains the contents of the function arguments
// Struct owner, ScMatch or ScXLookup
bool isXLookup = false;
// OpCode of struct owner
sal_uInt16 nSearchOpCode = SC_OPCODE_NONE;
// match mode (common, enum values are from XLOOKUP)
// optional 5th argument to set match mode
@@ -541,7 +541,7 @@ private:
inline void TreatDoubleError( double& rVal );
// Lookup using ScLookupCache, @returns true if found and result address
bool LookupQueryWithCache( ScAddress & o_rResultPos, const ScQueryParam & rParam,
const ScComplexRefData* refData, sal_Int8 nSearchMode, bool bXlookupMode ) const;
const ScComplexRefData* refData, sal_Int8 nSearchMode, sal_Int16 nOpCode ) const;
void ScIfJump();
void ScIfError( bool bNAonly );
+18 -17
View File
@@ -4920,7 +4920,7 @@ void ScInterpreter::ScMatch()
return;
VectorSearchArguments vsa;
vsa.isXLookup = false;
vsa.nSearchOpCode = SC_OPCODE_MATCH;
// get match mode
double fType = ( nParamCount == 3 ? GetDouble() : 1.0 );
@@ -7545,7 +7545,8 @@ void ScInterpreter::CalculateLookup(bool bHLookup)
else
{
ScAddress aResultPos( nCol1, nRow1, nTab1);
bFound = LookupQueryWithCache( aResultPos, aParam, refData, 0, false );
bFound = LookupQueryWithCache( aResultPos, aParam, refData, 0,
( bHLookup ? SC_OPCODE_H_LOOKUP : SC_OPCODE_V_LOOKUP ) );
nRow = aResultPos.Row();
nCol = nSpIndex;
}
@@ -7638,7 +7639,7 @@ void ScInterpreter::ScXLookup()
return;
VectorSearchArguments vsa;
vsa.isXLookup = true;
vsa.nSearchOpCode = SC_OPCODE_X_LOOKUP;
if ( nParamCount == 6 )
{
@@ -10663,7 +10664,7 @@ bool ScInterpreter::SearchRangeForValue( VectorSearchArguments& vsa, ScQueryPara
rParam.bByRow = true;
ScAddress aResultPos( vsa.nCol1, vsa.nRow1, vsa.nTab1 );
const ScComplexRefData* refData = nullptr;
if ( LookupQueryWithCache( aResultPos, rParam, refData, vsa.eSearchMode, vsa.isXLookup ) )
if ( LookupQueryWithCache( aResultPos, rParam, refData, vsa.eSearchMode, vsa.nSearchOpCode ) )
vsa.nHitIndex = aResultPos.Row() - vsa.nRow1 + 1;
}
else
@@ -10674,7 +10675,7 @@ bool ScInterpreter::SearchRangeForValue( VectorSearchArguments& vsa, ScQueryPara
ScQueryCellIteratorDirect aCellIter(mrDoc, mrContext, vsa.nTab1, rParam, false, bReverseSearch);
// Advance Entry.nField in Iterator if column changed
aCellIter.SetAdvanceQueryParamEntryField(true);
aCellIter.SetXlookupMode(vsa.isXLookup);
aCellIter.SetLookupMode(vsa.nSearchOpCode);
// TODO: no binary search for column (horizontal) search (use linear)
aCellIter.SetSortedBinarySearchMode(vsa.eSearchMode);
if (rEntry.eOp == SC_EQUAL)
@@ -10741,7 +10742,7 @@ bool ScInterpreter::SearchVectorForValue( VectorSearchArguments& vsa )
case wildcard :
// this mode can only used with XLOOKUP
if ( vsa.isXLookup )
if ( vsa.nSearchOpCode == SC_OPCODE_X_LOOKUP )
{
rEntry.eOp = SC_EQUAL;
if ( vsa.isStringSearch )
@@ -10774,7 +10775,7 @@ bool ScInterpreter::SearchVectorForValue( VectorSearchArguments& vsa )
{
rItem.meType = ScQueryEntry::ByString;
rItem.maString = vsa.sSearchStr;
if ( !vsa.isXLookup )
if ( vsa.nSearchOpCode == SC_OPCODE_MATCH )
{
if ( mrDoc.IsInVBAMode() )
rParam.eSearchType = utl::SearchParam::SearchType::Wildcard;
@@ -10805,12 +10806,12 @@ bool ScInterpreter::SearchVectorForValue( VectorSearchArguments& vsa )
// MATCH expects index starting with 1, XLOOKUP expects index starting with 0
if ( vsa.nHitIndex > 0 )
{
vsa.nIndex = ( vsa.isXLookup ? --vsa.nHitIndex : vsa.nHitIndex );
vsa.nIndex = ( vsa.nSearchOpCode == SC_OPCODE_X_LOOKUP ? --vsa.nHitIndex : vsa.nHitIndex );
return true;
}
else if ( vsa.nHitIndex == 0 && vsa.nBestFit != SCSIZE_MAX )
{
if ( vsa.isXLookup )
if ( vsa.nSearchOpCode == SC_OPCODE_X_LOOKUP )
{
vsa.nIndex = vsa.nBestFit;
if ( !vsa.pMatSrc )
@@ -10832,7 +10833,7 @@ bool ScInterpreter::SearchVectorForValue( VectorSearchArguments& vsa )
static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument& rDoc, ScInterpreterContext& rContext,
const ScQueryParam & rParam, const ScQueryEntry & rEntry, const ScFormulaCell* cell,
const ScComplexRefData* refData, sal_Int8 nSearchMode, bool bXlookupMode )
const ScComplexRefData* refData, sal_Int8 nSearchMode, sal_Int16 nOpCode )
{
if (rEntry.eOp != SC_EQUAL)
{
@@ -10849,7 +10850,7 @@ static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument& rDoc, ScInter
// search for the first GreaterOrEqual value if SearchMode is asc
ScQueryCellIteratorSortedCache aCellIter(rDoc, rContext, rParam.nTab, rParam, false, false);
aCellIter.SetSortedBinarySearchMode(nSearchMode);
aCellIter.SetXlookupMode(bXlookupMode);
aCellIter.SetLookupMode(nOpCode);
if (aCellIter.GetFirst())
{
o_rResultPos.SetCol(aCellIter.GetCol());
@@ -10864,7 +10865,7 @@ static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument& rDoc, ScInter
ScQueryCellIteratorDirect aCellIter(rDoc, rContext, rParam.nTab, rParam, false, bReverse);
aCellIter.SetSortedBinarySearchMode(nSearchMode);
aCellIter.SetXlookupMode(bXlookupMode);
aCellIter.SetLookupMode(nOpCode);
if (aCellIter.FindEqualOrSortedLastInRange(nCol, nRow))
{
o_rResultPos.SetCol(nCol);
@@ -10886,7 +10887,7 @@ static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument& rDoc, ScInter
{
ScQueryCellIteratorSortedCache aCellIter( rDoc, rContext, rParam.nTab, rParam, false, false );
aCellIter.SetSortedBinarySearchMode(nSearchMode);
aCellIter.SetXlookupMode(bXlookupMode);
aCellIter.SetLookupMode(nOpCode);
if (aCellIter.GetFirst())
{
o_rResultPos.SetCol( aCellIter.GetCol());
@@ -10899,7 +10900,7 @@ static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument& rDoc, ScInter
ScQueryCellIteratorDirect aCellIter( rDoc, rContext, rParam.nTab, rParam, false,
static_cast<SearchMode>(nSearchMode) == searchrev);
aCellIter.SetSortedBinarySearchMode(nSearchMode);
aCellIter.SetXlookupMode(bXlookupMode);
aCellIter.SetLookupMode(nOpCode);
if (aCellIter.GetFirst())
{
o_rResultPos.SetCol( aCellIter.GetCol());
@@ -10951,7 +10952,7 @@ static SCROW lcl_getPrevRowWithEmptyValueLookup( const ScLookupCache& rCache,
bool ScInterpreter::LookupQueryWithCache( ScAddress & o_rResultPos,
const ScQueryParam & rParam, const ScComplexRefData* refData,
sal_Int8 nSearchMode, bool bXlookupMode ) const
sal_Int8 nSearchMode, sal_Int16 nOpCode ) const
{
bool bFound = false;
const ScQueryEntry& rEntry = rParam.GetEntry(0);
@@ -10964,7 +10965,7 @@ bool ScInterpreter::LookupQueryWithCache( ScAddress & o_rResultPos,
* parameter so it would affect only the lookup range parameter. */
if (!bColumnsMatch || GetVolatileType() != NOT_VOLATILE)
bFound = lcl_LookupQuery( o_rResultPos, mrDoc, mrContext, rParam, rEntry, pMyFormulaCell,
refData, nSearchMode, bXlookupMode );
refData, nSearchMode, nOpCode );
else
{
ScRange aLookupRange( rParam.nCol1, rParam.nRow1, rParam.nTab,
@@ -10996,7 +10997,7 @@ bool ScInterpreter::LookupQueryWithCache( ScAddress & o_rResultPos,
case ScLookupCache::NOT_CACHED :
case ScLookupCache::CRITERIA_DIFFERENT :
bFound = lcl_LookupQuery( o_rResultPos, mrDoc, mrContext, rParam, rEntry,
pMyFormulaCell, refData, nSearchMode, bXlookupMode );
pMyFormulaCell, refData, nSearchMode, nOpCode );
if (eCacheResult == ScLookupCache::NOT_CACHED)
rCache.insert( o_rResultPos, aCriteria, aPos, bFound);
break;