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 <boost/unordered_map.hpp>
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 618 : void deleteString()
72 : {
73 618 : if (mbAlloc && mbString)
74 180 : delete mpStr;
75 618 : }
76 :
77 : // prevent usage
78 : QueryCriteria();
79 : QueryCriteria & operator=( const QueryCriteria & r );
80 :
81 : public:
82 :
83 : explicit QueryCriteria( const ScQueryEntry & rEntry );
84 : QueryCriteria( const QueryCriteria & r );
85 : ~QueryCriteria();
86 :
87 248 : QueryOp getQueryOp() const { return meOp; }
88 :
89 78 : void setDouble( double fVal )
90 : {
91 78 : deleteString();
92 78 : mbAlloc = mbString = false;
93 78 : mfVal = fVal;
94 78 : }
95 :
96 : void setString( const OUString * pStr )
97 : {
98 : deleteString();
99 : mbAlloc = false;
100 : mbString = true;
101 : mpStr = pStr;
102 : }
103 :
104 48 : void setString( const OUString & rStr )
105 : {
106 48 : deleteString();
107 48 : mbAlloc = mbString = true;
108 48 : mpStr = new OUString( rStr);
109 48 : }
110 :
111 4 : bool operator==( const QueryCriteria & r ) const
112 : {
113 8 : return meOp == r.meOp && mbString == r.mbString &&
114 8 : (mbString ? (*mpStr == *r.mpStr) : (mfVal == r.mfVal));
115 : }
116 :
117 : };
118 :
119 : /// MUST be new'd because Notify() deletes.
120 : ScLookupCache( ScDocument * pDoc, const ScRange & rRange );
121 : virtual ~ScLookupCache();
122 : /// Remove from document structure and delete (!) cache on modify hint.
123 : virtual void Notify( const SfxHint& rHint ) SAL_OVERRIDE;
124 :
125 : /// @returns document address in o_rAddress if Result==FOUND
126 : Result lookup( ScAddress & o_rResultAddress,
127 : const QueryCriteria & rCriteria,
128 : const ScAddress & rQueryAddress ) const;
129 :
130 : /** Insert query and result.
131 : @param bAvailable
132 : Pass sal_False if the search didn't deliver a result. A subsequent
133 : lookup() then will return Result::NOT_AVAILABLE.
134 : @returns successful insertion.
135 : */
136 : bool insert( const ScAddress & rResultAddress,
137 : const QueryCriteria & rCriteria,
138 : const ScAddress & rQueryAddress,
139 : const bool bAvailable );
140 :
141 56 : inline const ScRange& getRange() const { return maRange; }
142 :
143 : struct Hash
144 : {
145 154 : size_t operator()( const ScRange & rRange ) const
146 : {
147 : // Lookups are performed on the first column.
148 154 : return rRange.hashStartColumn();
149 : }
150 : };
151 :
152 : private:
153 :
154 : struct QueryKey
155 : {
156 : SCROW mnRow;
157 : SCTAB mnTab;
158 : QueryOp meOp : 2;
159 :
160 248 : QueryKey( const ScAddress & rAddress, const QueryOp eOp ) :
161 248 : mnRow( rAddress.Row()),
162 248 : mnTab( rAddress.Tab()),
163 496 : meOp( eOp)
164 : {
165 248 : }
166 :
167 4 : bool operator==( const QueryKey & r ) const
168 : {
169 4 : return mnRow == r.mnRow && mnTab == r.mnTab && meOp == r.meOp && meOp != UNKNOWN;
170 : }
171 :
172 : struct Hash
173 : {
174 248 : size_t operator()( const QueryKey & r ) const
175 : {
176 496 : return (static_cast<size_t>(r.mnTab) << 24) ^
177 496 : (static_cast<size_t>(r.meOp) << 22) ^
178 248 : static_cast<size_t>(r.mnRow);
179 : }
180 : };
181 : };
182 :
183 244 : struct QueryCriteriaAndResult
184 : {
185 : QueryCriteria maCriteria;
186 : ScAddress maAddress;
187 :
188 122 : QueryCriteriaAndResult( const QueryCriteria & rCriteria, const ScAddress & rAddress ) :
189 : maCriteria( rCriteria),
190 122 : maAddress( rAddress)
191 : {
192 122 : }
193 366 : ~QueryCriteriaAndResult()
194 366 : {
195 366 : }
196 : };
197 :
198 : typedef ::boost::unordered_map< QueryKey, QueryCriteriaAndResult, QueryKey::Hash, ::std::equal_to< QueryKey > > QueryMap;
199 : QueryMap maQueryMap;
200 : ScRange maRange;
201 : ScDocument * mpDoc;
202 :
203 : // prevent usage
204 : ScLookupCache( const ScLookupCache & );
205 : ScLookupCache & operator=( const ScLookupCache & );
206 :
207 : };
208 :
209 : typedef ::boost::unordered_map< ScRange, ScLookupCache*, ScLookupCache::Hash, ::std::equal_to< ScRange > > ScLookupCacheMap;
210 :
211 : #endif
212 :
213 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|