summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@suse.com>2012-12-07 13:16:23 +0000
committerMichael Meeks <michael.meeks@suse.com>2012-12-07 13:35:50 +0000
commita48e2fd9049797110b3b2505c363557284987ca8 (patch)
tree02f5462093214a1d98f8824bb1f4fc2fdd0c1842
parent7d88aac6029353c293dfdacbfa462d62c0da69ea (diff)
fdo#44736 - convert RTFSprms to a copy-on-write structure.
Also try to avoid copy/delete thrash of RTFParserState.
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.cxx7
-rw-r--r--writerfilter/source/rtftok/rtfsprm.cxx58
-rw-r--r--writerfilter/source/rtftok/rtfsprm.hxx67
3 files changed, 92 insertions, 40 deletions
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index aa90d3b07b7e..78bd1058fa56 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 2958cde25cb8..e11dbe6a9f80 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 80d41a3c0f69..5f7a793cb28a 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