xref: /aoo4110/main/sc/inc/lookupcache.hxx (revision b1cdbd2c)
1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski #ifndef INCLUDED_SC_LOOKUPCACHE_HXX
25*b1cdbd2cSJim Jagielski #define INCLUDED_SC_LOOKUPCACHE_HXX
26*b1cdbd2cSJim Jagielski 
27*b1cdbd2cSJim Jagielski #include "address.hxx"
28*b1cdbd2cSJim Jagielski #include "global.hxx"
29*b1cdbd2cSJim Jagielski #include "formula/token.hxx"
30*b1cdbd2cSJim Jagielski #include <svl/listener.hxx>
31*b1cdbd2cSJim Jagielski #include <tools/string.hxx>
32*b1cdbd2cSJim Jagielski 
33*b1cdbd2cSJim Jagielski #include <hash_map>
34*b1cdbd2cSJim Jagielski 
35*b1cdbd2cSJim Jagielski class ScDocument;
36*b1cdbd2cSJim Jagielski 
37*b1cdbd2cSJim Jagielski 
38*b1cdbd2cSJim Jagielski /** Lookup cache for one range used with interpreter functions such as VLOOKUP
39*b1cdbd2cSJim Jagielski     and MATCH. Caches query for a specific row and the resulting address looked
40*b1cdbd2cSJim Jagielski     up, in case other lookups of the same query in the same row are to be
41*b1cdbd2cSJim Jagielski     performed, which usually occur to obtain a different offset column of the
42*b1cdbd2cSJim Jagielski     same query.
43*b1cdbd2cSJim Jagielski  */
44*b1cdbd2cSJim Jagielski 
45*b1cdbd2cSJim Jagielski class ScLookupCache : public SvtListener
46*b1cdbd2cSJim Jagielski {
47*b1cdbd2cSJim Jagielski public:
48*b1cdbd2cSJim Jagielski 
49*b1cdbd2cSJim Jagielski     enum Result
50*b1cdbd2cSJim Jagielski     {
51*b1cdbd2cSJim Jagielski         NOT_CACHED,         /// Query not found in cache.
52*b1cdbd2cSJim Jagielski         CRITERIA_DIFFERENT, /// Different criteria for same query position exists.
53*b1cdbd2cSJim Jagielski         NOT_AVAILABLE,      /// Criteria not available in lookup range.
54*b1cdbd2cSJim Jagielski         FOUND               /// Criteria found.
55*b1cdbd2cSJim Jagielski     };
56*b1cdbd2cSJim Jagielski 
57*b1cdbd2cSJim Jagielski     enum QueryOp
58*b1cdbd2cSJim Jagielski     {
59*b1cdbd2cSJim Jagielski         UNKNOWN,
60*b1cdbd2cSJim Jagielski         EQUAL,
61*b1cdbd2cSJim Jagielski         LESS_EQUAL,
62*b1cdbd2cSJim Jagielski         GREATER_EQUAL
63*b1cdbd2cSJim Jagielski     };
64*b1cdbd2cSJim Jagielski 
65*b1cdbd2cSJim Jagielski     class QueryCriteria
66*b1cdbd2cSJim Jagielski     {
67*b1cdbd2cSJim Jagielski         union
68*b1cdbd2cSJim Jagielski         {
69*b1cdbd2cSJim Jagielski             double          mfVal;
70*b1cdbd2cSJim Jagielski             const String *  mpStr;
71*b1cdbd2cSJim Jagielski         };
72*b1cdbd2cSJim Jagielski         bool                mbAlloc  : 1;
73*b1cdbd2cSJim Jagielski         bool                mbString : 1;
74*b1cdbd2cSJim Jagielski         QueryOp             meOp     : 2;
75*b1cdbd2cSJim Jagielski 
deleteString()76*b1cdbd2cSJim Jagielski         void deleteString()
77*b1cdbd2cSJim Jagielski         {
78*b1cdbd2cSJim Jagielski             if (mbAlloc && mbString)
79*b1cdbd2cSJim Jagielski                 delete mpStr;
80*b1cdbd2cSJim Jagielski         }
81*b1cdbd2cSJim Jagielski 
82*b1cdbd2cSJim Jagielski         // prevent usage
83*b1cdbd2cSJim Jagielski         QueryCriteria();
84*b1cdbd2cSJim Jagielski         QueryCriteria & operator=( const QueryCriteria & r );
85*b1cdbd2cSJim Jagielski 
86*b1cdbd2cSJim Jagielski     public:
87*b1cdbd2cSJim Jagielski 
QueryCriteria(const ScQueryEntry & rEntry)88*b1cdbd2cSJim Jagielski         explicit QueryCriteria( const ScQueryEntry & rEntry ) :
89*b1cdbd2cSJim Jagielski             mfVal(0.0), mbAlloc(false), mbString(false)
90*b1cdbd2cSJim Jagielski         {
91*b1cdbd2cSJim Jagielski             switch (rEntry.eOp)
92*b1cdbd2cSJim Jagielski             {
93*b1cdbd2cSJim Jagielski                 case SC_EQUAL :
94*b1cdbd2cSJim Jagielski                     meOp = EQUAL;
95*b1cdbd2cSJim Jagielski                     break;
96*b1cdbd2cSJim Jagielski                 case SC_LESS_EQUAL :
97*b1cdbd2cSJim Jagielski                     meOp = LESS_EQUAL;
98*b1cdbd2cSJim Jagielski                     break;
99*b1cdbd2cSJim Jagielski                 case SC_GREATER_EQUAL :
100*b1cdbd2cSJim Jagielski                     meOp = GREATER_EQUAL;
101*b1cdbd2cSJim Jagielski                     break;
102*b1cdbd2cSJim Jagielski                 default:
103*b1cdbd2cSJim Jagielski                     meOp = UNKNOWN;
104*b1cdbd2cSJim Jagielski                     DBG_ERRORFILE( "ScLookupCache::QueryCriteria not prepared for this ScQueryOp");
105*b1cdbd2cSJim Jagielski             }
106*b1cdbd2cSJim Jagielski             if (rEntry.bQueryByString)
107*b1cdbd2cSJim Jagielski                 setString( rEntry.pStr);
108*b1cdbd2cSJim Jagielski             else
109*b1cdbd2cSJim Jagielski                 setDouble( rEntry.nVal);
110*b1cdbd2cSJim Jagielski         }
QueryCriteria(const QueryCriteria & r)111*b1cdbd2cSJim Jagielski         QueryCriteria( const QueryCriteria & r ) :
112*b1cdbd2cSJim Jagielski             mfVal( r.mfVal),
113*b1cdbd2cSJim Jagielski             mbAlloc( false),
114*b1cdbd2cSJim Jagielski             mbString( false),
115*b1cdbd2cSJim Jagielski             meOp( r.meOp)
116*b1cdbd2cSJim Jagielski         {
117*b1cdbd2cSJim Jagielski             if (r.mbString && r.mpStr)
118*b1cdbd2cSJim Jagielski             {
119*b1cdbd2cSJim Jagielski                 mpStr = new String( *r.mpStr);
120*b1cdbd2cSJim Jagielski                 mbAlloc = mbString = true;
121*b1cdbd2cSJim Jagielski             }
122*b1cdbd2cSJim Jagielski         }
~QueryCriteria()123*b1cdbd2cSJim Jagielski         ~QueryCriteria()
124*b1cdbd2cSJim Jagielski         {
125*b1cdbd2cSJim Jagielski             deleteString();
126*b1cdbd2cSJim Jagielski         }
127*b1cdbd2cSJim Jagielski 
getQueryOp() const128*b1cdbd2cSJim Jagielski         QueryOp getQueryOp() const { return meOp; }
129*b1cdbd2cSJim Jagielski 
setDouble(double fVal)130*b1cdbd2cSJim Jagielski         void setDouble( double fVal )
131*b1cdbd2cSJim Jagielski         {
132*b1cdbd2cSJim Jagielski             deleteString();
133*b1cdbd2cSJim Jagielski             mbAlloc = mbString = false;
134*b1cdbd2cSJim Jagielski             mfVal = fVal;
135*b1cdbd2cSJim Jagielski         }
136*b1cdbd2cSJim Jagielski 
setString(const String * pStr)137*b1cdbd2cSJim Jagielski         void setString( const String * pStr )
138*b1cdbd2cSJim Jagielski         {
139*b1cdbd2cSJim Jagielski             deleteString();
140*b1cdbd2cSJim Jagielski             mbAlloc = false;
141*b1cdbd2cSJim Jagielski             mbString = true;
142*b1cdbd2cSJim Jagielski             mpStr = pStr;
143*b1cdbd2cSJim Jagielski         }
144*b1cdbd2cSJim Jagielski 
setString(const String & rStr)145*b1cdbd2cSJim Jagielski         void setString( const String & rStr )
146*b1cdbd2cSJim Jagielski         {
147*b1cdbd2cSJim Jagielski             deleteString();
148*b1cdbd2cSJim Jagielski             mbAlloc = mbString = true;
149*b1cdbd2cSJim Jagielski             mpStr = new String( rStr);
150*b1cdbd2cSJim Jagielski         }
151*b1cdbd2cSJim Jagielski 
operator ==(const QueryCriteria & r) const152*b1cdbd2cSJim Jagielski         bool operator==( const QueryCriteria & r ) const
153*b1cdbd2cSJim Jagielski         {
154*b1cdbd2cSJim Jagielski             return meOp == r.meOp && mbString == r.mbString &&
155*b1cdbd2cSJim Jagielski                 (mbString ? (*mpStr == *r.mpStr) : (mfVal == r.mfVal));
156*b1cdbd2cSJim Jagielski         }
157*b1cdbd2cSJim Jagielski 
158*b1cdbd2cSJim Jagielski     };
159*b1cdbd2cSJim Jagielski 
160*b1cdbd2cSJim Jagielski     /// MUST be new'd because Notify() deletes.
161*b1cdbd2cSJim Jagielski                             ScLookupCache( ScDocument * pDoc, const ScRange & rRange );
162*b1cdbd2cSJim Jagielski     virtual                 ~ScLookupCache();
163*b1cdbd2cSJim Jagielski     /// Remove from document structure and delete (!) cache on modify hint.
164*b1cdbd2cSJim Jagielski     virtual void            Notify( SvtBroadcaster & rBC, const SfxHint &  rHint );
165*b1cdbd2cSJim Jagielski 
166*b1cdbd2cSJim Jagielski     /// @returns document address in o_rAddress if Result==FOUND
167*b1cdbd2cSJim Jagielski             Result          lookup( ScAddress & o_rResultAddress,
168*b1cdbd2cSJim Jagielski                                     const QueryCriteria & rCriteria,
169*b1cdbd2cSJim Jagielski                                     const ScAddress & rQueryAddress ) const;
170*b1cdbd2cSJim Jagielski 
171*b1cdbd2cSJim Jagielski     /** Insert query and result.
172*b1cdbd2cSJim Jagielski         @param bAvailable
173*b1cdbd2cSJim Jagielski             Pass sal_False if the search didn't deliver a result. A subsequent
174*b1cdbd2cSJim Jagielski             lookup() then will return Result::NOT_AVAILABLE.
175*b1cdbd2cSJim Jagielski         @returns successful insertion.
176*b1cdbd2cSJim Jagielski       */
177*b1cdbd2cSJim Jagielski             bool            insert( const ScAddress & rResultAddress,
178*b1cdbd2cSJim Jagielski                                     const QueryCriteria & rCriteria,
179*b1cdbd2cSJim Jagielski                                     const ScAddress & rQueryAddress,
180*b1cdbd2cSJim Jagielski                                     const bool bAvailable );
181*b1cdbd2cSJim Jagielski 
getRange() const182*b1cdbd2cSJim Jagielski     inline  const ScRange&  getRange() const { return maRange; }
183*b1cdbd2cSJim Jagielski 
184*b1cdbd2cSJim Jagielski     struct Hash
185*b1cdbd2cSJim Jagielski     {
operator ()ScLookupCache::Hash186*b1cdbd2cSJim Jagielski         size_t operator()( const ScRange & rRange ) const
187*b1cdbd2cSJim Jagielski         {
188*b1cdbd2cSJim Jagielski             // Lookups are performed on the first column.
189*b1cdbd2cSJim Jagielski             return rRange.hashStartColumn();
190*b1cdbd2cSJim Jagielski         }
191*b1cdbd2cSJim Jagielski     };
192*b1cdbd2cSJim Jagielski 
193*b1cdbd2cSJim Jagielski private:
194*b1cdbd2cSJim Jagielski 
195*b1cdbd2cSJim Jagielski     struct QueryKey
196*b1cdbd2cSJim Jagielski     {
197*b1cdbd2cSJim Jagielski         SCROW           mnRow;
198*b1cdbd2cSJim Jagielski         SCTAB           mnTab;
199*b1cdbd2cSJim Jagielski         QueryOp         meOp : 2;
200*b1cdbd2cSJim Jagielski 
QueryKeyScLookupCache::QueryKey201*b1cdbd2cSJim Jagielski         QueryKey( const ScAddress & rAddress, const QueryOp eOp ) :
202*b1cdbd2cSJim Jagielski             mnRow( rAddress.Row()),
203*b1cdbd2cSJim Jagielski             mnTab( rAddress.Tab()),
204*b1cdbd2cSJim Jagielski             meOp( eOp)
205*b1cdbd2cSJim Jagielski         {
206*b1cdbd2cSJim Jagielski         }
207*b1cdbd2cSJim Jagielski 
operator ==ScLookupCache::QueryKey208*b1cdbd2cSJim Jagielski         bool operator==( const QueryKey & r ) const
209*b1cdbd2cSJim Jagielski         {
210*b1cdbd2cSJim Jagielski             return mnRow == r.mnRow && mnTab == r.mnTab && meOp == r.meOp && meOp != UNKNOWN;
211*b1cdbd2cSJim Jagielski         }
212*b1cdbd2cSJim Jagielski 
213*b1cdbd2cSJim Jagielski         struct Hash
214*b1cdbd2cSJim Jagielski         {
operator ()ScLookupCache::QueryKey::Hash215*b1cdbd2cSJim Jagielski             size_t operator()( const QueryKey & r ) const
216*b1cdbd2cSJim Jagielski             {
217*b1cdbd2cSJim Jagielski                 return (static_cast<size_t>(r.mnTab) << 24) ^
218*b1cdbd2cSJim Jagielski                     (static_cast<size_t>(r.meOp) << 22) ^
219*b1cdbd2cSJim Jagielski                     static_cast<size_t>(r.mnRow);
220*b1cdbd2cSJim Jagielski             }
221*b1cdbd2cSJim Jagielski         };
222*b1cdbd2cSJim Jagielski     };
223*b1cdbd2cSJim Jagielski 
224*b1cdbd2cSJim Jagielski     struct QueryCriteriaAndResult
225*b1cdbd2cSJim Jagielski     {
226*b1cdbd2cSJim Jagielski         QueryCriteria   maCriteria;
227*b1cdbd2cSJim Jagielski         ScAddress       maAddress;
228*b1cdbd2cSJim Jagielski 
QueryCriteriaAndResultScLookupCache::QueryCriteriaAndResult229*b1cdbd2cSJim Jagielski         QueryCriteriaAndResult( const QueryCriteria & rCriteria, const ScAddress & rAddress ) :
230*b1cdbd2cSJim Jagielski             maCriteria( rCriteria),
231*b1cdbd2cSJim Jagielski             maAddress( rAddress)
232*b1cdbd2cSJim Jagielski         {
233*b1cdbd2cSJim Jagielski         }
~QueryCriteriaAndResultScLookupCache::QueryCriteriaAndResult234*b1cdbd2cSJim Jagielski         ~QueryCriteriaAndResult()
235*b1cdbd2cSJim Jagielski         {
236*b1cdbd2cSJim Jagielski         }
237*b1cdbd2cSJim Jagielski     };
238*b1cdbd2cSJim Jagielski 
239*b1cdbd2cSJim Jagielski     typedef ::std::hash_map< QueryKey, QueryCriteriaAndResult, QueryKey::Hash, ::std::equal_to< QueryKey > > QueryMap;
240*b1cdbd2cSJim Jagielski     QueryMap        maQueryMap;
241*b1cdbd2cSJim Jagielski     ScRange         maRange;
242*b1cdbd2cSJim Jagielski     ScDocument *    mpDoc;
243*b1cdbd2cSJim Jagielski 
244*b1cdbd2cSJim Jagielski     // prevent usage
245*b1cdbd2cSJim Jagielski     ScLookupCache( const ScLookupCache & );
246*b1cdbd2cSJim Jagielski     ScLookupCache & operator=( const ScLookupCache & );
247*b1cdbd2cSJim Jagielski 
248*b1cdbd2cSJim Jagielski };
249*b1cdbd2cSJim Jagielski 
250*b1cdbd2cSJim Jagielski 
251*b1cdbd2cSJim Jagielski typedef ::std::hash_map< ScRange, ScLookupCache*, ScLookupCache::Hash, ::std::equal_to< ScRange > > ScLookupCacheMap;
252*b1cdbd2cSJim Jagielski 
253*b1cdbd2cSJim Jagielski #endif
254