summaryrefslogtreecommitdiff
path: root/sc/inc/queryiter.hxx
blob: ae7b8066c57bd2794f9eaacbb6b129b4b4182247 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#pragma once

#include "address.hxx"
#include "global.hxx"
#include "scdllapi.h"
#include "queryparam.hxx"
#include "mtvelements.hxx"
#include "types.hxx"

// Query-related iterators. There is one template class ScQueryCellIteratorBase
// that implements most of the shared functionality, specific parts are done
// by specializing the templates and then subclassing as the actual class to use.

// Specific data should be in ScQueryCellIteratorSpecific (otherwise adding data
// members here would mean specializing the entire ScQueryCellIteratorBase).
template< ScQueryCellIteratorType iteratorType >
class ScQueryCellIteratorSpecific
{
};

// Shared code for query-based iterators.
template< ScQueryCellIteratorType iteratorType >
class ScQueryCellIteratorBase : public ScQueryCellIteratorSpecific< iteratorType >
{
protected:
    enum StopOnMismatchBits
    {
        nStopOnMismatchDisabled = 0x00,
        nStopOnMismatchEnabled  = 0x01,
        nStopOnMismatchOccurred  = 0x02,
        nStopOnMismatchExecuted = nStopOnMismatchEnabled | nStopOnMismatchOccurred
    };

    enum TestEqualConditionBits
    {
        nTestEqualConditionDisabled = 0x00,
        nTestEqualConditionEnabled  = 0x01,
        nTestEqualConditionMatched  = 0x02,
        nTestEqualConditionFulfilled = nTestEqualConditionEnabled | nTestEqualConditionMatched
    };

    typedef sc::CellStoreType::const_position_type PositionType;
    PositionType maCurPos;

    ScQueryParam    maParam;
    ScDocument&     rDoc;
    const ScInterpreterContext& mrContext;
    SCTAB           nTab;
    SCCOL           nCol;
    SCROW           nRow;
    sal_uInt8            nStopOnMismatch;
    sal_uInt8            nTestEqualCondition;
    bool            bAdvanceQuery;
    bool            bIgnoreMismatchOnLeadingStrings;

    /** Initialize position for new column. */
    void InitPos();
    void IncPos();
    void IncBlock();

    // The actual query function. It will call HandleItemFound() for any matching type
    // and return if HandleItemFound() returns true.
    void PerformQuery();
    bool HandleItemFound(); // not implemented, needs specialization

    SCCOL           GetCol() const { return nCol; }
    SCROW           GetRow() const { return nRow; }

public:
                    ScQueryCellIteratorBase(ScDocument& rDocument, const ScInterpreterContext& rContext, SCTAB nTable,
                                            const ScQueryParam& aParam, bool bMod);
                                        // when !bMod, the QueryParam has to be filled
                                        // (bIsString)

                    // increments all Entry.nField, if column
                    // changes, for ScInterpreter ScHLookup()
    void            SetAdvanceQueryParamEntryField( bool bVal )
                        { bAdvanceQuery = bVal; }
    void            AdvanceQueryParamEntryField();

                    /** If set, iterator stops on first non-matching cell
                        content. May be used in SC_LESS_EQUAL queries where a
                        cell range is assumed to be sorted; stops on first
                        value being greater than the queried value and
                        GetFirst()/GetNext() return NULL. StoppedOnMismatch()
                        returns true then.
                        However, the iterator's conditions are not set to end
                        all queries, GetCol() and GetRow() return values for
                        the non-matching cell, further GetNext() calls may be
                        executed. */
    void            SetStopOnMismatch( bool bVal )
                        {
                            nStopOnMismatch = sal::static_int_cast<sal_uInt8>(bVal ? nStopOnMismatchEnabled :
                                nStopOnMismatchDisabled);
                        }
    bool            StoppedOnMismatch() const
                        { return nStopOnMismatch == nStopOnMismatchExecuted; }

                    /** If set, an additional test for SC_EQUAL condition is
                        executed in ScTable::ValidQuery() if SC_LESS_EQUAL or
                        SC_GREATER_EQUAL conditions are to be tested. May be
                        used where a cell range is assumed to be sorted to stop
                        if an equal match is found. */
    void            SetTestEqualCondition( bool bVal )
                        {
                            nTestEqualCondition = sal::static_int_cast<sal_uInt8>(bVal ?
                                nTestEqualConditionEnabled :
                                nTestEqualConditionDisabled);
                        }
    bool            IsEqualConditionFulfilled() const
                        { return nTestEqualCondition == nTestEqualConditionFulfilled; }
};

template<>
class ScQueryCellIteratorSpecific< ScQueryCellIteratorType::Generic >
{
protected:
    bool getThisResult;
};

// The generic query iterator, used e.g. by VLOOKUP.
class ScQueryCellIterator : public ScQueryCellIteratorBase< ScQueryCellIteratorType::Generic >
{
                    /* Only works if no regular expression is involved, only
                       searches for rows in one column, and only the first
                       query entry is considered with simple conditions
                       SC_LESS_EQUAL (sorted ascending) or SC_GREATER_EQUAL
                       (sorted descending). Check these things before
                       invocation! Delivers a starting point, continue with
                       GetThis() and GetNext() afterwards. Introduced for
                       FindEqualOrSortedLastInRange()
                     */
    bool BinarySearch();

    bool GetThis();

public:
    using ScQueryCellIteratorBase::ScQueryCellIteratorBase;
    bool GetFirst();
    bool GetNext();
    using ScQueryCellIteratorBase::GetCol;
    using ScQueryCellIteratorBase::GetRow;

                    /** In a range assumed to be sorted find either the last of
                        a sequence of equal entries or the last being less than
                        (or greater than) the queried value. Used by the
                        interpreter for [HV]?LOOKUP() and MATCH(). Column and
                        row position of the found entry are returned, otherwise
                        invalid.

                        The search does not stop when encountering a string and does not
                        assume that no values follow anymore.
                        If querying for a string a mismatch on the first
                        entry, e.g. column header, is ignored.

                        @ATTENTION! StopOnMismatch, TestEqualCondition and
                        the internal IgnoreMismatchOnLeadingStrings and query
                        params are in an undefined state upon return! The
                        iterator is not usable anymore except for obtaining the
                        number format!
                      */
    bool            FindEqualOrSortedLastInRange( SCCOL& nFoundCol, SCROW& nFoundRow );
};


template<>
class ScQueryCellIteratorSpecific< ScQueryCellIteratorType::CountIf >
{
protected:
    sal_uInt64 countIfCount;
};

// Used by ScInterpreter::ScCountIf.
class ScCountIfCellIterator : public ScQueryCellIteratorBase< ScQueryCellIteratorType::CountIf >
{
public:
    using ScQueryCellIteratorBase::ScQueryCellIteratorBase;
    sal_uInt64 GetCount();
};

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */