summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/dpobject.hxx8
-rw-r--r--sc/source/core/data/dpobject.cxx100
2 files changed, 99 insertions, 9 deletions
diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index cc73fcbee82a..db8ea9222f0f 100644
--- a/sc/inc/dpobject.hxx
+++ b/sc/inc/dpobject.hxx
@@ -259,12 +259,18 @@ public:
class SheetCaches
{
friend class ScDPCollection;
- typedef ::boost::ptr_map<ScRange, ScDPCache> CachesType;
+ typedef boost::ptr_map<size_t, ScDPCache> CachesType;
+ typedef std::vector<ScRange> RangeIndexType;
CachesType maCaches;
+ RangeIndexType maRanges;
ScDocument* mpDoc;
public:
SheetCaches(ScDocument* pDoc);
const ScDPCache* getCache(const ScRange& rRange);
+
+ void updateReference(
+ UpdateRefMode eMode, const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz);
+
private:
void removeCache(const ScRange& rRange);
};
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 51be02db8971..b0bbace516fa 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -2459,27 +2459,108 @@ uno::Reference<sheet::XDimensionsSupplier> ScDPObject::CreateSource( const ScDPS
ScDPCollection::SheetCaches::SheetCaches(ScDocument* pDoc) : mpDoc(pDoc) {}
+namespace {
+
+struct FindInvalidRange : public std::unary_function<ScRange, bool>
+{
+ bool operator() (const ScRange& r) const
+ {
+ return !r.IsValid();
+ }
+};
+
+}
+
const ScDPCache* ScDPCollection::SheetCaches::getCache(const ScRange& rRange)
{
- CachesType::const_iterator itr = maCaches.find(rRange);
- if (itr != maCaches.end())
- // already cached.
- return itr->second;
+ RangeIndexType::iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
+ if (it != maRanges.end())
+ {
+ // Already cached.
+ size_t nIndex = std::distance(maRanges.begin(), it);
+ CachesType::iterator itCache = maCaches.find(nIndex);
+ if (itCache == maCaches.end())
+ // cache pool and index pool out-of-sync !!!
+ return NULL;
+ return itCache->second;
+ }
+
+ // Not cached. Create a new cache.
SAL_WNODEPRECATED_DECLARATIONS_PUSH
::std::auto_ptr<ScDPCache> pCache(new ScDPCache(mpDoc));
SAL_WNODEPRECATED_DECLARATIONS_POP
pCache->InitFromDoc(mpDoc, rRange);
+
+ // Get the smallest available range index.
+ it = std::find_if(maRanges.begin(), maRanges.end(), FindInvalidRange());
+
+ size_t nIndex = maRanges.size();
+ if (it == maRanges.end())
+ {
+ // All range indices are valid. Append a new index.
+ maRanges.push_back(rRange);
+ }
+ else
+ {
+ // Slot with invalid range. Re-use this slot.
+ *it = rRange;
+ nIndex = std::distance(maRanges.begin(), it);
+ }
+
const ScDPCache* p = pCache.get();
- maCaches.insert(rRange, pCache);
+ maCaches.insert(nIndex, pCache);
return p;
}
+void ScDPCollection::SheetCaches::updateReference(
+ UpdateRefMode eMode, const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz)
+{
+ if (maRanges.empty())
+ // No caches.
+ return;
+
+ RangeIndexType::iterator it = maRanges.begin(), itEnd = maRanges.end();
+ for (; it != itEnd; ++it)
+ {
+ const ScRange& rKeyRange = *it;
+ SCCOL nCol1 = rKeyRange.aStart.Col();
+ SCROW nRow1 = rKeyRange.aStart.Row();
+ SCTAB nTab1 = rKeyRange.aStart.Tab();
+ SCCOL nCol2 = rKeyRange.aEnd.Col();
+ SCROW nRow2 = rKeyRange.aEnd.Row();
+ SCTAB nTab2 = rKeyRange.aEnd.Tab();
+
+ ScRefUpdateRes eRes = ScRefUpdate::Update(
+ mpDoc, eMode,
+ r.aStart.Col(), r.aStart.Row(), r.aStart.Tab(),
+ r.aEnd.Col(), r.aEnd.Row(), r.aEnd.Tab(), nDx, nDy, nDz,
+ nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+
+ if (eRes != UR_NOTHING)
+ {
+ // range updated.
+ ScRange aNew(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ *it = aNew;
+ }
+ }
+}
+
void ScDPCollection::SheetCaches::removeCache(const ScRange& rRange)
{
- CachesType::iterator itr = maCaches.find(rRange);
- if (itr != maCaches.end())
- maCaches.erase(itr);
+ RangeIndexType::iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
+ if (it == maRanges.end())
+ // Not cached. Nothing to do.
+ return;
+
+ size_t nIndex = std::distance(maRanges.begin(), it);
+ CachesType::iterator itCache = maCaches.find(nIndex);
+ if (itCache == maCaches.end())
+ // Cache pool and index pool out-of-sync !!!
+ return;
+
+ it->SetInvalid(); // Make this slot available for future caches.
+ maCaches.erase(itCache);
}
ScDPCollection::NameCaches::NameCaches(ScDocument* pDoc) : mpDoc(pDoc) {}
@@ -2687,6 +2768,9 @@ void ScDPCollection::UpdateReference( UpdateRefMode eUpdateRefMode,
TablesType::iterator itr = maTables.begin(), itrEnd = maTables.end();
for (; itr != itrEnd; ++itr)
itr->UpdateReference(eUpdateRefMode, r, nDx, nDy, nDz);
+
+ // Update the source ranges of the caches.
+ maSheetCaches.updateReference(eUpdateRefMode, r, nDx, nDy, nDz);
}
bool ScDPCollection::RefsEqual( const ScDPCollection& r ) const