diff options
-rw-r--r-- | comphelper/source/misc/anycompare.cxx | 11 | ||||
-rw-r--r-- | include/comphelper/anycompare.hxx | 4 | ||||
-rw-r--r-- | include/xmloff/xmlexppr.hxx | 8 | ||||
-rw-r--r-- | xmloff/source/style/impastpl.cxx | 110 | ||||
-rw-r--r-- | xmloff/source/style/xmlexppr.cxx | 101 |
5 files changed, 134 insertions, 100 deletions
diff --git a/comphelper/source/misc/anycompare.cxx b/comphelper/source/misc/anycompare.cxx index 5a7859514ac9..f4d2a8b5d260 100644 --- a/comphelper/source/misc/anycompare.cxx +++ b/comphelper/source/misc/anycompare.cxx @@ -226,6 +226,17 @@ namespace comphelper return pComparator; } + bool anyLess( css::uno::Any const & lhs, css::uno::Any const & rhs) + { + auto lhsTypeClass = lhs.getValueType().getTypeClass(); + auto rhsTypeClass = rhs.getValueType().getTypeClass(); + if (lhsTypeClass != rhsTypeClass) + return lhsTypeClass < rhsTypeClass; + std::unique_ptr< IKeyPredicateLess > pred = getStandardLessPredicate( lhs.getValueType(), Reference< XCollator >() ); + if (!pred) // type==VOID + return false; + return pred->isLess(lhs, rhs); + } } // namespace comphelper diff --git a/include/comphelper/anycompare.hxx b/include/comphelper/anycompare.hxx index dd92d2734ca2..8b5a941a781c 100644 --- a/include/comphelper/anycompare.hxx +++ b/include/comphelper/anycompare.hxx @@ -205,6 +205,10 @@ namespace comphelper css::uno::Reference< css::i18n::XCollator > const & i_collator ); + /** + Compare two Anys. + */ + bool COMPHELPER_DLLPUBLIC anyLess( css::uno::Any const & lhs, css::uno::Any const & rhs); } // namespace comphelper diff --git a/include/xmloff/xmlexppr.hxx b/include/xmloff/xmlexppr.hxx index 28be918474ee..84d2d60c2fb5 100644 --- a/include/xmloff/xmlexppr.hxx +++ b/include/xmloff/xmlexppr.hxx @@ -124,10 +124,14 @@ public: std::vector<XMLPropertyState> FilterDefaults( const css::uno::Reference<css::beans::XPropertySet>& rPropSet ) const; - /** Compare to arrays of XMLPropertyState */ - bool Equals( const ::std::vector< XMLPropertyState >& aProperties1, + /** Provides a partial ordering over two arrays of XMLPropertyState, + Partial because implementing a full order requires quite a lot of code. */ + bool LessPartial( const ::std::vector< XMLPropertyState >& aProperties1, const ::std::vector< XMLPropertyState >& aProperties2 ) const; + /** Compare two arrays of XMLPropertyState */ + bool Equals( const ::std::vector< XMLPropertyState >& aProperties1, + const ::std::vector< XMLPropertyState >& aProperties2 ) const; void exportXML( SvXMLExport& rExport, const ::std::vector< XMLPropertyState >& rProperties, diff --git a/xmloff/source/style/impastpl.cxx b/xmloff/source/style/impastpl.cxx index 1b574adc8b97..c64a35d26141 100644 --- a/xmloff/source/style/impastpl.cxx +++ b/xmloff/source/style/impastpl.cxx @@ -270,39 +270,39 @@ XMLAutoStylePoolParent::~XMLAutoStylePoolParent() { } +struct ComparePartial +{ + const XMLAutoStyleFamily& rFamilyData; + + bool operator()(const vector< XMLPropertyState >& lhs, + const std::unique_ptr<XMLAutoStylePoolProperties>& rhs) const + { + return rFamilyData.mxMapper->LessPartial(lhs, rhs->GetProperties()); + } + bool operator()(const std::unique_ptr<XMLAutoStylePoolProperties>& lhs, + const vector< XMLPropertyState >& rhs ) const + { + return rFamilyData.mxMapper->LessPartial(lhs->GetProperties(), rhs); + } +}; + // Adds a array of XMLPropertyState ( vector< XMLPropertyState > ) to list // if not added, yet. bool XMLAutoStylePoolParent::Add( XMLAutoStyleFamily& rFamilyData, const vector< XMLPropertyState >& rProperties, OUString& rName, bool bDontSeek ) { - bool bAdded = false; XMLAutoStylePoolProperties *pProperties = nullptr; - sal_Int32 nProperties = rProperties.size(); - size_t i = 0; - for (size_t n = m_PropertiesList.size(); i < n; ++i) - { - XMLAutoStylePoolProperties *const pIS = m_PropertiesList[i].get(); - if( nProperties > static_cast<sal_Int32>(pIS->GetProperties().size()) ) - { - continue; - } - else if( nProperties < static_cast<sal_Int32>(pIS->GetProperties().size()) ) - { - break; - } - else if( !bDontSeek && rFamilyData.mxMapper->Equals( pIS->GetProperties(), rProperties ) ) - { - pProperties = pIS; - break; - } - } + auto [itBegin, itEnd] = std::equal_range(m_PropertiesList.begin(), m_PropertiesList.end(), rProperties, ComparePartial{rFamilyData}); + if (!bDontSeek) + for (auto it = itBegin; it != itEnd; ++it) + if (rFamilyData.mxMapper->Equals((*it)->GetProperties(), rProperties)) + pProperties = it->get(); - if( !pProperties ) + bool bAdded = false; + if( bDontSeek || !pProperties ) { pProperties = new XMLAutoStylePoolProperties( rFamilyData, rProperties, msParent ); - PropertiesListType::iterator it = m_PropertiesList.begin(); - ::std::advance( it, i ); - m_PropertiesList.insert(it, std::unique_ptr<XMLAutoStylePoolProperties>(pProperties)); + m_PropertiesList.insert(itBegin, std::unique_ptr<XMLAutoStylePoolProperties>(pProperties)); bAdded = true; } @@ -319,35 +319,17 @@ bool XMLAutoStylePoolParent::Add( XMLAutoStyleFamily& rFamilyData, const vector< bool XMLAutoStylePoolParent::AddNamed( XMLAutoStyleFamily& rFamilyData, const vector< XMLPropertyState >& rProperties, const OUString& rName ) { - bool bAdded = false; - sal_Int32 nProperties = rProperties.size(); - size_t i = 0; - for (size_t n = m_PropertiesList.size(); i < n; ++i) - { - XMLAutoStylePoolProperties *const pIS = m_PropertiesList[i].get(); - if( nProperties > static_cast<sal_Int32>(pIS->GetProperties().size()) ) - { - continue; - } - else if( nProperties < static_cast<sal_Int32>(pIS->GetProperties().size()) ) - { - break; - } - } - - if (rFamilyData.maNameSet.find(rName) == rFamilyData.maNameSet.end()) - { - std::unique_ptr<XMLAutoStylePoolProperties> pProperties( - new XMLAutoStylePoolProperties(rFamilyData, rProperties, msParent)); - // ignore the generated name - pProperties->SetName( rName ); - PropertiesListType::iterator it = m_PropertiesList.begin(); - ::std::advance( it, i ); - m_PropertiesList.insert(it, std::move(pProperties)); - bAdded = true; - } - - return bAdded; + if (rFamilyData.maNameSet.find(rName) != rFamilyData.maNameSet.end()) + return false; + + auto it = std::lower_bound(m_PropertiesList.begin(), m_PropertiesList.end(), rProperties, ComparePartial{rFamilyData}); + + std::unique_ptr<XMLAutoStylePoolProperties> pProperties( + new XMLAutoStylePoolProperties(rFamilyData, rProperties, msParent)); + // ignore the generated name + pProperties->SetName( rName ); + m_PropertiesList.insert(it, std::move(pProperties)); + return true; } @@ -357,24 +339,10 @@ bool XMLAutoStylePoolParent::AddNamed( XMLAutoStyleFamily& rFamilyData, const ve OUString XMLAutoStylePoolParent::Find( const XMLAutoStyleFamily& rFamilyData, const vector< XMLPropertyState >& rProperties ) const { OUString sName; - vector< XMLPropertyState>::size_type nItems = rProperties.size(); - for (const auto & i : m_PropertiesList) - { - const XMLAutoStylePoolProperties *const pIS = i.get(); - if( nItems > pIS->GetProperties().size() ) - { - continue; - } - else if( nItems < pIS->GetProperties().size() ) - { - break; - } - else if( rFamilyData.mxMapper->Equals( pIS->GetProperties(), rProperties ) ) - { - sName = pIS->GetName(); - break; - } - } + auto [itBegin,itEnd] = std::equal_range(m_PropertiesList.begin(), m_PropertiesList.end(), rProperties, ComparePartial{rFamilyData}); + for (auto it = itBegin; it != itEnd; ++it) + if (rFamilyData.mxMapper->Equals((*it)->GetProperties(), rProperties)) + sName = (*it)->GetName(); return sName; } diff --git a/xmloff/source/style/xmlexppr.cxx b/xmloff/source/style/xmlexppr.cxx index 63994492afbc..aa465016bb7f 100644 --- a/xmloff/source/style/xmlexppr.cxx +++ b/xmloff/source/style/xmlexppr.cxx @@ -27,6 +27,7 @@ #include <com/sun/star/beans/XTolerantMultiPropertySet.hpp> #include <com/sun/star/beans/TolerantPropertySetResultType.hpp> #include <rtl/ustrbuf.hxx> +#include <comphelper/anycompare.hxx> #include <cppuhelper/weakref.hxx> #include <osl/diagnose.h> #include <list> @@ -655,44 +656,90 @@ bool SvXMLExportPropertyMapper::Equals( const vector< XMLPropertyState >& aProperties1, const vector< XMLPropertyState >& aProperties2 ) const { - bool bRet = true; + if (aProperties1.size() < aProperties2.size()) + return true; + if (aProperties1.size() > aProperties2.size()) + return false; + sal_uInt32 nCount = aProperties1.size(); - if( nCount == aProperties2.size() ) + for (sal_uInt32 nIndex = 0; nIndex < nCount; ++nIndex) { - sal_uInt32 nIndex = 0; - while( bRet && nIndex < nCount ) - { - const XMLPropertyState& rProp1 = aProperties1[ nIndex ]; - const XMLPropertyState& rProp2 = aProperties2[ nIndex ]; + const XMLPropertyState& rProp1 = aProperties1[ nIndex ]; + const XMLPropertyState& rProp2 = aProperties2[ nIndex ]; - // Compare index. If equal, compare value - if( rProp1.mnIndex == rProp2.mnIndex ) + // Compare index. If equal, compare value + if( rProp1.mnIndex < rProp2.mnIndex ) + return true; + if( rProp1.mnIndex > rProp2.mnIndex ) + return false; + + if( rProp1.mnIndex != -1 ) + { + // Now compare values + if ( (mpImpl->mxPropMapper->GetEntryType( rProp1.mnIndex ) & + XML_TYPE_BUILDIN_CMP ) != 0 ) { - if( rProp1.mnIndex != -1 ) - { - // Now compare values - if ( (mpImpl->mxPropMapper->GetEntryType( rProp1.mnIndex ) & - XML_TYPE_BUILDIN_CMP ) != 0 ) - // simple type ( binary compare ) - bRet = ( rProp1.maValue == rProp2.maValue ); - else - // complex type ( ask for compare-function ) - bRet = mpImpl->mxPropMapper->GetPropertyHandler( - rProp1.mnIndex )->equals( rProp1.maValue, - rProp2.maValue ); - } + // simple type ( binary compare ) + if ( rProp1.maValue != rProp2.maValue) + return false; } else - bRet = false; + { + // complex type ( ask for compare-function ) + if (!mpImpl->mxPropMapper->GetPropertyHandler( + rProp1.mnIndex )->equals( rProp1.maValue, + rProp2.maValue )) + return false; + } + } + } + + return true; +} - nIndex++; +// Compares two Sequences of XMLPropertyState: +// 1.Number of elements equal ? +// 2.Index of each element equal ? (So I know whether the propertynames are the same) +// 3.Value of each element equal ? +bool SvXMLExportPropertyMapper::LessPartial( + const vector< XMLPropertyState >& aProperties1, + const vector< XMLPropertyState >& aProperties2 ) const +{ + if (aProperties1.size() < aProperties2.size()) + return true; + if (aProperties1.size() > aProperties2.size()) + return false; + + sal_uInt32 nCount = aProperties1.size(); + + for (sal_uInt32 nIndex = 0; nIndex < nCount; ++nIndex) + { + const XMLPropertyState& rProp1 = aProperties1[ nIndex ]; + const XMLPropertyState& rProp2 = aProperties2[ nIndex ]; + + // Compare index. If equal, compare value + if( rProp1.mnIndex < rProp2.mnIndex ) + return true; + if( rProp1.mnIndex > rProp2.mnIndex ) + return false; + + if( rProp1.mnIndex != -1 ) + { + // Now compare values + if ( (mpImpl->mxPropMapper->GetEntryType( rProp1.mnIndex ) & + XML_TYPE_BUILDIN_CMP ) != 0 ) + { + // simple type ( binary compare ) + if ( comphelper::anyLess(rProp1.maValue, rProp2.maValue) ) + return true; + if ( comphelper::anyLess(rProp2.maValue, rProp1.maValue ) ) + return false; + } } } - else - bRet = false; - return bRet; + return false; } /** fills the given attribute list with the items in the given set |