Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #ifndef INCLUDED_SC_INC_LOOKUPCACHE_HXX
21 : #define INCLUDED_SC_INC_LOOKUPCACHE_HXX
22 :
23 : #include "address.hxx"
24 : #include "global.hxx"
25 : #include <formula/token.hxx>
26 : #include <svl/listener.hxx>
27 :
28 : #include <unordered_map>
29 :
30 : class ScDocument;
31 : struct ScQueryEntry;
32 :
33 : /** Lookup cache for one range used with interpreter functions such as VLOOKUP
34 : and MATCH. Caches query for a specific row and the resulting address looked
35 : up, in case other lookups of the same query in the same row are to be
36 : performed, which usually occur to obtain a different offset column of the
37 : same query.
38 : */
39 :
40 : class ScLookupCache : public SvtListener
41 : {
42 : public:
43 :
44 : enum Result
45 : {
46 : NOT_CACHED, /// Query not found in cache.
47 : CRITERIA_DIFFERENT, /// Different criteria for same query position exists.
48 : NOT_AVAILABLE, /// Criteria not available in lookup range.
49 : FOUND /// Criteria found.
50 : };
51 :
52 : enum QueryOp
53 : {
54 : UNKNOWN,
55 : EQUAL,
56 : LESS_EQUAL,
57 : GREATER_EQUAL
58 : };
59 :
60 : class QueryCriteria
61 : {
62 : union
63 : {
64 : double mfVal;
65 : const OUString *mpStr;
66 : };
67 : bool mbAlloc : 1;
68 : bool mbString : 1;
69 : QueryOp meOp : 2;
70 :
71 362 : void deleteString()
72 : {
73 362 : if (mbAlloc && mbString)
74 129 : delete mpStr;
75 362 : }
76 :
77 : QueryCriteria & operator=( const QueryCriteria & r ) SAL_DELETED_FUNCTION;
78 :
79 : public:
80 :
81 : explicit QueryCriteria( const ScQueryEntry & rEntry );
82 : QueryCriteria( const QueryCriteria & r );
83 : ~QueryCriteria();
84 :
85 149 : QueryOp getQueryOp() const { return meOp; }
86 :
87 39 : void setDouble( double fVal )
88 : {
89 39 : deleteString();
90 39 : mbAlloc = mbString = false;
91 39 : mfVal = fVal;
92 39 : }
93 :
94 : void setString( const OUString * pStr )
95 : {
96 : deleteString();
97 : mbAlloc = false;
98 : mbString = true;
99 : mpStr = pStr;
100 : }
101 :
102 38 : void setString( const OUString & rStr )
103 : {
104 38 : deleteString();
105 38 : mbAlloc = mbString = true;
106 38 : mpStr = new OUString( rStr);
107 38 : }
108 :
109 5 : bool operator==( const QueryCriteria & r ) const
110 : {
111 10 : return meOp == r.meOp && mbString == r.mbString &&
112 10 : (mbString ? (*mpStr == *r.mpStr) : (mfVal == r.mfVal));
113 : }
114 :
115 : };
116 :
117 : /// MUST be new'd because Notify() deletes.
118 : ScLookupCache( ScDocument * pDoc, const ScRange & rRange );
119 : virtual ~ScLookupCache();
120 : /// Remove from document structure and delete (!) cache on modify hint.
121 : virtual void Notify( const SfxHint& rHint ) SAL_OVERRIDE;
122 :
123 : /// @returns document address in o_rAddress if Result==FOUND
124 : Result lookup( ScAddress & o_rResultAddress,
125 : const QueryCriteria & rCriteria,
126 : const ScAddress & rQueryAddress ) const;
127 :
128 : /** Insert query and result.
129 : @param bAvailable
130 : Pass sal_False if the search didn't deliver a result. A subsequent
131 : lookup() then will return Result::NOT_AVAILABLE.
132 : @returns successful insertion.
133 : */
134 : bool insert( const ScAddress & rResultAddress,
135 : const QueryCriteria & rCriteria,
136 : const ScAddress & rQueryAddress,
137 : const bool bAvailable );
138 :
139 44 : inline const ScRange& getRange() const { return maRange; }
140 :
141 : struct Hash
142 : {
143 99 : size_t operator()( const ScRange & rRange ) const
144 : {
145 : // Lookups are performed on the first column.
146 99 : return rRange.hashStartColumn();
147 : }
148 : };
149 :
150 : private:
151 :
152 : struct QueryKey
153 : {
154 : SCROW mnRow;
155 : SCTAB mnTab;
156 : QueryOp meOp : 2;
157 :
158 149 : QueryKey( const ScAddress & rAddress, const QueryOp eOp ) :
159 149 : mnRow( rAddress.Row()),
160 149 : mnTab( rAddress.Tab()),
161 298 : meOp( eOp)
162 : {
163 149 : }
164 :
165 5 : bool operator==( const QueryKey & r ) const
166 : {
167 5 : return mnRow == r.mnRow && mnTab == r.mnTab && meOp == r.meOp && meOp != UNKNOWN;
168 : }
169 :
170 : struct Hash
171 : {
172 149 : size_t operator()( const QueryKey & r ) const
173 : {
174 298 : return (static_cast<size_t>(r.mnTab) << 24) ^
175 298 : (static_cast<size_t>(r.meOp) << 22) ^
176 149 : static_cast<size_t>(r.mnRow);
177 : }
178 : };
179 : };
180 :
181 144 : struct QueryCriteriaAndResult
182 : {
183 : QueryCriteria maCriteria;
184 : ScAddress maAddress;
185 :
186 72 : QueryCriteriaAndResult( const QueryCriteria & rCriteria, const ScAddress & rAddress ) :
187 : maCriteria( rCriteria),
188 72 : maAddress( rAddress)
189 : {
190 72 : }
191 208 : ~QueryCriteriaAndResult()
192 208 : {
193 208 : }
194 : };
195 :
196 : typedef std::unordered_map< QueryKey, QueryCriteriaAndResult, QueryKey::Hash, ::std::equal_to< QueryKey > > QueryMap;
197 : QueryMap maQueryMap;
198 : ScRange maRange;
199 : ScDocument * mpDoc;
200 :
201 : ScLookupCache( const ScLookupCache & ) SAL_DELETED_FUNCTION;
202 : ScLookupCache & operator=( const ScLookupCache & ) SAL_DELETED_FUNCTION;
203 :
204 : };
205 :
206 : typedef std::unordered_map< ScRange, ScLookupCache*, ScLookupCache::Hash, ::std::equal_to< ScRange > > ScLookupCacheMap;
207 :
208 : #endif
209 :
210 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|