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