writerfilter/source/rtftok/rtfdocumentimpl.cxx | 7 +- writerfilter/source/rtftok/rtfsprm.cxx | 58 ++++++++++++++++----- writerfilter/source/rtftok/rtfsprm.hxx | 67 ++++++++++++++++--------- 3 files changed, 92 insertions(+), 40 deletions(-)
New commits: commit a48e2fd9049797110b3b2505c363557284987ca8 Author: Michael Meeks <michael.me...@suse.com> Date: Fri Dec 7 13:16:23 2012 +0000 fdo#44736 - convert RTFSprms to a copy-on-write structure. Also try to avoid copy/delete thrash of RTFParserState. diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx index aa90d3b..78bd105 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx @@ -3407,16 +3407,15 @@ int RTFDocumentImpl::pushState() checkUnicode(); m_nGroupStartPos = Strm().Tell(); - RTFParserState aState(this); + if (m_aStates.empty()) - aState = m_aDefaultState; + m_aStates.push(m_aDefaultState); else { if (m_aStates.top().nDestinationState == DESTINATION_MR) lcl_DestinationToMath(m_aStates.top().aDestinationText, m_aMathBuffer); - aState = m_aStates.top(); + m_aStates.push(m_aStates.top()); } - m_aStates.push(aState); m_aStates.top().aDestinationText.setLength(0); m_pTokenizer->pushGroup(); diff --git a/writerfilter/source/rtftok/rtfsprm.cxx b/writerfilter/source/rtftok/rtfsprm.cxx index 2958cde..e11dbe6 100644 --- a/writerfilter/source/rtftok/rtfsprm.cxx +++ b/writerfilter/source/rtftok/rtfsprm.cxx @@ -1,3 +1,4 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * Version: MPL 1.1 / GPLv3+ / LGPLv3+ * @@ -99,7 +100,7 @@ std::string RTFSprm::toString() const RTFValue::Pointer_t RTFSprms::find(Id nKeyword) { - for (RTFSprms::Iterator_t i = m_aSprms.begin(); i != m_aSprms.end(); ++i) + for (RTFSprms::Iterator_t i = m_pSprms->begin(); i != m_pSprms->end(); ++i) if (i->first == nKeyword) return i->second; RTFValue::Pointer_t pValue; @@ -108,33 +109,39 @@ RTFValue::Pointer_t RTFSprms::find(Id nKeyword) void RTFSprms::set(Id nKeyword, RTFValue::Pointer_t pValue, bool bOverwrite) { + ensureCopyBeforeWrite(); if (bOverwrite) { - for (RTFSprms::Iterator_t i = m_aSprms.begin(); i != m_aSprms.end(); ++i) + for (RTFSprms::Iterator_t i = m_pSprms->begin(); i != m_pSprms->end(); ++i) if (i->first == nKeyword) { i->second = pValue; return; } } - m_aSprms.push_back(std::make_pair(nKeyword, pValue)); + m_pSprms->push_back(std::make_pair(nKeyword, pValue)); } bool RTFSprms::erase(Id nKeyword) { - for (RTFSprms::Iterator_t i = m_aSprms.begin(); i != m_aSprms.end(); ++i) + ensureCopyBeforeWrite(); + for (RTFSprms::Iterator_t i = m_pSprms->begin(); i != m_pSprms->end(); ++i) + { if (i->first == nKeyword) { - m_aSprms.erase(i); + m_pSprms->erase(i); return true; } + } return false; } void RTFSprms::deduplicate(RTFSprms& rReference) { - RTFSprms::Iterator_t i = m_aSprms.begin(); - while (i != m_aSprms.end()) + ensureCopyBeforeWrite(); + + RTFSprms::Iterator_t i = m_pSprms->begin(); + while (i != m_pSprms->end()) { bool bIgnore = false; if (i->first != NS_rtf::LN_ISTD) @@ -144,33 +151,56 @@ void RTFSprms::deduplicate(RTFSprms& rReference) bIgnore = true; } if (bIgnore) - i = m_aSprms.erase(i); + i = m_pSprms->erase(i); else ++i; } } +void RTFSprms::ensureCopyBeforeWrite() +{ + if (m_pSprms->m_nRefCount > 1) { + boost::intrusive_ptr<RTFSprmsImpl> pClone(new RTFSprmsImpl()); + for (std::vector< std::pair<Id, RTFValue::Pointer_t> >::const_iterator i = m_pSprms->begin(); i != m_pSprms->end(); ++i) + pClone->push_back(std::make_pair(i->first, RTFValue::Pointer_t(i->second->Clone()))); + m_pSprms = pClone; + assert(m_pSprms->m_nRefCount == 1); + } +} + RTFSprms::RTFSprms() - : m_aSprms() + : m_pSprms(new RTFSprmsImpl()) +{ +} + +RTFSprms::~RTFSprms() { } RTFSprms::RTFSprms(const RTFSprms& rSprms) { - for (std::vector< std::pair<Id, RTFValue::Pointer_t> >::const_iterator i = rSprms.m_aSprms.begin(); i != rSprms.m_aSprms.end(); ++i) - m_aSprms.push_back(std::make_pair(i->first, RTFValue::Pointer_t(i->second->Clone()))); + *this = rSprms; } RTFSprms& RTFSprms::operator=(const RTFSprms& rOther) { - RTFSprms aTmp(rOther); - swap(aTmp); + m_pSprms = rOther.m_pSprms; return *this; } void RTFSprms::swap(RTFSprms& rOther) { - m_aSprms.swap(rOther.m_aSprms); + boost::intrusive_ptr<RTFSprmsImpl> pTmp = rOther.m_pSprms; + rOther.m_pSprms = m_pSprms; + m_pSprms = pTmp; +} + +void RTFSprms::clear() +{ + if (m_pSprms->m_nRefCount == 1) + return m_pSprms->clear(); + else + m_pSprms.reset(new RTFSprmsImpl()); } } // namespace rtftok diff --git a/writerfilter/source/rtftok/rtfsprm.hxx b/writerfilter/source/rtftok/rtfsprm.hxx index 80d41a3..5f7a793 100644 --- a/writerfilter/source/rtftok/rtfsprm.hxx +++ b/writerfilter/source/rtftok/rtfsprm.hxx @@ -1,3 +1,4 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * Version: MPL 1.1 / GPLv3+ / LGPLv3+ * @@ -28,36 +29,58 @@ #ifndef _RTFSPRM_HXX_ #define _RTFSPRM_HXX_ +#include <boost/intrusive_ptr.hpp> #include <rtfcontrolwords.hxx> #include <rtfvalue.hxx> namespace writerfilter { namespace rtftok { + + typedef std::vector< std::pair<Id, RTFValue::Pointer_t> > RTFSprmsImplBase; + class RTFSprmsImpl : public RTFSprmsImplBase + { + public: + sal_Int32 m_nRefCount; + RTFSprmsImpl() : RTFSprmsImplBase(), m_nRefCount(0) {} + }; + + inline void intrusive_ptr_add_ref(RTFSprmsImpl* p) + { + ++(p->m_nRefCount); + } + inline void intrusive_ptr_release(RTFSprmsImpl* p) + { + if (!--(p->m_nRefCount)) + delete p; + } + /// A list of RTFSprm with a copy constructor that performs a deep copy. class RTFSprms { - public: - typedef ::boost::shared_ptr<RTFSprms> Pointer_t; - typedef std::pair<Id, RTFValue::Pointer_t> Entry_t; - typedef std::vector<Entry_t>::iterator Iterator_t; - RTFSprms(); - RTFSprms(const RTFSprms& rSprms); - RTFSprms& operator=(const RTFSprms& rOther); - RTFValue::Pointer_t find(Id nKeyword); - /// Does the same as ->push_back(), except that it can overwrite existing entries. - void set(Id nKeyword, RTFValue::Pointer_t pValue, bool bOverwrite = true); - bool erase(Id nKeyword); - /// Removes elements, which are already in the reference set. - void deduplicate(RTFSprms& rReference); - void swap(RTFSprms& rOther); - size_t size() const { return m_aSprms.size(); } - bool empty() const { return m_aSprms.empty(); } - Entry_t& back() { return m_aSprms.back(); } - Iterator_t begin() { return m_aSprms.begin(); } - Iterator_t end() { return m_aSprms.end(); } - void clear() { return m_aSprms.clear(); } - private: - std::vector< std::pair<Id, RTFValue::Pointer_t> > m_aSprms; + public: + typedef ::boost::shared_ptr<RTFSprms> Pointer_t; + typedef std::pair<Id, RTFValue::Pointer_t> Entry_t; + typedef std::vector<Entry_t>::iterator Iterator_t; + RTFSprms(); + RTFSprms(const RTFSprms& rSprms); + ~RTFSprms(); + RTFSprms& operator=(const RTFSprms& rOther); + RTFValue::Pointer_t find(Id nKeyword); + /// Does the same as ->push_back(), except that it can overwrite existing entries. + void set(Id nKeyword, RTFValue::Pointer_t pValue, bool bOverwrite = true); + bool erase(Id nKeyword); + /// Removes elements, which are already in the reference set. + void deduplicate(RTFSprms& rReference); + void swap(RTFSprms& rOther); + size_t size() const { return m_pSprms->size(); } + bool empty() const { return m_pSprms->empty(); } + Entry_t& back() { return m_pSprms->back(); } + Iterator_t begin() { return m_pSprms->begin(); } + Iterator_t end() { return m_pSprms->end(); } + void clear(); + private: + void ensureCopyBeforeWrite(); + boost::intrusive_ptr<RTFSprmsImpl> m_pSprms; }; /// RTF keyword with a parameter _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits