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