summaryrefslogtreecommitdiffstats
path: root/sc/inc/lookupcache.hxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sc/inc/lookupcache.hxx209
1 files changed, 209 insertions, 0 deletions
diff --git a/sc/inc/lookupcache.hxx b/sc/inc/lookupcache.hxx
new file mode 100644
index 000000000..ca1d33388
--- /dev/null
+++ b/sc/inc/lookupcache.hxx
@@ -0,0 +1,209 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "address.hxx"
+#include <svl/listener.hxx>
+
+#include <memory>
+#include <unordered_map>
+
+class ScDocument;
+struct ScLookupCacheMap;
+struct ScQueryEntry;
+
+/** Lookup cache for one range used with interpreter functions such as VLOOKUP
+ and MATCH. Caches query for a specific row and the resulting address looked
+ up, in case other lookups of the same query in the same row are to be
+ performed, which usually occur to obtain a different offset column of the
+ same query.
+ */
+
+class ScLookupCache final : public SvtListener
+{
+public:
+
+ enum Result
+ {
+ NOT_CACHED, /// Query not found in cache.
+ CRITERIA_DIFFERENT, /// Different criteria for same query position exists.
+ NOT_AVAILABLE, /// Criteria not available in lookup range.
+ FOUND /// Criteria found.
+ };
+
+ enum QueryOp
+ {
+ UNKNOWN,
+ EQUAL,
+ LESS_EQUAL,
+ GREATER_EQUAL
+ };
+
+ class QueryCriteria
+ {
+ union
+ {
+ double mfVal;
+ const OUString *mpStr;
+ };
+ bool mbAlloc;
+ bool mbString;
+ QueryOp meOp;
+
+ void deleteString()
+ {
+ if (mbAlloc && mbString)
+ delete mpStr;
+ }
+
+ QueryCriteria & operator=( const QueryCriteria & r ) = delete;
+
+ public:
+
+ explicit QueryCriteria( const ScQueryEntry & rEntry );
+ QueryCriteria( const QueryCriteria & r );
+ ~QueryCriteria();
+
+ QueryOp getQueryOp() const { return meOp; }
+
+ void setDouble( double fVal )
+ {
+ deleteString();
+ mbAlloc = mbString = false;
+ mfVal = fVal;
+ }
+
+ void setString( const OUString & rStr )
+ {
+ deleteString();
+ mbAlloc = mbString = true;
+ mpStr = new OUString( rStr);
+ }
+
+ bool operator==( const QueryCriteria & r ) const
+ {
+ return meOp == r.meOp && mbString == r.mbString &&
+ (mbString ? (*mpStr == *r.mpStr) : (mfVal == r.mfVal));
+ }
+
+ bool isEmptyStringQuery() const
+ {
+ return (getQueryOp() == QueryOp::EQUAL) && mbString && mpStr && mpStr->isEmpty();
+ }
+ };
+
+ /// MUST be new'd because Notify() deletes.
+ ScLookupCache( ScDocument * pDoc, const ScRange & rRange, ScLookupCacheMap & cacheMap )
+ : maRange( rRange), mpDoc( pDoc), mCacheMap(cacheMap) {}
+ /// Remove from document structure and delete (!) cache on modify hint.
+ virtual void Notify( const SfxHint& rHint ) override;
+
+ /// @returns document address in o_rResultAddress if Result==FOUND
+ Result lookup( ScAddress & o_rResultAddress,
+ const QueryCriteria & rCriteria,
+ const ScAddress & rQueryAddress ) const;
+
+ SCROW lookup( const QueryCriteria & rCriteria ) const;
+
+ /** Insert query and result.
+ @param bAvailable
+ Pass sal_False if the search didn't deliver a result. A subsequent
+ lookup() then will return Result::NOT_AVAILABLE.
+ @returns successful insertion.
+ */
+ bool insert( const ScAddress & rResultAddress,
+ const QueryCriteria & rCriteria,
+ const ScAddress & rQueryAddress,
+ const bool bAvailable );
+
+ const ScRange& getRange() const { return maRange; }
+
+ ScLookupCacheMap & getCacheMap() const { return mCacheMap; }
+
+ struct Hash
+ {
+ size_t operator()( const ScRange & rRange ) const
+ {
+ // Lookups are performed on the first column.
+ return rRange.hashStartColumn();
+ }
+ };
+
+private:
+
+ struct QueryKey
+ {
+ SCROW mnRow;
+ SCTAB mnTab;
+ QueryOp meOp;
+
+ QueryKey( const ScAddress & rAddress, const QueryOp eOp ) :
+ mnRow( rAddress.Row()),
+ mnTab( rAddress.Tab()),
+ meOp( eOp)
+ {
+ }
+
+ bool operator==( const QueryKey & r ) const
+ {
+ return mnRow == r.mnRow && mnTab == r.mnTab && meOp == r.meOp && meOp != UNKNOWN;
+ }
+
+ struct Hash
+ {
+ size_t operator()( const QueryKey & r ) const
+ {
+ return (static_cast<size_t>(r.mnTab) << 24) ^
+ (static_cast<size_t>(r.meOp) << 22) ^
+ static_cast<size_t>(r.mnRow);
+ }
+ };
+ };
+
+ struct QueryCriteriaAndResult
+ {
+ QueryCriteria maCriteria;
+ ScAddress maAddress;
+
+ QueryCriteriaAndResult( const QueryCriteria & rCriteria, const ScAddress & rAddress ) :
+ maCriteria( rCriteria),
+ maAddress( rAddress)
+ {
+ }
+ };
+
+ std::unordered_map< QueryKey, QueryCriteriaAndResult, QueryKey::Hash > maQueryMap;
+ ScRange maRange;
+ ScDocument * mpDoc;
+ ScLookupCacheMap & mCacheMap;
+
+ ScLookupCache( const ScLookupCache & ) = delete;
+ ScLookupCache & operator=( const ScLookupCache & ) = delete;
+
+};
+
+// Struct because including lookupcache.hxx in document.hxx isn't wanted.
+struct ScLookupCacheMap
+{
+ std::unordered_map< ScRange, std::unique_ptr<ScLookupCache>, ScLookupCache::Hash > aCacheMap;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */