diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2013-11-08 12:33:57 -0500 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@collabora.com> | 2013-11-11 16:17:29 -0500 |
commit | 6ad8f2618ae153281ccd2f78c676452db7d1b25a (patch) | |
tree | af200502c22911042fb5f6f379d92e149ef2bd53 /sc/source/filter | |
parent | d8fe172ea08f57675b6b1f69331c19502ec02119 (diff) |
Cache previous formula tokens to avoid formula re-compilations.
Change-Id: If20e0ebf5410af0b7655f36f7e4fc06f53d8b14b
Diffstat (limited to 'sc/source/filter')
-rw-r--r-- | sc/source/filter/oox/formulabuffer.cxx | 85 |
1 files changed, 83 insertions, 2 deletions
diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx index fa8e06ac4a5f..86c9e6c10573 100644 --- a/sc/source/filter/oox/formulabuffer.cxx +++ b/sc/source/filter/oox/formulabuffer.cxx @@ -34,11 +34,80 @@ using namespace ::com::sun::star::sheet; using namespace ::com::sun::star::container; #include <boost/scoped_ptr.hpp> +#include <boost/noncopyable.hpp> namespace oox { namespace xls { namespace { +/** + * Cache the token array for the last cell position in each column. We use + * one cache per sheet. + */ +class CachedTokenArray : boost::noncopyable +{ + struct Item : boost::noncopyable + { + SCROW mnRow; + boost::scoped_ptr<ScTokenArray> mpCode; + + Item() : mnRow(-1), mpCode(NULL) {} + Item( SCROW nRow, ScTokenArray* p ) : mnRow(nRow), mpCode(p) {} + }; + + typedef boost::unordered_map<SCCOL, Item*> ColCacheType; + ColCacheType maCache; + ScDocument& mrDoc; + +public: + CachedTokenArray( ScDocument& rDoc ) : mrDoc(rDoc) {} + + ~CachedTokenArray() + { + ColCacheType::const_iterator it = maCache.begin(), itEnd = maCache.end(); + for (; it != itEnd; ++it) + delete it->second; + } + + const ScTokenArray* get( const ScAddress& rPos, const OUString& rFormula ) const + { + // Check if a token array is cached for this column. + ColCacheType::const_iterator it = maCache.find(rPos.Col()); + if (it == maCache.end()) + return NULL; + + const Item& rCached = *it->second; + ScCompiler aComp(&mrDoc, rPos, *rCached.mpCode); + aComp.SetGrammar(formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX); + OUStringBuffer aBuf; + aComp.CreateStringFromTokenArray(aBuf); + OUString aPredicted = aBuf.makeStringAndClear(); + if (rFormula == aPredicted) + return rCached.mpCode.get(); + + return NULL; + } + + void store( const ScAddress& rPos, const ScTokenArray& rArray ) + { + ColCacheType::iterator it = maCache.find(rPos.Col()); + if (it == maCache.end()) + { + // Create an entry for this column. + std::pair<ColCacheType::iterator,bool> r = + maCache.insert(ColCacheType::value_type(rPos.Col(), new Item)); + if (!r.second) + // Insertion failed. + return; + + it = r.first; + } + + it->second->mnRow = rPos.Row(); + it->second->mpCode.reset(rArray.Clone()); + } +}; + void applySharedFormulas( ScDocumentImport& rDoc, SvNumberFormatter& rFormatter, @@ -104,7 +173,7 @@ void applySharedFormulas( } void applyCellFormulas( - ScDocumentImport& rDoc, SvNumberFormatter& rFormatter, + ScDocumentImport& rDoc, CachedTokenArray& rCache, SvNumberFormatter& rFormatter, const std::vector<FormulaBuffer::TokenAddressItem>& rCells ) { std::vector<FormulaBuffer::TokenAddressItem>::const_iterator it = rCells.begin(), itEnd = rCells.end(); @@ -112,6 +181,14 @@ void applyCellFormulas( { ScAddress aPos; ScUnoConversion::FillScAddress(aPos, it->maCellAddress); + const ScTokenArray* p = rCache.get(aPos, it->maTokenStr); + if (p) + { + // Use the cached version to avoid re-compilation. + rDoc.setFormulaCell(aPos, p->Clone()); + continue; + } + ScCompiler aCompiler(&rDoc.getDoc(), aPos); aCompiler.SetNumberFormatter(&rFormatter); aCompiler.SetGrammar(formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX); @@ -120,6 +197,7 @@ void applyCellFormulas( continue; rDoc.setFormulaCell(aPos, pCode); + rCache.store(aPos, *pCode); } } @@ -185,7 +263,10 @@ protected: applySharedFormulas(mrDoc, *mpFormatter, *mrItem.mpSharedFormulaEntries, *mrItem.mpSharedFormulaIDs); if (mrItem.mpCellFormulas) - applyCellFormulas(mrDoc, *mpFormatter, *mrItem.mpCellFormulas); + { + CachedTokenArray aCache(mrDoc.getDoc()); + applyCellFormulas(mrDoc, aCache, *mpFormatter, *mrItem.mpCellFormulas); + } if (mrItem.mpArrayFormulas) applyArrayFormulas(mrDoc, *mpFormatter, *mrItem.mpArrayFormulas); |