tdf#154546 skip dispatch when presenter controller is not set
[LibreOffice.git] / sc / inc / queryiter.hxx
blob1d0066de7fb8af3fb9f05f1d3ff90ba200543a29
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #pragma once
22 #include "address.hxx"
23 #include "global.hxx"
24 #include "scdllapi.h"
25 #include "queryparam.hxx"
26 #include "mtvelements.hxx"
27 #include "types.hxx"
29 struct ScComplexRefData;
30 class ScSortedRangeCache;
33 Query-related iterators. There is one template class ScQueryCellIteratorBase
34 that implements most of the shared functionality, specific parts are done
35 by specializing the templates and then subclassing as the actual class to use.
36 A template is used for maximum performance, as that allows fast code specializing,
37 inlining, etc.
38 There are two template arguments:
39 * ScQueryCellIteratorAccess specifies how cells are accessed:
40 + Direct - direct access to cells using mdds.
41 + SortedCache - for accessing unsorted cells in a sorted way using ScSortedRangeCache.
42 * ScQueryCellIteratorType specifies the type of the query operation:
43 + Generic - the generic lookup, used e.g. by VLOOKUP.
44 + CountIf - faster implementation for COUNTIF(S).
46 Specific data should be in specific templated base classes, otherwise adding data
47 members would mean specializing the entire ScQueryCellIteratorBase. Some specific
48 functionality may also be implemented in the base classes or depending on the template
49 parameter.
52 // Data and functionality for accessing cells in a specific way.
53 // Needs specialization, see ScQueryCellIteratorAccess::Direct for what is needed.
54 template< ScQueryCellIteratorAccess accessType >
55 class ScQueryCellIteratorAccessSpecific
59 // The implementation using linear direct mdds access.
60 template<>
61 class ScQueryCellIteratorAccessSpecific< ScQueryCellIteratorAccess::Direct >
63 protected:
64 ScQueryCellIteratorAccessSpecific( ScDocument& rDocument, ScInterpreterContext& rContext,
65 const ScQueryParam& rParam );
66 // Initialize position for new column.
67 void InitPos();
68 // Increase position (next row).
69 void IncPos();
70 // Next mdds block. If access is not direct/linear, then
71 // should call IncPos().
72 void IncBlock();
74 // These members needs to be available already in the base class.
75 typedef sc::CellStoreType::const_position_type PositionType;
76 PositionType maCurPos;
77 ScQueryParam maParam;
78 ScDocument& rDoc;
79 ScInterpreterContext& mrContext;
80 SCTAB nTab;
81 SCCOL nCol;
82 SCROW nRow;
84 class NonEmptyCellIndexer;
85 typedef std::pair<ScRefCellValue, SCROW> BinarySearchCellType;
86 static NonEmptyCellIndexer MakeBinarySearchIndexer(const sc::CellStoreType& rCells,
87 SCROW nStartRow, SCROW nEndRow);
90 // The implementation using ScSortedRangeCache, which allows sorted iteration
91 // of unsorted cells.
92 template<>
93 class ScQueryCellIteratorAccessSpecific< ScQueryCellIteratorAccess::SortedCache >
95 public:
96 void SetSortedRangeCache( const ScSortedRangeCache& cache );
97 template<bool fast>
98 bool IncPosImpl();
99 protected:
100 ScQueryCellIteratorAccessSpecific( ScDocument& rDocument, ScInterpreterContext& rContext,
101 const ScQueryParam& rParam );
102 void InitPosStart();
103 void InitPosFinish( SCROW beforeRow, SCROW lastRow );
104 void IncPos() { IncPosImpl<false>(); }
105 bool IncPosFast() { return IncPosImpl<true>(); }
106 void IncBlock() { IncPos(); } // Cannot skip entire block, not linear.
108 // These members needs to be available already in the base class.
109 typedef sc::CellStoreType::const_position_type PositionType;
110 PositionType maCurPos;
111 ScQueryParam maParam;
112 ScDocument& rDoc;
113 ScInterpreterContext& mrContext;
114 SCTAB nTab;
115 SCCOL nCol;
116 SCROW nRow;
117 const ScColumn* pColumn; // matching nCol, set by InitPos()
119 const ScSortedRangeCache* sortedCache;
120 size_t sortedCachePos;
121 size_t sortedCachePosLast;
123 class SortedCacheIndexer;
124 typedef std::pair<ScRefCellValue, SCROW> BinarySearchCellType;
125 SortedCacheIndexer MakeBinarySearchIndexer(const sc::CellStoreType& rCells,
126 SCROW nStartRow, SCROW nEndRow);
129 // Data and functionality for specific types of query.
130 template< ScQueryCellIteratorType iteratorType >
131 class ScQueryCellIteratorTypeSpecific
133 protected:
134 bool HandleItemFound(); // not implemented, needs specialization
137 // Shared code for query-based iterators. The main class.
138 template< ScQueryCellIteratorAccess accessType, ScQueryCellIteratorType queryType >
139 class ScQueryCellIteratorBase
140 : public ScQueryCellIteratorAccessSpecific< accessType >
141 , public ScQueryCellIteratorTypeSpecific< queryType >
143 typedef ScQueryCellIteratorAccessSpecific< accessType > AccessBase;
144 typedef ScQueryCellIteratorTypeSpecific< queryType > TypeBase;
145 protected:
146 enum StopOnMismatchBits
148 nStopOnMismatchDisabled = 0x00,
149 nStopOnMismatchEnabled = 0x01,
150 nStopOnMismatchOccurred = 0x02,
151 nStopOnMismatchExecuted = nStopOnMismatchEnabled | nStopOnMismatchOccurred
154 enum TestEqualConditionBits
156 nTestEqualConditionDisabled = 0x00,
157 nTestEqualConditionEnabled = 0x01,
158 nTestEqualConditionMatched = 0x02,
159 nTestEqualConditionFulfilled = nTestEqualConditionEnabled | nTestEqualConditionMatched
162 sal_uInt8 nStopOnMismatch;
163 sal_uInt8 nTestEqualCondition;
164 bool bAdvanceQuery;
165 bool bIgnoreMismatchOnLeadingStrings;
167 // Make base members directly visible here (templated bases need 'this->').
168 using AccessBase::maCurPos;
169 using AccessBase::maParam;
170 using AccessBase::rDoc;
171 using AccessBase::mrContext;
172 using AccessBase::nTab;
173 using AccessBase::nCol;
174 using AccessBase::nRow;
175 using AccessBase::IncPos;
176 using AccessBase::IncBlock;
177 using typename AccessBase::BinarySearchCellType;
178 using AccessBase::MakeBinarySearchIndexer;
179 using TypeBase::HandleItemFound;
181 void InitPos();
183 // The actual query function. It will call HandleItemFound() for any matching type
184 // and return if HandleItemFound() returns true.
185 void PerformQuery();
187 /* Only works if no regular expression is involved, only searches for rows in one column,
188 and only the first query entry is considered with simple conditions SC_LESS,SC_LESS_EQUAL,
189 SC_EQUAL (sorted ascending) or SC_GREATER,SC_GREATER_EQUAL (sorted descending). It
190 delivers a starting point set to nRow, i.e. the last row that either matches the searched
191 for value, or the last row that matches the condition. Continue with e.g. GetThis() and
192 GetNext() afterwards. Returns false if the searched for value is not in the search range
193 or if the range is not properly sorted, with nRow in that case set to the first row or after
194 the last row. In that case use GetFirst().
196 bool BinarySearch( SCCOL col, bool forEqual = false );
198 /** If set, iterator stops on first non-matching cell
199 content. May be used in SC_LESS_EQUAL queries where a
200 cell range is assumed to be sorted; stops on first
201 value being greater than the queried value and
202 GetFirst()/GetNext() return NULL. StoppedOnMismatch()
203 returns true then.
204 However, the iterator's conditions are not set to end
205 all queries, GetCol() and GetRow() return values for
206 the non-matching cell, further GetNext() calls may be
207 executed. */
208 void SetStopOnMismatch( bool bVal )
210 nStopOnMismatch = sal::static_int_cast<sal_uInt8>(bVal ? nStopOnMismatchEnabled :
211 nStopOnMismatchDisabled);
213 bool StoppedOnMismatch() const
214 { return nStopOnMismatch == nStopOnMismatchExecuted; }
216 /** If set, an additional test for SC_EQUAL condition is
217 executed in ScTable::ValidQuery() if SC_LESS_EQUAL or
218 SC_GREATER_EQUAL conditions are to be tested. May be
219 used where a cell range is assumed to be sorted to stop
220 if an equal match is found. */
221 void SetTestEqualCondition( bool bVal )
223 nTestEqualCondition = sal::static_int_cast<sal_uInt8>(bVal ?
224 nTestEqualConditionEnabled :
225 nTestEqualConditionDisabled);
227 bool IsEqualConditionFulfilled() const
228 { return nTestEqualCondition == nTestEqualConditionFulfilled; }
230 public:
231 ScQueryCellIteratorBase(ScDocument& rDocument, ScInterpreterContext& rContext, SCTAB nTable,
232 const ScQueryParam& aParam, bool bMod);
233 // when !bMod, the QueryParam has to be filled
234 // (bIsString)
236 // increments all Entry.nField, if column
237 // changes, for ScInterpreter ScHLookup()
238 void SetAdvanceQueryParamEntryField( bool bVal )
239 { bAdvanceQuery = bVal; }
240 void AdvanceQueryParamEntryField();
244 template<>
245 class ScQueryCellIteratorTypeSpecific< ScQueryCellIteratorType::Generic >
247 protected:
248 bool HandleItemFound();
249 bool getThisResult;
252 // The generic query iterator, used e.g. by VLOOKUP.
253 template< ScQueryCellIteratorAccess accessType >
254 class ScQueryCellIterator
255 : public ScQueryCellIteratorBase< accessType, ScQueryCellIteratorType::Generic >
257 typedef ScQueryCellIteratorBase< accessType, ScQueryCellIteratorType::Generic > Base;
258 // Make base members directly visible here (templated bases need 'this->').
259 using Base::maParam;
260 using Base::rDoc;
261 using Base::mrContext;
262 using Base::nTab;
263 using Base::nCol;
264 using Base::nRow;
265 using Base::InitPos;
266 using Base::IncPos;
267 using Base::bIgnoreMismatchOnLeadingStrings;
268 using Base::SetStopOnMismatch;
269 using Base::SetTestEqualCondition;
270 using Base::BinarySearch;
271 using typename Base::PositionType;
272 using Base::maCurPos;
273 using Base::IsEqualConditionFulfilled;
274 using Base::bAdvanceQuery;
275 using Base::StoppedOnMismatch;
276 using Base::nStopOnMismatch;
277 using Base::nStopOnMismatchEnabled;
278 using Base::nTestEqualCondition;
279 using Base::nTestEqualConditionEnabled;
280 using Base::PerformQuery;
281 using Base::getThisResult;
283 bool GetThis();
285 public:
286 ScQueryCellIterator(ScDocument& rDocument, ScInterpreterContext& rContext, SCTAB nTable,
287 const ScQueryParam& aParam, bool bMod)
288 : Base( rDocument, rContext, nTable, aParam, bMod ) {}
289 bool GetFirst();
290 bool GetNext();
291 SCCOL GetCol() const { return nCol; }
292 SCROW GetRow() const { return nRow; }
294 /** In a range assumed to be sorted find either the last of
295 a sequence of equal entries or the last being less than
296 (or greater than) the queried value. Used by the
297 interpreter for [HV]?LOOKUP() and MATCH(). Column and
298 row position of the found entry are returned, otherwise
299 invalid.
301 The search does not stop when encountering a string and does not
302 assume that no values follow anymore.
303 If querying for a string a mismatch on the first
304 entry, e.g. column header, is ignored.
306 @ATTENTION! StopOnMismatch, TestEqualCondition and
307 the internal IgnoreMismatchOnLeadingStrings and query
308 params are in an undefined state upon return! The
309 iterator is not usable anymore except for obtaining the
310 number format!
312 bool FindEqualOrSortedLastInRange( SCCOL& nFoundCol, SCROW& nFoundRow );
315 typedef ScQueryCellIterator< ScQueryCellIteratorAccess::Direct > ScQueryCellIteratorDirect;
317 class ScQueryCellIteratorSortedCache
318 : public ScQueryCellIterator< ScQueryCellIteratorAccess::SortedCache >
320 typedef ScQueryCellIterator< ScQueryCellIteratorAccess::SortedCache > Base;
321 public:
322 ScQueryCellIteratorSortedCache(ScDocument& rDocument, ScInterpreterContext& rContext,
323 SCTAB nTable, const ScQueryParam& aParam, bool bMod)
324 : Base( rDocument, rContext, nTable, aParam, bMod ) {}
325 // Returns true if this iterator can be used for the given query.
326 static bool CanBeUsed(ScDocument& rDoc, const ScQueryParam& aParam,
327 SCTAB nTab, const ScFormulaCell* cell, const ScComplexRefData* refData,
328 ScInterpreterContext& context);
332 template<>
333 class ScQueryCellIteratorTypeSpecific< ScQueryCellIteratorType::CountIf >
335 protected:
336 bool HandleItemFound();
337 sal_uInt64 countIfCount;
340 // Used by ScInterpreter::ScCountIf.
341 template< ScQueryCellIteratorAccess accessType >
342 class ScCountIfCellIterator
343 : public ScQueryCellIteratorBase< accessType, ScQueryCellIteratorType::CountIf >
345 protected:
346 typedef ScQueryCellIteratorBase< accessType, ScQueryCellIteratorType::CountIf > Base;
347 // Make base members directly visible here (templated bases need 'this->').
348 using Base::maParam;
349 using Base::rDoc;
350 using Base::nTab;
351 using Base::nCol;
352 using Base::nRow;
353 using Base::InitPos;
354 using Base::PerformQuery;
355 using Base::SetAdvanceQueryParamEntryField;
356 using Base::countIfCount;
358 public:
359 ScCountIfCellIterator(ScDocument& rDocument, ScInterpreterContext& rContext, SCTAB nTable,
360 const ScQueryParam& aParam, bool bMod)
361 : Base( rDocument, rContext, nTable, aParam, bMod ) {}
362 sal_uInt64 GetCount();
365 typedef ScCountIfCellIterator< ScQueryCellIteratorAccess::Direct > ScCountIfCellIteratorDirect;
367 class ScCountIfCellIteratorSortedCache
368 : public ScCountIfCellIterator< ScQueryCellIteratorAccess::SortedCache >
370 typedef ScCountIfCellIterator< ScQueryCellIteratorAccess::SortedCache > Base;
371 public:
372 ScCountIfCellIteratorSortedCache(ScDocument& rDocument, ScInterpreterContext& rContext,
373 SCTAB nTable, const ScQueryParam& aParam, bool bMod)
374 : Base( rDocument, rContext, nTable, aParam, bMod ) {}
375 // Returns true if this iterator can be used for the given query.
376 static bool CanBeUsed(ScDocument& rDoc, const ScQueryParam& aParam,
377 SCTAB nTab, const ScFormulaCell* cell, const ScComplexRefData* refData,
378 ScInterpreterContext& context);
381 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */