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