diff options
Diffstat (limited to 'comphelper/source')
99 files changed, 5702 insertions, 2875 deletions
diff --git a/comphelper/source/container/IndexedPropertyValuesContainer.cxx b/comphelper/source/container/IndexedPropertyValuesContainer.cxx index 639fb625797e..f5b7358d64c4 100644 --- a/comphelper/source/container/IndexedPropertyValuesContainer.cxx +++ b/comphelper/source/container/IndexedPropertyValuesContainer.cxx @@ -17,57 +17,21 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include <com/sun/star/container/XIndexContainer.hpp> -#include <com/sun/star/uno/Sequence.h> -#include <com/sun/star/beans/PropertyValue.hpp> -#include <cppuhelper/implbase.hxx> #include <com/sun/star/lang/IllegalArgumentException.hpp> #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> -#include <com/sun/star/lang/XServiceInfo.hpp> +#include <comphelper/indexedpropertyvalues.hxx> #include <cppuhelper/supportsservice.hxx> - -#include <vector> +#include <o3tl/safeint.hxx> namespace com::sun::star::uno { class XComponentContext; } using namespace com::sun::star; -typedef std::vector < uno::Sequence< beans::PropertyValue > > IndexedPropertyValues; - -namespace { - -class IndexedPropertyValuesContainer : public cppu::WeakImplHelper< container::XIndexContainer, lang::XServiceInfo > -{ -public: - IndexedPropertyValuesContainer() throw(); - - // XIndexContainer - virtual void SAL_CALL insertByIndex( sal_Int32 nIndex, const css::uno::Any& aElement ) override; - virtual void SAL_CALL removeByIndex( sal_Int32 nIndex ) override; - - // XIndexReplace - virtual void SAL_CALL replaceByIndex( sal_Int32 nIndex, const css::uno::Any& aElement ) override; - // XIndexAccess - virtual sal_Int32 SAL_CALL getCount( ) override; - virtual css::uno::Any SAL_CALL getByIndex( sal_Int32 nIndex ) override; +namespace comphelper { - // XElementAccess - virtual css::uno::Type SAL_CALL getElementType( ) override; - virtual sal_Bool SAL_CALL hasElements( ) override; - //XServiceInfo - virtual OUString SAL_CALL getImplementationName( ) override; - virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; - virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; - -private: - IndexedPropertyValues maProperties; -}; - -} - -IndexedPropertyValuesContainer::IndexedPropertyValuesContainer() throw() +IndexedPropertyValuesContainer::IndexedPropertyValuesContainer() noexcept { } @@ -89,7 +53,7 @@ void SAL_CALL IndexedPropertyValuesContainer::insertByIndex( sal_Int32 nIndex, c void SAL_CALL IndexedPropertyValuesContainer::removeByIndex( sal_Int32 nIndex ) { - if ((nIndex >= sal_Int32(maProperties.size())) || (nIndex < 0)) + if ((nIndex < 0) || (o3tl::make_unsigned(nIndex) >= maProperties.size())) throw lang::IndexOutOfBoundsException(); maProperties.erase(maProperties.begin() + nIndex); @@ -150,12 +114,14 @@ css::uno::Sequence< OUString > SAL_CALL IndexedPropertyValuesContainer::getSuppo return { "com.sun.star.document.IndexedPropertyValues" }; } +} // namespace comphelper + extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * IndexedPropertyValuesContainer_get_implementation( css::uno::XComponentContext *, css::uno::Sequence<css::uno::Any> const &) { - return cppu::acquire(new IndexedPropertyValuesContainer()); + return cppu::acquire(new comphelper::IndexedPropertyValuesContainer()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/container/NamedPropertyValuesContainer.cxx b/comphelper/source/container/NamedPropertyValuesContainer.cxx index dbd0e422b5fb..a44837f11700 100644 --- a/comphelper/source/container/NamedPropertyValuesContainer.cxx +++ b/comphelper/source/container/NamedPropertyValuesContainer.cxx @@ -37,7 +37,7 @@ namespace { class NamedPropertyValuesContainer : public cppu::WeakImplHelper< container::XNameContainer, lang::XServiceInfo > { public: - NamedPropertyValuesContainer() throw(); + NamedPropertyValuesContainer() noexcept; // XNameContainer virtual void SAL_CALL insertByName( const OUString& aName, const css::uno::Any& aElement ) override; @@ -66,7 +66,7 @@ private: } -NamedPropertyValuesContainer::NamedPropertyValuesContainer() throw() +NamedPropertyValuesContainer::NamedPropertyValuesContainer() noexcept { } diff --git a/comphelper/source/container/container.cxx b/comphelper/source/container/container.cxx index 1a6132e0d65a..7b2432723360 100644 --- a/comphelper/source/container/container.cxx +++ b/comphelper/source/container/container.cxx @@ -22,6 +22,7 @@ #include <com/sun/star/container/XChild.hpp> #include <comphelper/container.hxx> #include <o3tl/any.hxx> +#include <utility> #include <osl/diagnose.h> @@ -29,8 +30,8 @@ namespace comphelper { -IndexAccessIterator::IndexAccessIterator(css::uno::Reference< css::uno::XInterface> const & xStartingPoint) - :m_xStartingPoint(xStartingPoint) +IndexAccessIterator::IndexAccessIterator(css::uno::Reference< css::uno::XInterface> xStartingPoint) + :m_xStartingPoint(std::move(xStartingPoint)) { OSL_ENSURE(m_xStartingPoint.is(), "IndexAccessIterator::IndexAccessIterator : no starting point !"); } diff --git a/comphelper/source/container/embeddedobjectcontainer.cxx b/comphelper/source/container/embeddedobjectcontainer.cxx index faed14065082..a66ac2dec527 100644 --- a/comphelper/source/container/embeddedobjectcontainer.cxx +++ b/comphelper/source/container/embeddedobjectcontainer.cxx @@ -42,9 +42,12 @@ #include <comphelper/embeddedobjectcontainer.hxx> #include <comphelper/sequence.hxx> #include <comphelper/propertysequence.hxx> +#include <comphelper/propertyvalue.hxx> #include <cppuhelper/weakref.hxx> #include <sal/log.hxx> +#include <officecfg/Office/Common.hxx> + #include <algorithm> #include <unordered_map> @@ -134,31 +137,31 @@ void EmbeddedObjectContainer::SwitchPersistence( const uno::Reference < embed::X bool EmbeddedObjectContainer::CommitImageSubStorage() { - if ( pImpl->mxImageStorage.is() ) + if ( !pImpl->mxImageStorage ) + return true; + + try { - try + bool bReadOnlyMode = true; + uno::Reference < beans::XPropertySet > xSet(pImpl->mxImageStorage,uno::UNO_QUERY); + if ( xSet.is() ) { - bool bReadOnlyMode = true; - uno::Reference < beans::XPropertySet > xSet(pImpl->mxImageStorage,uno::UNO_QUERY); - if ( xSet.is() ) - { - // get the open mode from the parent storage - sal_Int32 nMode = 0; - uno::Any aAny = xSet->getPropertyValue("OpenMode"); - if ( aAny >>= nMode ) - bReadOnlyMode = !(nMode & embed::ElementModes::WRITE ); - } // if ( xSet.is() ) - if ( !bReadOnlyMode ) - { - uno::Reference< embed::XTransactedObject > xTransact( pImpl->mxImageStorage, uno::UNO_QUERY_THROW ); - xTransact->commit(); - } - } - catch (const uno::Exception&) + // get the open mode from the parent storage + sal_Int32 nMode = 0; + uno::Any aAny = xSet->getPropertyValue("OpenMode"); + if ( aAny >>= nMode ) + bReadOnlyMode = !(nMode & embed::ElementModes::WRITE ); + } // if ( xSet.is() ) + if ( !bReadOnlyMode ) { - return false; + uno::Reference< embed::XTransactedObject > xTransact( pImpl->mxImageStorage, uno::UNO_QUERY_THROW ); + xTransact->commit(); } } + catch (const uno::Exception&) + { + return false; + } return true; } @@ -235,8 +238,7 @@ bool EmbeddedObjectContainer::HasEmbeddedObjects() const bool EmbeddedObjectContainer::HasEmbeddedObject( const OUString& rName ) { - auto aIt = pImpl->maNameToObjectMap.find( rName ); - if (aIt != pImpl->maNameToObjectMap.end()) + if (pImpl->maNameToObjectMap.contains(rName)) return true; if (!pImpl->mxStorage.is()) return false; @@ -245,7 +247,7 @@ bool EmbeddedObjectContainer::HasEmbeddedObject( const OUString& rName ) bool EmbeddedObjectContainer::HasEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj ) const { - return pImpl->maObjectToNameMap.find(xObj) != pImpl->maObjectToNameMap.end(); + return pImpl->maObjectToNameMap.contains(xObj); } bool EmbeddedObjectContainer::HasInstantiatedEmbeddedObject( const OUString& rName ) @@ -253,8 +255,7 @@ bool EmbeddedObjectContainer::HasInstantiatedEmbeddedObject( const OUString& rNa // allows to detect whether the object was already instantiated // currently the filter instantiate it on loading, so this method allows // to avoid objects pointing to the same persistence - auto aIt = pImpl->maNameToObjectMap.find( rName ); - return ( aIt != pImpl->maNameToObjectMap.end() ); + return pImpl->maNameToObjectMap.contains(rName); } OUString EmbeddedObjectContainer::GetEmbeddedObjectName( const css::uno::Reference < css::embed::XEmbeddedObject >& xObj ) const @@ -322,24 +323,24 @@ uno::Reference<embed::XEmbeddedObject> EmbeddedObjectContainer::Get_Impl( //TODO/LATER: it would be good to detect an error when an object should be created already, but isn't (not an "inside" call) uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() ); uno::Sequence< beans::PropertyValue > aObjDescr(1 + (xCopy.is() ? 1 : 0) + (pBaseURL ? 1 : 0)); - aObjDescr[0].Name = "Parent"; - aObjDescr[0].Value <<= pImpl->m_xModel.get(); - sal_Int32 i = 1; + auto itObjDescr = aObjDescr.getArray(); + itObjDescr->Name = "Parent"; + itObjDescr->Value <<= pImpl->m_xModel.get(); if (pBaseURL) { - aObjDescr[i].Name = "DefaultParentBaseURL"; - aObjDescr[i].Value <<= *pBaseURL; - ++i; + ++itObjDescr; + itObjDescr->Name = "DefaultParentBaseURL"; + itObjDescr->Value <<= *pBaseURL; } if ( xCopy.is() ) { - aObjDescr[i].Name = "CloneFrom"; - aObjDescr[i].Value <<= xCopy; + ++itObjDescr; + itObjDescr->Name = "CloneFrom"; + itObjDescr->Value <<= xCopy; } - uno::Sequence< beans::PropertyValue > aMediaDescr( 1 ); - aMediaDescr[0].Name = "ReadOnly"; - aMediaDescr[0].Value <<= bReadOnlyMode; + uno::Sequence< beans::PropertyValue > aMediaDescr{ comphelper::makePropertyValue( + "ReadOnly", bReadOnlyMode) }; xObj.set( xFactory->createInstanceInitFromEntry( pImpl->mxStorage, rName, aMediaDescr, aObjDescr ), uno::UNO_QUERY ); @@ -371,14 +372,15 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CreateEmbedde const size_t nExtraArgs = pBaseURL ? 2 : 1; uno::Sequence< beans::PropertyValue > aObjDescr( rArgs.getLength() + nExtraArgs ); - aObjDescr[0].Name = "Parent"; - aObjDescr[0].Value <<= pImpl->m_xModel.get(); + auto pObjDescr = aObjDescr.getArray(); + pObjDescr[0].Name = "Parent"; + pObjDescr[0].Value <<= pImpl->m_xModel.get(); if (pBaseURL) { - aObjDescr[1].Name = "DefaultParentBaseURL"; - aObjDescr[1].Value <<= *pBaseURL; + pObjDescr[1].Name = "DefaultParentBaseURL"; + pObjDescr[1].Value <<= *pBaseURL; } - std::copy( rArgs.begin(), rArgs.end(), aObjDescr.getArray() + nExtraArgs ); + std::copy( rArgs.begin(), rArgs.end(), pObjDescr + nExtraArgs ); xObj.set( xFactory->createInstanceInitNew( rClassId, OUString(), pImpl->mxStorage, rNewName, aObjDescr ), uno::UNO_QUERY ); @@ -591,12 +593,13 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbedde { uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() ); uno::Sequence< beans::PropertyValue > aObjDescr(pBaseURL ? 2 : 1); - aObjDescr[0].Name = "Parent"; - aObjDescr[0].Value <<= pImpl->m_xModel.get(); + auto pObjDescr = aObjDescr.getArray(); + pObjDescr[0].Name = "Parent"; + pObjDescr[0].Value <<= pImpl->m_xModel.get(); if (pBaseURL) { - aObjDescr[1].Name = "DefaultParentBaseURL"; - aObjDescr[1].Value <<= *pBaseURL; + pObjDescr[1].Name = "DefaultParentBaseURL"; + pObjDescr[1].Value <<= *pBaseURL; } xObj.set( xFactory->createInstanceInitFromMediaDescriptor( pImpl->mxStorage, rNewName, aMedium, aObjDescr ), uno::UNO_QUERY ); @@ -627,9 +630,8 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbedde try { uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create(::comphelper::getProcessComponentContext()); - uno::Sequence< beans::PropertyValue > aObjDescr( 1 ); - aObjDescr[0].Name = "Parent"; - aObjDescr[0].Value <<= pImpl->m_xModel.get(); + uno::Sequence< beans::PropertyValue > aObjDescr{ comphelper::makePropertyValue( + "Parent", pImpl->m_xModel.get()) }; xObj.set( xFactory->createInstanceLink( pImpl->mxStorage, rNewName, aMedium, aObjDescr ), uno::UNO_QUERY ); uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); @@ -714,12 +716,10 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CopyAndGetEmb uno::Reference < embed::XEmbeddedObjectCreator > xCreator = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() ); - uno::Sequence< beans::PropertyValue > aMediaDescr( 1 ); - aMediaDescr[0].Name = "URL"; - aMediaDescr[0].Value <<= aURL; - uno::Sequence< beans::PropertyValue > aObjDescr( 1 ); - aObjDescr[0].Name = "Parent"; - aObjDescr[0].Value <<= pImpl->m_xModel.get(); + uno::Sequence< beans::PropertyValue > aMediaDescr{ comphelper::makePropertyValue( + "URL", aURL) }; + uno::Sequence< beans::PropertyValue > aObjDescr{ comphelper::makePropertyValue( + "Parent", pImpl->m_xModel.get()) }; xResult.set(xCreator->createInstanceLink( pImpl->mxStorage, rName, @@ -740,9 +740,8 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CopyAndGetEmb uno::Reference < embed::XEmbeddedObjectCreator > xCreator = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() ); - uno::Sequence< beans::PropertyValue > aObjDescr( 1 ); - aObjDescr[0].Name = "Parent"; - aObjDescr[0].Value <<= pImpl->m_xModel.get(); + uno::Sequence< beans::PropertyValue > aObjDescr{ comphelper::makePropertyValue( + "Parent", pImpl->m_xModel.get()) }; xResult.set(xCreator->createInstanceInitNew( xObj->getClassID(), xObj->getClassName(), @@ -914,7 +913,7 @@ bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed // the media type will be provided with object insertion OUString aOrigStorMediaType; uno::Reference< beans::XPropertySet > xStorProps( pImpl->mxStorage, uno::UNO_QUERY_THROW ); - static constexpr OUStringLiteral s_sMediaType(u"MediaType"); + static constexpr OUString s_sMediaType(u"MediaType"_ustr); xStorProps->getPropertyValue( s_sMediaType ) >>= aOrigStorMediaType; SAL_WARN_IF( aOrigStorMediaType.isEmpty(), "comphelper.container", "No valuable media type in the storage!" ); @@ -970,26 +969,26 @@ bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed else SAL_WARN( "comphelper.container", "Object not found for removal!" ); - if ( xPersist.is() && bKeepToTempStorage ) // #i119941# - { - // remove replacement image (if there is one) - RemoveGraphicStream( aName ); + if ( !xPersist || !bKeepToTempStorage ) // #i119941# + return true; - // now it's time to remove the storage from the container storage - try - { + // remove replacement image (if there is one) + RemoveGraphicStream( aName ); + + // now it's time to remove the storage from the container storage + try + { #if OSL_DEBUG_LEVEL > 1 - // if the object has a persistence and the object is not a link than it must have persistence entry in storage - OSL_ENSURE( bIsNotEmbedded || pImpl->mxStorage->hasByName( aName ), "The object has no persistence entry in the storage!" ); + // if the object has a persistence and the object is not a link than it must have persistence entry in storage + OSL_ENSURE( bIsNotEmbedded || pImpl->mxStorage->hasByName( aName ), "The object has no persistence entry in the storage!" ); #endif - if ( xPersist.is() && pImpl->mxStorage->hasByName( aName ) ) - pImpl->mxStorage->removeElement( aName ); - } - catch (const uno::Exception&) - { - SAL_WARN( "comphelper.container", "Failed to remove object from storage!" ); - return false; - } + if ( xPersist.is() && pImpl->mxStorage->hasByName( aName ) ) + pImpl->mxStorage->removeElement( aName ); + } + catch (const uno::Exception&) + { + SAL_WARN( "comphelper.container", "Failed to remove object from storage!" ); + return false; } return true; @@ -1095,13 +1094,11 @@ bool EmbeddedObjectContainer::InsertGraphicStreamDirectly( const css::uno::Refer uno::Reference < embed::XOptimizedStorage > xOptRepl( xReplacement, uno::UNO_QUERY_THROW ); // store it into the subfolder - uno::Sequence< beans::PropertyValue > aProps( 3 ); - aProps[0].Name = "MediaType"; - aProps[0].Value <<= rMediaType; - aProps[1].Name = "UseCommonStoragePasswordEncryption"; - aProps[1].Value <<= true; - aProps[2].Name = "Compressed"; - aProps[2].Value <<= true; + uno::Sequence< beans::PropertyValue > aProps{ + comphelper::makePropertyValue("MediaType", rMediaType), + comphelper::makePropertyValue("UseCommonStoragePasswordEncryption", true), + comphelper::makePropertyValue("Compressed", true) + }; if ( xReplacement->hasByName( rObjectName ) ) xReplacement->removeElement( rObjectName ); @@ -1161,7 +1158,8 @@ namespace { } -bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEmbedded,const uno::Reference < embed::XStorage >& _xStorage) +bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEmbedded, bool _bAutoSaveEvent, + const uno::Reference < embed::XStorage >& _xStorage) { bool bResult = false; try @@ -1225,18 +1223,23 @@ bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEm uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); if ( xPersist.is() ) { - uno::Sequence< beans::PropertyValue > aArgs( _bOasisFormat ? 2 : 3 ); - aArgs[0].Name = "StoreVisualReplacement"; - aArgs[0].Value <<= !_bOasisFormat; + uno::Sequence< beans::PropertyValue > aArgs( _bOasisFormat ? 3 : 4 ); + auto pArgs = aArgs.getArray(); + pArgs[0].Name = "StoreVisualReplacement"; + pArgs[0].Value <<= !_bOasisFormat; // if it is an embedded object or the optimized inserting fails the normal inserting should be done - aArgs[1].Name = "CanTryOptimization"; - aArgs[1].Value <<= !_bCreateEmbedded; + pArgs[1].Name = "CanTryOptimization"; + pArgs[1].Value <<= !_bCreateEmbedded; + + pArgs[2].Name = "AutoSaveEvent"; + pArgs[2].Value <<= _bAutoSaveEvent; + if ( !_bOasisFormat ) { // if object has no cached replacement it will use this one - aArgs[2].Name = "VisualReplacement"; - aArgs[2].Value <<= xStream; + pArgs[3].Name = "VisualReplacement"; + pArgs[3].Value <<= xStream; } try @@ -1489,6 +1492,8 @@ bool EmbeddedObjectContainer::SetPersistentEntries(const uno::Reference< embed:: bool EmbeddedObjectContainer::getUserAllowsLinkUpdate() const { + if (officecfg::Office::Common::Security::Scripting::DisableActiveContent::get()) + return false; return pImpl->mbUserAllowsLinkUpdate; } diff --git a/comphelper/source/container/enumerablemap.cxx b/comphelper/source/container/enumerablemap.cxx index ae6053d7520c..ae78223a20fe 100644 --- a/comphelper/source/container/enumerablemap.cxx +++ b/comphelper/source/container/enumerablemap.cxx @@ -31,7 +31,7 @@ #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/uno/XComponentContext.hpp> -#include <cppuhelper/compbase3.hxx> +#include <cppuhelper/compbase.hxx> #include <cppuhelper/implbase.hxx> #include <cppuhelper/supportsservice.hxx> #include <typelib/typedescription.hxx> @@ -39,6 +39,7 @@ #include <cmath> #include <map> #include <memory> +#include <optional> #include <utility> namespace comphelper @@ -89,7 +90,7 @@ namespace comphelper { Type m_aKeyType; Type m_aValueType; - std::unique_ptr< KeyedValues > m_pValues; + std::optional< KeyedValues > m_pValues; std::shared_ptr< IKeyPredicateLess > m_pKeyCompare; bool m_bMutable; std::vector< MapEnumerator* > m_aModListeners; @@ -102,11 +103,10 @@ namespace comphelper MapData( const MapData& _source ) :m_aKeyType( _source.m_aKeyType ) ,m_aValueType( _source.m_aValueType ) - ,m_pValues( new KeyedValues( *_source.m_pValues ) ) ,m_pKeyCompare( _source.m_pKeyCompare ) ,m_bMutable( false ) - ,m_aModListeners() { + m_pValues.emplace( *_source.m_pValues ); } private: MapData& operator=( const MapData& _source ) = delete; @@ -143,7 +143,7 @@ namespace comphelper // EnumerableMap - typedef ::cppu::WeakAggComponentImplHelper3 < XInitialization + typedef ::cppu::WeakComponentImplHelper < XInitialization , XEnumerableMap , XServiceInfo > Map_IFace; @@ -356,7 +356,7 @@ namespace comphelper m_aData.m_aKeyType = aKeyType; m_aData.m_aValueType = aValueType; m_aData.m_pKeyCompare = std::move(pComparator); - m_aData.m_pValues.reset( new KeyedValues( *m_aData.m_pKeyCompare ) ); + m_aData.m_pValues.emplace( *m_aData.m_pKeyCompare ); m_aData.m_bMutable = bMutable; if ( aInitialValues.hasElements() ) diff --git a/comphelper/source/container/enumhelper.cxx b/comphelper/source/container/enumhelper.cxx index edcb03c669cc..66ba15198232 100644 --- a/comphelper/source/container/enumhelper.cxx +++ b/comphelper/source/container/enumhelper.cxx @@ -21,13 +21,14 @@ #include <com/sun/star/lang/XComponent.hpp> #include <com/sun/star/container/XIndexAccess.hpp> #include <com/sun/star/container/XNameAccess.hpp> +#include <utility> namespace comphelper { -OEnumerationByName::OEnumerationByName(const css::uno::Reference<css::container::XNameAccess>& _rxAccess) - :m_aNames(_rxAccess->getElementNames()) - ,m_xAccess(_rxAccess) +OEnumerationByName::OEnumerationByName(css::uno::Reference<css::container::XNameAccess> _xAccess) + :m_aNames(_xAccess->getElementNames()) + ,m_xAccess(_xAccess) ,m_nPos(0) ,m_bListening(false) { @@ -35,28 +36,29 @@ OEnumerationByName::OEnumerationByName(const css::uno::Reference<css::container: } -OEnumerationByName::OEnumerationByName(const css::uno::Reference<css::container::XNameAccess>& _rxAccess, - const css::uno::Sequence< OUString >& _aNames ) - :m_aNames(_aNames) - ,m_xAccess(_rxAccess) +OEnumerationByName::OEnumerationByName(css::uno::Reference<css::container::XNameAccess> _xAccess, + std::vector<OUString> _aNames ) + :m_aNames(std::move(_aNames)) + ,m_xAccess(std::move(_xAccess)) ,m_nPos(0) ,m_bListening(false) { impl_startDisposeListening(); } - OEnumerationByName::~OEnumerationByName() { + std::lock_guard aLock(m_aLock); + impl_stopDisposeListening(); } sal_Bool SAL_CALL OEnumerationByName::hasMoreElements( ) { - osl::MutexGuard aLock(m_aLock); + std::lock_guard aLock(m_aLock); - if (m_xAccess.is() && m_aNames.getLength() > m_nPos) + if (m_xAccess.is() && getLength() > m_nPos) return true; if (m_xAccess.is()) @@ -71,13 +73,13 @@ sal_Bool SAL_CALL OEnumerationByName::hasMoreElements( ) css::uno::Any SAL_CALL OEnumerationByName::nextElement( ) { - osl::MutexGuard aLock(m_aLock); + std::lock_guard aLock(m_aLock); css::uno::Any aRes; - if (m_xAccess.is() && m_nPos < m_aNames.getLength()) - aRes = m_xAccess->getByName(m_aNames.getConstArray()[m_nPos++]); + if (m_xAccess.is() && m_nPos < getLength()) + aRes = m_xAccess->getByName(getElement(m_nPos++)); - if (m_xAccess.is() && m_nPos >= m_aNames.getLength()) + if (m_xAccess.is() && m_nPos >= getLength()) { impl_stopDisposeListening(); m_xAccess.clear(); @@ -89,10 +91,9 @@ css::uno::Any SAL_CALL OEnumerationByName::nextElement( ) return aRes; } - void SAL_CALL OEnumerationByName::disposing(const css::lang::EventObject& aEvent) { - osl::MutexGuard aLock(m_aLock); + std::lock_guard aLock(m_aLock); if (aEvent.Source == m_xAccess) m_xAccess.clear(); @@ -101,8 +102,6 @@ void SAL_CALL OEnumerationByName::disposing(const css::lang::EventObject& aEvent void OEnumerationByName::impl_startDisposeListening() { - osl::MutexGuard aLock(m_aLock); - if (m_bListening) return; @@ -119,8 +118,6 @@ void OEnumerationByName::impl_startDisposeListening() void OEnumerationByName::impl_stopDisposeListening() { - osl::MutexGuard aLock(m_aLock); - if (!m_bListening) return; @@ -134,8 +131,25 @@ void OEnumerationByName::impl_stopDisposeListening() osl_atomic_decrement(&m_refCount); } -OEnumerationByIndex::OEnumerationByIndex(const css::uno::Reference< css::container::XIndexAccess >& _rxAccess) - :m_xAccess(_rxAccess) +sal_Int32 OEnumerationByName::getLength() const +{ + if (m_aNames.index() == 0) + return std::get<css::uno::Sequence<OUString>>(m_aNames).getLength(); + else + return std::get<std::vector<OUString>>(m_aNames).size(); +} + +const OUString& OEnumerationByName::getElement(sal_Int32 nIndex) const +{ + if (m_aNames.index() == 0) + return std::get<css::uno::Sequence<OUString>>(m_aNames).getConstArray()[nIndex]; + else + return std::get<std::vector<OUString>>(m_aNames)[nIndex]; +} + + +OEnumerationByIndex::OEnumerationByIndex(css::uno::Reference< css::container::XIndexAccess > _xAccess) + :m_xAccess(std::move(_xAccess)) ,m_nPos(0) ,m_bListening(false) { @@ -145,13 +159,15 @@ OEnumerationByIndex::OEnumerationByIndex(const css::uno::Reference< css::contain OEnumerationByIndex::~OEnumerationByIndex() { + std::lock_guard aLock(m_aLock); + impl_stopDisposeListening(); } sal_Bool SAL_CALL OEnumerationByIndex::hasMoreElements( ) { - osl::MutexGuard aLock(m_aLock); + std::lock_guard aLock(m_aLock); if (m_xAccess.is() && m_xAccess->getCount() > m_nPos) return true; @@ -168,7 +184,7 @@ sal_Bool SAL_CALL OEnumerationByIndex::hasMoreElements( ) css::uno::Any SAL_CALL OEnumerationByIndex::nextElement( ) { - osl::MutexGuard aLock(m_aLock); + std::lock_guard aLock(m_aLock); css::uno::Any aRes; if (m_xAccess.is() && m_nPos < m_xAccess->getCount()) @@ -188,7 +204,7 @@ css::uno::Any SAL_CALL OEnumerationByIndex::nextElement( ) void SAL_CALL OEnumerationByIndex::disposing(const css::lang::EventObject& aEvent) { - osl::MutexGuard aLock(m_aLock); + std::lock_guard aLock(m_aLock); if (aEvent.Source == m_xAccess) m_xAccess.clear(); @@ -197,8 +213,6 @@ void SAL_CALL OEnumerationByIndex::disposing(const css::lang::EventObject& aEven void OEnumerationByIndex::impl_startDisposeListening() { - osl::MutexGuard aLock(m_aLock); - if (m_bListening) return; @@ -215,8 +229,6 @@ void OEnumerationByIndex::impl_startDisposeListening() void OEnumerationByIndex::impl_stopDisposeListening() { - osl::MutexGuard aLock(m_aLock); - if (!m_bListening) return; @@ -244,7 +256,7 @@ OAnyEnumeration::~OAnyEnumeration() sal_Bool SAL_CALL OAnyEnumeration::hasMoreElements( ) { - osl::MutexGuard aLock(m_aLock); + std::lock_guard aLock(m_aLock); return (m_lItems.getLength() > m_nPos); } @@ -255,7 +267,7 @@ css::uno::Any SAL_CALL OAnyEnumeration::nextElement( ) if ( ! hasMoreElements()) throw css::container::NoSuchElementException(); - osl::MutexGuard aLock(m_aLock); + std::lock_guard aLock(m_aLock); sal_Int32 nPos = m_nPos; ++m_nPos; return m_lItems[nPos]; diff --git a/comphelper/source/container/interfacecontainer2.cxx b/comphelper/source/container/interfacecontainer2.cxx index 1524600affd0..a2e2119be0d2 100644 --- a/comphelper/source/container/interfacecontainer2.cxx +++ b/comphelper/source/container/interfacecontainer2.cxx @@ -19,7 +19,9 @@ #include <comphelper/interfacecontainer2.hxx> +#include <comphelper/multicontainer2.hxx> +#include <o3tl/safeint.hxx> #include <osl/diagnose.h> #include <osl/mutex.hxx> @@ -36,13 +38,13 @@ namespace comphelper { OInterfaceIteratorHelper2::OInterfaceIteratorHelper2( OInterfaceContainerHelper2 & rCont_ ) - : rCont( rCont_ ), - bIsList( rCont_.bIsList ) + : rCont( rCont_ ) { MutexGuard aGuard( rCont.rMutex ); if( rCont.bInUse ) // worst case, two iterators at the same time rCont.copyAndResetInUse(); + bIsList = rCont_.bIsList; aData = rCont_.aData; if( bIsList ) { @@ -102,7 +104,7 @@ void OInterfaceIteratorHelper2::remove() if( bIsList ) { OSL_ASSERT( nRemain >= 0 && - nRemain < static_cast<sal_Int32>(aData.pAsVector->size()) ); + o3tl::make_unsigned(nRemain) < aData.pAsVector->size() ); rCont.removeInterface( (*aData.pAsVector)[nRemain] ); } else @@ -170,6 +172,9 @@ void OInterfaceContainerHelper2::copyAndResetInUse() sal_Int32 OInterfaceContainerHelper2::addInterface( const Reference<XInterface> & rListener ) { OSL_ASSERT( rListener.is() ); + if ( !rListener.is() ) + return 0; + MutexGuard aGuard( rMutex ); if( bInUse ) copyAndResetInUse(); @@ -239,6 +244,16 @@ sal_Int32 OInterfaceContainerHelper2::removeInterface( const Reference<XInterfac return aData.pAsInterface ? 1 : 0; } +Reference<XInterface> OInterfaceContainerHelper2::getInterface( sal_Int32 nIndex ) const +{ + MutexGuard aGuard( rMutex ); + + if (bIsList) + return (*aData.pAsVector)[nIndex]; + assert(aData.pAsInterface && nIndex == 0); + return aData.pAsInterface; +} + void OInterfaceContainerHelper2::disposeAndClear( const EventObject & rEvt ) { ClearableMutexGuard aGuard( rMutex ); @@ -285,6 +300,121 @@ void OInterfaceContainerHelper2::clear() } + +// specialized class for type + +OMultiTypeInterfaceContainerHelper2::OMultiTypeInterfaceContainerHelper2( Mutex & rMutex_ ) + : rMutex( rMutex_ ) +{ +} + +OMultiTypeInterfaceContainerHelper2::~OMultiTypeInterfaceContainerHelper2() +{ +} + +std::vector< css::uno::Type > OMultiTypeInterfaceContainerHelper2::getContainedTypes() const +{ + ::osl::MutexGuard aGuard( rMutex ); + std::vector< Type > aInterfaceTypes; + aInterfaceTypes.reserve( m_aMap.size() ); + for (const auto& rItem : m_aMap) + { + // are interfaces added to this container? + if( rItem.second->getLength() ) + // yes, put the type in the array + aInterfaceTypes.push_back(rItem.first); + } + return aInterfaceTypes; +} + +OMultiTypeInterfaceContainerHelper2::t_type2ptr::iterator OMultiTypeInterfaceContainerHelper2::findType(const Type & rKey ) +{ + return std::find_if(m_aMap.begin(), m_aMap.end(), + [&rKey](const t_type2ptr::value_type& rItem) { return rItem.first == rKey; }); +} + +OMultiTypeInterfaceContainerHelper2::t_type2ptr::const_iterator OMultiTypeInterfaceContainerHelper2::findType(const Type & rKey ) const +{ + return std::find_if(m_aMap.begin(), m_aMap.end(), + [&rKey](const t_type2ptr::value_type& rItem) { return rItem.first == rKey; }); +} + +OInterfaceContainerHelper2 * OMultiTypeInterfaceContainerHelper2::getContainer( const Type & rKey ) const +{ + ::osl::MutexGuard aGuard( rMutex ); + + auto iter = findType( rKey ); + if( iter != m_aMap.end() ) + return (*iter).second.get(); + return nullptr; +} + +sal_Int32 OMultiTypeInterfaceContainerHelper2::addInterface( + const Type & rKey, const Reference< XInterface > & rListener ) +{ + ::osl::MutexGuard aGuard( rMutex ); + auto iter = findType( rKey ); + if( iter == m_aMap.end() ) + { + OInterfaceContainerHelper2 * pLC = new OInterfaceContainerHelper2( rMutex ); + m_aMap.emplace_back(rKey, pLC); + return pLC->addInterface( rListener ); + } + return (*iter).second->addInterface( rListener ); +} + +sal_Int32 OMultiTypeInterfaceContainerHelper2::removeInterface( + const Type & rKey, const Reference< XInterface > & rListener ) +{ + ::osl::MutexGuard aGuard( rMutex ); + + // search container with id nUik + auto iter = findType( rKey ); + // container found? + if( iter != m_aMap.end() ) + return (*iter).second->removeInterface( rListener ); + + // no container with this id. Always return 0 + return 0; +} + +void OMultiTypeInterfaceContainerHelper2::disposeAndClear( const EventObject & rEvt ) +{ + t_type2ptr::size_type nSize = 0; + std::unique_ptr<OInterfaceContainerHelper2 *[]> ppListenerContainers; + { + ::osl::MutexGuard aGuard( rMutex ); + nSize = m_aMap.size(); + if( nSize ) + { + typedef OInterfaceContainerHelper2* ppp; + ppListenerContainers.reset(new ppp[nSize]); + + t_type2ptr::size_type i = 0; + for (const auto& rItem : m_aMap) + { + ppListenerContainers[i++] = rItem.second.get(); + } + } + } + + // create a copy, because do not fire event in a guarded section + for( t_type2ptr::size_type i = 0; i < nSize; i++ ) + { + if( ppListenerContainers[i] ) + ppListenerContainers[i]->disposeAndClear( rEvt ); + } +} + +void OMultiTypeInterfaceContainerHelper2::clear() +{ + ::osl::MutexGuard aGuard( rMutex ); + + for (auto& rItem : m_aMap) + rItem.second->clear(); +} + + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/container/namecontainer.cxx b/comphelper/source/container/namecontainer.cxx index fc43d871d7e4..cfa958a0272b 100644 --- a/comphelper/source/container/namecontainer.cxx +++ b/comphelper/source/container/namecontainer.cxx @@ -20,6 +20,7 @@ #include <sal/config.h> #include <map> +#include <mutex> #include <comphelper/namecontainer.hxx> #include <comphelper/sequence.hxx> @@ -58,14 +59,13 @@ namespace comphelper private: SvGenericNameContainerMapImpl maProperties; const css::uno::Type maType; - osl::Mutex maMutex; + std::mutex maMutex; }; } } using namespace ::comphelper; -using namespace ::osl; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::container; using namespace ::com::sun::star::lang; @@ -79,7 +79,7 @@ NameContainer::NameContainer( const css::uno::Type& aType ) // XNameContainer void SAL_CALL NameContainer::insertByName( const OUString& aName, const Any& aElement ) { - MutexGuard aGuard( maMutex ); + std::scoped_lock aGuard( maMutex ); if( maProperties.find( aName ) != maProperties.end() ) throw ElementExistException(); @@ -92,7 +92,7 @@ void SAL_CALL NameContainer::insertByName( const OUString& aName, const Any& aEl void SAL_CALL NameContainer::removeByName( const OUString& Name ) { - MutexGuard aGuard( maMutex ); + std::scoped_lock aGuard( maMutex ); SvGenericNameContainerMapImpl::iterator aIter = maProperties.find( Name ); if( aIter == maProperties.end() ) @@ -105,7 +105,7 @@ void SAL_CALL NameContainer::removeByName( const OUString& Name ) void SAL_CALL NameContainer::replaceByName( const OUString& aName, const Any& aElement ) { - MutexGuard aGuard( maMutex ); + std::scoped_lock aGuard( maMutex ); SvGenericNameContainerMapImpl::iterator aIter( maProperties.find( aName ) ); if( aIter == maProperties.end() ) @@ -121,7 +121,7 @@ void SAL_CALL NameContainer::replaceByName( const OUString& aName, const Any& aE Any SAL_CALL NameContainer::getByName( const OUString& aName ) { - MutexGuard aGuard( maMutex ); + std::scoped_lock aGuard( maMutex ); SvGenericNameContainerMapImpl::iterator aIter = maProperties.find( aName ); if( aIter == maProperties.end() ) @@ -132,14 +132,14 @@ Any SAL_CALL NameContainer::getByName( const OUString& aName ) Sequence< OUString > SAL_CALL NameContainer::getElementNames( ) { - MutexGuard aGuard( maMutex ); + std::scoped_lock aGuard( maMutex ); return comphelper::mapKeysToSequence(maProperties); } sal_Bool SAL_CALL NameContainer::hasByName( const OUString& aName ) { - MutexGuard aGuard( maMutex ); + std::scoped_lock aGuard( maMutex ); SvGenericNameContainerMapImpl::iterator aIter = maProperties.find( aName ); return aIter != maProperties.end(); @@ -147,7 +147,7 @@ sal_Bool SAL_CALL NameContainer::hasByName( const OUString& aName ) sal_Bool SAL_CALL NameContainer::hasElements( ) { - MutexGuard aGuard( maMutex ); + std::scoped_lock aGuard( maMutex ); return !maProperties.empty(); } diff --git a/comphelper/source/eventattachermgr/eventattachermgr.cxx b/comphelper/source/eventattachermgr/eventattachermgr.cxx index 4a36c0f1192f..9a6d4af5afe5 100644 --- a/comphelper/source/eventattachermgr/eventattachermgr.cxx +++ b/comphelper/source/eventattachermgr/eventattachermgr.cxx @@ -21,7 +21,6 @@ #include <o3tl/any.hxx> #include <o3tl/safeint.hxx> -#include <osl/mutex.hxx> #include <osl/diagnose.h> #include <comphelper/eventattachermgr.hxx> #include <comphelper/sequence.hxx> @@ -42,13 +41,15 @@ #include <com/sun/star/script/XEventAttacherManager.hpp> #include <com/sun/star/script/XScriptListener.hpp> #include <cppuhelper/weak.hxx> -#include <comphelper/interfacecontainer2.hxx> +#include <comphelper/interfacecontainer4.hxx> #include <cppuhelper/exc_hlp.hxx> #include <cppuhelper/implbase.hxx> #include <rtl/ref.hxx> #include <deque> +#include <mutex> #include <algorithm> +#include <utility> using namespace com::sun::star::uno; using namespace com::sun::star::io; @@ -57,7 +58,6 @@ using namespace com::sun::star::beans; using namespace com::sun::star::script; using namespace com::sun::star::reflection; using namespace cppu; -using namespace osl; namespace comphelper @@ -84,9 +84,9 @@ class ImplEventAttacherManager { friend class AttacherAllListener_Impl; std::deque< AttacherIndex_Impl > aIndex; - Mutex aLock; + std::mutex m_aMutex; // Container for the ScriptListener - OInterfaceContainerHelper2 aScriptListeners; + OInterfaceContainerHelper4<XScriptListener> aScriptListeners; // Instance of EventAttacher Reference< XEventAttacher2 > xAttacher; Reference< XComponentContext > mxContext; @@ -116,8 +116,14 @@ public: virtual void SAL_CALL read(const Reference< XObjectInputStream >& InStream) override; private: + void registerScriptEvent(std::unique_lock<std::mutex>&, sal_Int32 Index, const ScriptEventDescriptor& ScriptEvent); + void registerScriptEvents(std::unique_lock<std::mutex>&, sal_Int32 Index, const Sequence< ScriptEventDescriptor >& ScriptEvents); + void attach(std::unique_lock<std::mutex>&, sal_Int32 Index, const Reference< XInterface >& Object, const Any& Helper); + void detach(std::unique_lock<std::mutex>&, sal_Int32 nIndex, const Reference< XInterface >& xObject); + void insertEntry(std::unique_lock<std::mutex>&, sal_Int32 Index); + /// @throws Exception - Reference< XIdlReflection > getReflection(); + Reference< XIdlReflection > getReflection(std::unique_lock<std::mutex>&); /** checks if <arg>_nIndex</arg> is a valid index, throws an <type>IllegalArgumentException</type> if not @param _nIndex @@ -140,8 +146,8 @@ class AttacherAllListener_Impl : public WeakImplHelper< XAllListener > /// @throws CannotConvertException void convertToEventReturn( Any & rRet, const Type & rRetType ); public: - AttacherAllListener_Impl( ImplEventAttacherManager* pManager_, const OUString &rScriptType_, - const OUString & rScriptCode_ ); + AttacherAllListener_Impl( ImplEventAttacherManager* pManager_, OUString aScriptType_, + OUString aScriptCode_ ); // Methods of XAllListener virtual void SAL_CALL firing(const AllEventObject& Event) override; @@ -156,12 +162,12 @@ public: AttacherAllListener_Impl::AttacherAllListener_Impl ( ImplEventAttacherManager* pManager_, - const OUString & rScriptType_, - const OUString & rScriptCode_ + OUString aScriptType_, + OUString aScriptCode_ ) : mxManager( pManager_ ) - , aScriptType( rScriptType_ ) - , aScriptCode( rScriptCode_ ) + , aScriptType(std::move( aScriptType_ )) + , aScriptCode(std::move( aScriptCode_ )) { } @@ -179,9 +185,8 @@ void SAL_CALL AttacherAllListener_Impl::firing(const AllEventObject& Event) aScriptEvent.ScriptCode = aScriptCode; // Iterate over all listeners and pass events. - OInterfaceIteratorHelper2 aIt( mxManager->aScriptListeners ); - while( aIt.hasMoreElements() ) - static_cast<XScriptListener *>(aIt.next())->firing( aScriptEvent ); + std::unique_lock l(mxManager->m_aMutex); + mxManager->aScriptListeners.notifyEach( l, &XScriptListener::firing, aScriptEvent ); } @@ -242,13 +247,17 @@ Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Even Any aRet; // Iterate over all listeners and pass events. - OInterfaceIteratorHelper2 aIt( mxManager->aScriptListeners ); + std::unique_lock l(mxManager->m_aMutex); + OInterfaceIteratorHelper4 aIt( l, mxManager->aScriptListeners ); while( aIt.hasMoreElements() ) { - aRet = static_cast<XScriptListener *>(aIt.next())->approveFiring( aScriptEvent ); + // cannot hold lock over call to approveFiring, since it might recurse back into us + l.unlock(); + aRet = aIt.next()->approveFiring( aScriptEvent ); + l.lock(); try { - Reference< XIdlClass > xListenerType = mxManager->getReflection()-> + Reference< XIdlClass > xListenerType = mxManager->getReflection(l)-> forName( Event.ListenerType.getTypeName() ); Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName ); if( xMeth.is() ) @@ -299,7 +308,7 @@ Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Even catch (const CannotConvertException&) { // silent ignore conversions errors from a script call - Reference< XIdlClass > xListenerType = mxManager->getReflection()-> + Reference< XIdlClass > xListenerType = mxManager->getReflection(l)-> forName( Event.ListenerType.getTypeName() ); Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName ); if( xMeth.is() ) @@ -340,8 +349,7 @@ Reference< XEventAttacherManager > createEventAttacherManager( const Reference< ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection, const Reference< XComponentContext >& rContext ) - : aScriptListeners( aLock ) - , mxContext( rContext ) + : mxContext( rContext ) , nVersion(0) { if ( rContext.is() ) @@ -358,15 +366,12 @@ ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospect Reference< XInitialization > xInit( xAttacher, UNO_QUERY ); if( xInit.is() ) { - Sequence< Any > Arguments( 1 ); - Arguments[0] <<= rIntrospection; - xInit->initialize( Arguments ); + xInit->initialize({ Any(rIntrospection) }); } } -Reference< XIdlReflection > ImplEventAttacherManager::getReflection() +Reference< XIdlReflection > ImplEventAttacherManager::getReflection(std::unique_lock<std::mutex>&) { - Guard< Mutex > aGuard( aLock ); // Do we already have a service? If not, create one. if( !mxCoreReflection.is() ) { @@ -392,8 +397,17 @@ void SAL_CALL ImplEventAttacherManager::registerScriptEvent const ScriptEventDescriptor& ScriptEvent ) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); + registerScriptEvent(l, nIndex, ScriptEvent); +} +void ImplEventAttacherManager::registerScriptEvent +( + std::unique_lock<std::mutex>&, + sal_Int32 nIndex, + const ScriptEventDescriptor& ScriptEvent +) +{ // Examine the index and apply the array std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); @@ -427,20 +441,29 @@ void SAL_CALL ImplEventAttacherManager::registerScriptEvents const Sequence< ScriptEventDescriptor >& ScriptEvents ) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); + registerScriptEvents(l, nIndex, ScriptEvents); +} +void ImplEventAttacherManager::registerScriptEvents +( + std::unique_lock<std::mutex>& l, + sal_Int32 nIndex, + const Sequence< ScriptEventDescriptor >& ScriptEvents +) +{ // Examine the index and apply the array std::deque< AttachedObject_Impl > aList = implCheckIndex( nIndex )->aObjList; for( const auto& rObj : aList ) - detach( nIndex, rObj.xTarget ); + detach( l, nIndex, rObj.xTarget ); const ScriptEventDescriptor* pArray = ScriptEvents.getConstArray(); sal_Int32 nLen = ScriptEvents.getLength(); for( sal_Int32 i = 0 ; i < nLen ; i++ ) - registerScriptEvent( nIndex, pArray[ i ] ); + registerScriptEvent( l, nIndex, pArray[ i ] ); for( const auto& rObj : aList ) - attach( nIndex, rObj.xTarget, rObj.aHelper ); + attach( l, nIndex, rObj.xTarget, rObj.aHelper ); } @@ -452,18 +475,18 @@ void SAL_CALL ImplEventAttacherManager::revokeScriptEvent const OUString& ToRemoveListenerParam ) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); std::deque< AttachedObject_Impl > aList = aIt->aObjList; for( const auto& rObj : aList ) - detach( nIndex, rObj.xTarget ); + detach( l, nIndex, rObj.xTarget ); - OUString aLstType = ListenerType; - sal_Int32 nLastDot = aLstType.lastIndexOf('.'); - if (nLastDot != -1) - aLstType = aLstType.copy(nLastDot+1); + std::u16string_view aLstType = ListenerType; + size_t nLastDot = aLstType.rfind('.'); + if (nLastDot != std::u16string_view::npos) + aLstType = aLstType.substr(nLastDot+1); auto aEvtIt = std::find_if(aIt->aEventList.begin(), aIt->aEventList.end(), [&aLstType, &EventMethod, &ToRemoveListenerParam](const ScriptEventDescriptor& rEvent) { @@ -475,30 +498,35 @@ void SAL_CALL ImplEventAttacherManager::revokeScriptEvent aIt->aEventList.erase( aEvtIt ); for( const auto& rObj : aList ) - attach( nIndex, rObj.xTarget, rObj.aHelper ); + attach( l, nIndex, rObj.xTarget, rObj.aHelper ); } void SAL_CALL ImplEventAttacherManager::revokeScriptEvents(sal_Int32 nIndex ) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); std::deque< AttachedObject_Impl > aList = aIt->aObjList; for( const auto& rObj : aList ) - detach( nIndex, rObj.xTarget ); + detach( l, nIndex, rObj.xTarget ); aIt->aEventList.clear(); for( const auto& rObj : aList ) - attach( nIndex, rObj.xTarget, rObj.aHelper ); + attach( l, nIndex, rObj.xTarget, rObj.aHelper ); } void SAL_CALL ImplEventAttacherManager::insertEntry(sal_Int32 nIndex) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); if( nIndex < 0 ) throw IllegalArgumentException("negative index", static_cast<cppu::OWeakObject*>(this), 1); + insertEntry(l, nIndex); +} + +void ImplEventAttacherManager::insertEntry(std::unique_lock<std::mutex>&, sal_Int32 nIndex) +{ if ( o3tl::make_unsigned(nIndex) >= aIndex.size() ) aIndex.resize(nIndex+1); @@ -506,15 +534,14 @@ void SAL_CALL ImplEventAttacherManager::insertEntry(sal_Int32 nIndex) aIndex.insert( aIndex.begin() + nIndex, aTmp ); } - void SAL_CALL ImplEventAttacherManager::removeEntry(sal_Int32 nIndex) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); std::deque< AttachedObject_Impl > aList = aIt->aObjList; for( const auto& rObj : aList ) - detach( nIndex, rObj.xTarget ); + detach( l, nIndex, rObj.xTarget ); aIndex.erase( aIt ); } @@ -522,7 +549,7 @@ void SAL_CALL ImplEventAttacherManager::removeEntry(sal_Int32 nIndex) Sequence< ScriptEventDescriptor > SAL_CALL ImplEventAttacherManager::getScriptEvents(sal_Int32 nIndex) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); return comphelper::containerToSequence(aIt->aEventList); } @@ -530,17 +557,21 @@ Sequence< ScriptEventDescriptor > SAL_CALL ImplEventAttacherManager::getScriptEv void SAL_CALL ImplEventAttacherManager::attach(sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); if( nIndex < 0 || !xObject.is() ) throw IllegalArgumentException("negative index, or null object", static_cast<cppu::OWeakObject*>(this), -1); + attach(l, nIndex, xObject, Helper); +} +void ImplEventAttacherManager::attach(std::unique_lock<std::mutex>& l, sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper) +{ if( o3tl::make_unsigned(nIndex) >= aIndex.size() ) { // read older files if( nVersion != 1 ) throw IllegalArgumentException(); - insertEntry( nIndex ); - attach( nIndex, xObject, Helper ); + insertEntry( l, nIndex ); + attach( l, nIndex, xObject, Helper ); return; } @@ -586,11 +617,15 @@ void SAL_CALL ImplEventAttacherManager::attach(sal_Int32 nIndex, const Reference void SAL_CALL ImplEventAttacherManager::detach(sal_Int32 nIndex, const Reference< XInterface >& xObject) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); //return; if( nIndex < 0 || o3tl::make_unsigned(nIndex) >= aIndex.size() || !xObject.is() ) throw IllegalArgumentException("bad index or null object", static_cast<cppu::OWeakObject*>(this), 1); + detach(l, nIndex, xObject); +} +void ImplEventAttacherManager::detach(std::unique_lock<std::mutex>&, sal_Int32 nIndex, const Reference< XInterface >& xObject) +{ std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex; auto aObjIt = std::find_if(aCurrentPosition->aObjList.begin(), aCurrentPosition->aObjList.end(), [&xObject](const AttachedObject_Impl& rObj) { return rObj.xTarget == xObject; }); @@ -618,14 +653,14 @@ void SAL_CALL ImplEventAttacherManager::detach(sal_Int32 nIndex, const Reference void SAL_CALL ImplEventAttacherManager::addScriptListener(const Reference< XScriptListener >& aListener) { - Guard< Mutex > aGuard( aLock ); - aScriptListeners.addInterface( aListener ); + std::unique_lock l(m_aMutex); + aScriptListeners.addInterface( l, aListener ); } void SAL_CALL ImplEventAttacherManager::removeScriptListener(const Reference< XScriptListener >& aListener) { - Guard< Mutex > aGuard( aLock ); - aScriptListeners.removeInterface( aListener ); + std::unique_lock l(m_aMutex); + aScriptListeners.removeInterface( l, aListener ); } @@ -637,7 +672,7 @@ OUString SAL_CALL ImplEventAttacherManager::getServiceName() void SAL_CALL ImplEventAttacherManager::write(const Reference< XObjectOutputStream >& OutStream) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); // Don't run without XMarkableStream Reference< XMarkableStream > xMarkStream( OutStream, UNO_QUERY ); if( !xMarkStream.is() ) @@ -676,7 +711,7 @@ void SAL_CALL ImplEventAttacherManager::write(const Reference< XObjectOutputStre void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream >& InStream) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); // Don't run without XMarkableStream Reference< XMarkableStream > xMarkStream( InStream, UNO_QUERY ); if( !xMarkStream.is() ) @@ -697,7 +732,7 @@ void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream for( sal_Int32 i = 0 ; i < nItemCount ; i++ ) { - insertEntry( i ); + insertEntry( l, i ); // Read the length of the sequence sal_Int32 nSeqLen = InStream->readLong(); @@ -713,7 +748,7 @@ void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream rDesc.ScriptType = InStream->readUTF(); rDesc.ScriptCode = InStream->readUTF(); } - registerScriptEvents( i, aSEDSeq ); + registerScriptEvents( l, i, aSEDSeq ); } // Have we read the specified length? diff --git a/comphelper/source/misc/AccessibleImplementationHelper.cxx b/comphelper/source/misc/AccessibleImplementationHelper.cxx index a45b6e5f3cd7..a02f4380dd33 100644 --- a/comphelper/source/misc/AccessibleImplementationHelper.cxx +++ b/comphelper/source/misc/AccessibleImplementationHelper.cxx @@ -33,8 +33,7 @@ OUString GetkeyBindingStrByXkeyBinding(const Sequence<KeyStroke>& keySet) OUStringBuffer buf; for (const auto& k : keySet) { - buf.append('\n'); - buf.append(k.KeyChar); + buf.append("\n" + OUStringChar(k.KeyChar)); } return buf.makeStringAndClear(); } diff --git a/comphelper/source/misc/DirectoryHelper.cxx b/comphelper/source/misc/DirectoryHelper.cxx index 4ac2dfe7e829..badfe9b62d80 100644 --- a/comphelper/source/misc/DirectoryHelper.cxx +++ b/comphelper/source/misc/DirectoryHelper.cxx @@ -11,6 +11,7 @@ #include <sal/config.h> #include <osl/file.hxx> +#include <rtl/uri.hxx> #include <memory> @@ -18,24 +19,24 @@ namespace comphelper { typedef std::shared_ptr<osl::File> FileSharedPtr; -OUString DirectoryHelper::splitAtLastToken(const OUString& rSrc, sal_Unicode aToken, - OUString& rRight) +std::u16string_view DirectoryHelper::splitAtLastToken(std::u16string_view rSrc, sal_Unicode aToken, + OUString& rRight) { - const sal_Int32 nIndex(rSrc.lastIndexOf(aToken)); - OUString aRetval; + const size_t nIndex(rSrc.rfind(aToken)); + std::u16string_view aRetval; - if (-1 == nIndex) + if (std::u16string_view::npos == nIndex) { aRetval = rSrc; rRight.clear(); } else if (nIndex > 0) { - aRetval = rSrc.copy(0, nIndex); + aRetval = rSrc.substr(0, nIndex); - if (rSrc.getLength() > nIndex + 1) + if (rSrc.size() > nIndex + 1) { - rRight = rSrc.copy(nIndex + 1); + rRight = rSrc.substr(nIndex + 1); } } @@ -77,12 +78,16 @@ void DirectoryHelper::scanDirsAndFiles(const OUString& rDirURL, std::set<OUStrin if (osl::FileBase::E_None != aDirectory.open()) return; + auto lcl_encodeUriSegment = [](OUString const& rPath) { + return rtl::Uri::encode(rPath, rtl_UriCharClassUricNoSlash, rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8); + }; + osl::DirectoryItem aDirectoryItem; while (osl::FileBase::E_None == aDirectory.getNextItem(aDirectoryItem)) { - osl::FileStatus aFileStatus(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL - | osl_FileStatus_Mask_FileName); + osl::FileStatus aFileStatus(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName); if (osl::FileBase::E_None == aDirectoryItem.getFileStatus(aFileStatus)) { @@ -92,7 +97,7 @@ void DirectoryHelper::scanDirsAndFiles(const OUString& rDirURL, std::set<OUStrin if (!aFileName.isEmpty()) { - rDirs.insert(aFileName); + rDirs.insert(lcl_encodeUriSegment(aFileName)); } } else if (aFileStatus.isRegular()) @@ -103,7 +108,8 @@ void DirectoryHelper::scanDirsAndFiles(const OUString& rDirURL, std::set<OUStrin if (!aFileName.isEmpty()) { - rFiles.insert(std::pair<OUString, OUString>(aFileName, aExtension)); + rFiles.insert(std::pair<OUString, OUString>(lcl_encodeUriSegment(aFileName), + lcl_encodeUriSegment(aExtension))); } } } @@ -204,4 +210,4 @@ bool DirectoryHelper::moveDirContent(const OUString& rSourceDirURL, return bError; } -}
\ No newline at end of file +} diff --git a/comphelper/source/misc/SelectionMultiplex.cxx b/comphelper/source/misc/SelectionMultiplex.cxx index 267266388c71..37e4e30037b3 100644 --- a/comphelper/source/misc/SelectionMultiplex.cxx +++ b/comphelper/source/misc/SelectionMultiplex.cxx @@ -95,7 +95,20 @@ void SAL_CALL OSelectionChangeMultiplexer::selectionChanged( const EventObject& m_pListener->_selectionChanged(_rEvent); } +void OSelectionChangeMultiplexer::dispose() +{ + osl_atomic_increment(&m_refCount); + { + Reference< XSelectionChangeListener> xPreventDelete(this); + if(m_xSet.is()) + { + m_xSet->removeSelectionChangeListener(xPreventDelete); + m_xSet.clear(); + } + } + osl_atomic_decrement(&m_refCount); } +} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/accessiblecomponenthelper.cxx b/comphelper/source/misc/accessiblecomponenthelper.cxx index 2962bbac95a8..3922812b92af 100644 --- a/comphelper/source/misc/accessiblecomponenthelper.cxx +++ b/comphelper/source/misc/accessiblecomponenthelper.cxx @@ -18,6 +18,11 @@ */ #include <comphelper/accessiblecomponenthelper.hxx> +#include <comphelper/accessiblecontexthelper.hxx> +#include <osl/diagnose.h> +#include <com/sun/star/accessibility/IllegalAccessibleComponentStateException.hpp> +#include <comphelper/accessibleeventnotifier.hxx> +#include <comphelper/solarmutex.hxx> namespace comphelper @@ -30,12 +35,209 @@ namespace comphelper using namespace ::com::sun::star::accessibility; OCommonAccessibleComponent::OCommonAccessibleComponent( ) + :OCommonAccessibleComponent_Base( GetMutex() ) + ,m_nClientId( 0 ) { } OCommonAccessibleComponent::~OCommonAccessibleComponent( ) { + // this ensures that the lock, which may be already destroyed as part of the derivee, + // is not used anymore + + ensureDisposed(); + } + + + void SAL_CALL OCommonAccessibleComponent::disposing() + { + // rhbz#1001768: de facto this class is locked by SolarMutex; + // do not lock m_Mutex because it may cause deadlock + osl::Guard<SolarMutex> aGuard(SolarMutex::get()); + + if ( m_nClientId ) + { + AccessibleEventNotifier::revokeClientNotifyDisposing( m_nClientId, *this ); + m_nClientId=0; + } + } + + + void SAL_CALL OCommonAccessibleComponent::addAccessibleEventListener( const Reference< XAccessibleEventListener >& _rxListener ) + { + osl::Guard<SolarMutex> aGuard(SolarMutex::get()); + // don't use the OContextEntryGuard - it will throw an exception if we're not alive + // anymore, while the most recent specification for XComponent states that we should + // silently ignore the call in such a situation + if ( !isAlive() ) + { + if ( _rxListener.is() ) + _rxListener->disposing( EventObject( *this ) ); + return; + } + + if ( _rxListener.is() ) + { + if ( !m_nClientId ) + m_nClientId = AccessibleEventNotifier::registerClient( ); + + AccessibleEventNotifier::addEventListener( m_nClientId, _rxListener ); + } + } + + + void SAL_CALL OCommonAccessibleComponent::removeAccessibleEventListener( const Reference< XAccessibleEventListener >& _rxListener ) + { + osl::Guard<SolarMutex> aGuard(SolarMutex::get()); + // don't use the OContextEntryGuard - it will throw an exception if we're not alive + // anymore, while the most recent specification for XComponent states that we should + // silently ignore the call in such a situation + if ( !isAlive() ) + return; + + if ( !(_rxListener.is() && m_nClientId) ) + return; + + sal_Int32 nListenerCount = AccessibleEventNotifier::removeEventListener( m_nClientId, _rxListener ); + if ( !nListenerCount ) + { + // no listeners anymore + // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client), + // and at least to us not firing any events anymore, in case somebody calls + // NotifyAccessibleEvent, again + AccessibleEventNotifier::revokeClient( m_nClientId ); + m_nClientId = 0; + } + } + + + void OCommonAccessibleComponent::NotifyAccessibleEvent( const sal_Int16 _nEventId, + const Any& _rOldValue, const Any& _rNewValue, sal_Int32 nIndexHint ) + { + if ( !m_nClientId ) + // if we don't have a client id for the notifier, then we don't have listeners, then + // we don't need to notify anything + return; + + // build an event object + AccessibleEventObject aEvent(*this, _nEventId, _rNewValue, _rOldValue, nIndexHint); + + // let the notifier handle this event + AccessibleEventNotifier::addEvent( m_nClientId, aEvent ); + } + + + bool OCommonAccessibleComponent::isAlive() const + { + return !rBHelper.bDisposed && !rBHelper.bInDispose; + } + + + void OCommonAccessibleComponent::ensureAlive() const + { + if( !isAlive() ) + throw DisposedException(); + } + + + void OCommonAccessibleComponent::ensureDisposed( ) + { + if ( !rBHelper.bDisposed ) + { + OSL_ENSURE( 0 == m_refCount, "OCommonAccessibleComponent::ensureDisposed: this method _has_ to be called from without your dtor only!" ); + acquire(); + dispose(); + } + } + + + void OCommonAccessibleComponent::lateInit( const Reference< XAccessible >& _rxAccessible ) + { + m_aCreator = _rxAccessible; + } + + + Reference< XAccessible > OCommonAccessibleComponent::getAccessibleCreator( ) const + { + return m_aCreator; + } + + + OUString SAL_CALL OCommonAccessibleComponent::getAccessibleId( ) + { + return OUString(); + } + + + sal_Int64 SAL_CALL OCommonAccessibleComponent::getAccessibleIndexInParent( ) + { + OExternalLockGuard aGuard( this ); + + // -1 for child not found/no parent (according to specification) + sal_Int64 nRet = -1; + + try + { + + Reference< XAccessibleContext > xParentContext( implGetParentContext() ); + + // iterate over parent's children and search for this object + if ( xParentContext.is() ) + { + // our own XAccessible for comparing with the children of our parent + Reference< XAccessible > xCreator( m_aCreator); + + OSL_ENSURE( xCreator.is(), "OCommonAccessibleComponent::getAccessibleIndexInParent: invalid creator!" ); + // two ideas why this could be NULL: + // * nobody called our late ctor (init), so we never had a creator at all -> bad + // * the creator is already dead. In this case, we should have been disposed, and + // never survived the above OContextEntryGuard. + // in all other situations the creator should be non-NULL + + if ( xCreator.is() ) + { + sal_Int64 nChildCount = xParentContext->getAccessibleChildCount(); + for ( sal_Int64 nChild = 0; ( nChild < nChildCount ) && ( -1 == nRet ); ++nChild ) + { + Reference< XAccessible > xChild( xParentContext->getAccessibleChild( nChild ) ); + if ( xChild.get() == xCreator.get() ) + nRet = nChild; + } + } + } + } + catch( const Exception& ) + { + OSL_FAIL( "OCommonAccessibleComponent::getAccessibleIndexInParent: caught an exception!" ); + } + + return nRet; + } + + + Locale SAL_CALL OCommonAccessibleComponent::getLocale( ) + { + // simply ask the parent + Reference< XAccessible > xParent = getAccessibleParent(); + Reference< XAccessibleContext > xParentContext; + if ( xParent.is() ) + xParentContext = xParent->getAccessibleContext(); + + if ( !xParentContext.is() ) + throw IllegalAccessibleComponentStateException( OUString(), *this ); + + return xParentContext->getLocale(); + } + + + Reference< XAccessibleContext > OCommonAccessibleComponent::implGetParentContext() + { + Reference< XAccessible > xParent = getAccessibleParent(); + Reference< XAccessibleContext > xParentContext; + if ( xParent.is() ) + xParentContext = xParent->getAccessibleContext(); + return xParentContext; } @@ -97,11 +299,6 @@ namespace comphelper } - IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleComponentHelper, OCommonAccessibleComponent, OAccessibleComponentHelper_Base ) - IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleComponentHelper, OCommonAccessibleComponent, OAccessibleComponentHelper_Base ) - // (order matters: the first is the class name, the second is the class doing the ref counting) - - sal_Bool SAL_CALL OAccessibleComponentHelper::containsPoint( const awt::Point& _rPoint ) { return OCommonAccessibleComponent::containsPoint( _rPoint ); @@ -136,11 +333,6 @@ namespace comphelper } - IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleExtendedComponentHelper, OCommonAccessibleComponent, OAccessibleExtendedComponentHelper_Base ) - IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleExtendedComponentHelper, OCommonAccessibleComponent, OAccessibleExtendedComponentHelper_Base ) - // (order matters: the first is the class name, the second is the class doing the ref counting) - - sal_Bool SAL_CALL OAccessibleExtendedComponentHelper::containsPoint( const awt::Point& _rPoint ) { return OCommonAccessibleComponent::containsPoint( _rPoint ); diff --git a/comphelper/source/misc/accessiblecontexthelper.cxx b/comphelper/source/misc/accessiblecontexthelper.cxx deleted file mode 100644 index a4d11cb59c1a..000000000000 --- a/comphelper/source/misc/accessiblecontexthelper.cxx +++ /dev/null @@ -1,279 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include <comphelper/accessiblecontexthelper.hxx> -#include <osl/diagnose.h> -#include <cppuhelper/weakref.hxx> -#include <com/sun/star/accessibility/IllegalAccessibleComponentStateException.hpp> -#include <comphelper/accessibleeventnotifier.hxx> -#include <comphelper/solarmutex.hxx> - - -namespace comphelper -{ - using namespace ::com::sun::star::uno; - using namespace ::com::sun::star::lang; - using namespace ::com::sun::star::accessibility; - - /** implementation class for OAccessibleContextHelper. No own thread safety! - */ - class OContextHelper_Impl - { - private: - WeakReference< XAccessible > m_aCreator; // the XAccessible which created our XAccessibleContext - - AccessibleEventNotifier::TClientId m_nClientId; - - public: - Reference< XAccessible > getCreator( ) const { return m_aCreator; } - inline void setCreator( const Reference< XAccessible >& _rAcc ); - - AccessibleEventNotifier::TClientId - getClientId() const { return m_nClientId; } - void setClientId( const AccessibleEventNotifier::TClientId _nId ) - { m_nClientId = _nId; } - - public: - OContextHelper_Impl() - :m_nClientId( 0 ) - { - } - }; - - - inline void OContextHelper_Impl::setCreator( const Reference< XAccessible >& _rAcc ) - { - m_aCreator = _rAcc; - } - - OAccessibleContextHelper::OAccessibleContextHelper( ) - :OAccessibleContextHelper_Base( GetMutex() ) - ,m_pImpl(new OContextHelper_Impl) - { - } - - - OAccessibleContextHelper::~OAccessibleContextHelper( ) - { - // this ensures that the lock, which may be already destroyed as part of the derivee, - // is not used anymore - - ensureDisposed(); - } - - - void SAL_CALL OAccessibleContextHelper::disposing() - { - // rhbz#1001768: de facto this class is locked by SolarMutex; - // do not lock m_Mutex because it may cause deadlock - osl::Guard<SolarMutex> aGuard(SolarMutex::get()); - - if ( m_pImpl->getClientId( ) ) - { - AccessibleEventNotifier::revokeClientNotifyDisposing( m_pImpl->getClientId( ), *this ); - m_pImpl->setClientId( 0 ); - } - } - - - void SAL_CALL OAccessibleContextHelper::addAccessibleEventListener( const Reference< XAccessibleEventListener >& _rxListener ) - { - osl::Guard<SolarMutex> aGuard(SolarMutex::get()); - // don't use the OContextEntryGuard - it will throw an exception if we're not alive - // anymore, while the most recent specification for XComponent states that we should - // silently ignore the call in such a situation - if ( !isAlive() ) - { - if ( _rxListener.is() ) - _rxListener->disposing( EventObject( *this ) ); - return; - } - - if ( _rxListener.is() ) - { - if ( !m_pImpl->getClientId( ) ) - m_pImpl->setClientId( AccessibleEventNotifier::registerClient( ) ); - - AccessibleEventNotifier::addEventListener( m_pImpl->getClientId( ), _rxListener ); - } - } - - - void SAL_CALL OAccessibleContextHelper::removeAccessibleEventListener( const Reference< XAccessibleEventListener >& _rxListener ) - { - osl::Guard<SolarMutex> aGuard(SolarMutex::get()); - // don't use the OContextEntryGuard - it will throw an exception if we're not alive - // anymore, while the most recent specification for XComponent states that we should - // silently ignore the call in such a situation - if ( !isAlive() ) - return; - - if ( !(_rxListener.is() && m_pImpl->getClientId()) ) - return; - - sal_Int32 nListenerCount = AccessibleEventNotifier::removeEventListener( m_pImpl->getClientId( ), _rxListener ); - if ( !nListenerCount ) - { - // no listeners anymore - // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client), - // and at least to us not firing any events anymore, in case somebody calls - // NotifyAccessibleEvent, again - AccessibleEventNotifier::revokeClient( m_pImpl->getClientId( ) ); - m_pImpl->setClientId( 0 ); - } - } - - - void OAccessibleContextHelper::NotifyAccessibleEvent( const sal_Int16 _nEventId, - const Any& _rOldValue, const Any& _rNewValue ) - { - if ( !m_pImpl->getClientId( ) ) - // if we don't have a client id for the notifier, then we don't have listeners, then - // we don't need to notify anything - return; - - // build an event object - AccessibleEventObject aEvent; - aEvent.Source = *this; - aEvent.EventId = _nEventId; - aEvent.OldValue = _rOldValue; - aEvent.NewValue = _rNewValue; - - // let the notifier handle this event - AccessibleEventNotifier::addEvent( m_pImpl->getClientId( ), aEvent ); - } - - - bool OAccessibleContextHelper::isAlive() const - { - return !rBHelper.bDisposed && !rBHelper.bInDispose; - } - - - void OAccessibleContextHelper::ensureAlive() const - { - if( !isAlive() ) - throw DisposedException(); - } - - - void OAccessibleContextHelper::ensureDisposed( ) - { - if ( !rBHelper.bDisposed ) - { - OSL_ENSURE( 0 == m_refCount, "OAccessibleContextHelper::ensureDisposed: this method _has_ to be called from without your dtor only!" ); - acquire(); - dispose(); - } - } - - - void OAccessibleContextHelper::lateInit( const Reference< XAccessible >& _rxAccessible ) - { - m_pImpl->setCreator( _rxAccessible ); - } - - - Reference< XAccessible > OAccessibleContextHelper::getAccessibleCreator( ) const - { - return m_pImpl->getCreator(); - } - - - OUString SAL_CALL OAccessibleContextHelper::getAccessibleId( ) - { - return OUString(); - } - - - sal_Int32 SAL_CALL OAccessibleContextHelper::getAccessibleIndexInParent( ) - { - OExternalLockGuard aGuard( this ); - - // -1 for child not found/no parent (according to specification) - sal_Int32 nRet = -1; - - try - { - - Reference< XAccessibleContext > xParentContext( implGetParentContext() ); - - // iterate over parent's children and search for this object - if ( xParentContext.is() ) - { - // our own XAccessible for comparing with the children of our parent - Reference< XAccessible > xCreator( m_pImpl->getCreator() ); - - OSL_ENSURE( xCreator.is(), "OAccessibleContextHelper::getAccessibleIndexInParent: invalid creator!" ); - // two ideas why this could be NULL: - // * nobody called our late ctor (init), so we never had a creator at all -> bad - // * the creator is already dead. In this case, we should have been disposed, and - // never survived the above OContextEntryGuard. - // in all other situations the creator should be non-NULL - - if ( xCreator.is() ) - { - sal_Int32 nChildCount = xParentContext->getAccessibleChildCount(); - for ( sal_Int32 nChild = 0; ( nChild < nChildCount ) && ( -1 == nRet ); ++nChild ) - { - Reference< XAccessible > xChild( xParentContext->getAccessibleChild( nChild ) ); - if ( xChild.get() == xCreator.get() ) - nRet = nChild; - } - } - } - } - catch( const Exception& ) - { - OSL_FAIL( "OAccessibleContextHelper::getAccessibleIndexInParent: caught an exception!" ); - } - - return nRet; - } - - - Locale SAL_CALL OAccessibleContextHelper::getLocale( ) - { - // simply ask the parent - Reference< XAccessible > xParent = getAccessibleParent(); - Reference< XAccessibleContext > xParentContext; - if ( xParent.is() ) - xParentContext = xParent->getAccessibleContext(); - - if ( !xParentContext.is() ) - throw IllegalAccessibleComponentStateException( OUString(), *this ); - - return xParentContext->getLocale(); - } - - - Reference< XAccessibleContext > OAccessibleContextHelper::implGetParentContext() - { - Reference< XAccessible > xParent = getAccessibleParent(); - Reference< XAccessibleContext > xParentContext; - if ( xParent.is() ) - xParentContext = xParent->getAccessibleContext(); - return xParentContext; - } - - -} // namespace comphelper - - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/accessibleeventnotifier.cxx b/comphelper/source/misc/accessibleeventnotifier.cxx index f14176a03528..9c3b55126bc6 100644 --- a/comphelper/source/misc/accessibleeventnotifier.cxx +++ b/comphelper/source/misc/accessibleeventnotifier.cxx @@ -19,12 +19,12 @@ #include <comphelper/accessibleeventnotifier.hxx> #include <com/sun/star/accessibility/XAccessibleEventListener.hpp> -#include <rtl/instance.hxx> -#include <comphelper/interfacecontainer2.hxx> +#include <comphelper/interfacecontainer4.hxx> +#include <limits> #include <map> #include <memory> -#include <limits> +#include <unordered_map> using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; @@ -36,31 +36,37 @@ namespace { typedef std::pair< AccessibleEventNotifier::TClientId, AccessibleEventObject > ClientEvent; -typedef std::map< AccessibleEventNotifier::TClientId, - ::comphelper::OInterfaceContainerHelper2* > ClientMap; +typedef ::comphelper::OInterfaceContainerHelper4<XAccessibleEventListener> ListenerContainer; +typedef std::unordered_map< AccessibleEventNotifier::TClientId, ListenerContainer > ClientMap; /// key is the end of the interval, value is the start of the interval typedef std::map<AccessibleEventNotifier::TClientId, AccessibleEventNotifier::TClientId> IntervalMap; -struct lclMutex : public rtl::Static< ::osl::Mutex, lclMutex > {}; +std::mutex& GetLocalMutex() +{ + static std::mutex MUTEX; + return MUTEX; +} -struct Clients : public rtl::Static< ClientMap, Clients > {}; +ClientMap gaClients; -struct FreeIntervals : public rtl::StaticWithInit<IntervalMap, FreeIntervals> +IntervalMap& GetFreeIntervals() { - IntervalMap operator() () + static IntervalMap MAP = + []() { IntervalMap map; map.insert(std::make_pair( std::numeric_limits<AccessibleEventNotifier::TClientId>::max(), 1)); return map; - } -}; + }(); + return MAP; +} void releaseId(AccessibleEventNotifier::TClientId const nId) { - IntervalMap & rFreeIntervals(FreeIntervals::get()); + IntervalMap & rFreeIntervals(GetFreeIntervals()); IntervalMap::iterator const upper(rFreeIntervals.upper_bound(nId)); assert(upper != rFreeIntervals.end()); assert(nId < upper->second); // second is start of the interval! @@ -89,7 +95,7 @@ void releaseId(AccessibleEventNotifier::TClientId const nId) /// generates a new client id AccessibleEventNotifier::TClientId generateId() { - IntervalMap & rFreeIntervals(FreeIntervals::get()); + IntervalMap & rFreeIntervals(GetFreeIntervals()); assert(!rFreeIntervals.empty()); IntervalMap::iterator const iter(rFreeIntervals.begin()); AccessibleEventNotifier::TClientId const nFirst = iter->first; @@ -104,7 +110,7 @@ AccessibleEventNotifier::TClientId generateId() rFreeIntervals.erase(iter); // remove 1-element interval } - assert(Clients::get().end() == Clients::get().find(nFreeId)); + assert(gaClients.end() == gaClients.find(nFreeId)); return nFreeId; } @@ -129,7 +135,7 @@ bool implLookupClient( ClientMap::iterator& rPos ) { // look up this client - ClientMap &rClients = Clients::get(); + ClientMap &rClients = gaClients; rPos = rClients.find( nClient ); assert( rClients.end() != rPos && "AccessibleEventNotifier::implLookupClient: invalid client id " @@ -144,21 +150,13 @@ namespace comphelper { AccessibleEventNotifier::TClientId AccessibleEventNotifier::registerClient() { - ::osl::MutexGuard aGuard( lclMutex::get() ); + std::scoped_lock aGuard( GetLocalMutex() ); // generate a new client id TClientId nNewClientId = generateId( ); - // the event listeners for the new client - ::comphelper::OInterfaceContainerHelper2 *const pNewListeners = - new ::comphelper::OInterfaceContainerHelper2( lclMutex::get() ); - // note that we're using our own mutex here, so the listener containers for all - // our clients share this same mutex. - // this is a reminiscence to the days where the notifier was asynchronous. Today this is - // completely nonsense, and potentially slowing down the Office me thinks... - // add the client - Clients::get().emplace( nNewClientId, pNewListeners ); + gaClients.emplace( nNewClientId, ListenerContainer{} ); // outta here return nNewClientId; @@ -166,7 +164,7 @@ AccessibleEventNotifier::TClientId AccessibleEventNotifier::registerClient() void AccessibleEventNotifier::revokeClient( const TClientId _nClient ) { - ::osl::MutexGuard aGuard( lclMutex::get() ); + std::scoped_lock aGuard( GetLocalMutex() ); ClientMap::iterator aClientPos; if ( !implLookupClient( _nClient, aClientPos ) ) @@ -174,48 +172,42 @@ void AccessibleEventNotifier::revokeClient( const TClientId _nClient ) return; // remove it from the clients map - delete aClientPos->second; - Clients::get().erase( aClientPos ); + gaClients.erase( aClientPos ); releaseId(_nClient); } void AccessibleEventNotifier::revokeClientNotifyDisposing( const TClientId _nClient, const Reference< XInterface >& _rxEventSource ) { - std::unique_ptr<::comphelper::OInterfaceContainerHelper2> pListeners; + std::unique_lock aGuard( GetLocalMutex() ); - { - // rhbz#1001768 drop the mutex before calling disposeAndClear - ::osl::MutexGuard aGuard( lclMutex::get() ); - - ClientMap::iterator aClientPos; - if (!implLookupClient(_nClient, aClientPos)) - // already asserted in implLookupClient - return; - - // notify the listeners - pListeners.reset(aClientPos->second); - - // we do not need the entry in the clients map anymore - // (do this before actually notifying, because some client - // implementations have re-entrance problems and call into - // revokeClient while we are notifying from here) - Clients::get().erase(aClientPos); - releaseId(_nClient); - } + ClientMap::iterator aClientPos; + if (!implLookupClient(_nClient, aClientPos)) + // already asserted in implLookupClient + return; + + // notify the listeners + ListenerContainer aListeners(std::move(aClientPos->second)); + + // we do not need the entry in the clients map anymore + // (do this before actually notifying, because some client + // implementations have re-entrance problems and call into + // revokeClient while we are notifying from here) + gaClients.erase(aClientPos); + releaseId(_nClient); // notify the "disposing" event for this client EventObject aDisposalEvent; aDisposalEvent.Source = _rxEventSource; // now really do the notification - pListeners->disposeAndClear( aDisposalEvent ); + aListeners.disposeAndClear( aGuard, aDisposalEvent ); } sal_Int32 AccessibleEventNotifier::addEventListener( const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) { - ::osl::MutexGuard aGuard( lclMutex::get() ); + std::unique_lock aGuard( GetLocalMutex() ); ClientMap::iterator aClientPos; if ( !implLookupClient( _nClient, aClientPos ) ) @@ -223,15 +215,15 @@ sal_Int32 AccessibleEventNotifier::addEventListener( return 0; if ( _rxListener.is() ) - aClientPos->second->addInterface( _rxListener ); + aClientPos->second.addInterface( aGuard, _rxListener ); - return aClientPos->second->getLength(); + return aClientPos->second.getLength(aGuard); } sal_Int32 AccessibleEventNotifier::removeEventListener( const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) { - ::osl::MutexGuard aGuard( lclMutex::get() ); + std::unique_lock aGuard( GetLocalMutex() ); ClientMap::iterator aClientPos; if ( !implLookupClient( _nClient, aClientPos ) ) @@ -239,35 +231,31 @@ sal_Int32 AccessibleEventNotifier::removeEventListener( return 0; if ( _rxListener.is() ) - aClientPos->second->removeInterface( _rxListener ); + aClientPos->second.removeInterface( aGuard, _rxListener ); - return aClientPos->second->getLength(); + return aClientPos->second.getLength(aGuard); } void AccessibleEventNotifier::addEvent( const TClientId _nClient, const AccessibleEventObject& _rEvent ) { - std::vector< Reference< XInterface > > aListeners; - - { - ::osl::MutexGuard aGuard( lclMutex::get() ); + std::unique_lock aGuard( GetLocalMutex() ); - ClientMap::iterator aClientPos; - if ( !implLookupClient( _nClient, aClientPos ) ) - // already asserted in implLookupClient - return; - - // since we're synchronous, again, we want to notify immediately - aListeners = aClientPos->second->getElements(); - } + ClientMap::iterator aClientPos; + if ( !implLookupClient( _nClient, aClientPos ) ) + // already asserted in implLookupClient + return; - // default handling: loop through all listeners, and notify them - for ( const auto& rListener : aListeners ) + // since we're synchronous, again, we want to notify immediately + OInterfaceIteratorHelper4 aIt(aGuard, aClientPos->second); + // no need to hold lock here, and we don't want to hold lock while calling listeners + aGuard.unlock(); + while (aIt.hasMoreElements()) { try { - static_cast< XAccessibleEventListener* >( rListener.get() )->notifyEvent( _rEvent ); + aIt.next()->notifyEvent(_rEvent); } - catch( const Exception& ) + catch (Exception&) { // no assertion, because a broken access remote bridge or something like this // can cause this exception @@ -275,6 +263,11 @@ void AccessibleEventNotifier::addEvent( const TClientId _nClient, const Accessib } } +void AccessibleEventNotifier::shutdown() +{ + gaClients.clear(); +} + } // namespace comphelper /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/accessiblekeybindinghelper.cxx b/comphelper/source/misc/accessiblekeybindinghelper.cxx index 8028464aff2b..d1db69b98fa8 100644 --- a/comphelper/source/misc/accessiblekeybindinghelper.cxx +++ b/comphelper/source/misc/accessiblekeybindinghelper.cxx @@ -21,6 +21,7 @@ #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> #include <comphelper/accessiblekeybindinghelper.hxx> +#include <o3tl/safeint.hxx> namespace comphelper @@ -55,7 +56,7 @@ namespace comphelper void OAccessibleKeyBindingHelper::AddKeyBinding( const Sequence< awt::KeyStroke >& rKeyBinding ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); m_aKeyBindings.push_back( rKeyBinding ); } @@ -63,11 +64,8 @@ namespace comphelper void OAccessibleKeyBindingHelper::AddKeyBinding( const awt::KeyStroke& rKeyStroke ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - Sequence< awt::KeyStroke > aSeq(1); - aSeq[0] = rKeyStroke; - m_aKeyBindings.push_back( aSeq ); + std::scoped_lock aGuard( m_aMutex ); + m_aKeyBindings.push_back( { rKeyStroke } ); } @@ -76,7 +74,7 @@ namespace comphelper sal_Int32 OAccessibleKeyBindingHelper::getAccessibleKeyBindingCount() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); return m_aKeyBindings.size(); } @@ -84,9 +82,9 @@ namespace comphelper Sequence< awt::KeyStroke > OAccessibleKeyBindingHelper::getAccessibleKeyBinding( sal_Int32 nIndex ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); - if ( nIndex < 0 || nIndex >= static_cast<sal_Int32>(m_aKeyBindings.size()) ) + if ( nIndex < 0 || o3tl::make_unsigned(nIndex) >= m_aKeyBindings.size() ) throw IndexOutOfBoundsException(); return m_aKeyBindings[nIndex]; diff --git a/comphelper/source/misc/accessibleselectionhelper.cxx b/comphelper/source/misc/accessibleselectionhelper.cxx index 967c1b079e48..ff880a76ee98 100644 --- a/comphelper/source/misc/accessibleselectionhelper.cxx +++ b/comphelper/source/misc/accessibleselectionhelper.cxx @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <comphelper/accessiblecontexthelper.hxx> #include <comphelper/accessibleselectionhelper.hxx> @@ -25,8 +26,6 @@ namespace comphelper using namespace ::com::sun::star::uno; - using namespace ::com::sun::star::awt; - using namespace ::com::sun::star::lang; using namespace ::com::sun::star::accessibility; OCommonAccessibleSelection::OCommonAccessibleSelection( ) @@ -36,13 +35,13 @@ namespace comphelper OCommonAccessibleSelection::~OCommonAccessibleSelection() {} - void OCommonAccessibleSelection::selectAccessibleChild( sal_Int32 nChildIndex ) + void OCommonAccessibleSelection::selectAccessibleChild( sal_Int64 nChildIndex ) { implSelect( nChildIndex, true ); } - bool OCommonAccessibleSelection::isAccessibleChildSelected( sal_Int32 nChildIndex ) + bool OCommonAccessibleSelection::isAccessibleChildSelected( sal_Int64 nChildIndex ) { return implIsSelected( nChildIndex ); } @@ -60,16 +59,16 @@ namespace comphelper } - sal_Int32 OCommonAccessibleSelection::getSelectedAccessibleChildCount( ) + sal_Int64 OCommonAccessibleSelection::getSelectedAccessibleChildCount( ) { - sal_Int32 nRet = 0; + sal_Int64 nRet = 0; Reference< XAccessibleContext > xParentContext( implGetAccessibleContext() ); OSL_ENSURE( xParentContext.is(), "OCommonAccessibleSelection::getSelectedAccessibleChildCount: no parent context!" ); if( xParentContext.is() ) { - for( sal_Int32 i = 0, nChildCount = xParentContext->getAccessibleChildCount(); i < nChildCount; i++ ) + for( sal_Int64 i = 0, nChildCount = xParentContext->getAccessibleChildCount(); i < nChildCount; i++ ) if( implIsSelected( i ) ) ++nRet; } @@ -78,7 +77,7 @@ namespace comphelper } - Reference< XAccessible > OCommonAccessibleSelection::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) + Reference< XAccessible > OCommonAccessibleSelection::getSelectedAccessibleChild( sal_Int64 nSelectedChildIndex ) { Reference< XAccessible > xRet; Reference< XAccessibleContext > xParentContext( implGetAccessibleContext() ); @@ -87,7 +86,7 @@ namespace comphelper if( xParentContext.is() ) { - for( sal_Int32 i = 0, nChildCount = xParentContext->getAccessibleChildCount(), nPos = 0; ( i < nChildCount ) && !xRet.is(); i++ ) + for( sal_Int64 i = 0, nChildCount = xParentContext->getAccessibleChildCount(), nPos = 0; ( i < nChildCount ) && !xRet.is(); i++ ) if( implIsSelected( i ) && ( nPos++ == nSelectedChildIndex ) ) xRet = xParentContext->getAccessibleChild( i ); } @@ -96,7 +95,7 @@ namespace comphelper } - void OCommonAccessibleSelection::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) + void OCommonAccessibleSelection::deselectAccessibleChild( sal_Int64 nSelectedChildIndex ) { implSelect( nSelectedChildIndex, false ); } @@ -106,25 +105,20 @@ namespace comphelper } - IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleSelectionHelper, OAccessibleComponentHelper, OAccessibleSelectionHelper_Base ) - IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleSelectionHelper, OAccessibleComponentHelper, OAccessibleSelectionHelper_Base ) - // (order matters: the first is the class name, the second is the class doing the ref counting) - - Reference< XAccessibleContext > OAccessibleSelectionHelper::implGetAccessibleContext() { return this; } - void SAL_CALL OAccessibleSelectionHelper::selectAccessibleChild( sal_Int32 nChildIndex ) + void SAL_CALL OAccessibleSelectionHelper::selectAccessibleChild( sal_Int64 nChildIndex ) { OExternalLockGuard aGuard( this ); OCommonAccessibleSelection::selectAccessibleChild( nChildIndex ); } - sal_Bool SAL_CALL OAccessibleSelectionHelper::isAccessibleChildSelected( sal_Int32 nChildIndex ) + sal_Bool SAL_CALL OAccessibleSelectionHelper::isAccessibleChildSelected( sal_Int64 nChildIndex ) { OExternalLockGuard aGuard( this ); return OCommonAccessibleSelection::isAccessibleChildSelected( nChildIndex ); @@ -145,21 +139,21 @@ namespace comphelper } - sal_Int32 SAL_CALL OAccessibleSelectionHelper::getSelectedAccessibleChildCount( ) + sal_Int64 SAL_CALL OAccessibleSelectionHelper::getSelectedAccessibleChildCount( ) { OExternalLockGuard aGuard( this ); return OCommonAccessibleSelection::getSelectedAccessibleChildCount(); } - Reference< XAccessible > SAL_CALL OAccessibleSelectionHelper::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) + Reference< XAccessible > SAL_CALL OAccessibleSelectionHelper::getSelectedAccessibleChild( sal_Int64 nSelectedChildIndex ) { OExternalLockGuard aGuard( this ); return OCommonAccessibleSelection::getSelectedAccessibleChild( nSelectedChildIndex ); } - void SAL_CALL OAccessibleSelectionHelper::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) + void SAL_CALL OAccessibleSelectionHelper::deselectAccessibleChild( sal_Int64 nSelectedChildIndex ) { OExternalLockGuard aGuard( this ); OCommonAccessibleSelection::deselectAccessibleChild( nSelectedChildIndex ); diff --git a/comphelper/source/misc/accessibletexthelper.cxx b/comphelper/source/misc/accessibletexthelper.cxx index 35fe769c1700..02cd77fc766d 100644 --- a/comphelper/source/misc/accessibletexthelper.cxx +++ b/comphelper/source/misc/accessibletexthelper.cxx @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <comphelper/accessiblecontexthelper.hxx> #include <comphelper/accessibletexthelper.hxx> #include <com/sun/star/accessibility/AccessibleTextType.hpp> #include <com/sun/star/i18n/BreakIterator.hpp> @@ -38,7 +39,6 @@ namespace comphelper using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; - using namespace ::com::sun::star::beans; using namespace ::com::sun::star::accessibility; @@ -215,9 +215,9 @@ namespace comphelper } - sal_Unicode OCommonAccessibleText::implGetCharacter( const OUString& rText, sal_Int32 nIndex ) + sal_Unicode OCommonAccessibleText::implGetCharacter( std::u16string_view rText, sal_Int32 nIndex ) { - if ( !implIsValidIndex( nIndex, rText.getLength() ) ) + if ( !implIsValidIndex( nIndex, rText.size() ) ) throw IndexOutOfBoundsException(); return rText[nIndex]; @@ -265,16 +265,16 @@ namespace comphelper } - OUString OCommonAccessibleText::implGetTextRange( const OUString& rText, sal_Int32 nStartIndex, sal_Int32 nEndIndex ) + OUString OCommonAccessibleText::implGetTextRange( std::u16string_view rText, sal_Int32 nStartIndex, sal_Int32 nEndIndex ) { - if ( !implIsValidRange( nStartIndex, nEndIndex, rText.getLength() ) ) + if ( !implIsValidRange( nStartIndex, nEndIndex, rText.size() ) ) throw IndexOutOfBoundsException(); sal_Int32 nMinIndex = std::min( nStartIndex, nEndIndex ); sal_Int32 nMaxIndex = std::max( nStartIndex, nEndIndex ); - return rText.copy( nMinIndex, nMaxIndex - nMinIndex ); + return OUString(rText.substr( nMinIndex, nMaxIndex - nMinIndex )); } TextSegment OCommonAccessibleText::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) @@ -296,9 +296,12 @@ namespace comphelper { if ( implIsValidIndex( nIndex, nLength ) ) { - aResult.SegmentText = sText.copy( nIndex, 1 ); + auto nIndexEnd = nIndex; + sText.iterateCodePoints(&nIndexEnd); + + aResult.SegmentText = sText.copy( nIndex, nIndexEnd - nIndex ); aResult.SegmentStart = nIndex; - aResult.SegmentEnd = nIndex+1; + aResult.SegmentEnd = nIndexEnd; } } break; @@ -400,9 +403,12 @@ namespace comphelper { if ( implIsValidIndex( nIndex - 1, nLength ) ) { - aResult.SegmentText = sText.copy( nIndex - 1, 1 ); - aResult.SegmentStart = nIndex-1; - aResult.SegmentEnd = nIndex; + sText.iterateCodePoints(&nIndex, -1); + auto nIndexEnd = nIndex; + sText.iterateCodePoints(&nIndexEnd); + aResult.SegmentText = sText.copy(nIndex, nIndexEnd - nIndex); + aResult.SegmentStart = nIndex; + aResult.SegmentEnd = nIndexEnd; } } break; @@ -524,9 +530,12 @@ namespace comphelper { if ( implIsValidIndex( nIndex + 1, nLength ) ) { - aResult.SegmentText = sText.copy( nIndex + 1, 1 ); - aResult.SegmentStart = nIndex+1; - aResult.SegmentEnd = nIndex+2; + sText.iterateCodePoints(&nIndex); + auto nIndexEnd = nIndex; + sText.iterateCodePoints(&nIndexEnd); + aResult.SegmentText = sText.copy(nIndex, nIndexEnd - nIndex); + aResult.SegmentStart = nIndex; + aResult.SegmentEnd = nIndexEnd; } } break; @@ -634,13 +643,13 @@ namespace comphelper bool OCommonAccessibleText::implInitTextChangedEvent( - const OUString& rOldString, - const OUString& rNewString, + std::u16string_view rOldString, + std::u16string_view rNewString, css::uno::Any& rDeleted, css::uno::Any& rInserted) // throw() { - sal_uInt32 nLenOld = rOldString.getLength(); - sal_uInt32 nLenNew = rNewString.getLength(); + size_t nLenOld = rOldString.size(); + size_t nLenNew = rNewString.size(); // equal if ((0 == nLenOld) && (0 == nLenNew)) @@ -659,7 +668,7 @@ namespace comphelper { aInsertedText.SegmentStart = 0; aInsertedText.SegmentEnd = nLenNew; - aInsertedText.SegmentText = rNewString.copy( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart ); + aInsertedText.SegmentText = rNewString.substr( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart ); rInserted <<= aInsertedText; return true; @@ -670,28 +679,27 @@ namespace comphelper { aDeletedText.SegmentStart = 0; aDeletedText.SegmentEnd = nLenOld; - aDeletedText.SegmentText = rOldString.copy( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart ); + aDeletedText.SegmentText = rOldString.substr( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart ); rDeleted <<= aDeletedText; return true; } - const sal_Unicode* pFirstDiffOld = rOldString.getStr(); - const sal_Unicode* pLastDiffOld = rOldString.getStr() + nLenOld; - const sal_Unicode* pFirstDiffNew = rNewString.getStr(); - const sal_Unicode* pLastDiffNew = rNewString.getStr() + nLenNew; + auto pFirstDiffOld = rOldString.begin(); + auto pLastDiffOld = rOldString.end(); + auto pFirstDiffNew = rNewString.begin(); + auto pLastDiffNew = rNewString.end(); // find first difference - while ((*pFirstDiffOld == *pFirstDiffNew) && - (pFirstDiffOld < pLastDiffOld) && - (pFirstDiffNew < pLastDiffNew)) + while ((pFirstDiffOld < pLastDiffOld) && (pFirstDiffNew < pLastDiffNew) + && (*pFirstDiffOld == *pFirstDiffNew)) { pFirstDiffOld++; pFirstDiffNew++; } // equality test - if ((0 == *pFirstDiffOld) && (0 == *pFirstDiffNew)) + if (pFirstDiffOld == pLastDiffOld && pFirstDiffNew == pLastDiffNew) return false; // find last difference @@ -705,18 +713,18 @@ namespace comphelper if (pFirstDiffOld < pLastDiffOld) { - aDeletedText.SegmentStart = pFirstDiffOld - rOldString.getStr(); - aDeletedText.SegmentEnd = pLastDiffOld - rOldString.getStr(); - aDeletedText.SegmentText = rOldString.copy( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart ); + aDeletedText.SegmentStart = pFirstDiffOld - rOldString.begin(); + aDeletedText.SegmentEnd = pLastDiffOld - rOldString.begin(); + aDeletedText.SegmentText = rOldString.substr( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart ); rDeleted <<= aDeletedText; } if (pFirstDiffNew < pLastDiffNew) { - aInsertedText.SegmentStart = pFirstDiffNew - rNewString.getStr(); - aInsertedText.SegmentEnd = pLastDiffNew - rNewString.getStr(); - aInsertedText.SegmentText = rNewString.copy( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart ); + aInsertedText.SegmentStart = pFirstDiffNew - rNewString.begin(); + aInsertedText.SegmentEnd = pLastDiffNew - rNewString.begin(); + aInsertedText.SegmentText = rNewString.substr( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart ); rInserted <<= aInsertedText; } @@ -732,18 +740,6 @@ namespace comphelper } - // XInterface - - - IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleTextHelper, OAccessibleExtendedComponentHelper, OAccessibleTextHelper_Base ) - - - // XTypeProvider - - - IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleTextHelper, OAccessibleExtendedComponentHelper, OAccessibleTextHelper_Base ) - - // XAccessibleText diff --git a/comphelper/source/misc/accessiblewrapper.cxx b/comphelper/source/misc/accessiblewrapper.cxx index 4d4edb1393dc..3e356f434faa 100644 --- a/comphelper/source/misc/accessiblewrapper.cxx +++ b/comphelper/source/misc/accessiblewrapper.cxx @@ -79,15 +79,14 @@ namespace comphelper xComp->removeEventListener( this ); } // clear the map - AccessibleMap aMap; - m_aChildrenMap.swap( aMap ); + m_aChildrenMap.clear(); } Reference< XAccessible > OWrappedAccessibleChildrenManager::getAccessibleWrapperFor( const Reference< XAccessible >& _rxKey ) { - Reference< XAccessible > xValue; + rtl::Reference< OAccessibleWrapper > xValue; if( !_rxKey.is() ) { @@ -141,15 +140,14 @@ namespace comphelper Reference< XComponent > xContextComponent; if( rChild.second.is() ) - xContextComponent.set( rChild.second->getAccessibleContext(), + xContextComponent.set( rChild.second->getContextNoCreate(), ::css::uno::UNO_QUERY ); if( xContextComponent.is() ) xContextComponent->dispose(); } // clear our children - AccessibleMap aMap; - m_aChildrenMap.swap( aMap ); + m_aChildrenMap.clear(); } @@ -308,7 +306,7 @@ namespace comphelper } - OAccessibleContextWrapper* OAccessibleWrapper::createAccessibleContext( const Reference< XAccessibleContext >& _rxInnerContext ) + rtl::Reference<OAccessibleContextWrapper> OAccessibleWrapper::createAccessibleContext( const Reference< XAccessibleContext >& _rxInnerContext ) { return new OAccessibleContextWrapper( getComponentContext(), _rxInnerContext, this, m_xParentAccessible ); } @@ -347,9 +345,8 @@ namespace comphelper ,m_xChildMapper( new OWrappedAccessibleChildrenManager( getComponentContext() ) ) { // determine if we're allowed to cache children - Reference< XAccessibleStateSet > xStates( m_xInnerContext->getAccessibleStateSet( ) ); - OSL_ENSURE( xStates.is(), "OAccessibleContextWrapperHelper::OAccessibleContextWrapperHelper: no inner state set!" ); - m_xChildMapper->setTransientChildren( !xStates.is() || xStates->contains( AccessibleStateType::MANAGES_DESCENDANTS) ); + sal_Int64 aStates = m_xInnerContext->getAccessibleStateSet( ); + m_xChildMapper->setTransientChildren( aStates & AccessibleStateType::MANAGES_DESCENDANTS ); m_xChildMapper->setOwningAccessible( m_xOwningAccessible ); } @@ -391,13 +388,13 @@ namespace comphelper IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleContextWrapperHelper, OComponentProxyAggregationHelper, OAccessibleContextWrapperHelper_Base ) - sal_Int32 OAccessibleContextWrapperHelper::baseGetAccessibleChildCount( ) + sal_Int64 OAccessibleContextWrapperHelper::baseGetAccessibleChildCount( ) { return m_xInnerContext->getAccessibleChildCount(); } - Reference< XAccessible > OAccessibleContextWrapperHelper::baseGetAccessibleChild( sal_Int32 i ) + Reference< XAccessible > OAccessibleContextWrapperHelper::baseGetAccessibleChild( sal_Int64 i ) { // get the child of the wrapped component Reference< XAccessible > xInnerChild = m_xInnerContext->getAccessibleChild( i ); @@ -419,7 +416,7 @@ namespace comphelper if ( AccessibleEventId::STATE_CHANGED == _rEvent.EventId ) { bool bChildTransienceChanged = false; - sal_Int16 nChangeState = 0; + sal_Int64 nChangeState = 0; if ( _rEvent.OldValue >>= nChangeState ) bChildTransienceChanged = bChildTransienceChanged || AccessibleStateType::MANAGES_DESCENDANTS == nChangeState; if ( _rEvent.NewValue >>= nChangeState ) @@ -497,13 +494,13 @@ namespace comphelper } - sal_Int32 SAL_CALL OAccessibleContextWrapper::getAccessibleChildCount( ) + sal_Int64 SAL_CALL OAccessibleContextWrapper::getAccessibleChildCount( ) { return baseGetAccessibleChildCount(); } - Reference< XAccessible > SAL_CALL OAccessibleContextWrapper::getAccessibleChild( sal_Int32 i ) + Reference< XAccessible > SAL_CALL OAccessibleContextWrapper::getAccessibleChild( sal_Int64 i ) { return baseGetAccessibleChild( i ); } @@ -515,7 +512,7 @@ namespace comphelper } - sal_Int32 SAL_CALL OAccessibleContextWrapper::getAccessibleIndexInParent( ) + sal_Int64 SAL_CALL OAccessibleContextWrapper::getAccessibleIndexInParent( ) { return m_xInnerContext->getAccessibleIndexInParent(); } @@ -545,7 +542,7 @@ namespace comphelper } - Reference< XAccessibleStateSet > SAL_CALL OAccessibleContextWrapper::getAccessibleStateSet( ) + sal_Int64 SAL_CALL OAccessibleContextWrapper::getAccessibleStateSet( ) { return m_xInnerContext->getAccessibleStateSet(); } @@ -588,7 +585,7 @@ namespace comphelper } - void SAL_CALL OAccessibleContextWrapper::disposing() + void OAccessibleContextWrapper::implDisposing(const css::lang::EventObject* pEvent) { AccessibleEventNotifier::TClientId nClientId( 0 ); @@ -606,12 +603,29 @@ namespace comphelper // --- </mutex lock> ----------------------------------------- // let the base class do - OAccessibleContextWrapperHelper::dispose(); + if (pEvent) + OAccessibleContextWrapperHelper::disposing(*pEvent); + else + OAccessibleContextWrapperHelper::dispose(); // notify the disposal if ( nClientId ) AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, *this ); } + + void SAL_CALL OAccessibleContextWrapper::disposing() + { + implDisposing(nullptr); + } + + void SAL_CALL OAccessibleContextWrapper::disposing(const css::lang::EventObject& rEvent) + { + assert(rEvent.Source == Reference<XInterface>(m_xInnerContext, UNO_QUERY) + && "OAccessibleContextWrapper::disposing called with event source that's not the " + "wrapped a11y context"); + + implDisposing(&rEvent); + } } // namespace accessibility diff --git a/comphelper/source/misc/accimplaccess.cxx b/comphelper/source/misc/accimplaccess.cxx deleted file mode 100644 index 71a12c8a7e98..000000000000 --- a/comphelper/source/misc/accimplaccess.cxx +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include <comphelper/accimplaccess.hxx> -#include <cppuhelper/typeprovider.hxx> - -#include <string.h> - - -namespace comphelper -{ - - - using ::com::sun::star::uno::Sequence; - - OAccessibleImplementationAccess::OAccessibleImplementationAccess( ) - { - } - - - OAccessibleImplementationAccess::~OAccessibleImplementationAccess( ) - { - } - - Sequence< sal_Int8 > OAccessibleImplementationAccess::getUnoTunnelImplementationId() - { - static cppu::OImplementationId implID; - - return implID.getImplementationId(); - } - - - sal_Int64 SAL_CALL OAccessibleImplementationAccess::getSomething( const Sequence< sal_Int8 >& _rIdentifier ) - { - sal_Int64 nReturn( 0 ); - - if ( ( _rIdentifier.getLength() == 16 ) - && ( 0 == memcmp( getUnoTunnelImplementationId().getConstArray(), _rIdentifier.getConstArray(), 16 ) ) - ) - nReturn = reinterpret_cast< sal_Int64 >( this ); - - return nReturn; - } - -} // namespace comphelper - - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/anycompare.cxx b/comphelper/source/misc/anycompare.cxx index 106892400c7c..8a23877239be 100644 --- a/comphelper/source/misc/anycompare.cxx +++ b/comphelper/source/misc/anycompare.cxx @@ -18,16 +18,21 @@ */ #include <memory> +#include <optional> #include <comphelper/anycompare.hxx> +#include <typelib/typedescription.hxx> #include <com/sun/star/util/Date.hpp> #include <com/sun/star/util/Time.hpp> #include <com/sun/star/util/DateTime.hpp> +#include "typedescriptionref.hxx" + namespace comphelper { using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Type; + using ::com::sun::star::uno::TypeDescription; using ::com::sun::star::uno::TypeClass_CHAR; using ::com::sun::star::uno::TypeClass_BOOLEAN; using ::com::sun::star::uno::TypeClass_BYTE; @@ -48,6 +53,7 @@ namespace comphelper using ::com::sun::star::util::Date; using ::com::sun::star::util::Time; using ::com::sun::star::util::DateTime; + using ::comphelper::detail::TypeDescriptionRef; namespace { @@ -160,8 +166,215 @@ namespace comphelper } }; + bool anyLess( void const * lhs, typelib_TypeDescriptionReference * lhsType, + void const * rhs, typelib_TypeDescriptionReference * rhsType ); + + // For compound types we need to compare them member by member until we've + // checked them all or found a member that differs. For inequality checks + // we need to call anyLess() twice in both directions, this function does that. + std::optional<bool> anyCompare( void const * lhs, typelib_TypeDescriptionReference * lhsType, + void const * rhs, typelib_TypeDescriptionReference * rhsType ) + { + if( anyLess( lhs, lhsType, rhs, rhsType )) + return std::optional( true ); + if( anyLess( rhs, rhsType, lhs, lhsType )) + return std::optional( false ); + return std::nullopt; // equal, so can't yet tell if anyLess() should return + } + + // This is typelib_typedescription_equals(), but returns -1/0/1 values like strcmp(). + int compareTypes( const typelib_TypeDescription * lhsType, + const typelib_TypeDescription * rhsType ) + { + if( lhsType == rhsType ) + return 0; + if( lhsType->eTypeClass != rhsType->eTypeClass ) + return lhsType->eTypeClass - rhsType->eTypeClass; + if( lhsType->pTypeName->length != rhsType->pTypeName->length ) + return lhsType->pTypeName->length - rhsType->pTypeName->length; + return rtl_ustr_compare( lhsType->pTypeName->buffer, rhsType->pTypeName->buffer ); + } + + bool anyLess( void const * lhs, typelib_TypeDescriptionReference * lhsType, + void const * rhs, typelib_TypeDescriptionReference * rhsType ) + { + if (lhsType->eTypeClass != rhsType->eTypeClass) + return lhsType->eTypeClass < rhsType->eTypeClass; + + if (lhsType->eTypeClass == typelib_TypeClass_VOID) { + return false; + } + assert(lhs != nullptr); + assert(rhs != nullptr); + + switch (lhsType->eTypeClass) { + case typelib_TypeClass_INTERFACE: + return lhs < rhs; + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: { + TypeDescription lhsTypeDescr( lhsType ); + if (!lhsTypeDescr.is()) + lhsTypeDescr.makeComplete(); + if (!lhsTypeDescr.is()) + throw css::lang::IllegalArgumentException("bad ordering", css::uno::Reference<css::uno::XInterface>(), -1); + TypeDescription rhsTypeDescr( rhsType ); + if (!rhsTypeDescr.is()) + rhsTypeDescr.makeComplete(); + if (!rhsTypeDescr.is()) + throw css::lang::IllegalArgumentException("bad ordering", css::uno::Reference<css::uno::XInterface>(), -1); + int compare = compareTypes( lhsTypeDescr.get(), rhsTypeDescr.get()); + if( compare != 0 ) + return compare < 0; + + typelib_CompoundTypeDescription * compType = + reinterpret_cast< typelib_CompoundTypeDescription * >( + lhsTypeDescr.get() ); + sal_Int32 nDescr = compType->nMembers; + + if (compType->pBaseTypeDescription) { + std::optional<bool> subLess = anyCompare( + lhs, reinterpret_cast< + typelib_TypeDescription * >( + compType->pBaseTypeDescription)->pWeakRef, + rhs, reinterpret_cast< + typelib_TypeDescription * >( + compType->pBaseTypeDescription)->pWeakRef); + if(subLess.has_value()) + return *subLess; + } + + typelib_TypeDescriptionReference ** ppTypeRefs = + compType->ppTypeRefs; + sal_Int32 * memberOffsets = compType->pMemberOffsets; + + for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos ) + { + TypeDescriptionRef memberType( ppTypeRefs[ nPos ] ); + if (!memberType.is()) + throw css::lang::IllegalArgumentException("bad ordering", css::uno::Reference<css::uno::XInterface>(), -1); + std::optional<bool> subLess = anyCompare( + static_cast< char const * >( + lhs ) + memberOffsets[ nPos ], + memberType->pWeakRef, + static_cast< char const * >( + rhs ) + memberOffsets[ nPos ], + memberType->pWeakRef); + if(subLess.has_value()) + return *subLess; + } + return false; // equal + } + case typelib_TypeClass_SEQUENCE: { + uno_Sequence * lhsSeq = *static_cast< uno_Sequence * const * >(lhs); + uno_Sequence * rhsSeq = *static_cast< uno_Sequence * const * >(rhs); + if( lhsSeq->nElements != rhsSeq->nElements) + return lhsSeq->nElements < rhsSeq->nElements; + sal_Int32 nElements = lhsSeq->nElements; + + TypeDescriptionRef lhsTypeDescr( lhsType ); + if (!lhsTypeDescr.is()) + throw css::lang::IllegalArgumentException("bad ordering", css::uno::Reference<css::uno::XInterface>(), -1); + TypeDescriptionRef rhsTypeDescr( rhsType ); + if (!rhsTypeDescr.is()) + throw css::lang::IllegalArgumentException("bad ordering", css::uno::Reference<css::uno::XInterface>(), -1); + int compare = compareTypes( lhsTypeDescr.get(), rhsTypeDescr.get()); + if( compare != 0 ) + return compare < 0; + + typelib_TypeDescriptionReference * elementTypeRef = + reinterpret_cast< typelib_IndirectTypeDescription * >(lhsTypeDescr.get())->pType; + TypeDescriptionRef elementTypeDescr( elementTypeRef ); + if (!elementTypeDescr.is()) + throw css::lang::IllegalArgumentException("bad ordering", css::uno::Reference<css::uno::XInterface>(), -1); + assert( elementTypeDescr.equals( TypeDescriptionRef( + reinterpret_cast< typelib_IndirectTypeDescription * >(lhsTypeDescr.get())->pType ))); + + sal_Int32 nElementSize = elementTypeDescr->nSize; + if (nElements > 0) + { + char const * lhsElements = lhsSeq->elements; + char const * rhsElements = rhsSeq->elements; + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + std::optional<bool> subLess = anyCompare( + lhsElements + (nElementSize * nPos), + elementTypeDescr->pWeakRef, + rhsElements + (nElementSize * nPos), + elementTypeDescr->pWeakRef ); + if(subLess.has_value()) + return *subLess; + } + } + return false; // equal + } + case typelib_TypeClass_ANY: { + uno_Any const * lhsAny = static_cast< uno_Any const * >(lhs); + uno_Any const * rhsAny = static_cast< uno_Any const * >(rhs); + return anyLess( lhsAny->pData, lhsAny->pType, rhsAny->pData, rhsAny->pType ); + } + case typelib_TypeClass_TYPE: { + OUString const & lhsTypeName = OUString::unacquired( + &(*static_cast< typelib_TypeDescriptionReference * const * >(lhs))->pTypeName); + OUString const & rhsTypeName = OUString::unacquired( + &(*static_cast< typelib_TypeDescriptionReference * const * >(rhs))->pTypeName); + return lhsTypeName < rhsTypeName; + } + case typelib_TypeClass_STRING: { + OUString const & lhsStr = OUString::unacquired( + static_cast< rtl_uString * const * >(lhs) ); + OUString const & rhsStr = OUString::unacquired( + static_cast< rtl_uString * const * >(rhs) ); + return lhsStr < rhsStr; + } + case typelib_TypeClass_ENUM: { + TypeDescription lhsTypeDescr( lhsType ); + if (!lhsTypeDescr.is()) + lhsTypeDescr.makeComplete(); + if (!lhsTypeDescr.is()) + throw css::lang::IllegalArgumentException("bad ordering", css::uno::Reference<css::uno::XInterface>(), -1); + TypeDescription rhsTypeDescr( rhsType ); + if (!rhsTypeDescr.is()) + rhsTypeDescr.makeComplete(); + if (!rhsTypeDescr.is()) + throw css::lang::IllegalArgumentException("bad ordering", css::uno::Reference<css::uno::XInterface>(), -1); + int compare = compareTypes( lhsTypeDescr.get(), rhsTypeDescr.get()); + if( compare != 0 ) + return compare < 0; + + return *static_cast< int const * >(lhs) < *static_cast< int const * >(rhs); + } + case typelib_TypeClass_BOOLEAN: + return *static_cast< sal_Bool const * >(lhs) < *static_cast< sal_Bool const * >(rhs); + case typelib_TypeClass_CHAR: + return *static_cast< sal_Unicode const * >(lhs) < *static_cast< sal_Unicode const * >(rhs); + case typelib_TypeClass_FLOAT: + return *static_cast< float const * >(lhs) < *static_cast< float const * >(rhs); + case typelib_TypeClass_DOUBLE: + return *static_cast< double const * >(lhs) < *static_cast< double const * >(rhs); + case typelib_TypeClass_BYTE: + return *static_cast< sal_Int8 const * >(lhs) < *static_cast< sal_Int8 const * >(rhs); + case typelib_TypeClass_SHORT: + return *static_cast< sal_Int16 const * >(lhs) < *static_cast< sal_Int16 const * >(rhs); + case typelib_TypeClass_UNSIGNED_SHORT: + return *static_cast< sal_uInt16 const * >(lhs) < *static_cast< sal_uInt16 const * >(rhs); + case typelib_TypeClass_LONG: + return *static_cast< sal_Int32 const * >(lhs) < *static_cast< sal_Int32 const * >(rhs); + case typelib_TypeClass_UNSIGNED_LONG: + return *static_cast< sal_uInt32 const * >(lhs) < *static_cast< sal_uInt32 const * >(rhs); + case typelib_TypeClass_HYPER: + return *static_cast< sal_Int64 const * >(lhs) < *static_cast< sal_Int64 const * >(rhs); + case typelib_TypeClass_UNSIGNED_HYPER: + return *static_cast< sal_uInt64 const * >(lhs) < *static_cast< sal_uInt64 const * >(rhs); + // case typelib_TypeClass_UNKNOWN: + // case typelib_TypeClass_SERVICE: + // case typelib_TypeClass_MODULE: + default: + return false; + } } + } // namespace + std::unique_ptr< IKeyPredicateLess > getStandardLessPredicate( Type const & i_type, Reference< XCollator > const & i_collator ) { std::unique_ptr< IKeyPredicateLess > pComparator; @@ -231,70 +444,7 @@ namespace comphelper 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; - - switch ( lhsTypeClass ) - { - case TypeClass_CHAR: - return ScalarPredicateLess< sal_Unicode >().isLess(lhs, rhs); - case TypeClass_BOOLEAN: - return ScalarPredicateLess< bool >().isLess(lhs, rhs); - break; - case TypeClass_BYTE: - return ScalarPredicateLess< sal_Int8 >().isLess(lhs, rhs); - break; - case TypeClass_SHORT: - return ScalarPredicateLess< sal_Int16 >().isLess(lhs, rhs); - break; - case TypeClass_UNSIGNED_SHORT: - return ScalarPredicateLess< sal_uInt16 >().isLess(lhs, rhs); - break; - case TypeClass_LONG: - return ScalarPredicateLess< sal_Int32 >().isLess(lhs, rhs); - break; - case TypeClass_UNSIGNED_LONG: - return ScalarPredicateLess< sal_uInt32 >().isLess(lhs, rhs); - break; - case TypeClass_HYPER: - return ScalarPredicateLess< sal_Int64 >().isLess(lhs, rhs); - break; - case TypeClass_UNSIGNED_HYPER: - return ScalarPredicateLess< sal_uInt64 >().isLess(lhs, rhs); - break; - case TypeClass_FLOAT: - return ScalarPredicateLess< float >().isLess(lhs, rhs); - break; - case TypeClass_DOUBLE: - return ScalarPredicateLess< double >().isLess(lhs, rhs); - break; - case TypeClass_STRING: - return StringPredicateLess().isLess(lhs, rhs); - break; - case TypeClass_TYPE: - return TypePredicateLess().isLess(lhs, rhs); - break; - case TypeClass_ENUM: - return EnumPredicateLess( lhs.getValueType() ).isLess(lhs, rhs); - break; - case TypeClass_INTERFACE: - return InterfacePredicateLess().isLess(lhs, rhs); - break; - case TypeClass_STRUCT: - if ( lhs.getValueType().equals( ::cppu::UnoType< Date >::get() ) ) - return DatePredicateLess().isLess(lhs, rhs); - else if ( lhs.getValueType().equals( ::cppu::UnoType< Time >::get() ) ) - return TimePredicateLess().isLess(lhs, rhs); - else if ( lhs.getValueType().equals( ::cppu::UnoType< DateTime >::get() ) ) - return DateTimePredicateLess().isLess(lhs, rhs); - break; - default: ; - } - - // type==VOID - return false; + return anyLess( lhs.getValue(), lhs.getValueTypeRef(), rhs.getValue(), rhs.getValueTypeRef()); } } // namespace comphelper diff --git a/comphelper/source/misc/anytohash.cxx b/comphelper/source/misc/anytohash.cxx new file mode 100644 index 000000000000..4e97ea124d41 --- /dev/null +++ b/comphelper/source/misc/anytohash.cxx @@ -0,0 +1,210 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <comphelper/anytohash.hxx> + +#include <o3tl/hash_combine.hxx> +#include <typelib/typedescription.hxx> + +#include <com/sun/star/uno/Sequence.hxx> + +#include "typedescriptionref.hxx" + +using namespace ::com::sun::star; +using ::com::sun::star::uno::TypeDescription; +using ::comphelper::detail::TypeDescriptionRef; + +namespace comphelper { +namespace { + +std::optional<size_t> hashValue( size_t hash, + void const * val, typelib_TypeDescriptionReference * typeRef ) +{ + o3tl::hash_combine( hash, typeRef->eTypeClass ); + if (typeRef->eTypeClass == typelib_TypeClass_VOID) { + return hash; + } + assert(val != nullptr); + + switch (typeRef->eTypeClass) { + case typelib_TypeClass_INTERFACE: { + return std::nullopt; // not implemented + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: { + TypeDescription typeDescr( typeRef ); + if (!typeDescr.is()) + typeDescr.makeComplete(); + if (!typeDescr.is()) + return std::nullopt; + + typelib_CompoundTypeDescription * compType = + reinterpret_cast< typelib_CompoundTypeDescription * >( + typeDescr.get() ); + sal_Int32 nDescr = compType->nMembers; + + if (compType->pBaseTypeDescription) { + std::optional<size_t> tmpHash = hashValue( + hash, val, reinterpret_cast< + typelib_TypeDescription * >( + compType->pBaseTypeDescription)->pWeakRef); + if(!tmpHash.has_value()) + return std::nullopt; + hash = *tmpHash; + } + + typelib_TypeDescriptionReference ** ppTypeRefs = + compType->ppTypeRefs; + sal_Int32 * memberOffsets = compType->pMemberOffsets; + + for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos ) + { + TypeDescriptionRef memberType( ppTypeRefs[ nPos ] ); + if (!memberType.is()) + return std::nullopt; + + std::optional<size_t> tmpHash = hashValue( hash, + static_cast< char const * >( + val ) + memberOffsets[ nPos ], + memberType->pWeakRef ); + if(!tmpHash.has_value()) + return std::nullopt; + hash = *tmpHash; + } + break; + } + case typelib_TypeClass_SEQUENCE: { + TypeDescriptionRef typeDescr( typeRef ); + if (!typeDescr.is()) + return std::nullopt; + + typelib_TypeDescriptionReference * elementTypeRef = + reinterpret_cast< + typelib_IndirectTypeDescription * >(typeDescr.get())->pType; + TypeDescriptionRef elementTypeDescr( elementTypeRef ); + if (!elementTypeDescr.is()) + return std::nullopt; + + sal_Int32 nElementSize = elementTypeDescr->nSize; + uno_Sequence * seq = + *static_cast< uno_Sequence * const * >(val); + sal_Int32 nElements = seq->nElements; + + if (nElements > 0) + { + char const * pElements = seq->elements; + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + std::optional<size_t> tmpHash = hashValue( hash, + pElements + (nElementSize * nPos), + elementTypeDescr->pWeakRef ); + if(!tmpHash.has_value()) + return std::nullopt; + hash = *tmpHash; + } + } + break; + } + case typelib_TypeClass_ANY: { + uno_Any const * pAny = static_cast< uno_Any const * >(val); + return hashValue( hash, pAny->pData, pAny->pType ); + } + case typelib_TypeClass_TYPE: { + OUString const & str = OUString::unacquired( + &(*static_cast< + typelib_TypeDescriptionReference * const * >(val) + )->pTypeName ); + o3tl::hash_combine( hash, str.hashCode() ); + break; + } + case typelib_TypeClass_STRING: { + OUString const & str = OUString::unacquired( + static_cast< rtl_uString * const * >(val) ); + o3tl::hash_combine( hash, str.hashCode() ); + break; + } + case typelib_TypeClass_ENUM: { + TypeDescription typeDescr( typeRef ); + if (!typeDescr.is()) + typeDescr.makeComplete(); + if (!typeDescr.is()) + return std::nullopt; + + o3tl::hash_combine( hash, *static_cast< int const * >(val)); + break; + } + case typelib_TypeClass_BOOLEAN: + if (*static_cast< sal_Bool const * >(val)) + o3tl::hash_combine( hash, true ); + else + o3tl::hash_combine( hash, false ); + break; + case typelib_TypeClass_CHAR: { + o3tl::hash_combine( hash, *static_cast< sal_Unicode const * >(val)); + break; + } + case typelib_TypeClass_FLOAT: + o3tl::hash_combine( hash, *static_cast< float const * >(val) ); + break; + case typelib_TypeClass_DOUBLE: + o3tl::hash_combine( hash, *static_cast< double const * >(val) ); + break; + case typelib_TypeClass_BYTE: + o3tl::hash_combine( hash, *static_cast< sal_Int8 const * >(val) ); + break; + case typelib_TypeClass_SHORT: + o3tl::hash_combine( hash, *static_cast< sal_Int16 const * >(val) ); + break; + case typelib_TypeClass_UNSIGNED_SHORT: + o3tl::hash_combine( hash, *static_cast< sal_uInt16 const * >(val) ); + break; + case typelib_TypeClass_LONG: + o3tl::hash_combine( hash, *static_cast< sal_Int32 const * >(val) ); + break; + case typelib_TypeClass_UNSIGNED_LONG: + o3tl::hash_combine( hash, *static_cast< sal_uInt32 const * >(val) ); + break; + case typelib_TypeClass_HYPER: + o3tl::hash_combine( hash, *static_cast< sal_Int64 const * >(val) ); + break; + case typelib_TypeClass_UNSIGNED_HYPER: + o3tl::hash_combine( hash, *static_cast< sal_uInt64 const * >(val) ); + break; +// case typelib_TypeClass_UNKNOWN: +// case typelib_TypeClass_SERVICE: +// case typelib_TypeClass_MODULE: + default: + return std::nullopt; + } + return hash; +} + +} // anon namespace + + +std::optional<size_t> anyToHash( uno::Any const & value ) +{ + size_t hash = 0; + return hashValue( hash, value.getValue(), value.getValueTypeRef()); +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/anytostring.cxx b/comphelper/source/misc/anytostring.cxx index 37242356e12b..ebc338b0b4be 100644 --- a/comphelper/source/misc/anytostring.cxx +++ b/comphelper/source/misc/anytostring.cxx @@ -20,16 +20,20 @@ #include <comphelper/anytostring.hxx> #include <rtl/ustrbuf.hxx> -#include <typelib/typedescription.h> +#include <typelib/typedescription.hxx> #include <com/sun/star/lang/XServiceInfo.hpp> +#include "typedescriptionref.hxx" + using namespace ::com::sun::star; +using ::com::sun::star::uno::TypeDescription; +using ::comphelper::detail::TypeDescriptionRef; namespace comphelper { namespace { void appendTypeError( - OUStringBuffer & buf, typelib_TypeDescriptionReference * typeRef ) + OUStringBuffer & buf, const typelib_TypeDescriptionReference * typeRef ) { buf.append( "<cannot get type description of type " ); buf.append( OUString::unacquired( &typeRef->pTypeName ) ); @@ -90,15 +94,16 @@ void appendValue( OUStringBuffer & buf, case typelib_TypeClass_STRUCT: case typelib_TypeClass_EXCEPTION: { buf.append( "{ " ); - typelib_TypeDescription * typeDescr = nullptr; - typelib_typedescriptionreference_getDescription( &typeDescr, typeRef ); - if (typeDescr == nullptr || !typelib_typedescription_complete( &typeDescr )) { + TypeDescription typeDescr( typeRef ); + if (!typeDescr.is()) + typeDescr.makeComplete(); + if (!typeDescr.is()) { appendTypeError( buf, typeRef ); } else { typelib_CompoundTypeDescription * compType = reinterpret_cast< typelib_CompoundTypeDescription * >( - typeDescr ); + typeDescr.get() ); sal_Int32 nDescr = compType->nMembers; if (compType->pBaseTypeDescription) { @@ -119,9 +124,8 @@ void appendValue( OUStringBuffer & buf, { buf.append( ppMemberNames[ nPos ] ); buf.append( " = " ); - typelib_TypeDescription * memberType = nullptr; - TYPELIB_DANGER_GET( &memberType, ppTypeRefs[ nPos ] ); - if (memberType == nullptr) { + TypeDescriptionRef memberType( ppTypeRefs[ nPos ] ); + if (!memberType.is()) { appendTypeError( buf, ppTypeRefs[ nPos ] ); } else { @@ -129,30 +133,25 @@ void appendValue( OUStringBuffer & buf, static_cast< char const * >( val ) + memberOffsets[ nPos ], memberType->pWeakRef, true ); - TYPELIB_DANGER_RELEASE( memberType ); } if (nPos < (nDescr - 1)) buf.append( ", " ); } } buf.append( " }" ); - if (typeDescr != nullptr) - typelib_typedescription_release( typeDescr ); break; } case typelib_TypeClass_SEQUENCE: { - typelib_TypeDescription * typeDescr = nullptr; - TYPELIB_DANGER_GET( &typeDescr, typeRef ); - if (typeDescr == nullptr) { + TypeDescriptionRef typeDescr( typeRef ); + if (!typeDescr.is()) { appendTypeError( buf,typeRef ); } else { typelib_TypeDescriptionReference * elementTypeRef = reinterpret_cast< - typelib_IndirectTypeDescription * >(typeDescr)->pType; - typelib_TypeDescription * elementTypeDescr = nullptr; - TYPELIB_DANGER_GET( &elementTypeDescr, elementTypeRef ); - if (elementTypeDescr == nullptr) + typelib_IndirectTypeDescription * >(typeDescr.get())->pType; + TypeDescriptionRef elementTypeDescr( elementTypeRef ); + if (!elementTypeDescr.is()) { appendTypeError( buf, elementTypeRef ); } @@ -181,9 +180,7 @@ void appendValue( OUStringBuffer & buf, { buf.append( "{}" ); } - TYPELIB_DANGER_RELEASE( elementTypeDescr ); } - TYPELIB_DANGER_RELEASE( typeDescr ); } break; } @@ -218,18 +215,19 @@ void appendValue( OUStringBuffer & buf, break; } case typelib_TypeClass_ENUM: { - typelib_TypeDescription * typeDescr = nullptr; - typelib_typedescriptionreference_getDescription( &typeDescr, typeRef ); - if (typeDescr == nullptr || !typelib_typedescription_complete( &typeDescr )) { + TypeDescription typeDescr( typeRef ); + if (!typeDescr.is()) + typeDescr.makeComplete(); + if (!typeDescr.is()) { appendTypeError( buf, typeRef ); } else { sal_Int32 * pValues = reinterpret_cast< typelib_EnumTypeDescription * >( - typeDescr )->pEnumValues; + typeDescr.get() )->pEnumValues; sal_Int32 nPos = reinterpret_cast< typelib_EnumTypeDescription * >( - typeDescr )->nEnumValues; + typeDescr.get() )->nEnumValues; while (nPos--) { if (pValues[ nPos ] == *static_cast< int const * >(val)) @@ -238,15 +236,13 @@ void appendValue( OUStringBuffer & buf, if (nPos >= 0) { buf.append( reinterpret_cast< typelib_EnumTypeDescription * >( - typeDescr )->ppEnumNames[ nPos ] ); + typeDescr.get() )->ppEnumNames[ nPos ] ); } else { buf.append( "?unknown enum value?" ); } } - if (typeDescr != nullptr) - typelib_typedescription_release( typeDescr ); break; } case typelib_TypeClass_BOOLEAN: diff --git a/comphelper/source/misc/asyncnotification.cxx b/comphelper/source/misc/asyncnotification.cxx index a360b7207fe4..72c6414e7281 100644 --- a/comphelper/source/misc/asyncnotification.cxx +++ b/comphelper/source/misc/asyncnotification.cxx @@ -18,12 +18,11 @@ */ #include <comphelper/asyncnotification.hxx> -#include <osl/mutex.hxx> -#include <osl/conditn.hxx> -#include <rtl/instance.hxx> +#include <comphelper/scopeguard.hxx> +#include <mutex> +#include <condition_variable> #include <cassert> -#include <deque> #include <stdexcept> #include <vector> #include <algorithm> @@ -44,24 +43,8 @@ namespace comphelper { AnyEventRef aEvent; ::rtl::Reference< IEventProcessor > xProcessor; - - ProcessableEvent() - { - } - - ProcessableEvent( const AnyEventRef& _rEvent, const ::rtl::Reference< IEventProcessor >& _xProcessor ) - :aEvent( _rEvent ) - ,xProcessor( _xProcessor ) - { - } }; - } - - typedef std::deque< ProcessableEvent > EventQueue; - - namespace { - struct EqualProcessor { const ::rtl::Reference< IEventProcessor >& rProcessor; @@ -77,9 +60,9 @@ namespace comphelper struct EventNotifierImpl { - ::osl::Mutex aMutex; - ::osl::Condition aPendingActions; - EventQueue aEvents; + std::mutex aMutex; + std::condition_variable aPendingActions; + std::vector< ProcessableEvent > aEvents; bool bTerminate; // only used for AsyncEventNotifierAutoJoin char const* name; @@ -105,34 +88,34 @@ namespace comphelper void AsyncEventNotifierBase::removeEventsForProcessor( const ::rtl::Reference< IEventProcessor >& _xProcessor ) { - ::osl::MutexGuard aGuard( m_xImpl->aMutex ); + std::scoped_lock aGuard( m_xImpl->aMutex ); // remove all events for this processor - m_xImpl->aEvents.erase(std::remove_if( m_xImpl->aEvents.begin(), m_xImpl->aEvents.end(), EqualProcessor( _xProcessor ) ), m_xImpl->aEvents.end()); + std::erase_if( m_xImpl->aEvents, EqualProcessor( _xProcessor ) ); } void SAL_CALL AsyncEventNotifierBase::terminate() { - ::osl::MutexGuard aGuard( m_xImpl->aMutex ); + std::scoped_lock aGuard( m_xImpl->aMutex ); // remember the termination request m_xImpl->bTerminate = true; // awake the thread - m_xImpl->aPendingActions.set(); + m_xImpl->aPendingActions.notify_all(); } void AsyncEventNotifierBase::addEvent( const AnyEventRef& _rEvent, const ::rtl::Reference< IEventProcessor >& _xProcessor ) { - ::osl::MutexGuard aGuard( m_xImpl->aMutex ); + std::scoped_lock aGuard( m_xImpl->aMutex ); // remember this event - m_xImpl->aEvents.emplace_back( _rEvent, _xProcessor ); + m_xImpl->aEvents.emplace_back( ProcessableEvent {_rEvent, _xProcessor} ); // awake the thread - m_xImpl->aPendingActions.set(); + m_xImpl->aPendingActions.notify_all(); } @@ -140,28 +123,22 @@ namespace comphelper { for (;;) { - m_xImpl->aPendingActions.wait(); - ProcessableEvent aEvent; + std::vector< ProcessableEvent > aEvents; { - osl::MutexGuard aGuard(m_xImpl->aMutex); + std::unique_lock aGuard(m_xImpl->aMutex); + m_xImpl->aPendingActions.wait(aGuard, + [this] { return m_xImpl->bTerminate || !m_xImpl->aEvents.empty(); } ); if (m_xImpl->bTerminate) - { - break; - } - if (!m_xImpl->aEvents.empty()) - { - aEvent = m_xImpl->aEvents.front(); - m_xImpl->aEvents.pop_front(); - } - if (m_xImpl->aEvents.empty()) - { - m_xImpl->aPendingActions.reset(); - } + return; + else + std::swap(aEvents, m_xImpl->aEvents); } - if (aEvent.aEvent.is()) { - assert(aEvent.xProcessor.is()); - aEvent.xProcessor->processEvent(*aEvent.aEvent); + for (ProcessableEvent& rEvent : aEvents) + { + assert(rEvent.xProcessor.is()); + rEvent.xProcessor->processEvent(*rEvent.aEvent); } + aEvents.clear(); } } @@ -186,7 +163,11 @@ namespace comphelper namespace { - struct theNotifiersMutex : public rtl::Static<osl::Mutex, theNotifiersMutex> {}; + std::mutex& GetTheNotifiersMutex() + { + static std::mutex MUTEX; + return MUTEX; + } } @@ -196,7 +177,7 @@ namespace comphelper { std::vector<std::weak_ptr<AsyncEventNotifierAutoJoin>> notifiers; { - ::osl::MutexGuard g(theNotifiersMutex::get()); + std::scoped_lock g(GetTheNotifiersMutex()); notifiers = g_Notifiers; } for (std::weak_ptr<AsyncEventNotifierAutoJoin> const& wNotifier : notifiers) @@ -220,7 +201,7 @@ namespace comphelper AsyncEventNotifierAutoJoin::~AsyncEventNotifierAutoJoin() { - ::osl::MutexGuard g(theNotifiersMutex::get()); + std::scoped_lock g(GetTheNotifiersMutex()); // note: this doesn't happen atomically with the refcount // hence it's possible this deletes > 1 or 0 elements g_Notifiers.erase( @@ -236,7 +217,7 @@ namespace comphelper { std::shared_ptr<AsyncEventNotifierAutoJoin> const ret( new AsyncEventNotifierAutoJoin(name)); - ::osl::MutexGuard g(theNotifiersMutex::get()); + std::scoped_lock g(GetTheNotifiersMutex()); g_Notifiers.push_back(ret); return ret; } @@ -250,26 +231,20 @@ namespace comphelper { // see salhelper::Thread::launch xThis->m_xImpl->pKeepThisAlive = xThis; - try { - if (!xThis->create()) { - throw std::runtime_error("osl::Thread::create failed"); - } - } catch (...) { - xThis->m_xImpl->pKeepThisAlive.reset(); - throw; + comphelper::ScopeGuard g([&xThis] { xThis->m_xImpl->pKeepThisAlive.reset(); }); + if (!xThis->create()) { + throw std::runtime_error("osl::Thread::create failed"); } + g.dismiss(); } void AsyncEventNotifierAutoJoin::run() { // see salhelper::Thread::run - try { - setName(m_xImpl->name); - execute(); - } catch (...) { - onTerminated(); - throw; - } + comphelper::ScopeGuard g([this] { onTerminated(); }); + setName(m_xImpl->name); + execute(); + g.dismiss(); } void AsyncEventNotifierAutoJoin::onTerminated() diff --git a/comphelper/source/misc/asyncquithandler.cxx b/comphelper/source/misc/asyncquithandler.cxx index fd53cbd9bf4b..a04534ec92e8 100644 --- a/comphelper/source/misc/asyncquithandler.cxx +++ b/comphelper/source/misc/asyncquithandler.cxx @@ -24,10 +24,7 @@ #include <comphelper/asyncquithandler.hxx> #include <comphelper/processfactory.hxx> -AsyncQuitHandler::AsyncQuitHandler() - : mbForceQuit(false) -{ -} +AsyncQuitHandler::AsyncQuitHandler() {} AsyncQuitHandler& AsyncQuitHandler::instance() { @@ -42,10 +39,6 @@ void AsyncQuitHandler::QuitApplication() xDesktop->terminate(); } -void AsyncQuitHandler::SetForceQuit() { mbForceQuit = true; } - -bool AsyncQuitHandler::IsForceQuit() const { return mbForceQuit; } - IMPL_STATIC_LINK_NOARG(AsyncQuitHandler, OnAsyncQuit, void*, void) { QuitApplication(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx index c7bcd4253ed0..0649c9c13fa5 100644 --- a/comphelper/source/misc/backupfilehelper.cxx +++ b/comphelper/source/misc/backupfilehelper.cxx @@ -19,6 +19,7 @@ #include <deque> #include <memory> #include <string_view> +#include <utility> #include <vector> #include <zlib.h> @@ -41,7 +42,6 @@ #include <com/sun/star/io/XStream.hpp> #include <com/sun/star/io/TempFile.hpp> #include <com/sun/star/io/XOutputStream.hpp> -#include <com/sun/star/xml/sax/XDocumentHandler.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <cppuhelper/exc_hlp.hxx> @@ -217,14 +217,13 @@ namespace public: ExtensionInfoEntry() - : maName(), - maRepository(USER), + : maRepository(USER), mbEnabled(false) { } - ExtensionInfoEntry(const OString& rName, bool bEnabled) - : maName(rName), + ExtensionInfoEntry(OString aName, bool bEnabled) + : maName(std::move(aName)), maRepository(USER), mbEnabled(bEnabled) { @@ -355,7 +354,7 @@ namespace typedef std::vector< ExtensionInfoEntry > ExtensionInfoEntryVector; - constexpr OUStringLiteral gaRegPath { u"/registry/com.sun.star.comp.deployment.bundle.PackageRegistryBackend/backenddb.xml" }; + constexpr OUString gaRegPath { u"/registry/com.sun.star.comp.deployment.bundle.PackageRegistryBackend/backenddb.xml"_ustr }; class ExtensionInfo { @@ -364,7 +363,6 @@ namespace public: ExtensionInfo() - : maEntries() { } @@ -413,7 +411,7 @@ namespace e.Context, anyEx ); } - for (const uno::Sequence< uno::Reference< deployment::XPackage > > & xPackageList : std::as_const(xAllPackages)) + for (const uno::Sequence< uno::Reference< deployment::XPackage > > & xPackageList : xAllPackages) { for (const uno::Reference< deployment::XPackage > & xPackage : xPackageList) { @@ -631,7 +629,7 @@ namespace // create a SAXWriter uno::Reference< xml::sax::XWriter > const xSaxWriter = xml::sax::Writer::create(xContext); - uno::Reference< io::XStream > xTempFile = io::TempFile::create(xContext); + uno::Reference< io::XTempFile > xTempFile = io::TempFile::create(xContext); uno::Reference< io::XOutputStream > xOutStrm = xTempFile->getOutputStream(); // set output stream and do the serialization @@ -639,10 +637,7 @@ namespace xSerializer->serialize(xSaxWriter, uno::Sequence< beans::StringPair >()); // get URL from temp file - uno::Reference < beans::XPropertySet > xTempFileProps(xTempFile, uno::UNO_QUERY); - uno::Any aUrl = xTempFileProps->getPropertyValue("Uri"); - OUString aTempURL; - aUrl >>= aTempURL; + OUString aTempURL = xTempFile->getUri(); // copy back file if (aTempURL.isEmpty() || !DirectoryHelper::fileExists(aTempURL)) @@ -666,8 +661,8 @@ namespace const ExtensionInfoEntryVector& rToBeEnabled, const ExtensionInfoEntryVector& rToBeDisabled) { - const OUString aRegPathFront("/uno_packages/cache/registry/com.sun.star.comp.deployment."); - const OUString aRegPathBack(".PackageRegistryBackend/backenddb.xml"); + static constexpr OUString aRegPathFront(u"/uno_packages/cache/registry/com.sun.star.comp.deployment."_ustr); + static constexpr OUString aRegPathBack(u".PackageRegistryBackend/backenddb.xml"_ustr); // first appearance to check { const OUString aUnoPackagReg(OUString::Concat(rUserConfigWorkURL) + aRegPathFront + "bundle" + aRegPathBack); @@ -808,197 +803,191 @@ namespace bool copy_content_straight(oslFileHandle& rTargetHandle) { - if (maFile && osl::File::E_None == maFile->open(osl_File_OpenFlag_Read)) - { - sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE]; - sal_uInt64 nBytesTransfer(0); - sal_uInt64 nSize(getPackFileSize()); + if (!maFile || osl::File::E_None != maFile->open(osl_File_OpenFlag_Read)) + return false; - // set offset in source file - when this is zero, a new file is to be added - if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset()))) - { - while (nSize != 0) - { - const sal_uInt64 nToTransfer(std::min(nSize, sal_uInt64(BACKUP_FILE_HELPER_BLOCK_SIZE))); + sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE]; + sal_uInt64 nBytesTransfer(0); + sal_uInt64 nSize(getPackFileSize()); - if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer) - { - break; - } + // set offset in source file - when this is zero, a new file is to be added + if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset()))) + { + while (nSize != 0) + { + const sal_uInt64 nToTransfer(std::min(nSize, sal_uInt64(BACKUP_FILE_HELPER_BLOCK_SIZE))); - if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aArray), nToTransfer, &nBytesTransfer) || nBytesTransfer != nToTransfer) - { - break; - } + if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer) + { + break; + } - nSize -= nToTransfer; + if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aArray), nToTransfer, &nBytesTransfer) || nBytesTransfer != nToTransfer) + { + break; } - } - maFile->close(); - return (0 == nSize); + nSize -= nToTransfer; + } } - return false; + maFile->close(); + return (0 == nSize); } bool copy_content_compress(oslFileHandle& rTargetHandle) { - if (maFile && osl::File::E_None == maFile->open(osl_File_OpenFlag_Read)) - { - sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE]; - sal_uInt8 aBuffer[BACKUP_FILE_HELPER_BLOCK_SIZE]; - sal_uInt64 nBytesTransfer(0); - sal_uInt64 nSize(getPackFileSize()); - std::unique_ptr< z_stream > zstream(new z_stream); - memset(zstream.get(), 0, sizeof(*zstream)); + if (!maFile || osl::File::E_None != maFile->open(osl_File_OpenFlag_Read)) + return false; - if (Z_OK == deflateInit(zstream.get(), Z_BEST_COMPRESSION)) + sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE]; + sal_uInt8 aBuffer[BACKUP_FILE_HELPER_BLOCK_SIZE]; + sal_uInt64 nBytesTransfer(0); + sal_uInt64 nSize(getPackFileSize()); + z_stream zstream; + memset(&zstream, 0, sizeof(zstream)); + + if (Z_OK == deflateInit(&zstream, Z_BEST_COMPRESSION)) + { + // set offset in source file - when this is zero, a new file is to be added + if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset()))) { - // set offset in source file - when this is zero, a new file is to be added - if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset()))) + bool bOkay(true); + + while (bOkay && nSize != 0) { - bool bOkay(true); + const sal_uInt64 nToTransfer(std::min(nSize, sal_uInt64(BACKUP_FILE_HELPER_BLOCK_SIZE))); - while (bOkay && nSize != 0) + if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer) { - const sal_uInt64 nToTransfer(std::min(nSize, sal_uInt64(BACKUP_FILE_HELPER_BLOCK_SIZE))); - - if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer) - { - break; - } + break; + } - zstream->avail_in = nToTransfer; - zstream->next_in = reinterpret_cast<unsigned char*>(aArray); + zstream.avail_in = nToTransfer; + zstream.next_in = reinterpret_cast<unsigned char*>(aArray); - do { - zstream->avail_out = BACKUP_FILE_HELPER_BLOCK_SIZE; - zstream->next_out = reinterpret_cast<unsigned char*>(aBuffer); + do { + zstream.avail_out = BACKUP_FILE_HELPER_BLOCK_SIZE; + zstream.next_out = reinterpret_cast<unsigned char*>(aBuffer); #if !defined Z_PREFIX - const sal_Int64 nRetval(deflate(zstream.get(), nSize == nToTransfer ? Z_FINISH : Z_NO_FLUSH)); + const sal_Int64 nRetval(deflate(&zstream, nSize == nToTransfer ? Z_FINISH : Z_NO_FLUSH)); #else - const sal_Int64 nRetval(z_deflate(zstream.get(), nSize == nToTransfer ? Z_FINISH : Z_NO_FLUSH)); + const sal_Int64 nRetval(z_deflate(&zstream, nSize == nToTransfer ? Z_FINISH : Z_NO_FLUSH)); #endif - if (Z_STREAM_ERROR == nRetval) + if (Z_STREAM_ERROR == nRetval) + { + bOkay = false; + } + else + { + const sal_uInt64 nAvailable(BACKUP_FILE_HELPER_BLOCK_SIZE - zstream.avail_out); + + if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aBuffer), nAvailable, &nBytesTransfer) || nBytesTransfer != nAvailable) { bOkay = false; } - else - { - const sal_uInt64 nAvailable(BACKUP_FILE_HELPER_BLOCK_SIZE - zstream->avail_out); - - if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aBuffer), nAvailable, &nBytesTransfer) || nBytesTransfer != nAvailable) - { - bOkay = false; - } - } - } while (bOkay && 0 == zstream->avail_out); - - if (!bOkay) - { - break; } + } while (bOkay && 0 == zstream.avail_out); - nSize -= nToTransfer; + if (!bOkay) + { + break; } + nSize -= nToTransfer; + } + #if !defined Z_PREFIX - deflateEnd(zstream.get()); + deflateEnd(&zstream); #else - z_deflateEnd(zstream.get()); + z_deflateEnd(&zstream); #endif - } } + } - maFile->close(); + maFile->close(); - // get compressed size and add to entry - if (mnFullFileSize == mnPackFileSize && mnFullFileSize == zstream->total_in) - { - mnPackFileSize = zstream->total_out; - } - - return (0 == nSize); + // get compressed size and add to entry + if (mnFullFileSize == mnPackFileSize && mnFullFileSize == zstream.total_in) + { + mnPackFileSize = zstream.total_out; } - return false; + return (0 == nSize); } bool copy_content_uncompress(oslFileHandle& rTargetHandle) { - if (maFile && osl::File::E_None == maFile->open(osl_File_OpenFlag_Read)) - { - sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE]; - sal_uInt8 aBuffer[BACKUP_FILE_HELPER_BLOCK_SIZE]; - sal_uInt64 nBytesTransfer(0); - sal_uInt64 nSize(getPackFileSize()); - std::unique_ptr< z_stream > zstream(new z_stream); - memset(zstream.get(), 0, sizeof(*zstream)); + if (!maFile || osl::File::E_None != maFile->open(osl_File_OpenFlag_Read)) + return false; - if (Z_OK == inflateInit(zstream.get())) + sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE]; + sal_uInt8 aBuffer[BACKUP_FILE_HELPER_BLOCK_SIZE]; + sal_uInt64 nBytesTransfer(0); + sal_uInt64 nSize(getPackFileSize()); + z_stream zstream; + memset(&zstream, 0, sizeof(zstream)); + + if (Z_OK == inflateInit(&zstream)) + { + // set offset in source file - when this is zero, a new file is to be added + if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset()))) { - // set offset in source file - when this is zero, a new file is to be added - if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset()))) + bool bOkay(true); + + while (bOkay && nSize != 0) { - bool bOkay(true); + const sal_uInt64 nToTransfer(std::min(nSize, sal_uInt64(BACKUP_FILE_HELPER_BLOCK_SIZE))); - while (bOkay && nSize != 0) + if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer) { - const sal_uInt64 nToTransfer(std::min(nSize, sal_uInt64(BACKUP_FILE_HELPER_BLOCK_SIZE))); - - if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer) - { - break; - } + break; + } - zstream->avail_in = nToTransfer; - zstream->next_in = reinterpret_cast<unsigned char*>(aArray); + zstream.avail_in = nToTransfer; + zstream.next_in = reinterpret_cast<unsigned char*>(aArray); - do { - zstream->avail_out = BACKUP_FILE_HELPER_BLOCK_SIZE; - zstream->next_out = reinterpret_cast<unsigned char*>(aBuffer); + do { + zstream.avail_out = BACKUP_FILE_HELPER_BLOCK_SIZE; + zstream.next_out = reinterpret_cast<unsigned char*>(aBuffer); #if !defined Z_PREFIX - const sal_Int64 nRetval(inflate(zstream.get(), Z_NO_FLUSH)); + const sal_Int64 nRetval(inflate(&zstream, Z_NO_FLUSH)); #else - const sal_Int64 nRetval(z_inflate(zstream.get(), Z_NO_FLUSH)); + const sal_Int64 nRetval(z_inflate(&zstream, Z_NO_FLUSH)); #endif - if (Z_STREAM_ERROR == nRetval) + if (Z_STREAM_ERROR == nRetval) + { + bOkay = false; + } + else + { + const sal_uInt64 nAvailable(BACKUP_FILE_HELPER_BLOCK_SIZE - zstream.avail_out); + + if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aBuffer), nAvailable, &nBytesTransfer) || nBytesTransfer != nAvailable) { bOkay = false; } - else - { - const sal_uInt64 nAvailable(BACKUP_FILE_HELPER_BLOCK_SIZE - zstream->avail_out); - - if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aBuffer), nAvailable, &nBytesTransfer) || nBytesTransfer != nAvailable) - { - bOkay = false; - } - } - } while (bOkay && 0 == zstream->avail_out); - - if (!bOkay) - { - break; } + } while (bOkay && 0 == zstream.avail_out); - nSize -= nToTransfer; + if (!bOkay) + { + break; } + nSize -= nToTransfer; + } + #if !defined Z_PREFIX - deflateEnd(zstream.get()); + deflateEnd(&zstream); #else - z_deflateEnd(zstream.get()); + z_deflateEnd(&zstream); #endif - } } - - maFile->close(); - return (0 == nSize); } - return false; + maFile->close(); + return (0 == nSize); } @@ -1007,13 +996,13 @@ namespace PackedFileEntry( sal_uInt32 nFullFileSize, sal_uInt32 nCrc32, - FileSharedPtr const & rFile, + FileSharedPtr xFile, bool bDoCompress) : mnFullFileSize(nFullFileSize), mnPackFileSize(nFullFileSize), mnOffset(0), mnCrc32(nCrc32), - maFile(rFile), + maFile(std::move(xFile)), mbDoCompress(bDoCompress) { } @@ -1024,7 +1013,6 @@ namespace mnPackFileSize(0), mnOffset(0), mnCrc32(0), - maFile(), mbDoCompress(false) { } @@ -1161,7 +1149,6 @@ namespace public: PackedFile(const OUString& rURL) : maURL(rURL), - maPackedFileEntryVector(), mbChanged(false) { FileSharedPtr aSourceFile = std::make_shared<osl::File>(rURL); @@ -1257,7 +1244,7 @@ namespace { // need to create a new pack file, do this in a temp file to which data // will be copied from local file (so keep it here until this is done) - oslFileHandle aHandle; + oslFileHandle aHandle = nullptr; OUString aTempURL; // open target temp file - it exists until deleted @@ -1425,26 +1412,24 @@ namespace bool tryPop(oslFileHandle& rHandle) { - if (!maPackedFileEntryVector.empty()) - { - // already backups there, check if different from last entry - PackedFileEntry& aLastEntry = maPackedFileEntryVector.back(); + if (maPackedFileEntryVector.empty()) + return false; - // here the uncompress flag has to be determined, true - // means to add the file compressed, false means to add it - // uncompressed - bool bRetval = aLastEntry.copy_content(rHandle, true); + // already backups there, check if different from last entry + PackedFileEntry& aLastEntry = maPackedFileEntryVector.back(); - if (bRetval) - { - maPackedFileEntryVector.pop_back(); - mbChanged = true; - } + // here the uncompress flag has to be determined, true + // means to add the file compressed, false means to add it + // uncompressed + bool bRetval = aLastEntry.copy_content(rHandle, true); - return bRetval; + if (bRetval) + { + maPackedFileEntryVector.pop_back(); + mbChanged = true; } - return false; + return bRetval; } void tryReduceToNumBackups(sal_uInt16 nNumBackups) @@ -1482,7 +1467,7 @@ namespace comphelper // points to registrymodifications.xcu OUString conf("${CONFIGURATION_LAYERS}"); rtl::Bootstrap::expandMacros(conf); - const OUString aTokenUser("user:"); + static constexpr OUString aTokenUser(u"user:"_ustr); sal_Int32 nStart(conf.indexOf(aTokenUser)); if (-1 != nStart) @@ -1527,15 +1512,13 @@ namespace comphelper const OUString& BackupFileHelper::getSafeModeName() { - static const OUString aSafeMode("SafeMode"); + static constexpr OUString aSafeMode(u"SafeMode"_ustr); return aSafeMode; } BackupFileHelper::BackupFileHelper() - : maDirs(), - maFiles(), - mnNumBackups(2), + : mnNumBackups(2), mnMode(1), mbActive(false), mbExtensions(true), @@ -1916,26 +1899,29 @@ namespace comphelper xRootElement->appendChild(lcl_getConfigElement(xDocument, "/org.openoffice.Office.Common/VCL", "ForceSkiaRaster", "true")); - // write back - uno::Reference< xml::sax::XSAXSerializable > xSerializer(xDocument, uno::UNO_QUERY); + OUString aTempURL; + { + // use the scope to make sure that the temp file gets properly closed before move - if (!xSerializer.is()) - return; + // write back + uno::Reference< xml::sax::XSAXSerializable > xSerializer(xDocument, uno::UNO_QUERY); - // create a SAXWriter - uno::Reference< xml::sax::XWriter > const xSaxWriter = xml::sax::Writer::create(xContext); - uno::Reference< io::XStream > xTempFile = io::TempFile::create(xContext); - uno::Reference< io::XOutputStream > xOutStrm = xTempFile->getOutputStream(); + if (!xSerializer.is()) + return; - // set output stream and do the serialization - xSaxWriter->setOutputStream(xOutStrm); - xSerializer->serialize(xSaxWriter, uno::Sequence< beans::StringPair >()); + // create a SAXWriter + uno::Reference< xml::sax::XWriter > const xSaxWriter = xml::sax::Writer::create(xContext); + uno::Reference< io::XTempFile > xTempFile = io::TempFile::create(xContext); + xTempFile->setRemoveFile(false); // avoid removal of tempfile when leaving the scope + uno::Reference< io::XOutputStream > xOutStrm = xTempFile->getOutputStream(); - // get URL from temp file - uno::Reference < beans::XPropertySet > xTempFileProps(xTempFile, uno::UNO_QUERY); - uno::Any aUrl = xTempFileProps->getPropertyValue("Uri"); - OUString aTempURL; - aUrl >>= aTempURL; + // set output stream and do the serialization + xSaxWriter->setOutputStream(xOutStrm); + xSerializer->serialize(xSaxWriter, uno::Sequence< beans::StringPair >()); + + // get URL from temp file + aTempURL = xTempFile->getUri(); + } // copy back file if (aTempURL.isEmpty() || !DirectoryHelper::fileExists(aTempURL)) @@ -2228,46 +2214,44 @@ namespace comphelper { const OUString aFileURL(createFileURL(rSourceURL, rName, rExt)); - if (DirectoryHelper::fileExists(aFileURL)) - { - // try Pop for base file - const OUString aPackURL(createPackURL(rTargetURL, rName)); - PackedFile aPackedFile(aPackURL); + if (!DirectoryHelper::fileExists(aFileURL)) + return false; - if (!aPackedFile.empty()) - { - oslFileHandle aHandle; - OUString aTempURL; + // try Pop for base file + const OUString aPackURL(createPackURL(rTargetURL, rName)); + PackedFile aPackedFile(aPackURL); - // open target temp file - it exists until deleted - if (osl::File::E_None == osl::FileBase::createTempFile(nullptr, &aHandle, &aTempURL)) - { - bool bRetval(aPackedFile.tryPop(aHandle)); + if (aPackedFile.empty()) + return false; - // close temp file (in all cases) - it exists until deleted - osl_closeFile(aHandle); + oslFileHandle aHandle; + OUString aTempURL; - if (bRetval) - { - // copy over existing file by first deleting original - // and moving the temp file to old original - osl::File::remove(aFileURL); - osl::File::move(aTempURL, aFileURL); - - // reduce to allowed number and flush - aPackedFile.tryReduceToNumBackups(mnNumBackups); - aPackedFile.flush(); - } + // open target temp file - it exists until deleted + if (osl::File::E_None != osl::FileBase::createTempFile(nullptr, &aHandle, &aTempURL)) + return false; - // delete temp file (in all cases - it may be moved already) - osl::File::remove(aTempURL); + bool bRetval(aPackedFile.tryPop(aHandle)); - return bRetval; - } - } + // close temp file (in all cases) - it exists until deleted + osl_closeFile(aHandle); + + if (bRetval) + { + // copy over existing file by first deleting original + // and moving the temp file to old original + osl::File::remove(aFileURL); + osl::File::move(aTempURL, aFileURL); + + // reduce to allowed number and flush + aPackedFile.tryReduceToNumBackups(mnNumBackups); + aPackedFile.flush(); } - return false; + // delete temp file (in all cases - it may be moved already) + osl::File::remove(aTempURL); + + return bRetval; } /////////////////// ExtensionInfo helpers /////////////////////// @@ -2320,103 +2304,101 @@ namespace comphelper const OUString aPackURL(createPackURL(rTargetURL, u"ExtensionInfo")); PackedFile aPackedFile(aPackURL); - if (!aPackedFile.empty()) - { - oslFileHandle aHandle; - OUString aTempURL; + if (aPackedFile.empty()) + return false; - // open target temp file - it exists until deleted - if (osl::File::E_None == osl::FileBase::createTempFile(nullptr, &aHandle, &aTempURL)) - { - bool bRetval(aPackedFile.tryPop(aHandle)); + oslFileHandle aHandle; + OUString aTempURL; - // close temp file (in all cases) - it exists until deleted - osl_closeFile(aHandle); + // open target temp file - it exists until deleted + if (osl::File::E_None != osl::FileBase::createTempFile(nullptr, &aHandle, &aTempURL)) + return false; - if (bRetval) - { - // last config is in temp file, load it to ExtensionInfo - ExtensionInfo aLoadedExtensionInfo; - FileSharedPtr aBaseFile = std::make_shared<osl::File>(aTempURL); + bool bRetval(aPackedFile.tryPop(aHandle)); - if (osl::File::E_None == aBaseFile->open(osl_File_OpenFlag_Read)) - { - if (aLoadedExtensionInfo.read_entries(aBaseFile)) - { - // get current extension info, but from XML config files - ExtensionInfo aCurrentExtensionInfo; + // close temp file (in all cases) - it exists until deleted + osl_closeFile(aHandle); - aCurrentExtensionInfo.createUserExtensionRegistryEntriesFromXML(maUserConfigWorkURL); + if (bRetval) + { + // last config is in temp file, load it to ExtensionInfo + ExtensionInfo aLoadedExtensionInfo; + FileSharedPtr aBaseFile = std::make_shared<osl::File>(aTempURL); - // now we have loaded last_working (aLoadedExtensionInfo) and - // current (aCurrentExtensionInfo) ExtensionInfo and may react on - // differences by de/activating these as needed - const ExtensionInfoEntryVector& aUserEntries = aCurrentExtensionInfo.getExtensionInfoEntryVector(); - const ExtensionInfoEntryVector& rLoadedVector = aLoadedExtensionInfo.getExtensionInfoEntryVector(); - ExtensionInfoEntryVector aToBeDisabled; - ExtensionInfoEntryVector aToBeEnabled; + if (osl::File::E_None == aBaseFile->open(osl_File_OpenFlag_Read)) + { + if (aLoadedExtensionInfo.read_entries(aBaseFile)) + { + // get current extension info, but from XML config files + ExtensionInfo aCurrentExtensionInfo; - for (const auto& rCurrentInfo : aUserEntries) - { - const ExtensionInfoEntry* pLoadedInfo = nullptr; + aCurrentExtensionInfo.createUserExtensionRegistryEntriesFromXML(maUserConfigWorkURL); - for (const auto& rLoadedInfo : rLoadedVector) - { - if (rCurrentInfo.isSameExtension(rLoadedInfo)) - { - pLoadedInfo = &rLoadedInfo; - break; - } - } + // now we have loaded last_working (aLoadedExtensionInfo) and + // current (aCurrentExtensionInfo) ExtensionInfo and may react on + // differences by de/activating these as needed + const ExtensionInfoEntryVector& aUserEntries = aCurrentExtensionInfo.getExtensionInfoEntryVector(); + const ExtensionInfoEntryVector& rLoadedVector = aLoadedExtensionInfo.getExtensionInfoEntryVector(); + ExtensionInfoEntryVector aToBeDisabled; + ExtensionInfoEntryVector aToBeEnabled; - if (nullptr != pLoadedInfo) - { - // loaded info contains information about the Extension rCurrentInfo - const bool bCurrentEnabled(rCurrentInfo.isEnabled()); - const bool bLoadedEnabled(pLoadedInfo->isEnabled()); + for (const auto& rCurrentInfo : aUserEntries) + { + const ExtensionInfoEntry* pLoadedInfo = nullptr; - if (bCurrentEnabled && !bLoadedEnabled) - { - aToBeDisabled.push_back(rCurrentInfo); - } - else if (!bCurrentEnabled && bLoadedEnabled) - { - aToBeEnabled.push_back(rCurrentInfo); - } - } - else - { - // There is no loaded info about the Extension rCurrentInfo. - // It needs to be disabled - if (rCurrentInfo.isEnabled()) - { - aToBeDisabled.push_back(rCurrentInfo); - } - } + for (const auto& rLoadedInfo : rLoadedVector) + { + if (rCurrentInfo.isSameExtension(rLoadedInfo)) + { + pLoadedInfo = &rLoadedInfo; + break; } + } + + if (nullptr != pLoadedInfo) + { + // loaded info contains information about the Extension rCurrentInfo + const bool bCurrentEnabled(rCurrentInfo.isEnabled()); + const bool bLoadedEnabled(pLoadedInfo->isEnabled()); - if (!aToBeDisabled.empty() || !aToBeEnabled.empty()) + if (bCurrentEnabled && !bLoadedEnabled) { - ExtensionInfo::changeEnableDisableStateInXML(maUserConfigWorkURL, aToBeEnabled, aToBeDisabled); + aToBeDisabled.push_back(rCurrentInfo); + } + else if (!bCurrentEnabled && bLoadedEnabled) + { + aToBeEnabled.push_back(rCurrentInfo); + } + } + else + { + // There is no loaded info about the Extension rCurrentInfo. + // It needs to be disabled + if (rCurrentInfo.isEnabled()) + { + aToBeDisabled.push_back(rCurrentInfo); } - - bRetval = true; } } - // reduce to allowed number and flush - aPackedFile.tryReduceToNumBackups(mnNumBackups); - aPackedFile.flush(); - } - - // delete temp file (in all cases - it may be moved already) - osl::File::remove(aTempURL); + if (!aToBeDisabled.empty() || !aToBeEnabled.empty()) + { + ExtensionInfo::changeEnableDisableStateInXML(maUserConfigWorkURL, aToBeEnabled, aToBeDisabled); + } - return bRetval; + bRetval = true; + } } + + // reduce to allowed number and flush + aPackedFile.tryReduceToNumBackups(mnNumBackups); + aPackedFile.flush(); } - return false; + // delete temp file (in all cases - it may be moved already) + osl::File::remove(aTempURL); + + return bRetval; } /////////////////// FileDirInfo helpers /////////////////////// diff --git a/comphelper/source/misc/base64.cxx b/comphelper/source/misc/base64.cxx index 75274f5a73cb..2646f297d7aa 100644 --- a/comphelper/source/misc/base64.cxx +++ b/comphelper/source/misc/base64.cxx @@ -17,10 +17,15 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <sal/config.h> + +#include <cstddef> + #include <comphelper/base64.hxx> #include <com/sun/star/uno/Sequence.hxx> +#include <o3tl/safeint.hxx> #include <osl/diagnose.h> using namespace com::sun::star; @@ -56,15 +61,11 @@ const // p q r s t u v w x y z -static void ThreeByteToFourByte(const sal_Int8* pBuffer, const sal_Int32 nStart, const sal_Int32 nFullLen, char* aCharBuffer) +template <typename C> +static void ThreeByteToFourByte(const sal_Int8* pBuffer, const sal_Int32 nStart, const sal_Int32 nFullLen, C* aCharBuffer) { - sal_Int32 nLen(nFullLen - nStart); - if (nLen > 3) - nLen = 3; - if (nLen == 0) - { - return; - } + const sal_Int32 nLen(std::min(nFullLen - nStart, sal_Int32(3))); + assert(nLen > 0); // We are never expected to leave the output buffer uninitialized sal_Int32 nBinaer; switch (nLen) @@ -89,7 +90,7 @@ static void ThreeByteToFourByte(const sal_Int8* pBuffer, const sal_Int32 nStart, break; } - aCharBuffer[0] = aCharBuffer[1] = aCharBuffer[2] = aCharBuffer[3] = '='; + aCharBuffer[2] = aCharBuffer[3] = '='; sal_uInt8 nIndex (static_cast<sal_uInt8>((nBinaer & 0xFC0000) >> 18)); aCharBuffer[0] = aBase64EncodeTable [nIndex]; @@ -108,56 +109,52 @@ static void ThreeByteToFourByte(const sal_Int8* pBuffer, const sal_Int32 nStart, } } -void Base64::encode(OStringBuffer& aStrBuffer, const uno::Sequence<sal_Int8>& aPass) +template <typename Buffer> +static void base64encode(Buffer& aStrBuffer, const uno::Sequence<sal_Int8>& aPass) { sal_Int32 i(0); sal_Int32 nBufferLength(aPass.getLength()); + aStrBuffer.ensureCapacity(aStrBuffer.getLength() + (nBufferLength * 4 + 2) / 3); const sal_Int8* pBuffer = aPass.getConstArray(); while (i < nBufferLength) { - char aCharBuffer[4]; - ThreeByteToFourByte(pBuffer, i, nBufferLength, aCharBuffer); - aStrBuffer.append(aCharBuffer, SAL_N_ELEMENTS(aCharBuffer)); + ThreeByteToFourByte(pBuffer, i, nBufferLength, aStrBuffer.appendUninitialized(4)); i += 3; } } +void Base64::encode(OStringBuffer& aStrBuffer, const uno::Sequence<sal_Int8>& aPass) +{ + base64encode(aStrBuffer, aPass); +} + void Base64::encode(OUStringBuffer& aStrBuffer, const uno::Sequence<sal_Int8>& aPass) { - sal_Int32 i(0); - sal_Int32 nBufferLength(aPass.getLength()); - const sal_Int8* pBuffer = aPass.getConstArray(); - while (i < nBufferLength) - { - char aCharBuffer[4]; - ThreeByteToFourByte(pBuffer, i, nBufferLength, aCharBuffer); - aStrBuffer.appendAscii(aCharBuffer, SAL_N_ELEMENTS(aCharBuffer)); - i += 3; - } + base64encode(aStrBuffer, aPass); } -void Base64::decode(uno::Sequence<sal_Int8>& aBuffer, const OUString& sBuffer) +void Base64::decode(uno::Sequence<sal_Int8>& aBuffer, std::u16string_view sBuffer) { - sal_Int32 nCharsDecoded = decodeSomeChars( aBuffer, sBuffer ); - OSL_ENSURE( nCharsDecoded == sBuffer.getLength(), "some bytes left in base64 decoding!" ); + std::size_t nCharsDecoded = decodeSomeChars( aBuffer, sBuffer ); + OSL_ENSURE( nCharsDecoded == sBuffer.size(), "some bytes left in base64 decoding!" ); } -sal_Int32 Base64::decodeSomeChars(uno::Sequence<sal_Int8>& rOutBuffer, const OUString& rInBuffer) +std::size_t Base64::decodeSomeChars(uno::Sequence<sal_Int8>& rOutBuffer, std::u16string_view rInBuffer) { - sal_Int32 nInBufferLen = rInBuffer.getLength(); - sal_Int32 nMinOutBufferLen = (nInBufferLen / 4) * 3; - if( rOutBuffer.getLength() < nMinOutBufferLen ) + std::size_t nInBufferLen = rInBuffer.size(); + std::size_t nMinOutBufferLen = (nInBufferLen / 4) * 3; + if( o3tl::make_unsigned(rOutBuffer.getLength()) < nMinOutBufferLen ) rOutBuffer.realloc( nMinOutBufferLen ); - const sal_Unicode *pInBuffer = rInBuffer.getStr(); + const sal_Unicode *pInBuffer = rInBuffer.data(); sal_Int8 *pOutBuffer = rOutBuffer.getArray(); sal_Int8 *pOutBufferStart = pOutBuffer; - sal_Int32 nCharsDecoded = 0; + std::size_t nCharsDecoded = 0; sal_uInt8 aDecodeBuffer[4]; sal_Int32 nBytesToDecode = 0; sal_Int32 nBytesGotFromDecoding = 3; - sal_Int32 nInBufferPos= 0; + std::size_t nInBufferPos= 0; while( nInBufferPos < nInBufferLen ) { sal_Unicode cChar = *pInBuffer; diff --git a/comphelper/source/misc/compbase.cxx b/comphelper/source/misc/compbase.cxx new file mode 100644 index 000000000000..1827527d1d56 --- /dev/null +++ b/comphelper/source/misc/compbase.cxx @@ -0,0 +1,260 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <comphelper/compbase.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <sal/log.hxx> +#include <osl/diagnose.h> + +namespace comphelper +{ +WeakComponentImplHelperBase::~WeakComponentImplHelperBase() {} + +// css::lang::XComponent +void SAL_CALL WeakComponentImplHelperBase::dispose() +{ + std::unique_lock aGuard(m_aMutex); + if (m_bDisposed) + return; + m_bDisposed = true; + disposing(aGuard); + if (!aGuard.owns_lock()) + aGuard.lock(); + css::lang::EventObject aEvt(static_cast<OWeakObject*>(this)); + maEventListeners.disposeAndClear(aGuard, aEvt); +} + +void WeakComponentImplHelperBase::disposing(std::unique_lock<std::mutex>&) {} + +void SAL_CALL WeakComponentImplHelperBase::addEventListener( + css::uno::Reference<css::lang::XEventListener> const& rxListener) +{ + std::unique_lock aGuard(m_aMutex); + if (m_bDisposed) + return; + maEventListeners.addInterface(aGuard, rxListener); +} + +void SAL_CALL WeakComponentImplHelperBase::removeEventListener( + css::uno::Reference<css::lang::XEventListener> const& rxListener) +{ + std::unique_lock aGuard(m_aMutex); + maEventListeners.removeInterface(aGuard, rxListener); +} + +css::uno::Any SAL_CALL WeakComponentImplHelperBase::queryInterface(css::uno::Type const& rType) +{ + css::uno::Any aReturn = ::cppu::queryInterface(rType, static_cast<css::uno::XWeak*>(this), + static_cast<css::lang::XComponent*>(this)); + if (aReturn.hasValue()) + return aReturn; + return OWeakObject::queryInterface(rType); +} + +static void checkInterface(css::uno::Type const& rType) +{ + if (css::uno::TypeClass_INTERFACE != rType.getTypeClass()) + { + OUString msg("querying for interface \"" + rType.getTypeName() + "\": no interface type!"); + SAL_WARN("cppuhelper", msg); + throw css::uno::RuntimeException(msg); + } +} + +static bool isXInterface(rtl_uString* pStr) +{ + return OUString::unacquired(&pStr) == "com.sun.star.uno.XInterface"; +} + +static bool td_equals(typelib_TypeDescriptionReference const* pTDR1, + typelib_TypeDescriptionReference const* pTDR2) +{ + return ((pTDR1 == pTDR2) + || OUString::unacquired(&pTDR1->pTypeName) == OUString::unacquired(&pTDR2->pTypeName)); +} + +static cppu::type_entry* getTypeEntries(cppu::class_data* cd) +{ + cppu::type_entry* pEntries = cd->m_typeEntries; + if (!cd->m_storedTypeRefs) // not inited? + { + static std::mutex aMutex; + std::scoped_lock guard(aMutex); + if (!cd->m_storedTypeRefs) // not inited? + { + // get all types + for (sal_Int32 n = cd->m_nTypes; n--;) + { + cppu::type_entry* pEntry = &pEntries[n]; + css::uno::Type const& rType = (*pEntry->m_type.getCppuType)(nullptr); + OSL_ENSURE(rType.getTypeClass() == css::uno::TypeClass_INTERFACE, + "### wrong helper init: expected interface!"); + OSL_ENSURE( + !isXInterface(rType.getTypeLibType()->pTypeName), + "### want to implement XInterface: template argument is XInterface?!?!?!"); + if (rType.getTypeClass() != css::uno::TypeClass_INTERFACE) + { + OUString msg("type \"" + rType.getTypeName() + "\" is no interface type!"); + SAL_WARN("cppuhelper", msg); + throw css::uno::RuntimeException(msg); + } + // ref is statically held by getCppuType() + pEntry->m_type.typeRef = rType.getTypeLibType(); + } + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + cd->m_storedTypeRefs = true; + } + } + else + { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + return pEntries; +} + +static void* makeInterface(sal_IntPtr nOffset, void* that) +{ + return (static_cast<char*>(that) + nOffset); +} + +static bool recursivelyFindType(typelib_TypeDescriptionReference const* demandedType, + typelib_InterfaceTypeDescription const* type, sal_IntPtr* offset) +{ + // This code assumes that the vtables of a multiple-inheritance class (the + // offset amount by which to adjust the this pointer) follow one another in + // the object layout, and that they contain slots for the inherited classes + // in a specific order. In theory, that need not hold for any given + // platform; in practice, it seems to work well on all supported platforms: +next: + for (sal_Int32 i = 0; i < type->nBaseTypes; ++i) + { + if (i > 0) + { + *offset += sizeof(void*); + } + typelib_InterfaceTypeDescription const* base = type->ppBaseTypes[i]; + // ignore XInterface: + if (base->nBaseTypes > 0) + { + if (td_equals(reinterpret_cast<typelib_TypeDescriptionReference const*>(base), + demandedType)) + { + return true; + } + // Profiling showed that it is important to speed up the common case + // of only one base: + if (type->nBaseTypes == 1) + { + type = base; + goto next; + } + if (recursivelyFindType(demandedType, base, offset)) + { + return true; + } + } + } + return false; +} + +static void* queryDeepNoXInterface(typelib_TypeDescriptionReference const* pDemandedTDR, + cppu::class_data* cd, void* that) +{ + cppu::type_entry* pEntries = getTypeEntries(cd); + sal_Int32 nTypes = cd->m_nTypes; + sal_Int32 n; + + // try top interfaces without getting td + for (n = 0; n < nTypes; ++n) + { + if (td_equals(pEntries[n].m_type.typeRef, pDemandedTDR)) + { + return makeInterface(pEntries[n].m_offset, that); + } + } + // query deep getting td + for (n = 0; n < nTypes; ++n) + { + typelib_TypeDescription* pTD = nullptr; + TYPELIB_DANGER_GET(&pTD, pEntries[n].m_type.typeRef); + if (pTD) + { + // exclude top (already tested) and bottom (XInterface) interface + OSL_ENSURE(reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD)->nBaseTypes > 0, + "### want to implement XInterface:" + " template argument is XInterface?!?!?!"); + sal_IntPtr offset = pEntries[n].m_offset; + bool found = recursivelyFindType( + pDemandedTDR, reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD), &offset); + TYPELIB_DANGER_RELEASE(pTD); + if (found) + { + return makeInterface(offset, that); + } + } + else + { + OUString msg("cannot get type description for type \"" + + OUString::unacquired(&pEntries[n].m_type.typeRef->pTypeName) + "\"!"); + SAL_WARN("cppuhelper", msg); + throw css::uno::RuntimeException(msg); + } + } + return nullptr; +} + +css::uno::Any WeakComponentImplHelper_query(css::uno::Type const& rType, cppu::class_data* cd, + WeakComponentImplHelperBase* pBase) +{ + checkInterface(rType); + typelib_TypeDescriptionReference* pTDR = rType.getTypeLibType(); + + // shortcut XInterface to WeakComponentImplHelperBase + if (!isXInterface(pTDR->pTypeName)) + { + void* p = queryDeepNoXInterface(pTDR, cd, pBase); + if (p) + { + return css::uno::Any(&p, pTDR); + } + } + return pBase->comphelper::WeakComponentImplHelperBase::queryInterface(rType); +} + +WeakImplHelperBase::~WeakImplHelperBase() {} + +css::uno::Any SAL_CALL WeakImplHelperBase::queryInterface(css::uno::Type const& rType) +{ + css::uno::Any aReturn = ::cppu::queryInterface(rType, static_cast<css::uno::XWeak*>(this)); + if (aReturn.hasValue()) + return aReturn; + return OWeakObject::queryInterface(rType); +} + +css::uno::Any WeakImplHelper_query(css::uno::Type const& rType, cppu::class_data* cd, + WeakImplHelperBase* pBase) +{ + checkInterface(rType); + typelib_TypeDescriptionReference* pTDR = rType.getTypeLibType(); + + // shortcut XInterface to WeakComponentImplHelperBase + if (!isXInterface(pTDR->pTypeName)) + { + void* p = queryDeepNoXInterface(pTDR, cd, pBase); + if (p) + { + return css::uno::Any(&p, pTDR); + } + } + return pBase->comphelper::WeakImplHelperBase::queryInterface(rType); +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/comphelper/source/misc/configuration.cxx b/comphelper/source/misc/configuration.cxx index 56b186dea805..b7d97bbb6533 100644 --- a/comphelper/source/misc/configuration.cxx +++ b/comphelper/source/misc/configuration.cxx @@ -10,7 +10,9 @@ #include <sal/config.h> #include <cassert> +#include <map> #include <memory> +#include <mutex> #include <string_view> #include <com/sun/star/beans/PropertyAttribute.hpp> @@ -28,7 +30,6 @@ #include <comphelper/solarmutex.hxx> #include <comphelper/configuration.hxx> #include <comphelper/configurationlistener.hxx> -#include <rtl/instance.hxx> #include <rtl/ustring.hxx> #include <sal/log.hxx> #include <i18nlangtag/languagetag.hxx> @@ -37,13 +38,6 @@ namespace com::sun::star::uno { class XComponentContext; } namespace { -struct TheConfigurationWrapper: - public rtl::StaticWithArg< - comphelper::detail::ConfigurationWrapper, - css::uno::Reference< css::uno::XComponentContext >, - TheConfigurationWrapper > -{}; - OUString getDefaultLocale( css::uno::Reference< css::uno::XComponentContext > const & context) { @@ -68,9 +62,9 @@ OUString extendLocalizedPath(std::u16string_view path, OUString const & locale) std::shared_ptr< comphelper::ConfigurationChanges > comphelper::ConfigurationChanges::create( - css::uno::Reference< css::uno::XComponentContext > const & context) + css::uno::Reference<css::uno::XComponentContext> const & context) { - return TheConfigurationWrapper::get(context).createChanges(); + return detail::ConfigurationWrapper::get(context).createChanges(); } comphelper::ConfigurationChanges::~ConfigurationChanges() {} @@ -108,15 +102,16 @@ comphelper::ConfigurationChanges::getSet(OUString const & path) const comphelper::detail::ConfigurationWrapper const & comphelper::detail::ConfigurationWrapper::get( - css::uno::Reference< css::uno::XComponentContext > const & context) + css::uno::Reference<css::uno::XComponentContext> const & context) { - return TheConfigurationWrapper::get(context); + static comphelper::detail::ConfigurationWrapper WRAPPER(context); + return WRAPPER; } comphelper::detail::ConfigurationWrapper::ConfigurationWrapper( - css::uno::Reference< css::uno::XComponentContext > const & context): - context_(context), - access_(css::configuration::ReadWriteAccess::create(context, "*")) + css::uno::Reference<css::uno::XComponentContext> const & context): + context_(context.is() ? context : comphelper::getProcessComponentContext()), + access_(css::configuration::ReadWriteAccess::create(context_, "*")) {} comphelper::detail::ConfigurationWrapper::~ConfigurationWrapper() {} @@ -130,10 +125,34 @@ bool comphelper::detail::ConfigurationWrapper::isReadOnly(OUString const & path) != 0; } -css::uno::Any comphelper::detail::ConfigurationWrapper::getPropertyValue( - OUString const & path) const +css::uno::Any comphelper::detail::ConfigurationWrapper::getPropertyValue(std::u16string_view path) const { - return access_->getByHierarchicalName(path); + // should be short-circuited in ConfigurationProperty::get() + assert(!comphelper::IsFuzzing()); + + // Cache the configuration access, since some of the keys are used in hot code. + // Note that this cache is only used by the officecfg:: auto-generated code, using it for anything + // else would be unwise because the cache could end up containing stale entries. + static std::mutex gMutex; + static std::map<OUString, css::uno::Reference< css::container::XNameAccess >> gAccessMap; + + sal_Int32 idx = path.rfind('/'); + assert(idx!=-1); + OUString parentPath(path.substr(0, idx)); + OUString childName(path.substr(idx+1)); + + std::scoped_lock aGuard(gMutex); + + // check cache + auto it = gAccessMap.find(parentPath); + if (it == gAccessMap.end()) + { + // not in the cache, look it up + css::uno::Reference<css::container::XNameAccess> access( + access_->getByHierarchicalName(parentPath), css::uno::UNO_QUERY_THROW); + it = gAccessMap.emplace(parentPath, access).first; + } + return it->second->getByName(childName); } void comphelper::detail::ConfigurationWrapper::setPropertyValue( @@ -231,6 +250,8 @@ void comphelper::ConfigurationListener::dispose() listener->dispose(); } maListeners.clear(); + mxConfig.clear(); + mbDisposed = true; } void SAL_CALL comphelper::ConfigurationListener::disposing(css::lang::EventObject const &) @@ -262,4 +283,23 @@ void SAL_CALL comphelper::ConfigurationListener::propertyChange( } } +namespace comphelper { + +static bool bIsFuzzing = false; + +#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) +bool IsFuzzing() +{ + return bIsFuzzing; +} +#endif + +void EnableFuzzing() +{ + bIsFuzzing = true; + LanguageTag::disable_lt_tag_parse(); +} + +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/date.cxx b/comphelper/source/misc/date.cxx new file mode 100644 index 000000000000..b95f63f75c97 --- /dev/null +++ b/comphelper/source/misc/date.cxx @@ -0,0 +1,210 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <comphelper/date.hxx> + +#include <cassert> + +namespace comphelper::date +{ +// Once upon a time the number of days we internally handled in tools' class +// Date was limited to MAX_DAYS 3636532. That changed with a full 16-bit year. +// Assuming the first valid positive date in a proleptic Gregorian calendar is +// 0001-01-01, this resulted in an end date of 9957-06-26. +// Hence we documented that years up to and including 9956 are handled. +/* XXX: it is unclear history why this value was chosen, the representable + * 9999-12-31 would be 3652060 days from 0001-01-01. Even 9998-12-31 to + * distinguish from a maximum possible date would be 3651695. + * There is connectivity/source/commontools/dbconversion.cxx that still has the + * same value to calculate with css::util::Date */ +/* XXX can that dbconversion cope with years > 9999 or negative years at all? + * Database fields may be limited to positive 4 digits. */ + +constexpr sal_Int32 MIN_DAYS = -11968265; // -32768-01-01 +constexpr sal_Int32 MAX_DAYS = 11967900; // 32767-12-31 + +constexpr sal_Int16 kYearMax = SAL_MAX_INT16; +constexpr sal_Int16 kYearMin = SAL_MIN_INT16; + +constexpr sal_Int32 nNullDateDays = convertDateToDays(30, 12, 1899); +static_assert(nNullDateDays == 693594); + +sal_Int32 convertDateToDaysNormalizing(sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear) +{ + // Speed-up the common null-date 1899-12-30. + if (nYear == 1899 && nMonth == 12 && nDay == 30) + return nNullDateDays; + + normalize(nDay, nMonth, nYear); + return convertDateToDays(nDay, nMonth, nYear); +} + +bool isValidDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear) +{ + if (nYear == 0) + return false; + if (nMonth < 1 || 12 < nMonth) + return false; + if (nDay < 1 || (nDay > comphelper::date::getDaysInMonth(nMonth, nYear))) + return false; + return true; +} + +void convertDaysToDate(sal_Int32 nDays, sal_uInt16& rDay, sal_uInt16& rMonth, sal_Int16& rYear) +{ + if (nDays <= MIN_DAYS) + { + rDay = 1; + rMonth = 1; + rYear = kYearMin; + return; + } + if (nDays >= MAX_DAYS) + { + rDay = 31; + rMonth = 12; + rYear = kYearMax; + return; + } + + // Day 0 is -0001-12-31, day 1 is 0001-01-01 + const sal_Int16 nSign = (nDays <= 0 ? -1 : 1); + sal_Int32 nTempDays; + sal_Int32 i = 0; + bool bCalc; + + do + { + rYear = static_cast<sal_Int16>((nDays / 365) - (i * nSign)); + if (rYear == 0) + rYear = nSign; + nTempDays = nDays - YearToDays(rYear); + bCalc = false; + if (nTempDays < 1) + { + i += nSign; + bCalc = true; + } + else + { + if (nTempDays > 365) + { + if ((nTempDays != 366) || !isLeapYear(rYear)) + { + i -= nSign; + bCalc = true; + } + } + } + } while (bCalc); + + rMonth = 1; + while (nTempDays > getDaysInMonth(rMonth, rYear)) + { + nTempDays -= getDaysInMonth(rMonth, rYear); + ++rMonth; + } + + rDay = static_cast<sal_uInt16>(nTempDays); +} + +bool normalize(sal_uInt16& rDay, sal_uInt16& rMonth, sal_Int16& rYear) +{ + if (isValidDate(rDay, rMonth, rYear)) + return false; + + if (rDay == 0 && rMonth == 0 && rYear == 0) + return false; // empty date + + if (rDay == 0) + { + if (rMonth == 0) + ; // nothing, handled below + else + --rMonth; + // Last day of month is determined at the end. + } + + if (rMonth > 12) + { + rYear += rMonth / 12; + rMonth = rMonth % 12; + if (rYear == 0) + rYear = 1; + } + if (rMonth == 0) + { + --rYear; + if (rYear == 0) + rYear = -1; + rMonth = 12; + } + + if (rYear < 0) + { + sal_uInt16 nDays; + while (rDay > (nDays = getDaysInMonth(rMonth, rYear))) + { + rDay -= nDays; + if (rMonth > 1) + --rMonth; + else + { + if (rYear == kYearMin) + { + rDay = 1; + rMonth = 1; + return true; + } + --rYear; + rMonth = 12; + } + } + } + else + { + sal_uInt16 nDays; + while (rDay > (nDays = getDaysInMonth(rMonth, rYear))) + { + rDay -= nDays; + if (rMonth < 12) + ++rMonth; + else + { + if (rYear == kYearMax) + { + rDay = 31; + rMonth = 12; + return true; + } + ++rYear; + rMonth = 1; + } + } + } + + if (rDay == 0) + rDay = getDaysInMonth(rMonth, rYear); + + return true; +} + +} // namespace comphelper::date + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/comphelper/source/misc/debuggerinfo.cxx b/comphelper/source/misc/debuggerinfo.cxx index 07b2f0132fff..1e7116a55300 100644 --- a/comphelper/source/misc/debuggerinfo.cxx +++ b/comphelper/source/misc/debuggerinfo.cxx @@ -16,6 +16,10 @@ #if defined(_WIN32) #define WIN32_LEAN_AND_MEAN #include <windows.h> +#elif defined MACOSX +#include <unistd.h> +#include <sys/types.h> +#include <sys/sysctl.h> #elif defined UNX #include <unistd.h> #include <fcntl.h> @@ -28,6 +32,35 @@ bool isDebuggerAttached() { #if defined(_WIN32) return IsDebuggerPresent(); +#elif defined MACOSX + // https://developer.apple.com/library/archive/qa/qa1361/_index.html + int junk; + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0); + assert(junk == 0); + + // We're being debugged if the P_TRACED flag is set. + + return ((info.kp_proc.p_flag & P_TRACED) != 0); #elif defined LINUX char buf[4096]; int fd = open("/proc/self/status", O_RDONLY); diff --git a/comphelper/source/misc/diagnose_ex.cxx b/comphelper/source/misc/diagnose_ex.cxx new file mode 100644 index 000000000000..487f98b637a0 --- /dev/null +++ b/comphelper/source/misc/diagnose_ex.cxx @@ -0,0 +1,392 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/configuration/CorruptedConfigurationException.hpp> +#include <com/sun/star/configuration/backend/BackendSetupException.hpp> +#include <com/sun/star/configuration/backend/MalformedDataException.hpp> +#include <com/sun/star/configuration/InvalidBootstrapFileException.hpp> +#include <com/sun/star/configuration/MissingBootstrapFileException.hpp> +#include <com/sun/star/deployment/DependencyException.hpp> +#include <com/sun/star/deployment/DeploymentException.hpp> +#include <com/sun/star/document/CorruptedFilterConfigurationException.hpp> +#include <com/sun/star/document/UndoFailedException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/WrappedTargetException.hpp> +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/ldap/LdapGenericException.hpp> +#include <com/sun/star/script/BasicErrorException.hpp> +#include <com/sun/star/script/CannotConvertException.hpp> +#include <com/sun/star/script/provider/ScriptExceptionRaisedException.hpp> +#include <com/sun/star/script/provider/ScriptFrameworkErrorException.hpp> +#include <com/sun/star/sdbc/SQLException.hpp> +#include <com/sun/star/system/SystemShellExecuteException.hpp> +#include <com/sun/star/task/ErrorCodeIOException.hpp> +#include <com/sun/star/ucb/CommandFailedException.hpp> +#include <com/sun/star/ucb/ContentCreationException.hpp> +#include <com/sun/star/ucb/MissingPropertiesException.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +#include <com/sun/star/ucb/InteractiveIOException.hpp> +#include <com/sun/star/util/MalformedNumberFormatException.hpp> +#include <com/sun/star/xml/dom/DOMException.hpp> +#include <com/sun/star/xml/sax/SAXException.hpp> +#include <com/sun/star/xml/sax/SAXParseException.hpp> +#include <comphelper/anytostring.hxx> +#include <sal/log.hxx> +#include <osl/thread.h> +#include <rtl/strbuf.hxx> + +#include <comphelper/diagnose_ex.hxx> + +#if defined __GLIBCXX__ +#include <cxxabi.h> +#endif + +static void exceptionToStringImpl(OStringBuffer& sMessage, const css::uno::Any & caught) +{ + auto toOString = [](OUString const & s) { + return OUStringToOString( s, osl_getThreadTextEncoding() ); + }; + // when called recursively, we might not have any exception to print + if (!caught.hasValue()) + return; + sMessage.append(toOString(caught.getValueTypeName())); + css::uno::Exception exception; + caught >>= exception; + if ( !exception.Message.isEmpty() ) + { + sMessage.append(" message: \""); + sMessage.append(toOString(exception.Message)); + sMessage.append("\""); + } + if ( exception.Context.is() ) + { + const char* pContext = typeid( *exception.Context ).name(); +#if defined __GLIBCXX__ + // demangle the type name, not necessary under windows, we already get demangled names there + int status; + pContext = abi::__cxa_demangle( pContext, nullptr, nullptr, &status); +#endif + sMessage.append(" context: "); + sMessage.append(pContext); +#if defined __GLIBCXX__ + std::free(const_cast<char *>(pContext)); +#endif + } + { + css::configuration::CorruptedConfigurationException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" details: "); + sMessage.append(toOString(specialized.Details)); + } + } + { + css::configuration::InvalidBootstrapFileException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" BootstrapFileURL: "); + sMessage.append(toOString(specialized.BootstrapFileURL)); + } + } + { + css::configuration::MissingBootstrapFileException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" BootstrapFileURL: "); + sMessage.append(toOString(specialized.BootstrapFileURL)); + } + } + { + css::configuration::backend::MalformedDataException specialized; + if ( caught >>= specialized ) + { + sMessage.append("\n wrapped: "); + exceptionToStringImpl(sMessage, specialized.ErrorDetails); + } + } + { + css::configuration::backend::BackendSetupException specialized; + if ( caught >>= specialized ) + { + sMessage.append("\n wrapped: "); + exceptionToStringImpl(sMessage, specialized.BackendException); + } + } + { + css::deployment::DependencyException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" UnsatisfiedDependencies: "); + sMessage.append(toOString(comphelper::anyToString(css::uno::Any(specialized.UnsatisfiedDependencies)))); + } + } + { + css::deployment::DeploymentException specialized; + if ( caught >>= specialized ) + { + sMessage.append("\n wrapped: "); + exceptionToStringImpl(sMessage, specialized.Cause); + } + } + { + css::document::CorruptedFilterConfigurationException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" Details: "); + sMessage.append(toOString(specialized.Details)); + } + } + { + css::document::UndoFailedException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" Reason: "); + sMessage.append(toOString(comphelper::anyToString(specialized.Reason))); + } + } + { + css::lang::IllegalArgumentException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" ArgumentPosition: "); + sMessage.append(static_cast<sal_Int32>(specialized.ArgumentPosition)); + } + } + { + css::lang::WrappedTargetException specialized; + if ( caught >>= specialized ) + { + sMessage.append("\n wrapped: "); + exceptionToStringImpl(sMessage, specialized.TargetException); + } + } + { + css::lang::WrappedTargetRuntimeException specialized; + if ( caught >>= specialized ) + { + sMessage.append("\n wrapped: "); + exceptionToStringImpl(sMessage, specialized.TargetException); + } + } + { + css::ldap::LdapGenericException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" ErrorCode: "); + sMessage.append(specialized.ErrorCode); + } + } + { + css::script::BasicErrorException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" ErrorCode: "); + sMessage.append(specialized.ErrorCode); + sMessage.append(" ErrorMessageArgument: "); + sMessage.append(toOString(specialized.ErrorMessageArgument)); + } + } + { + css::script::CannotConvertException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" DestinationTypeClass: "); + sMessage.append(toOString(comphelper::anyToString(css::uno::Any(specialized.DestinationTypeClass)))); + sMessage.append(" Reason: "); + sMessage.append(specialized.Reason); + sMessage.append(" ArgumentIndex: "); + sMessage.append(specialized.ArgumentIndex); + } + } + { + css::script::provider::ScriptErrorRaisedException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" scriptName: "); + sMessage.append(toOString(specialized.scriptName)); + sMessage.append(" language: "); + sMessage.append(toOString(specialized.language)); + sMessage.append(" lineNum: "); + sMessage.append(specialized.lineNum); + } + } + { + css::script::provider::ScriptExceptionRaisedException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" exceptionType: "); + sMessage.append(toOString(specialized.exceptionType)); + } + } + { + css::script::provider::ScriptFrameworkErrorException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" scriptName: "); + sMessage.append(toOString(specialized.scriptName)); + sMessage.append(" language: "); + sMessage.append(toOString(specialized.language)); + sMessage.append(" errorType: "); + sMessage.append(specialized.errorType); + } + } + { + css::sdbc::SQLException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" SQLState: "); + sMessage.append(toOString(specialized.SQLState)); + sMessage.append(" ErrorCode: "); + sMessage.append(specialized.ErrorCode); + sMessage.append("\n wrapped: "); + exceptionToStringImpl(sMessage, specialized.NextException); + } + } + { + css::system::SystemShellExecuteException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" PosixError: "); + sMessage.append(specialized.PosixError); + } + } + { + css::task::ErrorCodeIOException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" errcode: "); + sMessage.append( specialized.ErrCode ); + } + } + { + css::ucb::CommandFailedException specialized; + if ( caught >>= specialized ) + { + sMessage.append("\n Reason: "); + exceptionToStringImpl( sMessage, specialized.Reason ); + } + } + { + css::ucb::ContentCreationException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" eError: "); + sMessage.append(toOString(comphelper::anyToString( css::uno::Any(specialized.eError) ))); + } + } + { + css::ucb::MissingPropertiesException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" Properties: "); + sMessage.append(toOString(comphelper::anyToString( css::uno::Any(specialized.Properties) ))); + } + } + { + css::ucb::NameClashException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" Name: "); + sMessage.append(toOString( specialized.Name )); + } + } + { + css::util::MalformedNumberFormatException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" CheckPos: "); + sMessage.append( specialized.CheckPos ); + } + } + { + css::xml::dom::DOMException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" Code: "); + sMessage.append(toOString(comphelper::anyToString( css::uno::Any(specialized.Code) ))); + } + } + { + css::xml::dom::DOMException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" Code: "); + sMessage.append(toOString(comphelper::anyToString( css::uno::Any(specialized.Code) ))); + } + } + { + css::xml::sax::SAXException specialized; + if ( caught >>= specialized ) + { + sMessage.append("\n wrapped: "); + exceptionToStringImpl( sMessage, specialized.WrappedException ); + } + } + { + css::xml::sax::SAXParseException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" PublicId: "); + sMessage.append(toOString( specialized.PublicId )); + sMessage.append(" SystemId: "); + sMessage.append(toOString( specialized.SystemId )); + sMessage.append(" LineNumber: "); + sMessage.append( specialized.LineNumber ); + sMessage.append(" ColumnNumber: "); + sMessage.append( specialized.ColumnNumber ); + } + } + { + css::ucb::InteractiveIOException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" Code: "); + sMessage.append( static_cast<sal_Int32>(specialized.Code) ); + } + } +} + +OString exceptionToString(const css::uno::Any & caught) +{ + OStringBuffer sMessage(512); + exceptionToStringImpl(sMessage, caught); + return sMessage.makeStringAndClear(); +} + +void DbgUnhandledException(const css::uno::Any & caught, const char* currentFunction, const char* fileAndLineNo, + const char* area, const char* explanatory) +{ + OStringBuffer sMessage( 512 ); + sMessage.append( OString::Concat("DBG_UNHANDLED_EXCEPTION in ") + currentFunction); + if (explanatory) + { + sMessage.append(OString::Concat("\n when: ") + explanatory); + } + sMessage.append(" exception: "); + exceptionToStringImpl(sMessage, caught); + + if (area == nullptr) + area = "legacy.osl"; + + SAL_DETAIL_LOG_FORMAT( + SAL_DETAIL_ENABLE_LOG_WARN, SAL_DETAIL_LOG_LEVEL_WARN, + area, fileAndLineNo, "%s", sMessage.getStr()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/comphelper/source/misc/docpasswordhelper.cxx b/comphelper/source/misc/docpasswordhelper.cxx index bd8ce5d7de7f..1f73bd8d7026 100644 --- a/comphelper/source/misc/docpasswordhelper.cxx +++ b/comphelper/source/misc/docpasswordhelper.cxx @@ -23,6 +23,7 @@ #include <string_view> #include <comphelper/docpasswordhelper.hxx> +#include <comphelper/propertyvalue.hxx> #include <comphelper/storagehelper.hxx> #include <comphelper/hash.hxx> #include <comphelper/base64.hxx> @@ -50,7 +51,6 @@ using ::com::sun::star::task::PasswordRequestMode; using ::com::sun::star::task::PasswordRequestMode_PASSWORD_ENTER; using ::com::sun::star::task::PasswordRequestMode_PASSWORD_REENTER; using ::com::sun::star::task::XInteractionHandler; -using ::com::sun::star::task::XInteractionRequest; using namespace ::com::sun::star; @@ -95,15 +95,98 @@ uno::Sequence< beans::PropertyValue > DocPasswordHelper::GenerateNewModifyPasswo uno::Sequence< sal_Int8 > aNewHash = GeneratePBKDF2Hash(aPassword, aSalt, nPBKDF2IterationCount, 16); if ( aNewHash.hasElements() ) { - aResult.realloc( 4 ); - aResult[0].Name = "algorithm-name"; - aResult[0].Value <<= OUString( "PBKDF2" ); - aResult[1].Name = "salt"; - aResult[1].Value <<= aSalt; - aResult[2].Name = "iteration-count"; - aResult[2].Value <<= nPBKDF2IterationCount; - aResult[3].Name = "hash"; - aResult[3].Value <<= aNewHash; + aResult = { comphelper::makePropertyValue("algorithm-name", OUString( "PBKDF2" )), + comphelper::makePropertyValue("salt", aSalt), + comphelper::makePropertyValue("iteration-count", nPBKDF2IterationCount), + comphelper::makePropertyValue("hash", aNewHash) }; + } + + return aResult; +} + + +uno::Sequence<beans::PropertyValue> +DocPasswordHelper::GenerateNewModifyPasswordInfoOOXML(std::u16string_view aPassword) +{ + uno::Sequence<beans::PropertyValue> aResult; + + if (!aPassword.empty()) + { + uno::Sequence<sal_Int8> aSalt = GenerateRandomByteSequence(16); + OUStringBuffer aBuffer(22); + comphelper::Base64::encode(aBuffer, aSalt); + OUString sSalt = aBuffer.makeStringAndClear(); + + sal_Int32 const nIterationCount = 100000; + OUString sAlgorithm("SHA-512"); + + const OUString sHash(GetOoxHashAsBase64(OUString(aPassword), sSalt, nIterationCount, + comphelper::Hash::IterCount::APPEND, sAlgorithm)); + + if (!sHash.isEmpty()) + { + aResult = { comphelper::makePropertyValue("algorithm-name", sAlgorithm), + comphelper::makePropertyValue("salt", sSalt), + comphelper::makePropertyValue("iteration-count", nIterationCount), + comphelper::makePropertyValue("hash", sHash) }; + } + } + + return aResult; +} + + +uno::Sequence< beans::PropertyValue > DocPasswordHelper::ConvertPasswordInfo( const uno::Sequence< beans::PropertyValue >& aInfo ) +{ + uno::Sequence< beans::PropertyValue > aResult; + OUString sAlgorithm, sHash, sSalt, sCount; + sal_Int32 nAlgorithm = 0; + + for ( const auto & prop : aInfo ) + { + if ( prop.Name == "cryptAlgorithmSid" ) + { + prop.Value >>= sAlgorithm; + nAlgorithm = sAlgorithm.toInt32(); + } + else if ( prop.Name == "salt" ) + prop.Value >>= sSalt; + else if ( prop.Name == "cryptSpinCount" ) + prop.Value >>= sCount; + else if ( prop.Name == "hash" ) + prop.Value >>= sHash; + } + + if (nAlgorithm == 1) + sAlgorithm = "MD2"; + else if (nAlgorithm == 2) + sAlgorithm = "MD4"; + else if (nAlgorithm == 3) + sAlgorithm = "MD5"; + else if (nAlgorithm == 4) + sAlgorithm = "SHA-1"; + else if (nAlgorithm == 5) + sAlgorithm = "MAC"; + else if (nAlgorithm == 6) + sAlgorithm = "RIPEMD"; + else if (nAlgorithm == 7) + sAlgorithm = "RIPEMD-160"; + else if (nAlgorithm == 9) + sAlgorithm = "HMAC"; + else if (nAlgorithm == 12) + sAlgorithm = "SHA-256"; + else if (nAlgorithm == 13) + sAlgorithm = "SHA-384"; + else if (nAlgorithm == 14) + sAlgorithm = "SHA-512"; + + if ( !sCount.isEmpty() ) + { + sal_Int32 nCount = sCount.toInt32(); + aResult = { comphelper::makePropertyValue("algorithm-name", sAlgorithm), + comphelper::makePropertyValue("salt", sSalt), + comphelper::makePropertyValue("iteration-count", nCount), + comphelper::makePropertyValue("hash", sHash) }; } return aResult; @@ -116,8 +199,7 @@ bool DocPasswordHelper::IsModifyPasswordCorrect( std::u16string_view aPassword, if ( !aPassword.empty() && aInfo.hasElements() ) { OUString sAlgorithm; - uno::Sequence< sal_Int8 > aSalt; - uno::Sequence< sal_Int8 > aHash; + uno::Any aSalt, aHash; sal_Int32 nCount = 0; for ( const auto & prop : aInfo ) @@ -125,20 +207,43 @@ bool DocPasswordHelper::IsModifyPasswordCorrect( std::u16string_view aPassword, if ( prop.Name == "algorithm-name" ) prop.Value >>= sAlgorithm; else if ( prop.Name == "salt" ) - prop.Value >>= aSalt; + aSalt = prop.Value; else if ( prop.Name == "iteration-count" ) prop.Value >>= nCount; else if ( prop.Name == "hash" ) - prop.Value >>= aHash; + aHash = prop.Value; } - if ( sAlgorithm == "PBKDF2" && aSalt.hasElements() && nCount > 0 && aHash.hasElements() ) + if ( sAlgorithm == "PBKDF2" ) { - uno::Sequence< sal_Int8 > aNewHash = GeneratePBKDF2Hash( aPassword, aSalt, nCount, aHash.getLength() ); - for ( sal_Int32 nInd = 0; nInd < aNewHash.getLength() && nInd < aHash.getLength() && aNewHash[nInd] == aHash[nInd]; nInd ++ ) + uno::Sequence<sal_Int8> aIntSalt, aIntHash; + aSalt >>= aIntSalt; + aHash >>= aIntHash; + if (aIntSalt.hasElements() && nCount > 0 && aIntHash.hasElements()) { - if ( nInd == aNewHash.getLength() - 1 && nInd == aHash.getLength() - 1 ) - bResult = true; + uno::Sequence<sal_Int8> aNewHash + = GeneratePBKDF2Hash(aPassword, aIntSalt, nCount, aIntHash.getLength()); + for (sal_Int32 nInd = 0; nInd < aNewHash.getLength() && nInd < aIntHash.getLength() + && aNewHash[nInd] == aIntHash[nInd]; + nInd++) + { + if (nInd == aNewHash.getLength() - 1 && nInd == aIntHash.getLength() - 1) + bResult = true; + } + } + } + else if (nCount > 0) + { + OUString sSalt, sHash; + aSalt >>= sSalt; + aHash >>= sHash; + if (!sSalt.isEmpty() && !sHash.isEmpty()) + { + const OUString aNewHash(GetOoxHashAsBase64(OUString(aPassword), sSalt, nCount, + comphelper::Hash::IterCount::APPEND, + sAlgorithm)); + if (!aNewHash.isEmpty()) + bResult = aNewHash == sHash; } } } @@ -148,7 +253,7 @@ bool DocPasswordHelper::IsModifyPasswordCorrect( std::u16string_view aPassword, sal_uInt32 DocPasswordHelper::GetWordHashAsUINT32( - const OUString& aUString ) + std::u16string_view aUString ) { static const sal_uInt16 pInitialCode[] = { 0xE1F0, // 1 @@ -187,7 +292,7 @@ sal_uInt32 DocPasswordHelper::GetWordHashAsUINT32( }; sal_uInt32 nResult = 0; - sal_uInt32 nLen = aUString.getLength(); + size_t nLen = aUString.size(); if ( nLen ) { @@ -197,7 +302,7 @@ sal_uInt32 DocPasswordHelper::GetWordHashAsUINT32( sal_uInt16 nHighResult = pInitialCode[nLen - 1]; sal_uInt16 nLowResult = 0; - for ( sal_uInt32 nInd = 0; nInd < nLen; nInd++ ) + for ( size_t nInd = 0; nInd < nLen; nInd++ ) { // NO Encoding during conversion! // The specification says that the low byte should be used in case it is not NULL @@ -268,6 +373,8 @@ std::vector<unsigned char> DocPasswordHelper::GetOoxHashAsVector( eType = comphelper::HashType::SHA512; else if (rAlgorithmName == u"SHA-256" || rAlgorithmName == u"SHA256") eType = comphelper::HashType::SHA256; + else if (rAlgorithmName == u"SHA-384" || rAlgorithmName == u"SHA384") + eType = comphelper::HashType::SHA384; else if (rAlgorithmName == u"SHA-1" || rAlgorithmName == u"SHA1") // "SHA1" might be in the wild eType = comphelper::HashType::SHA1; else if (rAlgorithmName == u"MD5") @@ -281,13 +388,13 @@ std::vector<unsigned char> DocPasswordHelper::GetOoxHashAsVector( css::uno::Sequence<sal_Int8> DocPasswordHelper::GetOoxHashAsSequence( const OUString& rPassword, - const OUString& rSaltValue, + std::u16string_view rSaltValue, sal_uInt32 nSpinCount, comphelper::Hash::IterCount eIterCount, std::u16string_view rAlgorithmName) { std::vector<unsigned char> aSaltVec; - if (!rSaltValue.isEmpty()) + if (!rSaltValue.empty()) { css::uno::Sequence<sal_Int8> aSaltSeq; comphelper::Base64::decode( aSaltSeq, rSaltValue); @@ -301,7 +408,7 @@ css::uno::Sequence<sal_Int8> DocPasswordHelper::GetOoxHashAsSequence( OUString DocPasswordHelper::GetOoxHashAsBase64( const OUString& rPassword, - const OUString& rSaltValue, + std::u16string_view rSaltValue, sal_uInt32 nSpinCount, comphelper::Hash::IterCount eIterCount, std::u16string_view rAlgorithmName) @@ -320,22 +427,25 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( uno::Sequence< sal_Int8 > aResult( nLength ); rtlRandomPool aRandomPool = rtl_random_createPool (); - rtl_random_getBytes ( aRandomPool, aResult.getArray(), nLength ); + if (rtl_random_getBytes(aRandomPool, aResult.getArray(), nLength) != rtl_Random_E_None) + { + throw uno::RuntimeException("rtl_random_getBytes failed"); + } rtl_random_destroyPool ( aRandomPool ); return aResult; } -/*static*/ uno::Sequence< sal_Int8 > DocPasswordHelper::GenerateStd97Key( const OUString& aPassword, const uno::Sequence< sal_Int8 >& aDocId ) +/*static*/ uno::Sequence< sal_Int8 > DocPasswordHelper::GenerateStd97Key( std::u16string_view aPassword, const uno::Sequence< sal_Int8 >& aDocId ) { uno::Sequence< sal_Int8 > aResultKey; - if ( !aPassword.isEmpty() && aDocId.getLength() == 16 ) + if ( !aPassword.empty() && aDocId.getLength() == 16 ) { sal_uInt16 pPassData[16] = {}; - sal_Int32 nPassLen = std::min< sal_Int32 >( aPassword.getLength(), 15 ); - memcpy( pPassData, aPassword.getStr(), nPassLen * sizeof(pPassData[0]) ); + sal_Int32 nPassLen = std::min< sal_Int32 >( aPassword.size(), 15 ); + memcpy( pPassData, aPassword.data(), nPassLen * sizeof(pPassData[0]) ); aResultKey = GenerateStd97Key( pPassData, aDocId ); } @@ -494,9 +604,8 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( PasswordRequestMode eRequestMode = PasswordRequestMode_PASSWORD_ENTER; while( eResult == DocPasswordVerifierResult::WrongPassword ) { - DocPasswordRequest* pRequest = new DocPasswordRequest( eRequestType, eRequestMode, rDocumentUrl ); - Reference< XInteractionRequest > xRequest( pRequest ); - rxInteractHandler->handle( xRequest ); + rtl::Reference<DocPasswordRequest> pRequest = new DocPasswordRequest( eRequestType, eRequestMode, rDocumentUrl ); + rxInteractHandler->handle( pRequest ); if( pRequest->isPassword() ) { if( !pRequest->getPassword().isEmpty() ) @@ -517,11 +626,10 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( if (eResult == DocPasswordVerifierResult::OK && !aPassword.isEmpty()) { - if (std::find_if(std::cbegin(aEncData), std::cend(aEncData), + if (std::none_of(std::cbegin(aEncData), std::cend(aEncData), [](const css::beans::NamedValue& val) { return val.Name == PACKAGE_ENCRYPTIONDATA_SHA256UTF8; - }) - == std::cend(aEncData)) + })) { // tdf#118639: We need ODF encryption data for autorecovery, where password // will already be unavailable, so generate and append it here @@ -557,7 +665,7 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( if ( !rGpgProperties.hasElements() ) return uno::Sequence< beans::NamedValue >(); - uno::Sequence< beans::NamedValue > aEncryptionData(1); + uno::Sequence< beans::NamedValue > aEncryptionData; std::unique_ptr<GpgME::Context> ctx; GpgME::initializeLibrary(); GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP); @@ -612,19 +720,16 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( SAL_INFO("comphelper.crypto", "Extracted gpg session key of length: " << len); - aEncryptionData[0].Name = PACKAGE_ENCRYPTIONDATA_SHA256UTF8; - aEncryptionData[0].Value <<= aKeyValue; + aEncryptionData = { { PACKAGE_ENCRYPTIONDATA_SHA256UTF8, uno::Any(aKeyValue) } }; break; } } - if ( aEncryptionData[0].Value.hasValue() ) + if ( aEncryptionData.hasElements() ) { - uno::Sequence< beans::NamedValue > aContainer(2); - aContainer[0].Name = "GpgInfos"; - aContainer[0].Value <<= rGpgProperties; - aContainer[1].Name = "EncryptionKey"; - aContainer[1].Value <<= aEncryptionData; + uno::Sequence< beans::NamedValue > aContainer{ + { "GpgInfos", uno::Any(rGpgProperties) }, { "EncryptionKey", uno::Any(aEncryptionData) } + }; return aContainer; } diff --git a/comphelper/source/misc/docpasswordrequest.cxx b/comphelper/source/misc/docpasswordrequest.cxx index 56644d4d6e59..6f644336e1e2 100644 --- a/comphelper/source/misc/docpasswordrequest.cxx +++ b/comphelper/source/misc/docpasswordrequest.cxx @@ -108,7 +108,7 @@ Any SAL_CALL SimplePasswordRequest::getRequest() Sequence< Reference< XInteractionContinuation > > SAL_CALL SimplePasswordRequest::getContinuations() { - return { mxAbort.get(), mxPassword.get() }; + return { mxAbort, mxPassword }; } @@ -170,7 +170,7 @@ Any SAL_CALL DocPasswordRequest::getRequest() Sequence< Reference< XInteractionContinuation > > SAL_CALL DocPasswordRequest::getContinuations() { - return { mxAbort.get(), mxPassword.get() }; + return { mxAbort, mxPassword }; } diff --git a/comphelper/source/misc/documentinfo.cxx b/comphelper/source/misc/documentinfo.cxx index 60901fefeefe..21425524e64e 100644 --- a/comphelper/source/misc/documentinfo.cxx +++ b/comphelper/source/misc/documentinfo.cxx @@ -106,8 +106,7 @@ namespace comphelper { } // 4. try model arguments - NamedValueCollection aModelArgs( _rxDocument->getArgs() ); - sTitle = aModelArgs.getOrDefault( "Title", sTitle ); + sTitle = NamedValueCollection::getOrDefault( _rxDocument->getArgs(), u"Title", sTitle ); if ( !sTitle.isEmpty() ) return sTitle; @@ -166,8 +165,9 @@ namespace comphelper { css::uno::Sequence<css::beans::PropertyValue> aMedDescr = rModel->getArgs(); sal_Int32 nNewLen = aMedDescr.getLength() + 1; aMedDescr.realloc(nNewLen); - aMedDescr[nNewLen-1].Name = "MacroEventRead"; - aMedDescr[nNewLen-1].Value <<= true; + auto pMedDescr = aMedDescr.getArray(); + pMedDescr[nNewLen-1].Name = "MacroEventRead"; + pMedDescr[nNewLen-1].Value <<= true; rModel->attachResource(rModel->getURL(), aMedDescr); } diff --git a/comphelper/source/misc/errcode.cxx b/comphelper/source/misc/errcode.cxx new file mode 100644 index 000000000000..716daab1793e --- /dev/null +++ b/comphelper/source/misc/errcode.cxx @@ -0,0 +1,174 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <comphelper/errcode.hxx> +#include <rtl/ustrbuf.hxx> +#include <o3tl/runtimetooustring.hxx> + +UNLESS_MERGELIBS(COMPHELPER_DLLPUBLIC) OUString ErrCode::toString() const +{ + std::u16string_view pWarningError; + if (IsWarning()) + pWarningError = u"Warning"; + else + pWarningError = u"Error"; + + std::u16string_view pArea; + switch (GetArea()) + { + case ErrCodeArea::Io: + pArea = u"Io"; + break; + case ErrCodeArea::Sfx: + pArea = u"Sfx"; + break; + case ErrCodeArea::Inet: + pArea = u"Inet"; + break; + case ErrCodeArea::Vcl: + pArea = u"Vcl"; + break; + case ErrCodeArea::Svx: + pArea = u"Svx"; + break; + case ErrCodeArea::So: + pArea = u"So"; + break; + case ErrCodeArea::Sbx: + pArea = u"Sbx"; + break; + case ErrCodeArea::Uui: + pArea = u"Uui"; + break; + case ErrCodeArea::Sc: + pArea = u"Sc"; + break; + case ErrCodeArea::Sd: + pArea = u"Sd"; + break; + case ErrCodeArea::Sw: + pArea = u"Sw"; + break; + } + + std::u16string_view pClass; + switch (GetClass()) + { + case ErrCodeClass::NONE: + pClass = u"NONE"; + break; + case ErrCodeClass::Abort: + pClass = u"Abort"; + break; + case ErrCodeClass::General: + pClass = u"General"; + break; + case ErrCodeClass::NotExists: + pClass = u"NotExists"; + break; + case ErrCodeClass::AlreadyExists: + pClass = u"AlreadyExists"; + break; + case ErrCodeClass::Access: + pClass = u"Access"; + break; + case ErrCodeClass::Path: + pClass = u"Path"; + break; + case ErrCodeClass::Locking: + pClass = u"Locking"; + break; + case ErrCodeClass::Parameter: + pClass = u"Parameter"; + break; + case ErrCodeClass::Space: + pClass = u"Space"; + break; + case ErrCodeClass::NotSupported: + pClass = u"NotSupported"; + break; + case ErrCodeClass::Read: + pClass = u"Read"; + break; + case ErrCodeClass::Write: + pClass = u"Write"; + break; + case ErrCodeClass::Unknown: + pClass = u"Unknown"; + break; + case ErrCodeClass::Version: + pClass = u"Version"; + break; + case ErrCodeClass::Format: + pClass = u"Format"; + break; + case ErrCodeClass::Create: + pClass = u"Create"; + break; + case ErrCodeClass::Import: + pClass = u"Import"; + break; + case ErrCodeClass::Export: + pClass = u"Export"; + break; + case ErrCodeClass::So: + pClass = u"So"; + break; + case ErrCodeClass::Sbx: + pClass = u"Sbx"; + break; + case ErrCodeClass::Runtime: + pClass = u"Runtime"; + break; + case ErrCodeClass::Compiler: + pClass = u"Compiler"; + break; + } + return toHexString() + "(" + pWarningError + " Area:" + pArea + " Class:" + pClass + + " Code:" + OUString::number(GetCode()) + ")"; +} + +COMPHELPER_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const ErrCode& err) +{ + os << err.toString(); + return os; +} + +UNLESS_MERGELIBS(COMPHELPER_DLLPUBLIC) OUString ErrCodeMsg::toString() const +{ + OUString s = mnCode.toString(); + if (!maArg1.isEmpty()) + s += " arg1=" + maArg1; + if (!maArg2.isEmpty()) + s += " arg2=" + maArg2; +#ifdef LIBO_ERRMSG_USE_SOURCE_LOCATION + if (!moLoc) + s += OUString::Concat(" func=") + o3tl::runtimeToOUString(moLoc->function_name()) + " src=" + + o3tl::runtimeToOUString(moLoc->file_name()) + ":" + OUString::number(moLoc->line()); +#endif + return s; +} + +COMPHELPER_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const ErrCodeMsg& err) +{ + os << err.toString(); + return os; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/fileurl.cxx b/comphelper/source/misc/fileurl.cxx index 4f361ab4ba7a..2515b28c5b30 100644 --- a/comphelper/source/misc/fileurl.cxx +++ b/comphelper/source/misc/fileurl.cxx @@ -21,7 +21,11 @@ #include <comphelper/fileurl.hxx> #include <rtl/ustring.hxx> +#include <o3tl/string_view.hxx> -bool comphelper::isFileUrl(OUString const& url) { return url.startsWithIgnoreAsciiCase("file:"); } +bool comphelper::isFileUrl(std::u16string_view url) +{ + return o3tl::matchIgnoreAsciiCase(url, "file:"); +} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/graphicmimetype.cxx b/comphelper/source/misc/graphicmimetype.cxx index acee8ff80de7..8ae3dad5619c 100644 --- a/comphelper/source/misc/graphicmimetype.cxx +++ b/comphelper/source/misc/graphicmimetype.cxx @@ -18,6 +18,10 @@ */ #include <comphelper/graphicmimetype.hxx> +#include <comphelper/mediamimetype.hxx> + +#include <map> +#include <set> #include <com/sun/star/beans/PropertyValue.hpp> #include <com/sun/star/beans/XPropertySet.hpp> @@ -27,6 +31,7 @@ #include <com/sun/star/uno/Reference.hxx> #include <comphelper/processfactory.hxx> +#include <comphelper/propertyvalue.hxx> using namespace css; using namespace css::beans; @@ -52,8 +57,8 @@ OUString GraphicMimeTypeHelper::GetMimeTypeForExtension(std::string_view rExt) OUString aMimeType; - tools::Long const nCount = SAL_N_ELEMENTS(aMapper); - for (tools::Long i = 0; (i < nCount) && aMimeType.isEmpty(); ++i) + size_t const nCount = std::size(aMapper); + for (size_t i = 0; (i < nCount) && aMimeType.isEmpty(); ++i) { if (rExt == aMapper[i].pExt) aMimeType = OUString(aMapper[i].pMimeType, strlen(aMapper[i].pMimeType), @@ -81,9 +86,8 @@ GraphicMimeTypeHelper::GetMimeTypeForImageStream(const Reference<XInputStream>& // Create the graphic to retrieve the mimetype from it Reference<XGraphicProvider> xProvider = css::graphic::GraphicProvider::create(comphelper::getProcessComponentContext()); - Sequence<PropertyValue> aMediaProperties(1); - aMediaProperties[0].Name = "InputStream"; - aMediaProperties[0].Value <<= xInputStream; + Sequence<PropertyValue> aMediaProperties{ comphelper::makePropertyValue("InputStream", + xInputStream) }; Reference<XGraphic> xGraphic(xProvider->queryGraphic(aMediaProperties)); return GetMimeTypeForXGraphic(xGraphic); @@ -166,6 +170,70 @@ char const* GraphicMimeTypeHelper::GetExtensionForConvertDataFormat(ConvertDataF } return pExt; } + +static auto GetMediaMimes() -> std::map<OString, OString> const& +{ + static std::map<OString, OString> const mimes = { + { "mp4", "video/mp4" }, + { "ts", "video/MP2T" }, + { "mpeg", "video/mpeg" }, + { "mpg", "video/mpeg" }, + { "mkv", "video/x-matroska" }, + { "webm", "video/webm" }, + { "ogv", "video/ogg" }, + { "mov", "video/quicktime" }, + { "wmv", "video/x-ms-wmv" }, + { "avi", "video/x-msvideo" }, + { "m4a", "audio/mp4" }, + { "aac", "audio/aac" }, + { "mp3", "audio/mpeg" }, // https://bugs.chromium.org/p/chromium/issues/detail?id=227004 + { "ogg", "audio/ogg" }, + { "oga", "audio/ogg" }, + { "opus", "audio/ogg" }, + { "flac", "audio/flac" }, // missing at IANA? + // note there is RFC 2631 but i got the impression that vnd.wave + // requires specifying the codec in the container; also this page + // says "Historic" whatever that means: + // https://www.iana.org/assignments/wave-avi-codec-registry/wave-avi-codec-registry.xhtml + { "wav", "audio/x-wav" }, + }; + return mimes; +} + +auto IsMediaMimeType(::std::string_view const rMimeType) -> bool +{ + return IsMediaMimeType(OStringToOUString(rMimeType, RTL_TEXTENCODING_UTF8)); +} + +auto IsMediaMimeType(OUString const& rMimeType) -> bool +{ + static std::set<OUString> mimes; + if (mimes.empty()) + { + auto const& rMap(GetMediaMimes()); + for (auto const& it : rMap) + { + mimes.insert(OStringToOUString(it.second, RTL_TEXTENCODING_UTF8)); + } + } + return rMimeType == AVMEDIA_MIMETYPE_COMMON || mimes.find(rMimeType) != mimes.end(); +} + +auto GuessMediaMimeType(::std::u16string_view rFileName) -> OUString +{ + if (auto const i = rFileName.rfind('.'); i != ::std::string_view::npos) + { + OString const ext(OUStringToOString(rFileName.substr(i + 1), RTL_TEXTENCODING_UTF8)); + auto const& rMap(GetMediaMimes()); + auto const it(rMap.find(ext)); + if (it != rMap.end()) + { + return OStringToOUString(it->second, RTL_TEXTENCODING_ASCII_US); + } + } + return OUString(); } +} // namespace comphelper + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/hash.cxx b/comphelper/source/misc/hash.cxx index 50fd8cd0f961..25b93ad87e54 100644 --- a/comphelper/source/misc/hash.cxx +++ b/comphelper/source/misc/hash.cxx @@ -18,6 +18,7 @@ #if USE_TLS_NSS #include <nss.h> +#include <nspr.h> #include <sechash.h> #elif USE_TLS_OPENSSL #include <openssl/evp.h> @@ -42,6 +43,8 @@ struct HashImpl return HASH_AlgSHA1; case HashType::SHA256: return HASH_AlgSHA256; + case HashType::SHA384: + return HASH_AlgSHA384; case HashType::SHA512: return HASH_AlgSHA512; } @@ -61,6 +64,8 @@ struct HashImpl return EVP_sha1(); case HashType::SHA256: return EVP_sha256(); + case HashType::SHA384: + return EVP_sha384(); case HashType::SHA512: return EVP_sha512(); } @@ -76,9 +81,15 @@ struct HashImpl { #if USE_TLS_NSS - auto const e = NSS_NoDB_Init(nullptr); - if (e != SECSuccess) { - throw css::uno::RuntimeException("NSS_NoDB_Init failed with " + OUString::number(e)); + if (!NSS_IsInitialized()) + { + auto const e = NSS_NoDB_Init(nullptr); + if (e != SECSuccess) + { + PRErrorCode error = PR_GetError(); + const char* errorText = PR_ErrorToName(error); + throw css::uno::RuntimeException("NSS_NoDB_Init failed with " + OUString(errorText, strlen(errorText), RTL_TEXTENCODING_UTF8) + " (" + OUString::number(static_cast<int>(error)) + ")"); + } } mpContext = HASH_Create(getNSSType()); HASH_Begin(mpContext); @@ -144,6 +155,8 @@ size_t Hash::getLength() const return SHA1_HASH_LENGTH; case HashType::SHA256: return SHA256_HASH_LENGTH; + case HashType::SHA384: + return SHA384_HASH_LENGTH; case HashType::SHA512: return SHA512_HASH_LENGTH; } diff --git a/comphelper/source/misc/instancelocker.cxx b/comphelper/source/misc/instancelocker.cxx index b942d7ec8329..465cc5185834 100644 --- a/comphelper/source/misc/instancelocker.cxx +++ b/comphelper/source/misc/instancelocker.cxx @@ -19,7 +19,6 @@ #include <cppuhelper/supportsservice.hxx> -#include <comphelper/interfacecontainer2.hxx> #include <com/sun/star/util/CloseVetoException.hpp> #include <com/sun/star/util/XCloseBroadcaster.hpp> @@ -31,6 +30,7 @@ #include <com/sun/star/frame/DoubleInitializationException.hpp> #include <com/sun/star/embed/Actions.hpp> #include <com/sun/star/embed/XActionsApproval.hpp> +#include <utility> #include "instancelocker.hxx" @@ -66,19 +66,19 @@ OInstanceLocker::~OInstanceLocker() void SAL_CALL OInstanceLocker::dispose() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) ); - if ( m_pListenersContainer ) - m_pListenersContainer->disposeAndClear( aSource ); - + m_aListenersContainer.disposeAndClear( aGuard, aSource ); if ( m_xLockListener.is() ) { - m_xLockListener->Dispose(); - m_xLockListener.clear(); + auto tmp = std::move(m_xLockListener); + aGuard.unlock(); + tmp->Dispose(); + aGuard.lock(); } m_bDisposed = true; @@ -87,29 +87,25 @@ void SAL_CALL OInstanceLocker::dispose() void SAL_CALL OInstanceLocker::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); // TODO - if ( !m_pListenersContainer ) - m_pListenersContainer.reset( new ::comphelper::OInterfaceContainerHelper2( m_aMutex ) ); - - m_pListenersContainer->addInterface( xListener ); + m_aListenersContainer.addInterface( aGuard, xListener ); } void SAL_CALL OInstanceLocker::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) { - ::osl::MutexGuard aGuard( m_aMutex ); - if ( m_pListenersContainer ) - m_pListenersContainer->removeInterface( xListener ); + std::unique_lock aGuard( m_aMutex ); + m_aListenersContainer.removeInterface( aGuard, xListener ); } // XInitialization void SAL_CALL OInstanceLocker::initialize( const uno::Sequence< uno::Any >& aArguments ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( m_bInitialized ) throw frame::DoubleInitializationException(); @@ -166,6 +162,7 @@ void SAL_CALL OInstanceLocker::initialize( const uno::Sequence< uno::Any >& aArg } catch( uno::Exception& ) { + aGuard.unlock(); dispose(); throw; } @@ -192,13 +189,13 @@ uno::Sequence< OUString > SAL_CALL OInstanceLocker::getSupportedServiceNames() // OLockListener -OLockListener::OLockListener( const uno::WeakReference< lang::XComponent >& xWrapper, - const uno::Reference< uno::XInterface >& xInstance, +OLockListener::OLockListener( uno::WeakReference< lang::XComponent > xWrapper, + uno::Reference< uno::XInterface > xInstance, sal_Int32 nMode, - const uno::Reference< embed::XActionsApproval >& rApproval ) -: m_xInstance( xInstance ) -, m_xApproval( rApproval ) -, m_xWrapper( xWrapper ) + uno::Reference< embed::XActionsApproval > xApproval ) +: m_xInstance(std::move( xInstance )) +, m_xApproval(std::move( xApproval )) +, m_xWrapper(std::move( xWrapper )) , m_bDisposed( false ) , m_bInitialized( false ) , m_nMode( nMode ) @@ -213,20 +210,26 @@ OLockListener::~OLockListener() void OLockListener::Dispose() { - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( m_bDisposed ) return; - if ( m_nMode & embed::Actions::PREVENT_CLOSE ) + auto xInstance = std::move(m_xInstance); + auto xApproval = std::move(m_xApproval); + auto nMode = m_nMode; + m_bDisposed = true; + aGuard.unlock(); + + if ( nMode & embed::Actions::PREVENT_CLOSE ) { try { - uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xInstance, uno::UNO_QUERY ); + uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( xInstance, uno::UNO_QUERY ); if ( xCloseBroadcaster.is() ) xCloseBroadcaster->removeCloseListener( static_cast< util::XCloseListener* >( this ) ); - uno::Reference< util::XCloseable > xCloseable( m_xInstance, uno::UNO_QUERY ); + uno::Reference< util::XCloseable > xCloseable( xInstance, uno::UNO_QUERY ); if ( xCloseable.is() ) xCloseable->close( true ); } @@ -234,26 +237,23 @@ void OLockListener::Dispose() {} } - if ( m_nMode & embed::Actions::PREVENT_TERMINATION ) + if ( nMode & embed::Actions::PREVENT_TERMINATION ) { try { - uno::Reference< frame::XDesktop > xDesktop( m_xInstance, uno::UNO_QUERY_THROW ); + uno::Reference< frame::XDesktop > xDesktop( xInstance, uno::UNO_QUERY_THROW ); xDesktop->removeTerminateListener( static_cast< frame::XTerminateListener* >( this ) ); } catch( uno::Exception& ) {} } - - m_xInstance.clear(); - m_bDisposed = true; } // XEventListener void SAL_CALL OLockListener::disposing( const lang::EventObject& aEvent ) { - osl::ClearableMutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); // object is disposed if ( aEvent.Source != m_xInstance ) @@ -264,7 +264,7 @@ void SAL_CALL OLockListener::disposing( const lang::EventObject& aEvent ) // dispose the wrapper; uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY ); - aGuard.clear(); + aGuard.unlock(); if ( xComponent.is() ) { try { xComponent->dispose(); } @@ -278,7 +278,7 @@ void SAL_CALL OLockListener::disposing( const lang::EventObject& aEvent ) void SAL_CALL OLockListener::queryClosing( const lang::EventObject& aEvent, sal_Bool ) { // GetsOwnership parameter is always ignored, the user of the service must close the object always - osl::ClearableMutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( !(!m_bDisposed && aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_CLOSE )) ) return; @@ -287,7 +287,7 @@ void SAL_CALL OLockListener::queryClosing( const lang::EventObject& aEvent, sal_ uno::Reference< embed::XActionsApproval > xApprove = m_xApproval; // unlock the mutex here - aGuard.clear(); + aGuard.unlock(); if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_CLOSE ) ) throw util::CloseVetoException(); @@ -306,7 +306,7 @@ void SAL_CALL OLockListener::queryClosing( const lang::EventObject& aEvent, sal_ void SAL_CALL OLockListener::notifyClosing( const lang::EventObject& aEvent ) { - osl::ClearableMutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); // object is closed, no reason to listen if ( aEvent.Source != m_xInstance ) @@ -322,7 +322,7 @@ void SAL_CALL OLockListener::notifyClosing( const lang::EventObject& aEvent ) { // dispose the wrapper; uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY ); - aGuard.clear(); + aGuard.unlock(); if ( xComponent.is() ) { try { xComponent->dispose(); } @@ -336,7 +336,7 @@ void SAL_CALL OLockListener::notifyClosing( const lang::EventObject& aEvent ) void SAL_CALL OLockListener::queryTermination( const lang::EventObject& aEvent ) { - osl::ClearableMutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( !(aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_TERMINATION )) ) return; @@ -345,7 +345,7 @@ void SAL_CALL OLockListener::queryTermination( const lang::EventObject& aEvent ) uno::Reference< embed::XActionsApproval > xApprove = m_xApproval; // unlock the mutex here - aGuard.clear(); + aGuard.unlock(); if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_TERMINATION ) ) throw frame::TerminationVetoException(); @@ -364,7 +364,7 @@ void SAL_CALL OLockListener::queryTermination( const lang::EventObject& aEvent ) void SAL_CALL OLockListener::notifyTermination( const lang::EventObject& aEvent ) { - osl::ClearableMutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); // object is terminated, no reason to listen if ( aEvent.Source != m_xInstance ) @@ -382,7 +382,7 @@ void SAL_CALL OLockListener::notifyTermination( const lang::EventObject& aEvent { // dispose the wrapper; uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY ); - aGuard.clear(); + aGuard.unlock(); if ( xComponent.is() ) { try { xComponent->dispose(); } @@ -399,7 +399,7 @@ void SAL_CALL OLockListener::notifyTermination( const lang::EventObject& aEvent void OLockListener::Init() { - osl::ClearableMutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( m_bDisposed || m_bInitialized ) return; @@ -422,7 +422,7 @@ void OLockListener::Init() { // dispose the wrapper; uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY ); - aGuard.clear(); + aGuard.unlock(); if ( xComponent.is() ) { try { xComponent->dispose(); } diff --git a/comphelper/source/misc/instancelocker.hxx b/comphelper/source/misc/instancelocker.hxx index 02180e511c0f..6a050c7f437c 100644 --- a/comphelper/source/misc/instancelocker.hxx +++ b/comphelper/source/misc/instancelocker.hxx @@ -24,14 +24,13 @@ #include <com/sun/star/frame/XTerminateListener.hpp> #include <com/sun/star/lang/XInitialization.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> +#include <comphelper/interfacecontainer4.hxx> #include <cppuhelper/weakref.hxx> -#include <osl/mutex.hxx> #include <cppuhelper/implbase.hxx> #include <rtl/ref.hxx> -#include <memory> +#include <mutex> namespace com::sun::star::embed { class XActionsApproval; } -namespace comphelper { class OInterfaceContainerHelper2; } class OLockListener; @@ -42,11 +41,11 @@ class OInstanceLocker : public ::cppu::WeakImplHelper< css::lang::XComponent, css::lang::XInitialization, css::lang::XServiceInfo > { - ::osl::Mutex m_aMutex; + std::mutex m_aMutex; rtl::Reference< OLockListener > m_xLockListener; - std::unique_ptr<::comphelper::OInterfaceContainerHelper2> m_pListenersContainer; // list of listeners + comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aListenersContainer; // list of listeners bool m_bDisposed; bool m_bInitialized; @@ -74,7 +73,7 @@ public: class OLockListener : public ::cppu::WeakImplHelper< css::util::XCloseListener, css::frame::XTerminateListener > { - ::osl::Mutex m_aMutex; + std::mutex m_aMutex; css::uno::Reference< css::uno::XInterface > m_xInstance; css::uno::Reference< css::embed::XActionsApproval > m_xApproval; @@ -86,10 +85,10 @@ class OLockListener : public ::cppu::WeakImplHelper< css::util::XCloseListener, sal_Int32 m_nMode; public: - OLockListener( const css::uno::WeakReference< css::lang::XComponent >& xWrapper, - const css::uno::Reference< css::uno::XInterface >& xInstance, + OLockListener( css::uno::WeakReference< css::lang::XComponent > xWrapper, + css::uno::Reference< css::uno::XInterface > xInstance, sal_Int32 nMode, - const css::uno::Reference< css::embed::XActionsApproval >& rApproval ); + css::uno::Reference< css::embed::XActionsApproval > xApproval ); virtual ~OLockListener() override; diff --git a/comphelper/source/misc/interaction.cxx b/comphelper/source/misc/interaction.cxx index 5a24075504b7..9e7b1706d111 100644 --- a/comphelper/source/misc/interaction.cxx +++ b/comphelper/source/misc/interaction.cxx @@ -20,6 +20,7 @@ #include <comphelper/interaction.hxx> #include <comphelper/sequence.hxx> +#include <utility> #include <osl/diagnose.h> @@ -30,15 +31,15 @@ namespace comphelper using namespace ::com::sun::star::uno; using namespace ::com::sun::star::task; - OInteractionRequest::OInteractionRequest(const Any& _rRequestDescription) - :m_aRequest(_rRequestDescription) + OInteractionRequest::OInteractionRequest(Any _aRequestDescription) + :m_aRequest(std::move(_aRequestDescription)) { } - OInteractionRequest::OInteractionRequest(const Any& rRequestDescription, - std::vector<Reference<XInteractionContinuation>> const& rContinuations) - : m_aRequest(rRequestDescription) - , m_aContinuations(rContinuations) + OInteractionRequest::OInteractionRequest(Any aRequestDescription, + std::vector<Reference<XInteractionContinuation>>&& rContinuations) + : m_aRequest(std::move(aRequestDescription)) + , m_aContinuations(std::move(rContinuations)) { } diff --git a/comphelper/source/misc/listenernotification.cxx b/comphelper/source/misc/listenernotification.cxx deleted file mode 100644 index 4bb4e7f619a0..000000000000 --- a/comphelper/source/misc/listenernotification.cxx +++ /dev/null @@ -1,114 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include <comphelper/listenernotification.hxx> - -#include <com/sun/star/lang/XEventListener.hpp> -#include <com/sun/star/lang/DisposedException.hpp> -#include <osl/diagnose.h> - - -namespace comphelper -{ - - - using namespace ::com::sun::star::uno; - using namespace ::com::sun::star::lang; - - OListenerContainer::OListenerContainer( ::osl::Mutex& _rMutex ) - :m_aListeners( _rMutex ) - { - } - - OListenerContainer::~OListenerContainer() {} - - - void OListenerContainer::impl_addListener( const Reference< XEventListener >& _rxListener ) - { - OSL_PRECOND( _rxListener.is(), "OListenerContainer::impl_addListener: a NULL listener?!" ); - if ( _rxListener.is() ) - m_aListeners.addInterface( _rxListener ); - } - - - void OListenerContainer::impl_removeListener( const Reference< XEventListener >& _rxListener ) - { -#if OSL_DEBUG_LEVEL > 0 - ::comphelper::OInterfaceIteratorHelper2 aIter( m_aListeners ); - bool bFound = false; - while ( aIter.hasMoreElements() && !bFound ) - { - bFound = ( Reference< XInterface >( aIter.next() ) == _rxListener ); - } - OSL_ENSURE( bFound, "OListenerContainer::impl_removeListener: sure your listener handling is correct? The given listener is not registered!" ); -#endif - m_aListeners.removeInterface( _rxListener ); - } - - - void OListenerContainer::disposing( const EventObject& _rEventSource ) - { - m_aListeners.disposeAndClear( _rEventSource ); - } - - - void OListenerContainer::clear() - { - m_aListeners.clear(); - } - - - bool OListenerContainer::impl_notify( const EventObject& _rEvent ) - { - ::comphelper::OInterfaceIteratorHelper2 aIter( m_aListeners ); - bool bCancelled = false; - while ( aIter.hasMoreElements() && !bCancelled ) - { - Reference< XEventListener > xListener( static_cast< XEventListener* >( aIter.next() ) ); - if ( !xListener.is() ) - continue; - - try - { - bCancelled = !implNotify( xListener, _rEvent ); - } - catch( const DisposedException& e ) - { - // DisposedExceptions from the listener might indicate a - // broken connection to a different environment. - - OSL_ENSURE( e.Context.is(), "OListenerContainer::impl_notify: caught dispose exception with empty Context field" ); - - // If the exception stems from the listener then remove it - // from the list of listeners. If the Context field of the - // exception is empty this is interpreted to indicate the - // listener as well. - if ( e.Context == xListener || !e.Context.is() ) - aIter.remove(); - } - } - - return !bCancelled; - } - - -} // namespace comphelper - - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/logging.cxx b/comphelper/source/misc/logging.cxx index 405a4acaeb68..a7785d46a747 100644 --- a/comphelper/source/misc/logging.cxx +++ b/comphelper/source/misc/logging.cxx @@ -22,6 +22,7 @@ #include <com/sun/star/logging/LoggerPool.hpp> +#include <comphelper/diagnose_ex.hxx> #include <osl/diagnose.h> @@ -37,7 +38,6 @@ namespace comphelper class EventLogger_Impl { private: - Reference< XComponentContext > m_aContext; Reference< XLogger > m_xLogger; public: @@ -47,23 +47,32 @@ namespace comphelper const Reference< XLogger >& getLogger() const { return m_xLogger; } }; - EventLogger_Impl::EventLogger_Impl( const Reference< XComponentContext >& _rxContext, const OUString& _rLoggerName ) - :m_aContext( _rxContext ) + namespace { - try + Reference<XLogger> createLogger(const Reference<XComponentContext>& rxContext, const OUString& rLoggerName) { - Reference< XLoggerPool > xPool( LoggerPool::get( m_aContext ) ); - if ( !_rLoggerName.isEmpty() ) - m_xLogger = xPool->getNamedLogger( _rLoggerName ); - else - m_xLogger = xPool->getDefaultLogger(); - } - catch( const Exception& ) - { - OSL_FAIL( "EventLogger_Impl::impl_createLogger_nothrow: caught an exception!" ); + try + { + Reference<XLoggerPool> xPool(LoggerPool::get(rxContext)); + if (!rLoggerName.isEmpty()) + return xPool->getNamedLogger(rLoggerName); + else + return xPool->getDefaultLogger(); + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION( + "comphelper", "EventLogger_Impl::impl_createLogger_nothrow: caught an exception!" ); + } + return Reference<XLogger>(); } } + EventLogger_Impl::EventLogger_Impl(const Reference< XComponentContext >& _rxContext, const OUString& rLoggerName) + : m_xLogger(createLogger(_rxContext, rLoggerName)) + { + } + EventLogger::EventLogger( const Reference< XComponentContext >& _rxContext, const char* _pAsciiLoggerName ) :m_pImpl( std::make_shared<EventLogger_Impl>( _rxContext, OUString::createFromAscii( _pAsciiLoggerName ) ) ) { @@ -80,7 +89,7 @@ namespace comphelper } catch( const Exception& ) { - OSL_FAIL( "EventLogger::isLoggable: caught an exception!" ); + TOOLS_WARN_EXCEPTION( "comphelper", "EventLogger::isLoggable: caught an exception!" ); } return false; @@ -94,7 +103,7 @@ namespace comphelper namespace { - void lcl_replaceParameter( OUString& _inout_Message, const char* _rPlaceHolder, const OUString& _rReplacement ) + void lcl_replaceParameter( OUString& _inout_Message, const char* _rPlaceHolder, std::u16string_view _rReplacement ) { sal_Int32 nPlaceholderPosition = _inout_Message.indexOfAsciiL( _rPlaceHolder, strlen(_rPlaceHolder) ); OSL_ENSURE( nPlaceholderPosition >= 0, "lcl_replaceParameter: placeholder not found!" ); @@ -151,7 +160,7 @@ namespace comphelper } catch( const Exception& ) { - OSL_FAIL( "EventLogger::impl_log: caught an exception!" ); + TOOLS_WARN_EXCEPTION( "comphelper", "EventLogger::impl_log: caught an exception!" ); } } } // namespace comphelper diff --git a/comphelper/source/misc/lok.cxx b/comphelper/source/misc/lok.cxx index 82e5c7aed4f9..c042b0c626e5 100644 --- a/comphelper/source/misc/lok.cxx +++ b/comphelper/source/misc/lok.cxx @@ -8,6 +8,7 @@ */ #include <comphelper/lok.hxx> +#include <osl/process.h> #include <i18nlangtag/languagetag.hxx> #include <sal/log.hxx> @@ -18,6 +19,8 @@ namespace comphelper::LibreOfficeKit static bool g_bActive(false); +static bool g_bForkedChild(false); + static bool g_bPartInInvalidation(false); static bool g_bTiledPainting(false); @@ -73,7 +76,7 @@ public: { if (maLocaleLanguageTag != rLocaleLanguageTag) { - SAL_INFO("comphelper.lok", "Setting locale from " << maLanguageTag.getBcp47() << " to " << rLocaleLanguageTag.getBcp47()); + SAL_INFO("comphelper.lok", "Setting locale from " << maLocaleLanguageTag.getBcp47() << " to " << rLocaleLanguageTag.getBcp47()); maLocaleLanguageTag = rLocaleLanguageTag; } } @@ -97,6 +100,16 @@ bool isActive() return g_bActive; } +void setForkedChild(bool bIsChild) +{ + g_bForkedChild = bIsChild; +} + +bool isForkedChild() +{ + return g_bForkedChild; +} + void setPartInInvalidation(bool bPartInInvalidation) { g_bPartInInvalidation = bPartInInvalidation; @@ -181,6 +194,8 @@ void setCompatFlag(Compat flag) { g_eCompatFlags = static_cast<Compat>(g_eCompat bool isCompatFlagSet(Compat flag) { return (g_eCompatFlags & flag) == flag; } +void resetCompatFlag() { g_eCompatFlags = Compat::none; } + void setLocale(const LanguageTag& rLanguageTag) { g_aLanguageAndLocale.setLocale(rLanguageTag); @@ -210,14 +225,12 @@ bool isAllowlistedLanguage(const OUString& lang) if (!isActive()) return true; -#ifdef ANDROID +#if defined ANDROID || defined IOS (void) lang; return true; #else - static bool bInitialized = false; - static std::vector<OUString> aAllowlist; - if (!bInitialized) - { + static const std::vector<OUString> aAllowlist = [] { + std::vector<OUString> aList; // coverity[tainted_data] - we trust the contents of this variable const char* pAllowlist = getenv("LOK_ALLOWLIST_LANGUAGES"); if (pAllowlist) @@ -231,16 +244,16 @@ bool isAllowlistedLanguage(const OUString& lang) continue; std::cerr << s << " "; - aAllowlist.emplace_back(OStringToOUString(s.c_str(), RTL_TEXTENCODING_UTF8)); + aList.emplace_back(OStringToOUString(s, RTL_TEXTENCODING_UTF8)); } std::cerr << std::endl; } - if (aAllowlist.empty()) + if (aList.empty()) std::cerr << "No language allowlisted, turning off the language support." << std::endl; - bInitialized = true; - } + return aList; + }(); if (aAllowlist.empty()) return false; @@ -257,31 +270,49 @@ bool isAllowlistedLanguage(const OUString& lang) #endif } -static void (*pStatusIndicatorCallback)(void *data, statusIndicatorCallbackType type, int percent)(nullptr); +void setTimezone(bool isSet, const OUString& rTimezone) +{ + if (isSet) + { + // Set the given timezone, even if empty. + osl_setEnvironment(OUString("TZ").pData, rTimezone.pData); + } + else + { + // Unset and empty aren't the same. + // When unset, it means default to the system configured timezone. + osl_clearEnvironment(OUString("TZ").pData); + } + + // Update the timezone data. + ::tzset(); +} + +static void (*pStatusIndicatorCallback)(void *data, statusIndicatorCallbackType type, int percent, const char* pText)(nullptr); static void *pStatusIndicatorCallbackData(nullptr); -void setStatusIndicatorCallback(void (*callback)(void *data, statusIndicatorCallbackType type, int percent), void *data) +void setStatusIndicatorCallback(void (*callback)(void *data, statusIndicatorCallbackType type, int percent, const char* pText), void *data) { pStatusIndicatorCallback = callback; pStatusIndicatorCallbackData = data; } -void statusIndicatorStart() +void statusIndicatorStart(const OUString& sText) { if (pStatusIndicatorCallback) - pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::Start, 0); + pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::Start, 0, sText.toUtf8().getStr()); } void statusIndicatorSetValue(int percent) { if (pStatusIndicatorCallback) - pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::SetValue, percent); + pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::SetValue, percent, nullptr); } void statusIndicatorFinish() { if (pStatusIndicatorCallback) - pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::Finish, 0); + pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::Finish, 0, nullptr); } } // namespace diff --git a/comphelper/source/misc/mimeconfighelper.cxx b/comphelper/source/misc/mimeconfighelper.cxx index 73adf6918baf..30881876b925 100644 --- a/comphelper/source/misc/mimeconfighelper.cxx +++ b/comphelper/source/misc/mimeconfighelper.cxx @@ -33,17 +33,18 @@ #include <comphelper/documentconstants.hxx> #include <comphelper/propertysequence.hxx> #include <rtl/ustrbuf.hxx> +#include <utility> using namespace ::com::sun::star; using namespace comphelper; -MimeConfigurationHelper::MimeConfigurationHelper( const uno::Reference< uno::XComponentContext >& rxContext ) -: m_xContext( rxContext ) +MimeConfigurationHelper::MimeConfigurationHelper( uno::Reference< uno::XComponentContext > xContext ) +: m_xContext(std::move( xContext )) { if ( !m_xContext.is() ) - throw uno::RuntimeException(); + throw uno::RuntimeException("MimeConfigurationHelper:: empty component context"); } @@ -60,7 +61,7 @@ OUString MimeConfigurationHelper::GetStringClassIDRepresentation( const uno::Seq sal_Int32 nDigit1 = static_cast<sal_Int32>( static_cast<sal_uInt8>(aClassID[nInd]) / 16 ); sal_Int32 nDigit2 = static_cast<sal_uInt8>(aClassID[nInd]) % 16; - aResult.append(OUString::number( nDigit1, 16 )).append(OUString::number( nDigit2, 16 )); + aResult.append( OUString::number(nDigit1, 16) + OUString::number( nDigit2, 16 ) ); } } @@ -81,17 +82,18 @@ static sal_uInt8 GetDigit_Impl( char aChar ) } -uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassIDRepresentation( const OUString& aClassID ) +uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassIDRepresentation( std::u16string_view aClassID ) { - sal_Int32 nLength = aClassID.getLength(); + size_t nLength = aClassID.size(); if ( nLength == 36 ) { OString aCharClassID = OUStringToOString( aClassID, RTL_TEXTENCODING_ASCII_US ); uno::Sequence< sal_Int8 > aResult( 16 ); + auto pResult = aResult.getArray(); - sal_Int32 nStrPointer = 0; + size_t nStrPointer = 0; sal_Int32 nSeqInd = 0; - while( nSeqInd < 16 && nStrPointer + 1 < nLength ) + while( nSeqInd < 16 && nStrPointer + 1U < nLength ) { sal_uInt8 nDigit1 = GetDigit_Impl( aCharClassID[nStrPointer++] ); sal_uInt8 nDigit2 = GetDigit_Impl( aCharClassID[nStrPointer++] ); @@ -99,7 +101,7 @@ uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassIDRepresentat if ( nDigit1 > 15 || nDigit2 > 15 ) break; - aResult[nSeqInd++] = static_cast<sal_Int8>( nDigit1 * 16 + nDigit2 ); + pResult[nSeqInd++] = static_cast<sal_Int8>( nDigit1 * 16 + nDigit2 ); if ( nStrPointer < nLength && aCharClassID[nStrPointer] == '-' ) nStrPointer++; @@ -113,10 +115,8 @@ uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassIDRepresentat } -uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetConfigurationByPath( const OUString& aPath ) +uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetConfigurationByPathImpl( const OUString& aPath ) { - osl::MutexGuard aGuard( m_aMutex ); - uno::Reference< container::XNameAccess > xConfig; try @@ -142,10 +142,10 @@ uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetConfigurati uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetObjConfiguration() { - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( !m_xObjectConfig.is() ) - m_xObjectConfig = GetConfigurationByPath( + m_xObjectConfig = GetConfigurationByPathImpl( "/org.openoffice.Office.Embedding/Objects" ); return m_xObjectConfig; @@ -154,10 +154,10 @@ uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetObjConfigur uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetVerbsConfiguration() { - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( !m_xVerbsConfig.is() ) - m_xVerbsConfig = GetConfigurationByPath( + m_xVerbsConfig = GetConfigurationByPathImpl( "/org.openoffice.Office.Embedding/Verbs"); return m_xVerbsConfig; @@ -166,10 +166,10 @@ uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetVerbsConfig uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetMediaTypeConfiguration() { - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( !m_xMediaTypeConfig.is() ) - m_xMediaTypeConfig = GetConfigurationByPath( + m_xMediaTypeConfig = GetConfigurationByPathImpl( "/org.openoffice.Office.Embedding/MimeTypeClassIDRelations"); return m_xMediaTypeConfig; @@ -178,7 +178,7 @@ uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetMediaTypeCo uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetFilterFactory() { - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( !m_xFilterFactory.is() ) m_xFilterFactory.set( @@ -203,7 +203,7 @@ OUString MimeConfigurationHelper::GetDocServiceNameFromFilter( const OUString& a uno::Sequence< beans::PropertyValue > aFilterData; if ( aFilterAnyData >>= aFilterData ) { - for ( const auto & prop : std::as_const(aFilterData) ) + for (const auto& prop : aFilterData) if ( prop.Name == "DocumentService" ) prop.Value >>= aDocServiceName; } @@ -234,7 +234,7 @@ OUString MimeConfigurationHelper::GetDocServiceNameFromMediaType( const OUString uno::Sequence< beans::PropertyValue > aType; if ( xEnum->nextElement() >>= aType ) { - for ( const auto & prop : std::as_const(aType) ) + for (const auto& prop : aType) { OUString aFilterName; if ( prop.Name == "PreferredFilter" @@ -268,10 +268,14 @@ bool MimeConfigurationHelper::GetVerbByShortcut( const OUString& aVerbShortcut, if ( xVerbsConfig.is() && ( xVerbsConfig->getByName( aVerbShortcut ) >>= xVerbsProps ) && xVerbsProps.is() ) { embed::VerbDescriptor aTempDescr; - if ( ( xVerbsProps->getByName("VerbID") >>= aTempDescr.VerbID ) - && ( xVerbsProps->getByName("VerbUIName") >>= aTempDescr.VerbName ) - && ( xVerbsProps->getByName("VerbFlags") >>= aTempDescr.VerbFlags ) - && ( xVerbsProps->getByName("VerbAttributes") >>= aTempDescr.VerbAttributes ) ) + static constexpr OUStringLiteral sVerbID = u"VerbID"; + static constexpr OUStringLiteral sVerbUIName = u"VerbUIName"; + static constexpr OUStringLiteral sVerbFlags = u"VerbFlags"; + static constexpr OUStringLiteral sVerbAttributes = u"VerbAttributes"; + if ( ( xVerbsProps->getByName(sVerbID) >>= aTempDescr.VerbID ) + && ( xVerbsProps->getByName(sVerbUIName) >>= aTempDescr.VerbName ) + && ( xVerbsProps->getByName(sVerbFlags) >>= aTempDescr.VerbFlags ) + && ( xVerbsProps->getByName(sVerbAttributes) >>= aTempDescr.VerbAttributes ) ) { aDescriptor = aTempDescr; bResult = true; @@ -296,30 +300,32 @@ uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjPropsFromConfi { try { - uno::Sequence< OUString > aObjPropNames = xObjectProps->getElementNames(); + const uno::Sequence< OUString > aObjPropNames = xObjectProps->getElementNames(); aResult.realloc( aObjPropNames.getLength() + 1 ); - aResult[0].Name = "ClassID"; - aResult[0].Value <<= aClassID; + auto pResult = aResult.getArray(); + pResult[0].Name = "ClassID"; + pResult[0].Value <<= aClassID; for ( sal_Int32 nInd = 0; nInd < aObjPropNames.getLength(); nInd++ ) { - aResult[nInd + 1].Name = aObjPropNames[nInd]; + pResult[nInd + 1].Name = aObjPropNames[nInd]; if ( aObjPropNames[nInd] == "ObjectVerbs" ) { uno::Sequence< OUString > aVerbShortcuts; if ( !(xObjectProps->getByName( aObjPropNames[nInd] ) >>= aVerbShortcuts) ) - throw uno::RuntimeException(); + throw uno::RuntimeException("Failed to get verb shortcuts from object properties"); uno::Sequence< embed::VerbDescriptor > aVerbDescriptors( aVerbShortcuts.getLength() ); + auto aVerbDescriptorsRange = asNonConstRange(aVerbDescriptors); for ( sal_Int32 nVerbI = 0; nVerbI < aVerbShortcuts.getLength(); nVerbI++ ) - if ( !GetVerbByShortcut( aVerbShortcuts[nVerbI], aVerbDescriptors[nVerbI] ) ) - throw uno::RuntimeException(); + if ( !GetVerbByShortcut( aVerbShortcuts[nVerbI], aVerbDescriptorsRange[nVerbI] ) ) + throw uno::RuntimeException("Failed to get verb descriptor by shortcut"); - aResult[nInd+1].Value <<= aVerbDescriptors; + pResult[nInd+1].Value <<= aVerbDescriptors; } else - aResult[nInd+1].Value = xObjectProps->getByName( aObjPropNames[nInd] ); + pResult[nInd+1].Value = xObjectProps->getByName( aObjPropNames[nInd] ); } } catch( uno::Exception& ) @@ -359,11 +365,9 @@ uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByStri uno::Sequence< sal_Int8 > aClassID = GetSequenceClassIDRepresentation( aStringClassID ); if ( ClassIDsEqual( aClassID, GetSequenceClassID( SO3_DUMMY_CLASSID ) ) ) { - aObjProps.realloc(2); - aObjProps[0].Name = "ObjectFactory"; - aObjProps[0].Value <<= OUString( "com.sun.star.embed.OOoSpecialEmbeddedObjectFactory" ); - aObjProps[1].Name = "ClassID"; - aObjProps[1].Value <<= aClassID; + aObjProps = { { "ObjectFactory", + uno::Any(OUString("com.sun.star.embed.OOoSpecialEmbeddedObjectFactory")) }, + { "ClassID", uno::Any(aClassID) } }; return aObjProps; } @@ -392,11 +396,9 @@ uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByClas uno::Sequence< beans::NamedValue > aObjProps; if ( ClassIDsEqual( aClassID, GetSequenceClassID( SO3_DUMMY_CLASSID ) ) ) { - aObjProps.realloc(2); - aObjProps[0].Name = "ObjectFactory"; - aObjProps[0].Value <<= OUString( "com.sun.star.embed.OOoSpecialEmbeddedObjectFactory" ); - aObjProps[1].Name = "ClassID"; - aObjProps[1].Value <<= aClassID; + aObjProps = { { "ObjectFactory", + uno::Any(OUString("com.sun.star.embed.OOoSpecialEmbeddedObjectFactory")) }, + { "ClassID", uno::Any(aClassID) } }; } OUString aStringClassID = GetStringClassIDRepresentation( aClassID ); @@ -563,7 +565,7 @@ OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName( { OUString aFilterName; - for ( const auto & prop : std::as_const(aMediaDescr) ) + for (const auto& prop : aMediaDescr) if ( prop.Name == "FilterName" ) prop.Value >>= aFilterName; @@ -579,10 +581,10 @@ OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName( uno::Sequence< beans::PropertyValue > aTempMD( aMediaDescr ); // get TypeName - OUString aTypeName = xTypeDetection->queryTypeByDescriptor( aTempMD, true ); + OUString aTypeName = xTypeDetection->queryTypeByDescriptor(aTempMD, /*bAllowDeepDetection*/true); // get FilterName - for ( const auto & prop : std::as_const(aTempMD) ) + for (const auto& prop : aTempMD) if ( prop.Name == "FilterName" ) prop.Value >>= aFilterName; @@ -590,8 +592,9 @@ OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName( { sal_Int32 nOldLen = aMediaDescr.getLength(); aMediaDescr.realloc( nOldLen + 1 ); - aMediaDescr[nOldLen].Name = "FilterName"; - aMediaDescr[ nOldLen ].Value <<= aFilterName; + auto pMediaDescr = aMediaDescr.getArray(); + pMediaDescr[nOldLen].Name = "FilterName"; + pMediaDescr[ nOldLen ].Value <<= aFilterName; } else if ( !aTypeName.isEmpty() && !bIgnoreType ) @@ -601,14 +604,15 @@ OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName( if ( xNameAccess.is() && ( xNameAccess->getByName( aTypeName ) >>= aTypes ) ) { - for ( const auto & prop : std::as_const(aTypes) ) + for (const auto& prop : aTypes) { if ( prop.Name == "PreferredFilter" && ( prop.Value >>= aFilterName ) ) { sal_Int32 nOldLen = aMediaDescr.getLength(); aMediaDescr.realloc( nOldLen + 1 ); - aMediaDescr[nOldLen].Name = "FilterName"; - aMediaDescr[ nOldLen ].Value = prop.Value; + auto pMediaDescr = aMediaDescr.getArray(); + pMediaDescr[nOldLen].Name = "FilterName"; + pMediaDescr[ nOldLen ].Value = prop.Value; break; } } @@ -624,7 +628,7 @@ OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName( uno::Sequence< beans::NamedValue >& aObject ) { OUString aDocName; - for ( const auto & nv : std::as_const(aObject) ) + for (const auto& nv : aObject) if ( nv.Name == "ObjectDocumentServiceName" ) { nv.Value >>= aDocName; @@ -638,7 +642,7 @@ OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName( for ( sal_Int32 nMedInd = 0; nMedInd < aMediaDescr.getLength(); nMedInd++ ) if ( aMediaDescr[nMedInd].Name == "DocumentService" ) { - aMediaDescr[nMedInd].Value <<= aDocName; + aMediaDescr.getArray()[nMedInd].Value <<= aDocName; bNeedsAddition = false; break; } @@ -647,8 +651,9 @@ OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName( { sal_Int32 nOldLen = aMediaDescr.getLength(); aMediaDescr.realloc( nOldLen + 1 ); - aMediaDescr[nOldLen].Name = "DocumentService"; - aMediaDescr[nOldLen].Value <<= aDocName; + auto pMediaDescr = aMediaDescr.getArray(); + pMediaDescr[nOldLen].Name = "DocumentService"; + pMediaDescr[nOldLen].Value <<= aDocName; } return UpdateMediaDescriptorWithFilterName( aMediaDescr, true ); @@ -724,8 +729,19 @@ OUString MimeConfigurationHelper::GetDefaultFilterFromServiceName( const OUStrin uno::Sequence< beans::PropertyValue > aProps; if ( xFilterEnum->nextElement() >>= aProps ) { - SequenceAsHashMap aPropsHM( aProps ); - SfxFilterFlags nFlags = static_cast<SfxFilterFlags>(aPropsHM.getUnpackedValueOrDefault( "Flags", sal_Int32(0) )); + SfxFilterFlags nFlags = SfxFilterFlags::NONE; + OUString sName; + for (const auto & rPropVal : aProps) + { + if (rPropVal.Name == "Flags") + { + sal_Int32 nTmp(0); + if (rPropVal.Value >>= nTmp) + nFlags = static_cast<SfxFilterFlags>(nTmp); + } + else if (rPropVal.Name == "Name") + rPropVal.Value >>= sName; + } // that should be import, export, own filter and not a template filter ( TemplatePath flag ) SfxFilterFlags const nRequired = SfxFilterFlags::OWN @@ -739,7 +755,7 @@ OUString MimeConfigurationHelper::GetDefaultFilterFromServiceName( const OUStrin // if there are more than one filter the preferred one should be used // if there is no preferred filter the first one will be used if ( aResult.isEmpty() || ( nFlags & SfxFilterFlags::PREFERED ) ) - aResult = aPropsHM.getUnpackedValueOrDefault( "Name", OUString() ); + aResult = sName; if ( nFlags & SfxFilterFlags::PREFERED ) break; // the preferred filter was found } @@ -870,23 +886,22 @@ uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassID( sal_uInt3 sal_uInt8 b8, sal_uInt8 b9, sal_uInt8 b10, sal_uInt8 b11, sal_uInt8 b12, sal_uInt8 b13, sal_uInt8 b14, sal_uInt8 b15 ) { - uno::Sequence< sal_Int8 > aResult( 16 ); - aResult[0] = static_cast<sal_Int8>( n1 >> 24 ); - aResult[1] = static_cast<sal_Int8>( ( n1 << 8 ) >> 24 ); - aResult[2] = static_cast<sal_Int8>( ( n1 << 16 ) >> 24 ); - aResult[3] = static_cast<sal_Int8>( ( n1 << 24 ) >> 24 ); - aResult[4] = static_cast<sal_Int8>( n2 >> 8 ); - aResult[5] = static_cast<sal_Int8>( ( n2 << 8 ) >> 8 ); - aResult[6] = static_cast<sal_Int8>( n3 >> 8 ); - aResult[7] = static_cast<sal_Int8>( ( n3 << 8 ) >> 8 ); - aResult[8] = b8; - aResult[9] = b9; - aResult[10] = b10; - aResult[11] = b11; - aResult[12] = b12; - aResult[13] = b13; - aResult[14] = b14; - aResult[15] = b15; + uno::Sequence< sal_Int8 > aResult{ /* [ 0] */ static_cast<sal_Int8>( n1 >> 24 ), + /* [ 1] */ static_cast<sal_Int8>( ( n1 << 8 ) >> 24 ), + /* [ 2] */ static_cast<sal_Int8>( ( n1 << 16 ) >> 24 ), + /* [ 3] */ static_cast<sal_Int8>( ( n1 << 24 ) >> 24 ), + /* [ 4] */ static_cast<sal_Int8>( n2 >> 8 ), + /* [ 5] */ static_cast<sal_Int8>( ( n2 << 8 ) >> 8 ), + /* [ 6] */ static_cast<sal_Int8>( n3 >> 8 ), + /* [ 7] */ static_cast<sal_Int8>( ( n3 << 8 ) >> 8 ), + /* [ 8] */ static_cast<sal_Int8>( b8 ), + /* [ 9] */ static_cast<sal_Int8>( b9 ), + /* [10] */ static_cast<sal_Int8>( b10 ), + /* [11] */ static_cast<sal_Int8>( b11 ), + /* [12] */ static_cast<sal_Int8>( b12 ), + /* [13] */ static_cast<sal_Int8>( b13 ), + /* [14] */ static_cast<sal_Int8>( b14 ), + /* [15] */ static_cast<sal_Int8>( b15 ) }; return aResult; } diff --git a/comphelper/source/misc/namedvaluecollection.cxx b/comphelper/source/misc/namedvaluecollection.cxx index 0bda6c197267..11ef15b30854 100644 --- a/comphelper/source/misc/namedvaluecollection.cxx +++ b/comphelper/source/misc/namedvaluecollection.cxx @@ -24,7 +24,6 @@ #include <com/sun/star/beans/PropertyState.hpp> #include <com/sun/star/beans/PropertyValue.hpp> -#include <rtl/instance.hxx> #include <sal/log.hxx> #include <algorithm> @@ -180,43 +179,81 @@ namespace comphelper bool NamedValueCollection::get_ensureType( const OUString& _rValueName, void* _pValueLocation, const Type& _rExpectedValueType ) const { auto pos = maValues.find( _rValueName ); - if ( pos != maValues.end() ) + if ( pos == maValues.end() ) + // argument does not exist + return false; + + if ( uno_type_assignData( + _pValueLocation, _rExpectedValueType.getTypeLibType(), + const_cast< void* >( pos->second.getValue() ), pos->second.getValueType().getTypeLibType(), + reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ), + reinterpret_cast< uno_AcquireFunc >( cpp_acquire ), + reinterpret_cast< uno_ReleaseFunc >( cpp_release ) + ) ) + // argument exists, and could be extracted + return true; + + // argument exists, but is of wrong type + throw IllegalArgumentException( + "Invalid value type for '" + _rValueName + + "'.\nExpected: " + _rExpectedValueType.getTypeName() + + "\nFound: " + pos->second.getValueType().getTypeName(), + nullptr, 0 ); + } + + // static + bool NamedValueCollection::get_ensureType( const css::uno::Sequence<css::beans::PropertyValue>& rPropSeq, + std::u16string_view _rValueName, void* _pValueLocation, const Type& _rExpectedValueType ) + { + for (const css::beans::PropertyValue& rPropVal : rPropSeq) { - if ( uno_type_assignData( - _pValueLocation, _rExpectedValueType.getTypeLibType(), - const_cast< void* >( pos->second.getValue() ), pos->second.getValueType().getTypeLibType(), - reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ), - reinterpret_cast< uno_AcquireFunc >( cpp_acquire ), - reinterpret_cast< uno_ReleaseFunc >( cpp_release ) - ) ) - // argument exists, and could be extracted - return true; - - // argument exists, but is of wrong type - throw IllegalArgumentException( - "Invalid value type for '" + _rValueName - + "'.\nExpected: " + _rExpectedValueType.getTypeName() - + "\nFound: " + pos->second.getValueType().getTypeName(), - nullptr, 0 ); + if (rPropVal.Name == _rValueName) + { + if ( uno_type_assignData( + _pValueLocation, _rExpectedValueType.getTypeLibType(), + const_cast< void* >( rPropVal.Value.getValue() ), rPropVal.Value.getValueType().getTypeLibType(), + reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ), + reinterpret_cast< uno_AcquireFunc >( cpp_acquire ), + reinterpret_cast< uno_ReleaseFunc >( cpp_release ) + ) ) + // argument exists, and could be extracted + return true; + + // argument exists, but is of wrong type + throw IllegalArgumentException( + OUString::Concat("Invalid value type for '") + _rValueName + + "'.\nExpected: " + _rExpectedValueType.getTypeName() + + "\nFound: " + rPropVal.Value.getValueType().getTypeName(), + nullptr, 0 ); + } } - // argument does not exist return false; } - namespace + // static + const css::uno::Any& NamedValueCollection::get( const css::uno::Sequence<css::beans::PropertyValue>& rPropSeq, + std::u16string_view _rValueName ) { - class theEmptyDefault : public rtl::Static<Any, theEmptyDefault> {}; + static const Any theEmptyDefault; + for (const css::beans::PropertyValue& rPropVal : rPropSeq) + { + if (rPropVal.Name == _rValueName) + { + return rPropVal.Value; + } + } + return theEmptyDefault; } - const Any& NamedValueCollection::impl_get( const OUString& _rValueName ) const { + static const Any theEmptyDefault; auto pos = maValues.find( _rValueName ); if ( pos != maValues.end() ) return pos->second; - return theEmptyDefault::get(); + return theEmptyDefault; } diff --git a/comphelper/source/misc/numberedcollection.cxx b/comphelper/source/misc/numberedcollection.cxx index 9df6a878794b..9dec18e66a06 100644 --- a/comphelper/source/misc/numberedcollection.cxx +++ b/comphelper/source/misc/numberedcollection.cxx @@ -24,14 +24,10 @@ namespace comphelper{ -constexpr OUStringLiteral ERRMSG_INVALID_COMPONENT_PARAM = u"NULL as component reference not allowed."; +constexpr OUString ERRMSG_INVALID_COMPONENT_PARAM = u"NULL as component reference not allowed."_ustr; NumberedCollection::NumberedCollection() - : ::cppu::BaseMutex () - , m_sUntitledPrefix () - , m_lComponents () - , m_xOwner () { } @@ -44,7 +40,7 @@ NumberedCollection::~NumberedCollection() void NumberedCollection::setOwner(const css::uno::Reference< css::uno::XInterface >& xOwner) { // SYNCHRONIZED -> - osl::MutexGuard aLock(m_aMutex); + std::scoped_lock aLock(m_aMutex); m_xOwner = xOwner; @@ -55,7 +51,7 @@ void NumberedCollection::setOwner(const css::uno::Reference< css::uno::XInterfac void NumberedCollection::setUntitledPrefix(const OUString& sPrefix) { // SYNCHRONIZED -> - osl::MutexGuard aLock(m_aMutex); + std::scoped_lock aLock(m_aMutex); m_sUntitledPrefix = sPrefix; @@ -66,7 +62,7 @@ void NumberedCollection::setUntitledPrefix(const OUString& sPrefix) ::sal_Int32 SAL_CALL NumberedCollection::leaseNumber(const css::uno::Reference< css::uno::XInterface >& xComponent) { // SYNCHRONIZED -> - osl::MutexGuard aLock(m_aMutex); + std::scoped_lock aLock(m_aMutex); if ( ! xComponent.is ()) throw css::lang::IllegalArgumentException(ERRMSG_INVALID_COMPONENT_PARAM, m_xOwner.get(), 1); @@ -101,10 +97,10 @@ void NumberedCollection::setUntitledPrefix(const OUString& sPrefix) void SAL_CALL NumberedCollection::releaseNumber(::sal_Int32 nNumber) { // SYNCHRONIZED -> - osl::MutexGuard aLock(m_aMutex); + std::scoped_lock aLock(m_aMutex); if (nNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER) - throw css::lang::IllegalArgumentException ("Special valkud INVALID_NUMBER not allowed as input parameter.", m_xOwner.get(), 1); + throw css::lang::IllegalArgumentException ("Special value INVALID_NUMBER not allowed as input parameter.", m_xOwner.get(), 1); TDeadItemList lDeadItems; TNumberedItemHash::iterator pComponent; @@ -138,7 +134,7 @@ void SAL_CALL NumberedCollection::releaseNumber(::sal_Int32 nNumber) void SAL_CALL NumberedCollection::releaseNumberForComponent(const css::uno::Reference< css::uno::XInterface >& xComponent) { // SYNCHRONIZED -> - osl::MutexGuard aLock(m_aMutex); + std::scoped_lock aLock(m_aMutex); if ( ! xComponent.is ()) throw css::lang::IllegalArgumentException(ERRMSG_INVALID_COMPONENT_PARAM, m_xOwner.get(), 1); @@ -160,7 +156,7 @@ void SAL_CALL NumberedCollection::releaseNumberForComponent(const css::uno::Refe OUString SAL_CALL NumberedCollection::getUntitledPrefix() { // SYNCHRONIZED -> - osl::MutexGuard aLock(m_aMutex); + std::scoped_lock aLock(m_aMutex); return m_sUntitledPrefix; @@ -182,48 +178,25 @@ OUString SAL_CALL NumberedCollection::getUntitledPrefix() */ ::sal_Int32 NumberedCollection::impl_searchFreeNumber () { - // create ordered list of all possible numbers. - std::vector< ::sal_Int32 > lPossibleNumbers; - ::sal_Int32 c = static_cast<::sal_Int32>(m_lComponents.size ()); - ::sal_Int32 i = 1; + // create bitset, where each position represents one possible number. + std::vector<bool> aUsedNumbers((m_lComponents.size() * 2) + 1, false); - // c can't be less than 0 ... otherwise hash.size() has an error :-) - // But we need at least n+1 numbers here. - c += 1; - - for (i=1; i<=c; ++i) - lPossibleNumbers.push_back (i); - - // SYNCHRONIZED -> + for (const auto& rPair : m_lComponents) { - osl::MutexGuard aLock(m_aMutex); - TDeadItemList lDeadItems; - - for (const auto& [rComponent, rItem] : m_lComponents) - { - const css::uno::Reference< css::uno::XInterface > xItem = rItem.xItem.get(); - - if ( ! xItem.is ()) - { - lDeadItems.push_back(rComponent); - continue; - } - - std::vector< ::sal_Int32 >::iterator pPossible = std::find(lPossibleNumbers.begin (), lPossibleNumbers.end (), rItem.nNumber); - if (pPossible != lPossibleNumbers.end ()) - lPossibleNumbers.erase (pPossible); - } - - impl_cleanUpDeadItems(m_lComponents, lDeadItems); + // numbers start at 1 + sal_Int32 pos = rPair.second.nNumber - 1; + if (pos >= static_cast<sal_Int32>(aUsedNumbers.size())) + aUsedNumbers.resize(pos * 2, false); // should be rare + aUsedNumbers[pos] = true; + } - // a) non free numbers ... return INVALID_NUMBER - if (lPossibleNumbers.empty()) - return css::frame::UntitledNumbersConst::INVALID_NUMBER; + // a) non free numbers ... return INVALID_NUMBER + auto it = std::find(aUsedNumbers.begin(), aUsedNumbers.end(), false); + if (it == aUsedNumbers.end()) + return css::frame::UntitledNumbersConst::INVALID_NUMBER; - // b) return first free number - return *(lPossibleNumbers.begin ()); - } - // <- SYNCHRONIZED + // b) return first free number + return it - aUsedNumbers.begin() + 1; } void NumberedCollection::impl_cleanUpDeadItems ( TNumberedItemHash& lItems , diff --git a/comphelper/source/misc/officerestartmanager.cxx b/comphelper/source/misc/officerestartmanager.cxx index f56486858522..81e9b3351d7e 100644 --- a/comphelper/source/misc/officerestartmanager.cxx +++ b/comphelper/source/misc/officerestartmanager.cxx @@ -24,7 +24,6 @@ #include <com/sun/star/beans/XPropertySet.hpp> #include <cppuhelper/supportsservice.hxx> -#include <rtl/ref.hxx> #include "officerestartmanager.hxx" using namespace ::com::sun::star; @@ -37,10 +36,10 @@ namespace comphelper void SAL_CALL OOfficeRestartManager::requestRestart( const uno::Reference< task::XInteractionHandler >& /* xInteractionHandler */ ) { if ( !m_xContext.is() ) - throw uno::RuntimeException(); + throw uno::RuntimeException("no component context"); { - ::osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); // if the restart already running there is no need to trigger it again if ( m_bRestartRequested ) @@ -77,7 +76,7 @@ void SAL_CALL OOfficeRestartManager::requestRestart( const uno::Reference< task: sal_Bool SAL_CALL OOfficeRestartManager::isRestartRequested( sal_Bool bOfficeInitialized ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( bOfficeInitialized && !m_bOfficeInitialized ) m_bOfficeInitialized = bOfficeInitialized; @@ -146,31 +145,13 @@ uno::Sequence< OUString > SAL_CALL OOfficeRestartManager::getSupportedServiceNam } // namespace comphelper -namespace { - -struct Instance { - explicit Instance( - css::uno::Reference<css::uno::XComponentContext> const & context): - instance(static_cast<cppu::OWeakObject *>(new comphelper::OOfficeRestartManager(context))) - {} - - rtl::Reference<css::uno::XInterface> instance; -}; - -struct Singleton: - public rtl::StaticWithArg< - Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton> -{}; - -} extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_task_OfficeRestartManager( css::uno::XComponentContext *context, css::uno::Sequence<css::uno::Any> const &) { - return cppu::acquire(static_cast<cppu::OWeakObject *>( - Singleton::get(context).instance.get())); + return cppu::acquire(new comphelper::OOfficeRestartManager(context)); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/officerestartmanager.hxx b/comphelper/source/misc/officerestartmanager.hxx index 8b3658a8e892..ecf59c543270 100644 --- a/comphelper/source/misc/officerestartmanager.hxx +++ b/comphelper/source/misc/officerestartmanager.hxx @@ -24,8 +24,9 @@ #include <com/sun/star/awt/XCallback.hpp> #include <com/sun/star/uno/XComponentContext.hpp> -#include <osl/mutex.hxx> +#include <mutex> #include <cppuhelper/implbase.hxx> +#include <utility> namespace comphelper { @@ -34,15 +35,15 @@ class OOfficeRestartManager : public ::cppu::WeakImplHelper< css::task::XRestart , css::awt::XCallback , css::lang::XServiceInfo > { - ::osl::Mutex m_aMutex; + std::mutex m_aMutex; css::uno::Reference< css::uno::XComponentContext > m_xContext; bool m_bOfficeInitialized; bool m_bRestartRequested; public: - explicit OOfficeRestartManager( const css::uno::Reference< css::uno::XComponentContext >& xContext ) - : m_xContext( xContext ) + explicit OOfficeRestartManager( css::uno::Reference< css::uno::XComponentContext > xContext ) + : m_xContext(std::move( xContext )) , m_bOfficeInitialized( false ) , m_bRestartRequested( false ) {} diff --git a/comphelper/source/misc/profilezone.cxx b/comphelper/source/misc/profilezone.cxx deleted file mode 100644 index f9284b1f4a51..000000000000 --- a/comphelper/source/misc/profilezone.cxx +++ /dev/null @@ -1,114 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include <sal/config.h> - -#include <atomic> -#include <iostream> -#include <string_view> - -#include <comphelper/sequence.hxx> -#include <comphelper/profilezone.hxx> -#include <osl/time.h> -#include <osl/thread.h> - -namespace comphelper -{ - -std::atomic<bool> ProfileZone::g_bRecording(false); - -namespace ProfileRecording -{ - -static std::vector<OUString> g_aRecording; // recorded data -static long long g_aSumTime(0); // overall zone time in microsec -static int g_aNesting; // level of overlapped zones -static long long g_aStartTime; // start time of recording -static ::osl::Mutex g_aMutex; - -void startRecording(bool bStartRecording) -{ - if (bStartRecording) - { - TimeValue systemTime; - osl_getSystemTime( &systemTime ); - ::osl::MutexGuard aGuard( g_aMutex ); - g_aStartTime = static_cast<long long>(systemTime.Seconds) * 1000000 + systemTime.Nanosec/1000; - g_aNesting = 0; - } - ProfileZone::g_bRecording = bStartRecording; -} - -long long addRecording(const char * aProfileId, long long aCreateTime) -{ - assert( ProfileZone::g_bRecording ); - - TimeValue systemTime; - osl_getSystemTime( &systemTime ); - long long aTime = static_cast<long long>(systemTime.Seconds) * 1000000 + systemTime.Nanosec/1000; - - if (!aProfileId) - aProfileId = "(null)"; - OUString aString(aProfileId, strlen(aProfileId), RTL_TEXTENCODING_UTF8); - - OUString sRecordingData(OUString::number(osl_getThreadIdentifier(nullptr)) + " " + - OUString::number(aTime/1000000.0) + " " + aString + ": " + - (aCreateTime == 0 ? std::u16string_view(u"start") : std::u16string_view(u"stop")) + - (aCreateTime != 0 ? (" " + OUString::number((aTime - aCreateTime)/1000.0) + " ms") : OUString(""))); - - ::osl::MutexGuard aGuard( g_aMutex ); - - g_aRecording.emplace_back(sRecordingData); - if (aCreateTime == 0) - { - g_aNesting++; - return aTime; - } - // neglect ProfileZones created before startRecording - else if (aCreateTime >= g_aStartTime) - { - if (g_aNesting > 0) - g_aNesting--; - if (g_aNesting == 0) - g_aSumTime += aTime - aCreateTime; - } - return 0; -} - -css::uno::Sequence<OUString> getRecordingAndClear() -{ - bool bRecording; - std::vector<OUString> aRecording; - { - ::osl::MutexGuard aGuard( g_aMutex ); - bRecording = ProfileZone::g_bRecording; - startRecording(false); - aRecording.swap(g_aRecording); - long long aSumTime = g_aSumTime; - aRecording.insert(aRecording.begin(), OUString::number(aSumTime/1000000.0)); - } - // reset start time and nesting level - startRecording(bRecording); - return ::comphelper::containerToSequence(aRecording); -} - -} // namespace ProfileRecording - -void ProfileZone::startConsole() { m_aCreateTime = osl_getGlobalTimer(); } - -void ProfileZone::stopConsole() -{ - sal_uInt32 nEndTime = osl_getGlobalTimer(); - std::cerr << "comphelper::ProfileZone: " << m_sProfileId << " finished in " - << nEndTime - m_aCreateTime << " ms" << std::endl; -} - -} // namespace comphelper - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/proxyaggregation.cxx b/comphelper/source/misc/proxyaggregation.cxx index 5efb0f211f76..db580bea496c 100644 --- a/comphelper/source/misc/proxyaggregation.cxx +++ b/comphelper/source/misc/proxyaggregation.cxx @@ -110,7 +110,7 @@ namespace comphelper m_xInner = _rxComponent; // aggregate a proxy for the object - baseAggregateProxyFor( m_xInner.get(), _rRefCount, _rDelegator ); + baseAggregateProxyFor( m_xInner, _rRefCount, _rDelegator ); // add as event listener to the inner context, because we want to be notified of disposals osl_atomic_increment( &_rRefCount ); diff --git a/comphelper/source/misc/random.cxx b/comphelper/source/misc/random.cxx index ea9e7273756b..96d466641dfb 100644 --- a/comphelper/source/misc/random.cxx +++ b/comphelper/source/misc/random.cxx @@ -11,7 +11,6 @@ */ #include <comphelper/random.hxx> -#include <rtl/instance.hxx> #include <sal/log.hxx> #include <assert.h> #include <time.h> @@ -43,7 +42,8 @@ struct RandomNumberGenerator STD_RNG_ALGO global_rng; RandomNumberGenerator() { - bool bRepeatable = (getenv("SAL_RAND_REPEATABLE") != nullptr); + // make RR easier to use, breaks easily without the RNG being repeatable + bool bRepeatable = (getenv("SAL_RAND_REPEATABLE") != nullptr) || (getenv("RR") != nullptr); // valgrind on some platforms (e.g.Ubuntu16.04) does not support the new Intel RDRAND instructions, // which leads to "Illegal Opcode" errors, so just turn off randomness. #if defined HAVE_VALGRIND_HEADERS @@ -74,16 +74,18 @@ struct RandomNumberGenerator } }; -class theRandomNumberGenerator : public rtl::Static<RandomNumberGenerator, theRandomNumberGenerator> +RandomNumberGenerator& GetTheRandomNumberGenerator() { -}; + static RandomNumberGenerator RANDOM; + return RANDOM; +} } // uniform ints [a,b] distribution int uniform_int_distribution(int a, int b) { std::uniform_int_distribution<int> dist(a, b); - auto& gen = theRandomNumberGenerator::get(); + auto& gen = GetTheRandomNumberGenerator(); std::scoped_lock<std::mutex> g(gen.mutex); return dist(gen.global_rng); } @@ -92,7 +94,7 @@ int uniform_int_distribution(int a, int b) unsigned int uniform_uint_distribution(unsigned int a, unsigned int b) { std::uniform_int_distribution<unsigned int> dist(a, b); - auto& gen = theRandomNumberGenerator::get(); + auto& gen = GetTheRandomNumberGenerator(); std::scoped_lock<std::mutex> g(gen.mutex); return dist(gen.global_rng); } @@ -101,7 +103,7 @@ unsigned int uniform_uint_distribution(unsigned int a, unsigned int b) size_t uniform_size_distribution(size_t a, size_t b) { std::uniform_int_distribution<size_t> dist(a, b); - auto& gen = theRandomNumberGenerator::get(); + auto& gen = GetTheRandomNumberGenerator(); std::scoped_lock<std::mutex> g(gen.mutex); return dist(gen.global_rng); } @@ -111,7 +113,7 @@ double uniform_real_distribution(double a, double b) { assert(a < b); std::uniform_real_distribution<double> dist(a, b); - auto& gen = theRandomNumberGenerator::get(); + auto& gen = GetTheRandomNumberGenerator(); std::scoped_lock<std::mutex> g(gen.mutex); return dist(gen.global_rng); } diff --git a/comphelper/source/misc/sequenceashashmap.cxx b/comphelper/source/misc/sequenceashashmap.cxx index eb78e60c55d2..db2c99a7a814 100644 --- a/comphelper/source/misc/sequenceashashmap.cxx +++ b/comphelper/source/misc/sequenceashashmap.cxx @@ -19,11 +19,84 @@ #include <sal/config.h> +#include <boost/property_tree/json_parser.hpp> + #include <com/sun/star/beans/NamedValue.hpp> #include <com/sun/star/beans/PropertyValue.hpp> #include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/reflection/XIdlField.hpp> +#include <com/sun/star/reflection/theCoreReflection.hpp> #include <comphelper/sequenceashashmap.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/propertysequence.hxx> +#include <sal/log.hxx> +#include <o3tl/string_view.hxx> +#include <comphelper/sequence.hxx> +using namespace com::sun::star; + +namespace +{ +uno::Any jsonToUnoAny(const boost::property_tree::ptree& aTree) +{ + uno::Any aAny; + uno::Any aValue; + sal_Int32 nFields; + uno::Reference<reflection::XIdlField> aField; + boost::property_tree::ptree aNodeNull, aNodeValue, aNodeField; + const std::string& rType = aTree.get<std::string>("type", ""); + const std::string& rValue = aTree.get<std::string>("value", ""); + uno::Sequence<uno::Reference<reflection::XIdlField>> aFields; + uno::Reference<reflection::XIdlClass> xIdlClass + = css::reflection::theCoreReflection::get(comphelper::getProcessComponentContext()) + ->forName(OUString::fromUtf8(rType)); + if (xIdlClass.is()) + { + uno::TypeClass aTypeClass = xIdlClass->getTypeClass(); + xIdlClass->createObject(aAny); + aFields = xIdlClass->getFields(); + nFields = aFields.getLength(); + aNodeValue = aTree.get_child("value", aNodeNull); + if (nFields > 0 && aNodeValue != aNodeNull) + { + for (sal_Int32 itField = 0; itField < nFields; ++itField) + { + aField = aFields[itField]; + aNodeField = aNodeValue.get_child(aField->getName().toUtf8().getStr(), aNodeNull); + if (aNodeField != aNodeNull) + { + aValue = jsonToUnoAny(aNodeField); + aField->set(aAny, aValue); + } + } + } + else if (!rValue.empty()) + { + if (aTypeClass == uno::TypeClass_VOID) + aAny.clear(); + else if (aTypeClass == uno::TypeClass_BYTE) + aAny <<= static_cast<sal_Int8>(o3tl::toInt32(rValue)); + else if (aTypeClass == uno::TypeClass_BOOLEAN) + aAny <<= rtl_str_toBoolean(rValue.c_str()); + else if (aTypeClass == uno::TypeClass_SHORT) + aAny <<= static_cast<sal_Int16>(o3tl::toInt32(rValue)); + else if (aTypeClass == uno::TypeClass_UNSIGNED_SHORT) + aAny <<= static_cast<sal_uInt16>(o3tl::toUInt32(rValue)); + else if (aTypeClass == uno::TypeClass_LONG) + aAny <<= o3tl::toInt32(rValue); + else if (aTypeClass == uno::TypeClass_UNSIGNED_LONG) + aAny <<= static_cast<sal_uInt32>(o3tl::toInt32(rValue)); + else if (aTypeClass == uno::TypeClass_FLOAT) + aAny <<= rtl_str_toFloat(rValue.c_str()); + else if (aTypeClass == uno::TypeClass_DOUBLE) + aAny <<= o3tl::toDouble(rValue); + else if (aTypeClass == uno::TypeClass_STRING) + aAny <<= OUString::fromUtf8(rValue); + } + } + return aAny; +} +} namespace comphelper{ @@ -86,6 +159,7 @@ void SequenceAsHashMap::operator<<(const css::uno::Sequence< css::uno::Any >& lS sal_Int32 c = lSource.getLength(); sal_Int32 i = 0; + m_aMap.reserve(c); for (i=0; i<c; ++i) { css::beans::PropertyValue lP; @@ -131,6 +205,7 @@ void SequenceAsHashMap::operator<<(const css::uno::Sequence< css::beans::Propert sal_Int32 c = lSource.getLength(); const css::beans::PropertyValue* pSource = lSource.getConstArray(); + m_aMap.reserve(c); for (sal_Int32 i=0; i<c; ++i) (*this)[pSource[i].Name] = pSource[i].Value; } @@ -142,6 +217,7 @@ void SequenceAsHashMap::operator<<(const css::uno::Sequence< css::beans::NamedVa sal_Int32 c = lSource.getLength(); const css::beans::NamedValue* pSource = lSource.getConstArray(); + m_aMap.reserve(c); for (sal_Int32 i=0; i<c; ++i) (*this)[pSource[i].Name] = pSource[i].Value; } @@ -157,7 +233,7 @@ void SequenceAsHashMap::operator>>(css::uno::Sequence< css::beans::PropertyValue pThis != end() ; ++pThis ) { - pDestination[i].Name = pThis->first ; + pDestination[i].Name = pThis->first.maString; pDestination[i].Value = pThis->second; ++i; } @@ -174,7 +250,7 @@ void SequenceAsHashMap::operator>>(css::uno::Sequence< css::beans::NamedValue >& pThis != end() ; ++pThis ) { - pDestination[i].Name = pThis->first ; + pDestination[i].Name = pThis->first.maString; pDestination[i].Value = pThis->second; ++i; } @@ -208,7 +284,7 @@ bool SequenceAsHashMap::match(const SequenceAsHashMap& rCheck) const { for (auto const& elem : rCheck) { - const OUString& sCheckName = elem.first; + const OUString& sCheckName = elem.first.maString; const css::uno::Any& aCheckValue = elem.second; const_iterator pFound = find(sCheckName); @@ -225,13 +301,98 @@ bool SequenceAsHashMap::match(const SequenceAsHashMap& rCheck) const void SequenceAsHashMap::update(const SequenceAsHashMap& rUpdate) { - for (auto const& elem : rUpdate) + m_aMap.reserve(std::max(size(), rUpdate.size())); + for (auto const& elem : rUpdate.m_aMap) { - const OUString& sName = elem.first; - const css::uno::Any& aValue = elem.second; + m_aMap[elem.first] = elem.second; + } +} + +std::vector<css::beans::PropertyValue> JsonToPropertyValues(const OString& rJson) +{ + std::vector<beans::PropertyValue> aArguments; + boost::property_tree::ptree aTree, aNodeNull, aNodeValue; + std::stringstream aStream((std::string(rJson))); + boost::property_tree::read_json(aStream, aTree); - (*this)[sName] = aValue; + for (const auto& rPair : aTree) + { + const std::string& rType = rPair.second.get<std::string>("type", ""); + const std::string& rValue = rPair.second.get<std::string>("value", ""); + + beans::PropertyValue aValue; + aValue.Name = OUString::fromUtf8(rPair.first); + if (rType == "string") + aValue.Value <<= OUString::fromUtf8(rValue); + else if (rType == "boolean") + aValue.Value <<= rtl_str_toBoolean(rValue.c_str()); + else if (rType == "float") + aValue.Value <<= rtl_str_toFloat(rValue.c_str()); + else if (rType == "long") + aValue.Value <<= o3tl::toInt32(rValue); + else if (rType == "short") + aValue.Value <<= sal_Int16(o3tl::toInt32(rValue)); + else if (rType == "unsigned short") + aValue.Value <<= sal_uInt16(o3tl::toUInt32(rValue)); + else if (rType == "int64") + aValue.Value <<= o3tl::toInt64(rValue); + else if (rType == "int32") + aValue.Value <<= o3tl::toInt32(rValue); + else if (rType == "int16") + aValue.Value <<= sal_Int16(o3tl::toInt32(rValue)); + else if (rType == "uint64") + aValue.Value <<= rtl_str_toUInt64(rValue.c_str(), 10); + else if (rType == "uint32") + aValue.Value <<= o3tl::toUInt32(rValue); + else if (rType == "uint16") + aValue.Value <<= sal_uInt16(o3tl::toUInt32(rValue)); + else if (rType == "[]byte") + { + aNodeValue = rPair.second.get_child("value", aNodeNull); + if (aNodeValue != aNodeNull && aNodeValue.size() == 0) + { + uno::Sequence<sal_Int8> aSeqByte(reinterpret_cast<const sal_Int8*>(rValue.c_str()), + rValue.size()); + aValue.Value <<= aSeqByte; + } + } + else if (rType == "[]any") + { + aNodeValue = rPair.second.get_child("value", aNodeNull); + if (aNodeValue != aNodeNull && !aNodeValue.empty()) + { + uno::Sequence<uno::Any> aSeq(aNodeValue.size()); + std::transform(aNodeValue.begin(), aNodeValue.end(), aSeq.getArray(), + [](const auto& rSeqPair) { return jsonToUnoAny(rSeqPair.second); }); + aValue.Value <<= aSeq; + } + } + else if (rType == "[]com.sun.star.beans.PropertyValue") + { + aNodeValue = rPair.second.get_child("value", aNodeNull); + std::stringstream s; + boost::property_tree::write_json(s, aNodeValue); + std::vector<beans::PropertyValue> aPropertyValues = JsonToPropertyValues(OString(s.str())); + aValue.Value <<= comphelper::containerToSequence(aPropertyValues); + } + else if (rType == "[][]com.sun.star.beans.PropertyValue") + { + aNodeValue = rPair.second.get_child("value", aNodeNull); + std::vector<uno::Sequence<beans::PropertyValue>> aSeqs; + for (const auto& rItem : aNodeValue) + { + std::stringstream s; + boost::property_tree::write_json(s, rItem.second); + std::vector<beans::PropertyValue> aPropertyValues = JsonToPropertyValues(OString(s.str())); + aSeqs.push_back(comphelper::containerToSequence(aPropertyValues)); + } + aValue.Value <<= comphelper::containerToSequence(aSeqs); + } + else + SAL_WARN("comphelper", "JsonToPropertyValues: unhandled type '" << rType << "'"); + aArguments.push_back(aValue); } + return aArguments; } } // namespace comphelper diff --git a/comphelper/source/misc/servicedecl.cxx b/comphelper/source/misc/servicedecl.cxx deleted file mode 100644 index 1955f6b56251..000000000000 --- a/comphelper/source/misc/servicedecl.cxx +++ /dev/null @@ -1,160 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include <comphelper/servicedecl.hxx> -#include <rtl/string.hxx> -#include <cppuhelper/implbase.hxx> -#include <comphelper/sequence.hxx> -#include <com/sun/star/lang/XSingleComponentFactory.hpp> -#include <cassert> -#include <vector> - -using namespace com::sun::star; - -namespace comphelper::service_decl { - -const char cDelim = ';'; - -class ServiceDecl::Factory : - public cppu::WeakImplHelper<lang::XSingleComponentFactory, - lang::XServiceInfo> -{ -public: - explicit Factory( ServiceDecl const& rServiceDecl ) - : m_rServiceDecl(rServiceDecl) {} - // noncopyable - Factory(const Factory&) = delete; - const Factory& operator=(const Factory&) = delete; - - // XServiceInfo: - virtual OUString SAL_CALL getImplementationName() override; - virtual sal_Bool SAL_CALL supportsService( OUString const& name ) override; - virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; - // XSingleComponentFactory: - virtual uno::Reference<uno::XInterface> SAL_CALL createInstanceWithContext( - uno::Reference<uno::XComponentContext> const& xContext ) override; - virtual uno::Reference<uno::XInterface> SAL_CALL - createInstanceWithArgumentsAndContext( - uno::Sequence<uno::Any> const& args, - uno::Reference<uno::XComponentContext> const& xContext ) override; - -private: - virtual ~Factory() override; - - ServiceDecl const& m_rServiceDecl; -}; - -ServiceDecl::Factory::~Factory() -{ -} - -// XServiceInfo: -OUString ServiceDecl::Factory::getImplementationName() -{ - return m_rServiceDecl.getImplementationName(); -} - -sal_Bool ServiceDecl::Factory::supportsService( OUString const& name ) -{ - return m_rServiceDecl.supportsService(name); -} - -uno::Sequence<OUString> ServiceDecl::Factory::getSupportedServiceNames() -{ - return m_rServiceDecl.getSupportedServiceNames(); -} - -// XSingleComponentFactory: -uno::Reference<uno::XInterface> ServiceDecl::Factory::createInstanceWithContext( - uno::Reference<uno::XComponentContext> const& xContext ) -{ - return m_rServiceDecl.m_createFunc( - m_rServiceDecl, uno::Sequence<uno::Any>(), xContext ); -} - -uno::Reference<uno::XInterface> -ServiceDecl::Factory::createInstanceWithArgumentsAndContext( - uno::Sequence<uno::Any > const& args, - uno::Reference<uno::XComponentContext> const& xContext ) -{ - return m_rServiceDecl.m_createFunc( - m_rServiceDecl, args, xContext ); -} - -void * ServiceDecl::getFactory( char const* pImplName ) const -{ - if (rtl_str_compare(m_pImplName, pImplName) == 0) { - lang::XSingleComponentFactory * const pFac( new Factory(*this) ); - pFac->acquire(); - return pFac; - } - return nullptr; -} - -uno::Sequence<OUString> ServiceDecl::getSupportedServiceNames() const -{ - std::vector<OUString> vec; - - OString const str(m_pServiceNames); - sal_Int32 nIndex = 0; - do { - OString const token( str.getToken( 0, cDelim, nIndex ) ); - vec.emplace_back( token.getStr(), token.getLength(), - RTL_TEXTENCODING_ASCII_US ); - } - while (nIndex >= 0); - - return comphelper::containerToSequence(vec); -} - -bool ServiceDecl::supportsService( OUString const& name ) const -{ - OString const str(m_pServiceNames); - sal_Int32 nIndex = 0; - do { - OString const token( str.getToken( 0, cDelim, nIndex ) ); - if (name.equalsAsciiL( token.getStr(), token.getLength() )) - return true; - } - while (nIndex >= 0); - return false; -} - -OUString ServiceDecl::getImplementationName() const -{ - return OUString::createFromAscii(m_pImplName); -} - -void* component_getFactoryHelper( const char* pImplName, - std::initializer_list<ServiceDecl const *> args ) -{ - for (auto const i: args) { - assert(i != nullptr); - void * fac = i->getFactory(pImplName); - if (fac != nullptr) { - return fac; - } - } - return nullptr; -} - -} // namespace - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/simplefileaccessinteraction.cxx b/comphelper/source/misc/simplefileaccessinteraction.cxx index 2840e3dad0e7..8cd77af7d693 100644 --- a/comphelper/source/misc/simplefileaccessinteraction.cxx +++ b/comphelper/source/misc/simplefileaccessinteraction.cxx @@ -32,41 +32,29 @@ const sal_Int32 HANDLE_AUTHENTICATIONREQUEST = 4; SimpleFileAccessInteraction::SimpleFileAccessInteraction( const css::uno::Reference<css::task::XInteractionHandler>& xHandler) { - std::vector<::ucbhelper::InterceptedInteraction::InterceptedRequest> lInterceptions; - ::ucbhelper::InterceptedInteraction::InterceptedRequest aInterceptedRequest; - - //intercept standard IO error exception (local file and WebDAV) - aInterceptedRequest.Handle = HANDLE_INTERACTIVEIOEXCEPTION; - aInterceptedRequest.Request <<= css::ucb::InteractiveIOException(); - aInterceptedRequest.Continuation = cppu::UnoType<css::task::XInteractionAbort>::get(); - lInterceptions.push_back(aInterceptedRequest); - - //intercept internal error - aInterceptedRequest.Handle = HANDLE_UNSUPPORTEDDATASINKEXCEPTION; - aInterceptedRequest.Request <<= css::ucb::UnsupportedDataSinkException(); - aInterceptedRequest.Continuation = cppu::UnoType<css::task::XInteractionAbort>::get(); - lInterceptions.push_back(aInterceptedRequest); - - //intercept network error exception (WebDAV ucp provider) - aInterceptedRequest.Handle = HANDLE_INTERACTIVENETWORKEXCEPTION; - aInterceptedRequest.Request <<= css::ucb::InteractiveNetworkException(); - aInterceptedRequest.Continuation = cppu::UnoType<css::task::XInteractionAbort>::get(); - lInterceptions.push_back(aInterceptedRequest); - - //intercept certificate validation request (WebDAV ucp provider) - aInterceptedRequest.Handle = HANDLE_CERTIFICATEREQUEST; - aInterceptedRequest.Request <<= css::ucb::CertificateValidationRequest(); - aInterceptedRequest.Continuation = cppu::UnoType<css::task::XInteractionAbort>::get(); - lInterceptions.push_back(aInterceptedRequest); - - //intercept authentication request (WebDAV ucp provider) - aInterceptedRequest.Handle = HANDLE_AUTHENTICATIONREQUEST; - aInterceptedRequest.Request <<= css::ucb::AuthenticationRequest(); - aInterceptedRequest.Continuation = cppu::UnoType<css::task::XInteractionApprove>::get(); - lInterceptions.push_back(aInterceptedRequest); + std::vector<::ucbhelper::InterceptedInteraction::InterceptedRequest> lInterceptions{ + { //intercept standard IO error exception (local file and WebDAV) + css::uno::Any(css::ucb::InteractiveIOException()), + cppu::UnoType<css::task::XInteractionAbort>::get(), HANDLE_INTERACTIVEIOEXCEPTION }, + { //intercept internal error + css::uno::Any(css::ucb::UnsupportedDataSinkException()), + cppu::UnoType<css::task::XInteractionAbort>::get(), HANDLE_UNSUPPORTEDDATASINKEXCEPTION }, + { + //intercept network error exception (WebDAV ucp provider) + css::uno::Any(css::ucb::InteractiveNetworkException()), + cppu::UnoType<css::task::XInteractionAbort>::get(), + HANDLE_INTERACTIVENETWORKEXCEPTION, + }, + { //intercept certificate validation request (WebDAV ucp provider) + css::uno::Any(css::ucb::CertificateValidationRequest()), + cppu::UnoType<css::task::XInteractionAbort>::get(), HANDLE_CERTIFICATEREQUEST }, + { //intercept authentication request (WebDAV ucp provider) + css::uno::Any(css::ucb::AuthenticationRequest()), + cppu::UnoType<css::task::XInteractionApprove>::get(), HANDLE_AUTHENTICATIONREQUEST } + }; setInterceptedHandler(xHandler); - setInterceptions(lInterceptions); + setInterceptions(std::move(lInterceptions)); } SimpleFileAccessInteraction::~SimpleFileAccessInteraction() {} diff --git a/comphelper/source/misc/solarmutex.cxx b/comphelper/source/misc/solarmutex.cxx index 5d1052327154..3e45ae14582d 100644 --- a/comphelper/source/misc/solarmutex.cxx +++ b/comphelper/source/misc/solarmutex.cxx @@ -38,7 +38,6 @@ SolarMutex *SolarMutex::get() SolarMutex::SolarMutex() : m_nCount( 0 ) - , m_nThreadId( 0 ) , m_aBeforeReleaseHandler( nullptr ) { assert(!g_pSolarMutex); @@ -54,7 +53,7 @@ void SolarMutex::doAcquire( const sal_uInt32 nLockCount ) { for ( sal_uInt32 n = nLockCount; n ; --n ) m_aMutex.acquire(); - m_nThreadId = osl::Thread::getCurrentIdentifier(); + m_nThreadId = std::this_thread::get_id(); m_nCount += nLockCount; } @@ -72,7 +71,7 @@ sal_uInt32 SolarMutex::doRelease( bool bUnlockAll ) { if ( m_aBeforeReleaseHandler ) m_aBeforeReleaseHandler(); - m_nThreadId = 0; + m_nThreadId = std::thread::id(); } for ( sal_uInt32 n = nCount ; n ; --n ) @@ -83,14 +82,14 @@ sal_uInt32 SolarMutex::doRelease( bool bUnlockAll ) bool SolarMutex::IsCurrentThread() const { - return m_nThreadId == osl::Thread::getCurrentIdentifier(); + return m_nThreadId == std::this_thread::get_id(); } bool SolarMutex::tryToAcquire() { if ( m_aMutex.tryToAcquire() ) { - m_nThreadId = osl::Thread::getCurrentIdentifier(); + m_nThreadId = std::this_thread::get_id(); m_nCount++; return true; } diff --git a/comphelper/source/misc/stillreadwriteinteraction.cxx b/comphelper/source/misc/stillreadwriteinteraction.cxx index 0efec31b160b..88bc25bc46cb 100644 --- a/comphelper/source/misc/stillreadwriteinteraction.cxx +++ b/comphelper/source/misc/stillreadwriteinteraction.cxx @@ -30,16 +30,18 @@ #include <com/sun/star/ucb/AuthenticationRequest.hpp> #include <com/sun/star/ucb/CertificateValidationRequest.hpp> +#include <utility> namespace comphelper{ StillReadWriteInteraction::StillReadWriteInteraction(const css::uno::Reference< css::task::XInteractionHandler >& xHandler, - const css::uno::Reference< css::task::XInteractionHandler >& xAuxiliaryHandler) + css::uno::Reference< css::task::XInteractionHandler > xAuxiliaryHandler) : m_bUsed (false) , m_bHandledByMySelf (false) - , m_xAuxiliaryHandler(xAuxiliaryHandler) + , m_xAuxiliaryHandler(std::move(xAuxiliaryHandler)) { std::vector< ::ucbhelper::InterceptedInteraction::InterceptedRequest > lInterceptions; + lInterceptions.reserve(4); ::ucbhelper::InterceptedInteraction::InterceptedRequest aInterceptedRequest; aInterceptedRequest.Handle = HANDLE_INTERACTIVEIOEXCEPTION; @@ -63,7 +65,7 @@ StillReadWriteInteraction::StillReadWriteInteraction(const css::uno::Reference< lInterceptions.push_back(aInterceptedRequest); setInterceptedHandler(xHandler); - setInterceptions(lInterceptions); + setInterceptions(std::move(lInterceptions)); } void StillReadWriteInteraction::resetInterceptions() diff --git a/comphelper/source/misc/storagehelper.cxx b/comphelper/source/misc/storagehelper.cxx index b53c4086bf3c..c2d295c54f26 100644 --- a/comphelper/source/misc/storagehelper.cxx +++ b/comphelper/source/misc/storagehelper.cxx @@ -27,15 +27,13 @@ #include <com/sun/star/embed/FileSystemStorageFactory.hpp> #include <com/sun/star/io/IOException.hpp> #include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> #include <com/sun/star/ucb/SimpleFileAccess.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/beans/PropertyValue.hpp> #include <com/sun/star/beans/NamedValue.hpp> #include <com/sun/star/beans/IllegalTypeException.hpp> -#include <com/sun/star/xml/crypto/NSSInitializer.hpp> -#include <com/sun/star/xml/crypto/XDigestContext.hpp> -#include <com/sun/star/xml/crypto/DigestID.hpp> #include <com/sun/star/security/DocumentDigitalSignatures.hpp> #include <com/sun/star/security/XCertificate.hpp> @@ -48,13 +46,17 @@ #include <ucbhelper/content.hxx> +#include <comphelper/bytereader.hxx> +#include <comphelper/diagnose_ex.hxx> #include <comphelper/fileformat.h> #include <comphelper/hash.hxx> #include <comphelper/processfactory.hxx> #include <comphelper/documentconstants.hxx> +#include <comphelper/propertyvalue.hxx> #include <comphelper/storagehelper.hxx> #include <comphelper/sequence.hxx> #include <cppuhelper/exc_hlp.hxx> +#include <o3tl/string_view.hxx> #if HAVE_FEATURE_GPGME # include <context.h> @@ -98,10 +100,7 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromURL( sal_Int32 nStorageMode, const uno::Reference< uno::XComponentContext >& rxContext ) { - uno::Sequence< uno::Any > aArgs( 2 ); - aArgs[0] <<= aURL; - aArgs[1] <<= nStorageMode; - + uno::Sequence< uno::Any > aArgs{ uno::Any(aURL), uno::Any(nStorageMode) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; @@ -113,9 +112,7 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromURL2( sal_Int32 nStorageMode, const uno::Reference< uno::XComponentContext >& rxContext ) { - uno::Sequence< uno::Any > aArgs( 2 ); - aArgs[0] <<= aURL; - aArgs[1] <<= nStorageMode; + uno::Sequence< uno::Any > aArgs{ uno::Any(aURL), uno::Any(nStorageMode) }; uno::Reference< lang::XSingleServiceFactory > xFact; css::uno::Any anyEx; @@ -151,10 +148,7 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromInputStream( const uno::Reference < io::XInputStream >& xStream, const uno::Reference< uno::XComponentContext >& rxContext ) { - uno::Sequence< uno::Any > aArgs( 2 ); - aArgs[0] <<= xStream; - aArgs[1] <<= embed::ElementModes::READ; - + uno::Sequence< uno::Any > aArgs{ uno::Any(xStream), uno::Any(embed::ElementModes::READ) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; @@ -166,10 +160,7 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromStream( sal_Int32 nStorageMode, const uno::Reference< uno::XComponentContext >& rxContext ) { - uno::Sequence< uno::Any > aArgs( 2 ); - aArgs[0] <<= xStream; - aArgs[1] <<= nStorageMode; - + uno::Sequence< uno::Any > aArgs{ uno::Any(xStream), uno::Any(nStorageMode) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; @@ -182,19 +173,30 @@ void OStorageHelper::CopyInputToOutput( { static const sal_Int32 nConstBufferSize = 32000; + if (auto pByteReader = dynamic_cast< comphelper::ByteReader* >( xInput.get() )) + { + if (auto pByteWriter = dynamic_cast< comphelper::ByteWriter* >( xOutput.get() )) + { + sal_Int32 nRead; + sal_Int8 aTempBuf[ nConstBufferSize ]; + do + { + nRead = pByteReader->readSomeBytes ( aTempBuf, nConstBufferSize ); + pByteWriter->writeBytes ( aTempBuf, nRead ); + } + while ( nRead == nConstBufferSize ); + return; + } + } + sal_Int32 nRead; uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize ); - do { nRead = xInput->readBytes ( aSequence, nConstBufferSize ); if ( nRead < nConstBufferSize ) - { - uno::Sequence < sal_Int8 > aTempBuf ( aSequence.getConstArray(), nRead ); - xOutput->writeBytes ( aTempBuf ); - } - else - xOutput->writeBytes ( aSequence ); + aSequence.realloc( nRead ); + xOutput->writeBytes ( aSequence ); } while ( nRead == nConstBufferSize ); } @@ -285,7 +287,7 @@ sal_Int32 OStorageHelper::GetXStorageFormat( { // the mediatype is not known OUString aMsg = __func__ - + OUStringLiteral(u":") + + OUString::Concat(u":") + OUString::number(__LINE__) + ": unknown media type '" + aMediaType @@ -303,15 +305,10 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromURL( sal_Int32 nStorageMode, const uno::Reference< uno::XComponentContext >& rxContext ) { - uno::Sequence< beans::PropertyValue > aProps( 1 ); - aProps[0].Name = "StorageFormat"; - aProps[0].Value <<= aFormat; - - uno::Sequence< uno::Any > aArgs( 3 ); - aArgs[0] <<= aURL; - aArgs[1] <<= nStorageMode; - aArgs[2] <<= aProps; + uno::Sequence< beans::PropertyValue > aProps{ comphelper::makePropertyValue("StorageFormat", + aFormat) }; + uno::Sequence< uno::Any > aArgs{ uno::Any(aURL), uno::Any(nStorageMode), uno::Any(aProps) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; @@ -324,24 +321,17 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromInputStr const uno::Reference< uno::XComponentContext >& rxContext, bool bRepairStorage ) { - uno::Sequence< beans::PropertyValue > aProps( 1 ); - sal_Int32 nPos = 0; - aProps[nPos].Name = "StorageFormat"; - aProps[nPos].Value <<= aFormat; - ++nPos; + uno::Sequence< beans::PropertyValue > aProps( bRepairStorage ? 2 : 1 ); + auto pProps = aProps.getArray(); + pProps[0].Name = "StorageFormat"; + pProps[0].Value <<= aFormat; if ( bRepairStorage ) { - aProps.realloc(nPos+1); - aProps[nPos].Name = "RepairPackage"; - aProps[nPos].Value <<= bRepairStorage; - ++nPos; + pProps[1].Name = "RepairPackage"; + pProps[1].Value <<= bRepairStorage; } - uno::Sequence< uno::Any > aArgs( 3 ); - aArgs[0] <<= xStream; - aArgs[1] <<= embed::ElementModes::READ; - aArgs[2] <<= aProps; - + uno::Sequence< uno::Any > aArgs{ uno::Any(xStream), uno::Any(embed::ElementModes::READ), uno::Any(aProps) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; @@ -355,24 +345,17 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromStream( const uno::Reference< uno::XComponentContext >& rxContext, bool bRepairStorage ) { - uno::Sequence< beans::PropertyValue > aProps( 1 ); - sal_Int32 nPos = 0; - aProps[nPos].Name = "StorageFormat"; - aProps[nPos].Value <<= aFormat; - ++nPos; + uno::Sequence< beans::PropertyValue > aProps( bRepairStorage ? 2 : 1 ); + auto pProps = aProps.getArray(); + pProps[0].Name = "StorageFormat"; + pProps[0].Value <<= aFormat; if ( bRepairStorage ) { - aProps.realloc(nPos+1); - aProps[nPos].Name = "RepairPackage"; - aProps[nPos].Value <<= bRepairStorage; - ++nPos; + pProps[1].Name = "RepairPackage"; + pProps[1].Value <<= bRepairStorage; } - uno::Sequence< uno::Any > aArgs( 3 ); - aArgs[0] <<= xStream; - aArgs[1] <<= nStorageMode; - aArgs[2] <<= aProps; - + uno::Sequence< uno::Any > aArgs{ uno::Any(xStream), uno::Any(nStorageMode), uno::Any(aProps) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; @@ -389,31 +372,29 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreatePackageEncryptionData( // generate SHA256 start key try { - uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext(); - - uno::Reference< css::xml::crypto::XNSSInitializer > xDigestContextSupplier = css::xml::crypto::NSSInitializer::create(xContext); - uno::Reference< css::xml::crypto::XDigestContext > xDigestContext( xDigestContextSupplier->getDigestContext( css::xml::crypto::DigestID::SHA256, uno::Sequence< beans::NamedValue >() ), uno::UNO_SET_THROW ); - OString aUTF8Password( OUStringToOString( aPassword, RTL_TEXTENCODING_UTF8 ) ); - xDigestContext->updateDigest( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aUTF8Password.getStr() ), aUTF8Password.getLength() ) ); - uno::Sequence< sal_Int8 > aDigest = xDigestContext->finalizeDigestAndDispose(); + std::vector<unsigned char> const hash(comphelper::Hash::calculateHash( + reinterpret_cast<unsigned char const*>(aUTF8Password.getStr()), aUTF8Password.getLength(), + comphelper::HashType::SHA256)); + uno::Sequence<sal_Int8> aDigest(reinterpret_cast<const sal_Int8*>(hash.data()), hash.size()); - aEncryptionData.realloc( ++nSha1Ind ); - aEncryptionData[0].Name = PACKAGE_ENCRYPTIONDATA_SHA256UTF8; - aEncryptionData[0].Value <<= aDigest; + ++nSha1Ind; + aEncryptionData = { { PACKAGE_ENCRYPTIONDATA_SHA256UTF8, uno::Any(aDigest) } }; } catch ( uno::Exception& ) { - OSL_ENSURE( false, "Can not create SHA256 digest!" ); + TOOLS_WARN_EXCEPTION("comphelper", "Can not create SHA256 digest!" ); + throw; // tdf#159519 DO NOT RETURN SUCCESS } // MS_1252 encoding was used for SO60 document format password encoding, // this encoding supports only a minor subset of nonascii characters, // but for compatibility reasons it has to be used for old document formats aEncryptionData.realloc( nSha1Ind + 3 ); + auto pEncryptionData = aEncryptionData.getArray(); // these are StarOffice not-quite-SHA1 - aEncryptionData[nSha1Ind].Name = PACKAGE_ENCRYPTIONDATA_SHA1UTF8; - aEncryptionData[nSha1Ind + 1].Name = PACKAGE_ENCRYPTIONDATA_SHA1MS1252; + pEncryptionData[nSha1Ind].Name = PACKAGE_ENCRYPTIONDATA_SHA1UTF8; + pEncryptionData[nSha1Ind + 1].Name = PACKAGE_ENCRYPTIONDATA_SHA1MS1252; rtl_TextEncoding const pEncoding[2] = { RTL_TEXTENCODING_UTF8, RTL_TEXTENCODING_MS_1252 }; @@ -430,20 +411,20 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreatePackageEncryptionData( if ( nError != rtl_Digest_E_None ) { aEncryptionData.realloc( nSha1Ind ); - break; + return aEncryptionData; } // coverity[overrun-buffer-arg : FALSE] - coverity has difficulty with css::uno::Sequence - aEncryptionData[nSha1Ind+nInd].Value <<= uno::Sequence< sal_Int8 >( reinterpret_cast<sal_Int8*>(pBuffer), RTL_DIGEST_LENGTH_SHA1 ); + pEncryptionData[nSha1Ind+nInd].Value <<= uno::Sequence< sal_Int8 >( reinterpret_cast<sal_Int8*>(pBuffer), RTL_DIGEST_LENGTH_SHA1 ); } // actual SHA1 - aEncryptionData[nSha1Ind + 2].Name = PACKAGE_ENCRYPTIONDATA_SHA1CORRECT; + pEncryptionData[nSha1Ind + 2].Name = PACKAGE_ENCRYPTIONDATA_SHA1CORRECT; OString aByteStrPass = OUStringToOString(aPassword, RTL_TEXTENCODING_UTF8); std::vector<unsigned char> const sha1(::comphelper::Hash::calculateHash( reinterpret_cast<unsigned char const*>(aByteStrPass.getStr()), aByteStrPass.getLength(), ::comphelper::HashType::SHA1)); - aEncryptionData[nSha1Ind + 2].Value <<= uno::Sequence<sal_Int8>( + pEncryptionData[nSha1Ind + 2].Value <<= uno::Sequence<sal_Int8>( reinterpret_cast<sal_Int8 const*>(sha1.data()), sha1.size()); } @@ -460,14 +441,14 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat // get 32 random chars out of it uno::Sequence < sal_Int8 > aVector(32); - rtl_random_getBytes( aRandomPool, aVector.getArray(), aVector.getLength() ); + if (rtl_random_getBytes(aRandomPool, aVector.getArray(), aVector.getLength()) != rtl_Random_E_None) + { + throw uno::RuntimeException("rtl_random_getBytes failed"); + } rtl_random_destroyPool(aRandomPool); - uno::Sequence< beans::NamedValue > aContainer(2); std::vector< uno::Sequence< beans::NamedValue > > aGpgEncryptions; - uno::Sequence< beans::NamedValue > aGpgEncryptionEntry(3); - uno::Sequence< beans::NamedValue > aEncryptionData(1); uno::Reference< security::XDocumentDigitalSignatures > xSigner( // here none of the version-dependent methods are called @@ -489,22 +470,28 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat if (err) throw uno::RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); - ctx.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP) ); - if (ctx == nullptr) - throw uno::RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); - ctx->setArmor(false); - + bool bResetContext = true; for (const auto & cert : xSignCertificates) { + if (bResetContext) + { + bResetContext = false; + ctx.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP) ); + if (ctx == nullptr) + throw uno::RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + ctx->setArmor(false); + } + uno::Sequence < sal_Int8 > aKeyID; if (cert.is()) aKeyID = cert->getSHA1Thumbprint(); - std::vector<GpgME::Key> keys; - keys.push_back( + std::vector<GpgME::Key> keys + { ctx->key( reinterpret_cast<const char*>(aKeyID.getConstArray()), - err, false)); + err, false) + }; // ctx is setup now, let's encrypt the lot! GpgME::Data plain( @@ -516,6 +503,29 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat keys, plain, cipher, GpgME::Context::NoCompress); + // tdf#160184 ask user if they want to trust an untrusted certificate + // gpgme contexts uses the "auto" trust model by default which only + // allows encrypting with keys that have their trust level set to + // "Ultimate". The gpg command, however, gives the user the option + // to encrypt with a certificate that has a lower trust level so + // emulate that behavior by asking the user if they want to trust + // the certificate for just this operation only. + if (crypt_res.error().code() == GPG_ERR_UNUSABLE_PUBKEY) + { + if (xSigner->trustUntrustedCertificate(cert)) + { + // Reset the trust model back to "auto" before processing + // the next certificate + bResetContext = true; + + ctx->setFlag("trust-model", "tofu+pgp"); + ctx->setFlag("tofu-default-policy", "unknown"); + crypt_res = ctx->encrypt( + keys, plain, + cipher, GpgME::Context::NoCompress); + } + } + off_t result = cipher.seek(0,SEEK_SET); (void) result; assert(result == 0); @@ -536,23 +546,21 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat SAL_INFO("comphelper.crypto", "Generated gpg crypto of length: " << len); - aGpgEncryptionEntry[0].Name = "KeyId"; - aGpgEncryptionEntry[0].Value <<= aKeyID; - aGpgEncryptionEntry[1].Name = "KeyPacket"; - aGpgEncryptionEntry[1].Value <<= aKeyID; - aGpgEncryptionEntry[2].Name = "CipherValue"; - aGpgEncryptionEntry[2].Value <<= aCipherValue; + uno::Sequence< beans::NamedValue > aGpgEncryptionEntry{ + { "KeyId", uno::Any(aKeyID) }, + { "KeyPacket", uno::Any(aKeyID) }, + { "CipherValue", uno::Any(aCipherValue) } + }; aGpgEncryptions.push_back(aGpgEncryptionEntry); } - aEncryptionData[0].Name = PACKAGE_ENCRYPTIONDATA_SHA256UTF8; - aEncryptionData[0].Value <<= aVector; + uno::Sequence<beans::NamedValue> aEncryptionData + = { { PACKAGE_ENCRYPTIONDATA_SHA256UTF8, uno::Any(aVector) } }; - aContainer[0].Name = "GpgInfos"; - aContainer[0].Value <<= comphelper::containerToSequence(aGpgEncryptions); - aContainer[1].Name = "EncryptionKey"; - aContainer[1].Value <<= aEncryptionData; + uno::Sequence<beans::NamedValue> aContainer + = { { "GpgInfos", uno::Any(comphelper::containerToSequence(aGpgEncryptions)) }, + { "EncryptionKey", uno::Any(aEncryptionData) } }; return aContainer; #else @@ -560,18 +568,11 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat #endif } -bool OStorageHelper::IsValidZipEntryFileName( const OUString& aName, bool bSlashAllowed ) -{ - return IsValidZipEntryFileName( aName.getStr(), aName.getLength(), bSlashAllowed ); -} - - -bool OStorageHelper::IsValidZipEntryFileName( - const sal_Unicode *pChar, sal_Int32 nLength, bool bSlashAllowed ) +bool OStorageHelper::IsValidZipEntryFileName( std::u16string_view aName, bool bSlashAllowed ) { - for ( sal_Int32 i = 0; i < nLength; i++ ) + for ( size_t i = 0; i < aName.size(); i++ ) { - switch ( pChar[i] ) + switch ( aName[i] ) { case '\\': case '?': @@ -586,7 +587,7 @@ bool OStorageHelper::IsValidZipEntryFileName( return false; break; default: - if ( pChar[i] < 32 || (pChar[i] >= 0xD800 && pChar[i] <= 0xDFFF) ) + if ( aName[i] < 32 || (aName[i] >= 0xD800 && aName[i] <= 0xDFFF) ) return false; } } @@ -594,27 +595,27 @@ bool OStorageHelper::IsValidZipEntryFileName( } -bool OStorageHelper::PathHasSegment( const OUString& aPath, const OUString& aSegment ) +bool OStorageHelper::PathHasSegment( std::u16string_view aPath, std::u16string_view aSegment ) { bool bResult = false; - const sal_Int32 nPathLen = aPath.getLength(); - const sal_Int32 nSegLen = aSegment.getLength(); + const size_t nPathLen = aPath.size(); + const size_t nSegLen = aSegment.size(); - if ( !aSegment.isEmpty() && nPathLen >= nSegLen ) + if ( !aSegment.empty() && nPathLen >= nSegLen ) { - OUString aEndSegment = "/" + aSegment; + OUString aEndSegment = OUString::Concat("/") + aSegment; OUString aInternalSegment = aEndSegment + "/"; - if ( aPath.indexOf( aInternalSegment ) >= 0 ) + if ( aPath.find( aInternalSegment ) != std::u16string_view::npos ) bResult = true; - if ( !bResult && aPath.startsWith( aSegment ) ) + if ( !bResult && o3tl::starts_with(aPath, aSegment ) ) { if ( nPathLen == nSegLen || aPath[nSegLen] == '/' ) bResult = true; } - if ( !bResult && nPathLen > nSegLen && aPath.subView( nPathLen - nSegLen - 1, nSegLen + 1 ) == aEndSegment ) + if ( !bResult && nPathLen > nSegLen && aPath.substr( nPathLen - nSegLen - 1, nSegLen + 1 ) == aEndSegment ) bResult = true; } @@ -639,11 +640,10 @@ void LifecycleProxy::commitStorages() }); } -static void splitPath( std::vector<OUString> &rElems, - const OUString& rPath ) +static void splitPath( std::vector<OUString> &rElems, std::u16string_view rPath ) { for (sal_Int32 i = 0; i >= 0;) - rElems.push_back( rPath.getToken( 0, '/', i ) ); + rElems.push_back( OUString(o3tl::getToken(rPath, 0, '/', i )) ); } static uno::Reference< embed::XStorage > LookupStorageAtPath( @@ -663,7 +663,7 @@ static uno::Reference< embed::XStorage > LookupStorageAtPath( uno::Reference< embed::XStorage > OStorageHelper::GetStorageAtPath( const uno::Reference< embed::XStorage > &xStorage, - const OUString& rPath, sal_uInt32 nOpenMode, + std::u16string_view rPath, sal_uInt32 nOpenMode, LifecycleProxy const &rNastiness ) { std::vector<OUString> aElems; @@ -673,7 +673,7 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageAtPath( uno::Reference< io::XStream > OStorageHelper::GetStreamAtPath( const uno::Reference< embed::XStorage > &xParentStorage, - const OUString& rPath, sal_uInt32 nOpenMode, + std::u16string_view rPath, sal_uInt32 nOpenMode, LifecycleProxy const &rNastiness ) { std::vector<OUString> aElems; diff --git a/comphelper/source/misc/string.cxx b/comphelper/source/misc/string.cxx index ba84ff032b66..446e500e0250 100644 --- a/comphelper/source/misc/string.cxx +++ b/comphelper/source/misc/string.cxx @@ -19,16 +19,21 @@ #include <sal/config.h> +#include <cassert> #include <cstddef> #include <string_view> +#include <utility> #include <vector> #include <algorithm> +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> #include <rtl/character.hxx> #include <rtl/ustring.hxx> #include <rtl/ustrbuf.hxx> #include <rtl/string.hxx> #include <rtl/strbuf.hxx> +#include <sal/log.hxx> #include <sal/types.h> #include <comphelper/string.hxx> @@ -47,6 +52,23 @@ namespace template <typename T, typename C> T tmpl_stripStart(const T &rIn, const C cRemove) { + if (rIn.empty()) + return rIn; + + typename T::size_type i = 0; + + while (i < rIn.size()) + { + if (rIn[i] != cRemove) + break; + ++i; + } + + return rIn.substr(i); + } + template <typename T, typename C> T tmpl_stripStartString(const T &rIn, + const C cRemove) + { if (rIn.isEmpty()) return rIn; @@ -63,14 +85,24 @@ namespace } } -OString stripStart(const OString &rIn, char c) +OString stripStart(const OString& rIn, char c) { - return tmpl_stripStart<OString, char>(rIn, c); + return tmpl_stripStartString<OString, char>(rIn, c); } -OUString stripStart(const OUString &rIn, sal_Unicode c) +std::string_view stripStart(std::string_view rIn, char c) { - return tmpl_stripStart<OUString, sal_Unicode>(rIn, c); + return tmpl_stripStart<std::string_view, char>(rIn, c); +} + +OUString stripStart(const OUString& rIn, sal_Unicode c) +{ + return tmpl_stripStartString<OUString, sal_Unicode>(rIn, c); +} + +std::u16string_view stripStart(std::u16string_view rIn, sal_Unicode c) +{ + return tmpl_stripStart<std::u16string_view, sal_Unicode>(rIn, c); } namespace @@ -78,6 +110,23 @@ namespace template <typename T, typename C> T tmpl_stripEnd(const T &rIn, const C cRemove) { + if (rIn.empty()) + return rIn; + + typename T::size_type i = rIn.size(); + + while (i > 0) + { + if (rIn[i-1] != cRemove) + break; + --i; + } + + return rIn.substr(0, i); + } + template <typename T, typename C> T tmpl_stripEndString(const T &rIn, + const C cRemove) + { if (rIn.isEmpty()) return rIn; @@ -94,37 +143,108 @@ namespace } } -OString stripEnd(const OString &rIn, char c) +OString stripEnd(const OString& rIn, char c) +{ + return tmpl_stripEndString<OString, char>(rIn, c); +} + +std::string_view stripEnd(std::string_view rIn, char c) +{ + return tmpl_stripEnd<std::string_view, char>(rIn, c); +} + +OUString stripEnd(const OUString& rIn, sal_Unicode c) +{ + return tmpl_stripEndString<OUString, sal_Unicode>(rIn, c); +} + +std::u16string_view stripEnd(std::u16string_view rIn, sal_Unicode c) +{ + return tmpl_stripEnd<std::u16string_view, sal_Unicode>(rIn, c); +} + +namespace +{ + template <typename T, typename C> T tmpl_strip(const T &rIn, + const C cRemove) + { + if (rIn.empty()) + return rIn; + + typename T::size_type end = rIn.size(); + while (end > 0) + { + if (rIn[end-1] != cRemove) + break; + --end; + } + + typename T::size_type start = 0; + while (start < end) + { + if (rIn[start] != cRemove) + break; + ++start; + } + + return rIn.substr(start, end - start); + } + template <typename T, typename C> T tmpl_stripString(const T &rIn, + const C cRemove) + { + if (rIn.isEmpty()) + return rIn; + + sal_Int32 end = rIn.getLength(); + while (end > 0) + { + if (rIn[end-1] != cRemove) + break; + --end; + } + sal_Int32 start = 0; + while (start < end) + { + if (rIn[start] != cRemove) + break; + ++start; + } + + return rIn.copy(start, end - start); + } +} + +OString strip(const OString& rIn, char c) { - return tmpl_stripEnd<OString, char>(rIn, c); + return tmpl_stripString<OString, char>(rIn, c); } -OUString stripEnd(const OUString &rIn, sal_Unicode c) +std::string_view strip(std::string_view rIn, char c) { - return tmpl_stripEnd<OUString, sal_Unicode>(rIn, c); + return tmpl_strip<std::string_view, char>(rIn, c); } -OString strip(const OString &rIn, char c) +OUString strip(const OUString& rIn, sal_Unicode c) { - return stripEnd(stripStart(rIn, c), c); + return tmpl_stripString<OUString, sal_Unicode>(rIn, c); } -OUString strip(const OUString &rIn, sal_Unicode c) +std::u16string_view strip(std::u16string_view rIn, sal_Unicode c) { - return stripEnd(stripStart(rIn, c), c); + return tmpl_strip<std::u16string_view, sal_Unicode>(rIn, c); } namespace { - template <typename T, typename C> sal_Int32 tmpl_getTokenCount(const T &rIn, + template <typename T, typename C> sal_Int32 tmpl_getTokenCount( T rIn, C cTok) { // Empty String: TokenCount by Definition is 0 - if (rIn.isEmpty()) + if (rIn.empty()) return 0; sal_Int32 nTokCount = 1; - for (sal_Int32 i = 0; i < rIn.getLength(); ++i) + for (typename T::size_type i = 0; i < rIn.size(); ++i) { if (rIn[i] == cTok) ++nTokCount; @@ -133,23 +253,22 @@ namespace } } -sal_Int32 getTokenCount(const OString &rIn, char cTok) +sal_Int32 getTokenCount(std::string_view rIn, char cTok) { - return tmpl_getTokenCount<OString, char>(rIn, cTok); + return tmpl_getTokenCount<std::string_view, char>(rIn, cTok); } -sal_Int32 getTokenCount(const OUString &rIn, sal_Unicode cTok) +sal_Int32 getTokenCount(std::u16string_view rIn, sal_Unicode cTok) { - return tmpl_getTokenCount<OUString, sal_Unicode>(rIn, cTok); + return tmpl_getTokenCount<std::u16string_view, sal_Unicode>(rIn, cTok); } -static sal_uInt32 decimalStringToNumber( - OUString const & str, sal_Int32 nStart, sal_Int32 nLength ) +sal_uInt32 decimalStringToNumber(std::u16string_view str) { sal_uInt32 result = 0; - for( sal_Int32 i = nStart; i < nStart + nLength; ) + for( std::size_t i = 0; i < str.size(); ) { - sal_uInt32 c = str.iterateCodePoints(&i); + sal_uInt32 c = o3tl::iterateCodePoints(str, &i); sal_uInt32 value = 0; if( c <= 0x0039) // ASCII decimal digits, most common value = c - 0x0030; @@ -240,12 +359,6 @@ static sal_uInt32 decimalStringToNumber( return result; } -sal_uInt32 decimalStringToNumber( - OUString const & str ) -{ - return decimalStringToNumber(str, 0, str.getLength()); -} - using namespace ::com::sun::star; // convert between sequence of string and comma separated string @@ -260,33 +373,32 @@ OUString convertCommaSeparated( } std::vector<OUString> - split(const OUString& rStr, sal_Unicode cSeparator) + split(std::u16string_view rStr, sal_Unicode cSeparator) { std::vector< OUString > vec; - sal_Int32 idx = 0; + std::size_t idx = 0; do { - OUString kw = - rStr.getToken(0, cSeparator, idx); - kw = kw.trim(); - if (!kw.isEmpty()) + std::u16string_view kw = o3tl::getToken(rStr, cSeparator, idx); + kw = o3tl::trim(kw); + if (!kw.empty()) { - vec.push_back(kw); + vec.push_back(OUString(kw)); } - } while (idx >= 0); + } while (idx != std::u16string_view::npos); return vec; } uno::Sequence< OUString > - convertCommaSeparated( OUString const& i_rString ) + convertCommaSeparated( std::u16string_view i_rString ) { std::vector< OUString > vec = split(i_rString, ','); return comphelper::containerToSequence(vec); } -OString join(const OString& rSeparator, const std::vector<OString>& rSequence) +OString join(std::string_view rSeparator, const std::vector<OString>& rSequence) { OStringBuffer aBuffer; for (size_t i = 0; i < rSequence.size(); ++i) @@ -310,33 +422,50 @@ sal_Int32 compareNatural( const OUString & rLHS, const OUString & rRHS, sal_Int32 nLHSFirstDigitPos = 0; sal_Int32 nRHSFirstDigitPos = 0; + // Check if the string starts with a digit + sal_Int32 nStartsDigitLHS = rBI->endOfCharBlock(rLHS, nLHSFirstDigitPos, rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + sal_Int32 nStartsDigitRHS = rBI->endOfCharBlock(rRHS, nRHSFirstDigitPos, rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + + if (nStartsDigitLHS > 0 && nStartsDigitRHS > 0) + { + sal_uInt32 nLHS = comphelper::string::decimalStringToNumber(rLHS.subView(0, nStartsDigitLHS)); + sal_uInt32 nRHS = comphelper::string::decimalStringToNumber(rRHS.subView(0, nStartsDigitRHS)); + + if (nLHS != nRHS) + return nLHS < nRHS ? -1 : 1; + nLHSLastNonDigitPos = nStartsDigitLHS; + nRHSLastNonDigitPos = nStartsDigitRHS; + } + else if (nStartsDigitLHS > 0) + return -1; + else if (nStartsDigitRHS > 0) + return 1; + while (nLHSFirstDigitPos < rLHS.getLength() || nRHSFirstDigitPos < rRHS.getLength()) { sal_Int32 nLHSChunkLen; sal_Int32 nRHSChunkLen; //Compare non digit block as normal strings - nLHSFirstDigitPos = rBI->nextCharBlock(rLHS, nLHSLastNonDigitPos, - rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); - nRHSFirstDigitPos = rBI->nextCharBlock(rRHS, nRHSLastNonDigitPos, - rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + nLHSFirstDigitPos = rBI->nextCharBlock(rLHS, nLHSLastNonDigitPos, rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + nRHSFirstDigitPos = rBI->nextCharBlock(rRHS, nRHSLastNonDigitPos, rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + if (nLHSFirstDigitPos == -1) nLHSFirstDigitPos = rLHS.getLength(); + if (nRHSFirstDigitPos == -1) nRHSFirstDigitPos = rRHS.getLength(); + nLHSChunkLen = nLHSFirstDigitPos - nLHSLastNonDigitPos; nRHSChunkLen = nRHSFirstDigitPos - nRHSLastNonDigitPos; - nRet = rCollator->compareSubstring(rLHS, nLHSLastNonDigitPos, - nLHSChunkLen, rRHS, nRHSLastNonDigitPos, nRHSChunkLen); + nRet = rCollator->compareSubstring(rLHS, nLHSLastNonDigitPos, nLHSChunkLen, rRHS, nRHSLastNonDigitPos, nRHSChunkLen); if (nRet != 0) break; //Compare digit block as one number vs another - nLHSLastNonDigitPos = rBI->endOfCharBlock(rLHS, nLHSFirstDigitPos, - rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); - nRHSLastNonDigitPos = rBI->endOfCharBlock(rRHS, nRHSFirstDigitPos, - rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + nLHSLastNonDigitPos = rBI->endOfCharBlock(rLHS, nLHSFirstDigitPos, rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + nRHSLastNonDigitPos = rBI->endOfCharBlock(rRHS, nRHSFirstDigitPos, rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); if (nLHSLastNonDigitPos == -1) nLHSLastNonDigitPos = rLHS.getLength(); if (nRHSLastNonDigitPos == -1) @@ -348,8 +477,8 @@ sal_Int32 compareNatural( const OUString & rLHS, const OUString & rRHS, //numbers outside of the normal 0-9 range, e.g. see GetLocalizedChar in //vcl - sal_uInt32 nLHS = comphelper::string::decimalStringToNumber(rLHS, nLHSFirstDigitPos, nLHSChunkLen); - sal_uInt32 nRHS = comphelper::string::decimalStringToNumber(rRHS, nRHSFirstDigitPos, nRHSChunkLen); + sal_uInt32 nLHS = comphelper::string::decimalStringToNumber(rLHS.subView(nLHSFirstDigitPos, nLHSChunkLen)); + sal_uInt32 nRHS = comphelper::string::decimalStringToNumber(rRHS.subView(nRHSFirstDigitPos, nRHSChunkLen)); if (nLHS != nRHS) { @@ -363,56 +492,52 @@ sal_Int32 compareNatural( const OUString & rLHS, const OUString & rRHS, NaturalStringSorter::NaturalStringSorter( const uno::Reference< uno::XComponentContext > &rContext, - const lang::Locale &rLocale) : m_aLocale(rLocale) + lang::Locale aLocale) : m_aLocale(std::move(aLocale)) { m_xCollator = i18n::Collator::create( rContext ); m_xCollator->loadDefaultCollator(m_aLocale, 0); m_xBI = i18n::BreakIterator::create( rContext ); } -bool isdigitAsciiString(const OString &rString) +bool isdigitAsciiString(std::string_view rString) { return std::all_of( - rString.getStr(), rString.getStr() + rString.getLength(), + rString.data(), rString.data() + rString.size(), [](unsigned char c){ return rtl::isAsciiDigit(c); }); } -bool isdigitAsciiString(const OUString &rString) +bool isdigitAsciiString(std::u16string_view rString) { return std::all_of( - rString.getStr(), rString.getStr() + rString.getLength(), + rString.data(), rString.data() + rString.size(), [](sal_Unicode c){ return rtl::isAsciiDigit(c); }); } -namespace +OUString reverseString(std::u16string_view rStr) { - template <typename T, typename O> T tmpl_reverseString(const T &rIn) - { - if (rIn.isEmpty()) - return rIn; - - sal_Int32 i = rIn.getLength(); - O sBuf(i); - while (i) - sBuf.append(rIn[--i]); - return sBuf.makeStringAndClear(); - } -} - -OUString reverseString(const OUString &rStr) -{ - return tmpl_reverseString<OUString, OUStringBuffer>(rStr); + if (rStr.empty()) + return OUString(); + + std::size_t i = rStr.size(); + OUStringBuffer sBuf(static_cast<sal_Int32>(i)); + while (i) + sBuf.append(rStr[--i]); + return sBuf.makeStringAndClear(); } -OString reverseString(const OString &rStr) -{ - return tmpl_reverseString<OString, OStringBuffer>(rStr); +OUString reverseCodePoints(std::u16string_view str) { + auto const len = str.size(); + OUStringBuffer buf(len); + for (sal_Int32 i = len; i != 0;) { + buf.appendUtf32(o3tl::iterateCodePoints(str, &i, -1)); + } + return buf.makeStringAndClear(); } -sal_Int32 indexOfAny(OUString const& rIn, +sal_Int32 indexOfAny(std::u16string_view rIn, sal_Unicode const*const pChars, sal_Int32 const nPos) { - for (sal_Int32 i = nPos; i < rIn.getLength(); ++i) + for (std::u16string_view::size_type i = nPos; i < rIn.size(); ++i) { sal_Unicode const c = rIn[i]; for (sal_Unicode const* pChar = pChars; *pChar; ++pChar) @@ -426,12 +551,12 @@ sal_Int32 indexOfAny(OUString const& rIn, return -1; } -OUString removeAny(OUString const& rIn, +OUString removeAny(std::u16string_view rIn, sal_Unicode const*const pChars) { OUStringBuffer buf; bool isFound(false); - for (sal_Int32 i = 0; i < rIn.getLength(); ++i) + for (std::u16string_view::size_type i = 0; i < rIn.size(); ++i) { sal_Unicode const c = rIn[i]; bool removeC(false); @@ -449,7 +574,7 @@ OUString removeAny(OUString const& rIn, { if (i > 0) { - buf.append(std::u16string_view(rIn).substr(0, i)); + buf.append(rIn.substr(0, i)); } isFound = true; } @@ -459,11 +584,11 @@ OUString removeAny(OUString const& rIn, buf.append(c); } } - return isFound ? buf.makeStringAndClear() : rIn; + return isFound ? buf.makeStringAndClear() : OUString(rIn); } OUString setToken(const OUString& rIn, sal_Int32 nToken, sal_Unicode cTok, - const OUString& rNewToken) + std::u16string_view rNewToken) { sal_Int32 nLen = rIn.getLength(); sal_Int32 nTok = 0; @@ -492,6 +617,62 @@ OUString setToken(const OUString& rIn, sal_Int32 nToken, sal_Unicode cTok, return rIn; } +/** Similar to OUString::replaceAt, but for an OUStringBuffer. + + Replace n = count characters + from position index in this string with newStr. + */ +void replaceAt(OUStringBuffer& rIn, sal_Int32 nIndex, sal_Int32 nCount, std::u16string_view newStr ) +{ + assert(nIndex >= 0 && nIndex <= rIn.getLength()); + assert(nCount >= 0); + assert(nCount <= rIn.getLength() - nIndex); + + /* Append? */ + const sal_Int32 nOldLength = rIn.getLength(); + if ( nIndex == nOldLength ) + { + rIn.append(newStr); + return; + } + + sal_Int32 nNewLength = nOldLength + newStr.size() - nCount; + if (newStr.size() > o3tl::make_unsigned(nCount)) + rIn.ensureCapacity(nOldLength + newStr.size() - nCount); + + sal_Unicode* pStr = const_cast<sal_Unicode*>(rIn.getStr()); + memmove(pStr + nIndex + newStr.size(), pStr + nIndex + nCount, nOldLength - nIndex + nCount); + memcpy(pStr + nIndex, newStr.data(), newStr.size()); + + rIn.setLength(nNewLength); +} + +OUString sanitizeStringSurrogates(const OUString& rString) +{ + sal_Int32 i=0; + while (i < rString.getLength()) + { + sal_Unicode c = rString[i]; + if (rtl::isHighSurrogate(c)) + { + if (i+1 == rString.getLength() + || !rtl::isLowSurrogate(rString[i+1])) + { + SAL_WARN("comphelper", "Surrogate error: high without low"); + return rString.copy(0, i); + } + ++i; //skip correct low + } + if (rtl::isLowSurrogate(c)) //bare low without preceding high + { + SAL_WARN("comphelper", "Surrogate error: low without high"); + return rString.copy(0, i); + } + ++i; + } + return rString; +} + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/synchronousdispatch.cxx b/comphelper/source/misc/synchronousdispatch.cxx index a09f05db8331..1602c8963fb1 100644 --- a/comphelper/source/misc/synchronousdispatch.cxx +++ b/comphelper/source/misc/synchronousdispatch.cxx @@ -65,7 +65,9 @@ uno::Reference< lang::XComponent > SynchronousDispatch::dispatch( } catch ( uno::Exception& ) { - SAL_WARN("comphelper","SynchronousDispatch::dispatch() Error while dispatching!"); + // can't use TOOLS_WARN_EXCEPTION, as comphelper is used by libtl! + SAL_WARN("comphelper", "SynchronousDispatch::dispatch(): error while dispatching '" + << sURL << "' for '" << sTarget << "'!"); } } diff --git a/comphelper/source/misc/syntaxhighlight.cxx b/comphelper/source/misc/syntaxhighlight.cxx index f6eccc7b4fc3..89dcb73752e4 100644 --- a/comphelper/source/misc/syntaxhighlight.cxx +++ b/comphelper/source/misc/syntaxhighlight.cxx @@ -22,6 +22,7 @@ #include <cassert> #include <rtl/character.hxx> +#include <rtl/ustring.hxx> #include <unicode/uchar.h> #include <comphelper/syntaxhighlight.hxx> #include <o3tl/typed_flags_set.hxx> @@ -279,8 +280,8 @@ class SyntaxHighlighter::Tokenizer bool testCharFlags(sal_Unicode c, CharFlags nTestFlags) const; // Get new token, EmptyString == nothing more over there - bool getNextToken(const sal_Unicode*& pos, /*out*/TokenType& reType, - /*out*/const sal_Unicode*& rpStartPos, /*out*/const sal_Unicode*& rpEndPos) const; + bool getNextToken(std::u16string_view::const_iterator& pos, std::u16string_view::const_iterator end, /*out*/TokenType& reType, + /*out*/std::u16string_view::const_iterator& rpStartPos, /*out*/std::u16string_view::const_iterator& rpEndPos) const; const char** ppListKeyWords; sal_uInt16 nKeyWordCount; @@ -290,7 +291,7 @@ public: explicit Tokenizer( HighlighterLanguage aLang ); - void getHighlightPortions(const OUString& rLine, + void getHighlightPortions(std::u16string_view rLine, /*out*/std::vector<HighlightPortion>& portions) const; void setKeyWords( const char** ppKeyWords, sal_uInt16 nCount ); }; @@ -317,24 +318,25 @@ void SyntaxHighlighter::Tokenizer::setKeyWords( const char** ppKeyWords, sal_uIn nKeyWordCount = nCount; } -bool SyntaxHighlighter::Tokenizer::getNextToken(const sal_Unicode*& pos, /*out*/TokenType& reType, - /*out*/const sal_Unicode*& rpStartPos, /*out*/const sal_Unicode*& rpEndPos) const +bool SyntaxHighlighter::Tokenizer::getNextToken(std::u16string_view::const_iterator& pos, std::u16string_view::const_iterator end, + /*out*/TokenType& reType, + /*out*/std::u16string_view::const_iterator& rpStartPos, /*out*/std::u16string_view::const_iterator& rpEndPos) const { reType = TokenType::Unknown; rpStartPos = pos; - sal_Unicode c = *pos; - if( c == 0 ) + if( pos == end ) return false; + sal_Unicode c = *pos; ++pos; //*** Go through all possibilities *** // Space? if ( testCharFlags( c, CharFlags::Space ) ) { - while( testCharFlags( *pos, CharFlags::Space ) ) + while( pos != end && testCharFlags( *pos, CharFlags::Space ) ) ++pos; reType = TokenType::Whitespace; @@ -346,6 +348,8 @@ bool SyntaxHighlighter::Tokenizer::getNextToken(const sal_Unicode*& pos, /*out*/ bool bIdentifierChar; do { + if (pos == end) + break; // Fetch next character c = *pos; bIdentifierChar = testCharFlags( c, CharFlags::InIdentifier ); @@ -374,7 +378,7 @@ bool SyntaxHighlighter::Tokenizer::getNextToken(const sal_Unicode*& pos, /*out*/ if( bCanBeKeyword ) { - OUString aKWString(rpStartPos, nCount); + std::u16string_view aKWString(&*rpStartPos, nCount); OString aByteStr = OUStringToOString(aKWString, RTL_TEXTENCODING_ASCII_US).toAsciiLowerCase(); if ( bsearch( aByteStr.getStr(), ppListKeyWords, nKeyWordCount, sizeof( char* ), @@ -385,10 +389,14 @@ bool SyntaxHighlighter::Tokenizer::getNextToken(const sal_Unicode*& pos, /*out*/ if( aByteStr == "rem" ) { // Remove all characters until end of line or EOF - sal_Unicode cPeek = *pos; - while( cPeek != 0 && !testCharFlags( cPeek, CharFlags::EOL ) ) + for (;;) { - cPeek = *++pos; + if (pos == end) + break; + sal_Unicode cPeek = *pos; + if ( testCharFlags( cPeek, CharFlags::EOL ) ) + break; + ++pos; } reType = TokenType::Comment; @@ -411,6 +419,8 @@ bool SyntaxHighlighter::Tokenizer::getNextToken(const sal_Unicode*& pos, /*out*/ do { // Get next character + if (pos == end) + break; c = *pos; bIdentifierChar = isAlpha(c); if( bIdentifierChar ) @@ -422,14 +432,12 @@ bool SyntaxHighlighter::Tokenizer::getNextToken(const sal_Unicode*& pos, /*out*/ } else if ((c=='-') && (aLanguage == HighlighterLanguage::SQL)) { - sal_Unicode cPeekNext = *pos; - if (cPeekNext=='-') + if (pos != end && *pos=='-') { // Remove all characters until end of line or EOF - while( cPeekNext != 0 && !testCharFlags( cPeekNext, CharFlags::EOL ) ) + while( pos != end && !testCharFlags( *pos, CharFlags::EOL ) ) { ++pos; - cPeekNext = *pos; } reType = TokenType::Comment; } @@ -438,14 +446,12 @@ bool SyntaxHighlighter::Tokenizer::getNextToken(const sal_Unicode*& pos, /*out*/ } else if ((c=='/') && (aLanguage == HighlighterLanguage::SQL)) { - sal_Unicode cPeekNext = *pos; - if (cPeekNext=='/') + if (pos != end && *pos=='/') { // Remove all characters until end of line or EOF - while( cPeekNext != 0 && !testCharFlags( cPeekNext, CharFlags::EOL ) ) + while( pos != end && !testCharFlags( *pos, CharFlags::EOL ) ) { ++pos; - cPeekNext = *pos; } reType = TokenType::Comment; } @@ -459,8 +465,10 @@ bool SyntaxHighlighter::Tokenizer::getNextToken(const sal_Unicode*& pos, /*out*/ { // Skip all characters until end of input or end of line: for (;;) { + if (pos == end) + break; c = *pos; - if (c == 0 || testCharFlags(c, CharFlags::EOL)) { + if (testCharFlags(c, CharFlags::EOL)) { break; } ++pos; @@ -480,7 +488,7 @@ bool SyntaxHighlighter::Tokenizer::getNextToken(const sal_Unicode*& pos, /*out*/ } // Object separator? Must be handled before Number - else if( c == '.' && ( *pos < '0' || *pos > '9' ) ) + else if( c == '.' && ( pos == end || *pos < '0' || *pos > '9' ) ) { reType = TokenType::Operator; } @@ -497,25 +505,25 @@ bool SyntaxHighlighter::Tokenizer::getNextToken(const sal_Unicode*& pos, /*out*/ if( c == '&' ) { // Octal? - if( *pos == 'o' || *pos == 'O' ) + if( pos != end && (*pos == 'o' || *pos == 'O' )) { // remove o ++pos; nRadix = 8; // Octal base // Read all numbers - while( testCharFlags( *pos, CharFlags::InOctNumber ) ) + while( pos != end && testCharFlags( *pos, CharFlags::InOctNumber ) ) ++pos; } // Hexadecimal? - else if( *pos == 'h' || *pos == 'H' ) + else if( pos != end && (*pos == 'h' || *pos == 'H' )) { // remove x ++pos; nRadix = 16; // Hexadecimal base // Read all numbers - while( testCharFlags( *pos, CharFlags::InHexNumber ) ) + while( pos != end && testCharFlags( *pos, CharFlags::InHexNumber ) ) ++pos; } else @@ -531,9 +539,9 @@ bool SyntaxHighlighter::Tokenizer::getNextToken(const sal_Unicode*& pos, /*out*/ bool bAfterExpChar = false; // Read all numbers - while( testCharFlags( *pos, CharFlags::InNumber ) || + while( pos != end && (testCharFlags( *pos, CharFlags::InNumber ) || (bAfterExpChar && *pos == '+' ) || - (bAfterExpChar && *pos == '-' ) ) + (bAfterExpChar && *pos == '-' ) )) // After exponent +/- are OK, too { c = *pos++; @@ -551,10 +559,10 @@ bool SyntaxHighlighter::Tokenizer::getNextToken(const sal_Unicode*& pos, /*out*/ cEndString = ']'; // Read all characters - while( *pos != cEndString ) + while( pos == end || *pos != cEndString ) { // Detect EOF before reading next char, so we do not lose EOF - if( *pos == 0 ) + if( pos == end ) { // ERROR: unterminated string literal reType = TokenType::Error; @@ -583,9 +591,12 @@ bool SyntaxHighlighter::Tokenizer::getNextToken(const sal_Unicode*& pos, /*out*/ else if( testCharFlags( c, CharFlags::EOL ) ) { // If another EOL character comes, read it - sal_Unicode cNext = *pos; - if( cNext != c && testCharFlags( cNext, CharFlags::EOL ) ) - ++pos; + if (pos != end) + { + sal_Unicode cNext = *pos; + if( cNext != c && testCharFlags( cNext, CharFlags::EOL ) ) + ++pos; + } reType = TokenType::EOL; } @@ -676,22 +687,22 @@ SyntaxHighlighter::Tokenizer::Tokenizer( HighlighterLanguage aLang ): aLanguage( nKeyWordCount = 0; } -void SyntaxHighlighter::Tokenizer::getHighlightPortions(const OUString& rLine, +void SyntaxHighlighter::Tokenizer::getHighlightPortions(std::u16string_view rLine, /*out*/std::vector<HighlightPortion>& portions) const { // Set the position to the beginning of the source string - const sal_Unicode* pos = rLine.getStr(); + auto pos = rLine.begin(); // Variables for the out parameter TokenType eType; - const sal_Unicode* pStartPos; - const sal_Unicode* pEndPos; + std::u16string_view::const_iterator pStartPos; + std::u16string_view::const_iterator pEndPos; // Loop over all the tokens - while( getNextToken( pos, eType, pStartPos, pEndPos ) ) + while( getNextToken( pos, rLine.end(), eType, pStartPos, pEndPos ) ) { portions.emplace_back( - pStartPos - rLine.getStr(), pEndPos - rLine.getStr(), eType); + pStartPos - rLine.begin(), pEndPos - rLine.begin(), eType); } } @@ -703,11 +714,11 @@ SyntaxHighlighter::SyntaxHighlighter(HighlighterLanguage language): { case HighlighterLanguage::Basic: m_tokenizer->setKeyWords( strListBasicKeyWords, - SAL_N_ELEMENTS( strListBasicKeyWords )); + std::size( strListBasicKeyWords )); break; case HighlighterLanguage::SQL: m_tokenizer->setKeyWords( strListSqlKeyWords, - SAL_N_ELEMENTS( strListSqlKeyWords )); + std::size( strListSqlKeyWords )); break; default: assert(false); // this cannot happen @@ -716,7 +727,7 @@ SyntaxHighlighter::SyntaxHighlighter(HighlighterLanguage language): SyntaxHighlighter::~SyntaxHighlighter() {} -void SyntaxHighlighter::getHighlightPortions(const OUString& rLine, +void SyntaxHighlighter::getHighlightPortions(std::u16string_view rLine, /*out*/std::vector<HighlightPortion>& portions) const { m_tokenizer->getHighlightPortions( rLine, portions ); diff --git a/comphelper/source/misc/threadpool.cxx b/comphelper/source/misc/threadpool.cxx index 1ef0eeaaba5c..f0a71eb05168 100644 --- a/comphelper/source/misc/threadpool.cxx +++ b/comphelper/source/misc/threadpool.cxx @@ -11,15 +11,17 @@ #include <com/sun/star/uno/Exception.hpp> #include <config_options.h> +#include <o3tl/safeint.hxx> #include <sal/config.h> #include <sal/log.hxx> -#include <rtl/instance.hxx> #include <salhelper/thread.hxx> #include <algorithm> #include <memory> #include <thread> #include <chrono> +#include <cstddef> #include <comphelper/debuggerinfo.hxx> +#include <utility> #if defined HAVE_VALGRIND_HEADERS #include <valgrind/memcheck.h> @@ -91,7 +93,7 @@ public: } }; -ThreadPool::ThreadPool(sal_Int32 nWorkers) +ThreadPool::ThreadPool(std::size_t nWorkers) : mbTerminate(true) , mnMaxWorkers(nWorkers) , mnBusyWorkers(0) @@ -111,37 +113,40 @@ ThreadPool::~ThreadPool() namespace { -struct ThreadPoolStatic : public rtl::StaticWithInit< std::shared_ptr< ThreadPool >, - ThreadPoolStatic > +std::shared_ptr< ThreadPool >& GetStaticThreadPool() { - std::shared_ptr< ThreadPool > operator () () { - const sal_Int32 nThreads = ThreadPool::getPreferredConcurrency(); + static std::shared_ptr< ThreadPool > POOL = + []() + { + const std::size_t nThreads = ThreadPool::getPreferredConcurrency(); return std::make_shared< ThreadPool >( nThreads ); - }; -}; + }(); + return POOL; +} } ThreadPool& ThreadPool::getSharedOptimalPool() { - return *ThreadPoolStatic::get(); + return *GetStaticThreadPool(); } -sal_Int32 ThreadPool::getPreferredConcurrency() +std::size_t ThreadPool::getPreferredConcurrency() { - static sal_Int32 ThreadCount = [&]() + static std::size_t ThreadCount = []() { - const sal_Int32 nHardThreads = std::max(std::thread::hardware_concurrency(), 1U); - sal_Int32 nThreads = nHardThreads; + const std::size_t nHardThreads = o3tl::clamp_to_unsigned<std::size_t>( + std::max(std::thread::hardware_concurrency(), 1U)); + std::size_t nThreads = nHardThreads; const char *pEnv = getenv("MAX_CONCURRENCY"); if (pEnv != nullptr) { // Override with user/admin preference. - nThreads = rtl_str_toInt32(pEnv, 10); + nThreads = o3tl::clamp_to_unsigned<std::size_t>(rtl_str_toInt32(pEnv, 10)); } nThreads = std::min(nHardThreads, nThreads); - return std::max<sal_Int32>(nThreads, 1); + return std::max<std::size_t>(nThreads, 1); }(); return ThreadCount; @@ -303,8 +308,8 @@ bool ThreadPool::isTaskTagDone(const std::shared_ptr<ThreadTaskTag>& pTag) return pTag->isDone(); } -ThreadTask::ThreadTask(const std::shared_ptr<ThreadTaskTag>& pTag) - : mpTag(pTag) +ThreadTask::ThreadTask(std::shared_ptr<ThreadTaskTag> xTag) + : mpTag(std::move(xTag)) { } diff --git a/comphelper/source/misc/traceevent.cxx b/comphelper/source/misc/traceevent.cxx new file mode 100644 index 000000000000..1296404ebd32 --- /dev/null +++ b/comphelper/source/misc/traceevent.cxx @@ -0,0 +1,145 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <atomic> +#include <mutex> +#include <iostream> + +#include <comphelper/profilezone.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/traceevent.hxx> + +namespace comphelper +{ +#ifdef DBG_UTIL +std::atomic<bool> TraceEvent::s_bRecording = (getenv("TRACE_EVENT_RECORDING") != nullptr); +#else +std::atomic<bool> TraceEvent::s_bRecording = false; +#endif + +std::size_t TraceEvent::s_nBufferSize = 0; +void (*TraceEvent::s_pBufferFullCallback)() = nullptr; + +int AsyncEvent::s_nIdCounter = 0; + +static thread_local int nProfileZoneNesting = 0; // Level of Nested Profile Zones + +namespace +{ +std::vector<OUString> g_aRecording; // recorded data +std::mutex g_aMutex; +} + +void TraceEvent::addRecording(const OUString& sObject) +{ + bool bEmitCallback; + { + std::lock_guard aGuard(g_aMutex); + + g_aRecording.emplace_back(sObject); + + bEmitCallback = s_nBufferSize > 0 && g_aRecording.size() >= s_nBufferSize; + } + if (bEmitCallback && s_pBufferFullCallback != nullptr) + (*s_pBufferFullCallback)(); +} + +void TraceEvent::addInstantEvent(const char* sName, const std::map<OUString, OUString>& args) +{ + long long nNow = getNow(); + + int nPid = 0; + oslProcessInfo aProcessInfo; + aProcessInfo.Size = sizeof(oslProcessInfo); + if (osl_getProcessInfo(nullptr, osl_Process_IDENTIFIER, &aProcessInfo) == osl_Process_E_None) + nPid = aProcessInfo.Ident; + + addRecording("{" + "\"name:\"" + + OUString(sName, strlen(sName), RTL_TEXTENCODING_UTF8) + + "\"," + "\"ph\":\"i\"" + + createArgsString(args) + ",\"ts\":" + OUString::number(nNow) + + "," + "\"pid\":" + + OUString::number(nPid) + + "," + "\"tid\":" + + OUString::number(osl_getThreadIdentifier(nullptr)) + "},"); +} + +void TraceEvent::startRecording() +{ + std::lock_guard aGuard(g_aMutex); + s_bRecording = true; +} + +void TraceEvent::stopRecording() { s_bRecording = false; } + +void TraceEvent::setBufferSizeAndCallback(std::size_t bufferSize, void (*bufferFullCallback)()) +{ + s_nBufferSize = bufferSize; + s_pBufferFullCallback = bufferFullCallback; +} + +std::vector<OUString> TraceEvent::getEventVectorAndClear() +{ + bool bRecording; + std::vector<OUString> aRecording; + { + std::lock_guard aGuard(g_aMutex); + bRecording = s_bRecording; + stopRecording(); + aRecording.swap(g_aRecording); + } + // reset start time and nesting level + if (bRecording) + startRecording(); + return aRecording; +} + +css::uno::Sequence<OUString> TraceEvent::getRecordingAndClear() +{ + return comphelper::containerToSequence(getEventVectorAndClear()); +} + +void ProfileZone::addRecording() +{ + assert(s_bRecording); + + long long nNow = getNow(); + + // Generate a single "Complete Event" (type X) + TraceEvent::addRecording("{" + "\"name\":\"" + + OUString(m_sName, strlen(m_sName), RTL_TEXTENCODING_UTF8) + + "\"," + "\"ph\":\"X\"," + "\"ts\":" + + OUString::number(m_nCreateTime) + + "," + "\"dur\":" + + OUString::number(nNow - m_nCreateTime) + m_sArgs + + "," + "\"pid\":" + + OUString::number(m_nPid) + + "," + "\"tid\":" + + OUString::number(osl_getThreadIdentifier(nullptr)) + "},"); +} + +int ProfileZone::getNestingLevel() { return nProfileZoneNesting; } + +void ProfileZone::setNestingLevel(int nNestingLevel) { nProfileZoneNesting = nNestingLevel; } + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/weak.cxx b/comphelper/source/misc/typedescriptionref.hxx index 02cf40e2b646..f4580cb2e4cb 100644 --- a/comphelper/source/misc/weak.cxx +++ b/comphelper/source/misc/typedescriptionref.hxx @@ -17,41 +17,35 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#pragma once -#include <comphelper/weak.hxx> +#include <typelib/typedescription.h> -using namespace com::sun::star::uno; -using namespace com::sun::star::lang; - -namespace comphelper -{ - -OWeakTypeObject::OWeakTypeObject() +namespace comphelper::detail { -} - -OWeakTypeObject::~OWeakTypeObject() -{ -} - -Any SAL_CALL OWeakTypeObject::queryInterface(const Type & rType ) +// This is like com::sun::star::uno::TypeDescription, but it uses TYPELIB_DANGER_GET +// (which the code used originally, but it's easier to have a class to handle ownership). +class TypeDescriptionRef { - if( rType == cppu::UnoType<XTypeProvider>::get() ) - return Any( Reference< XTypeProvider >(this) ); - else - return ::cppu::OWeakObject::queryInterface( rType ); -} - -Sequence< Type > SAL_CALL OWeakTypeObject::getTypes( ) -{ - return Sequence< Type >(); -} - -Sequence< ::sal_Int8 > SAL_CALL OWeakTypeObject::getImplementationId( ) -{ - return Sequence< ::sal_Int8 >(); -} - -} +public: + TypeDescriptionRef(typelib_TypeDescriptionReference* typeDef) + { + TYPELIB_DANGER_GET(&typeDescr, typeDef); + } + ~TypeDescriptionRef() { TYPELIB_DANGER_RELEASE(typeDescr); } + typelib_TypeDescription* get() { return typeDescr; } + typelib_TypeDescription* operator->() { return typeDescr; } + bool is() { return typeDescr != nullptr; } + bool equals(const TypeDescriptionRef& other) const + { + return typeDescr && other.typeDescr + && typelib_typedescription_equals(typeDescr, other.typeDescr); + } + +private: + typelib_TypeDescription* typeDescr = nullptr; +}; + +} // namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/weakeventlistener.cxx b/comphelper/source/misc/weakeventlistener.cxx index e8ce46590559..0543816d0593 100644 --- a/comphelper/source/misc/weakeventlistener.cxx +++ b/comphelper/source/misc/weakeventlistener.cxx @@ -55,7 +55,7 @@ namespace comphelper } - void SAL_CALL OWeakEventListenerAdapter::disposing( ) + void OWeakEventListenerAdapter::disposing( std::unique_lock<std::mutex>& /*rGuard*/ ) { Reference< XComponent > xBroadcaster( getBroadcaster( ), UNO_QUERY ); OSL_ENSURE( xBroadcaster.is(), "OWeakEventListenerAdapter::disposing: broadcaster is invalid in the meantime! How this?" ); diff --git a/comphelper/source/misc/xmlsechelper.cxx b/comphelper/source/misc/xmlsechelper.cxx index c01743b36615..a96ff6937374 100644 --- a/comphelper/source/misc/xmlsechelper.cxx +++ b/comphelper/source/misc/xmlsechelper.cxx @@ -17,14 +17,14 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ - #include <comphelper/xmlsechelper.hxx> #include <rtl/ustrbuf.hxx> #include <osl/diagnose.h> -#include <vector> +#include <o3tl/string_view.hxx> -using namespace std; +#include <utility> +#include <vector> namespace comphelper::xmlsec { @@ -49,9 +49,9 @@ namespace comphelper::xmlsec The second string is for the details view at the bottom. It shows the attribute/value pairs on different lines. All escape characters ('"') are removed. */ - pair< OUString, OUString> GetDNForCertDetailsView( const OUString & rRawString) + std::pair< OUString, OUString> GetDNForCertDetailsView( std::u16string_view rRawString) { - vector< pair< OUString, OUString > > vecAttrValueOfDN = parseDN(rRawString); + std::vector< std::pair< OUString, OUString > > vecAttrValueOfDN = parseDN(rRawString); OUStringBuffer s1, s2; for (auto i = vecAttrValueOfDN.cbegin(); i < vecAttrValueOfDN.cend(); ++i) { @@ -61,9 +61,9 @@ namespace comphelper::xmlsec s2.append('\n'); } s1.append(i->second); - s2.append(i->first).append(" = ").append(i->second); + s2.append(i->first + " = " + i->second); } - return make_pair(s1.makeStringAndClear(), s2.makeStringAndClear()); + return std::make_pair(s1.makeStringAndClear(), s2.makeStringAndClear()); } /* @@ -73,18 +73,18 @@ namespace comphelper::xmlsec they are escaped with a double quote. This function removes the escape characters. */ #ifdef _WIN32 -vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) +std::vector< std::pair< OUString, OUString> > parseDN(std::u16string_view rRawString) { - vector< pair<OUString, OUString> > retVal; + std::vector< std::pair<OUString, OUString> > retVal; bool bInEscape = false; bool bInValue = false; bool bInType = true; sal_Int32 nTypeNameStart = 0; - OUString sType; + std::u16string_view sType; OUStringBuffer sbufValue; - sal_Int32 length = rRawString.getLength(); + size_t length = rRawString.size(); - for (sal_Int32 i = 0; i < length; i++) + for (size_t i = 0; i < length; i++) { sal_Unicode c = rRawString[i]; @@ -92,8 +92,8 @@ vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) { if (! bInValue) { - sType = rRawString.copy(nTypeNameStart, i - nTypeNameStart); - sType = sType.trim(); + sType = rRawString.substr(nTypeNameStart, i - nTypeNameStart); + sType = o3tl::trim(sType); bInType = false; } else @@ -129,9 +129,9 @@ vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) //then we have reached the end of the value if (!bInValue) { - OSL_ASSERT(!sType.isEmpty()); - retVal.push_back(make_pair(sType, sbufValue.makeStringAndClear())); - sType.clear(); + OSL_ASSERT(!sType.empty()); + retVal.emplace_back(OUString(sType), sbufValue.makeStringAndClear()); + sType = {}; //The next char is the start of the new type nTypeNameStart = i + 1; bInType = true; @@ -152,25 +152,25 @@ vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) } if (sbufValue.getLength()) { - OSL_ASSERT(!sType.isEmpty()); - retVal.push_back(make_pair(sType, sbufValue.makeStringAndClear())); + OSL_ASSERT(!sType.empty()); + retVal.emplace_back(OUString(sType), sbufValue.makeStringAndClear()); } return retVal; } #else -vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) +std::vector< std::pair< OUString, OUString> > parseDN(std::u16string_view rRawString) { - vector< pair<OUString, OUString> > retVal; + std::vector< std::pair<OUString, OUString> > retVal; //bInEscape == true means that the preceding character is an escape character bool bInEscape = false; bool bInValue = false; bool bInType = true; sal_Int32 nTypeNameStart = 0; - OUString sType; + std::u16string_view sType; OUStringBuffer sbufValue; - sal_Int32 length = rRawString.getLength(); + size_t length = rRawString.size(); - for (sal_Int32 i = 0; i < length; i++) + for (size_t i = 0; i < length; i++) { sal_Unicode c = rRawString[i]; @@ -178,8 +178,8 @@ vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) { if (! bInValue) { - sType = rRawString.copy(nTypeNameStart, i - nTypeNameStart); - sType = sType.trim(); + sType = rRawString.substr(nTypeNameStart, i - nTypeNameStart); + sType = o3tl::trim(sType); bInType = false; } else @@ -224,9 +224,9 @@ vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) //then we have reached the end of the value if (!bInValue) { - OSL_ASSERT(!sType.isEmpty()); + OSL_ASSERT(!sType.empty()); retVal.emplace_back(sType, sbufValue.makeStringAndClear()); - sType.clear(); + sType = {}; //The next char is the start of the new type nTypeNameStart = i + 1; bInType = true; @@ -250,7 +250,7 @@ vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) } if (!sbufValue.isEmpty()) { - OSL_ASSERT(!sType.isEmpty()); + OSL_ASSERT(!sType.empty()); retVal.emplace_back(sType, sbufValue.makeStringAndClear()); } return retVal; @@ -268,12 +268,12 @@ vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) OUString retVal; int i = 0; - vector< pair< OUString, OUString > > vecAttrValueOfDN = parseDN(_rRawString); + std::vector< std::pair< OUString, OUString > > vecAttrValueOfDN = parseDN(_rRawString); while ( aIDs[i] ) { OUString sPartId = OUString::createFromAscii( aIDs[i++] ); auto idn = std::find_if(vecAttrValueOfDN.cbegin(), vecAttrValueOfDN.cend(), - [&sPartId](const pair< OUString, OUString >& dn) { return dn.first == sPartId; }); + [&sPartId](const std::pair< OUString, OUString >& dn) { return dn.first == sPartId; }); if (idn != vecAttrValueOfDN.cend()) retVal = idn->second; if (!retVal.isEmpty()) diff --git a/comphelper/source/officeinstdir/officeinstallationdirectories.cxx b/comphelper/source/officeinstdir/officeinstallationdirectories.cxx index 1bee23622d42..010655964dcc 100644 --- a/comphelper/source/officeinstdir/officeinstallationdirectories.cxx +++ b/comphelper/source/officeinstdir/officeinstallationdirectories.cxx @@ -28,9 +28,9 @@ *************************************************************************/ #include <osl/file.hxx> -#include <rtl/ref.hxx> #include <com/sun/star/util/theMacroExpander.hpp> #include <comphelper/fileurl.hxx> +#include <utility> #include "officeinstallationdirectories.hxx" @@ -44,30 +44,30 @@ static bool makeCanonicalFileURL( OUString & rURL ) if ( osl::FileBase::getAbsoluteFileURL( OUString(), rURL, aNormalizedURL ) + != osl::DirectoryItem::E_None ) + return false; + + osl::DirectoryItem aDirItem; + if ( osl::DirectoryItem::get( aNormalizedURL, aDirItem ) + != osl::DirectoryItem::E_None ) + return false; + + osl::FileStatus aFileStatus( osl_FileStatus_Mask_FileURL ); + + if ( aDirItem.getFileStatus( aFileStatus ) == osl::DirectoryItem::E_None ) { - osl::DirectoryItem aDirItem; - if ( osl::DirectoryItem::get( aNormalizedURL, aDirItem ) - == osl::DirectoryItem::E_None ) + aNormalizedURL = aFileStatus.getFileURL(); + + if ( !aNormalizedURL.isEmpty() ) { - osl::FileStatus aFileStatus( osl_FileStatus_Mask_FileURL ); + if ( !aNormalizedURL.endsWith("/") ) + rURL = aNormalizedURL; + else + rURL = aNormalizedURL + .copy( 0, aNormalizedURL.getLength() - 1 ); - if ( aDirItem.getFileStatus( aFileStatus ) - == osl::DirectoryItem::E_None ) - { - aNormalizedURL = aFileStatus.getFileURL(); - - if ( !aNormalizedURL.isEmpty() ) - { - if ( !aNormalizedURL.endsWith("/") ) - rURL = aNormalizedURL; - else - rURL = aNormalizedURL - .copy( 0, aNormalizedURL.getLength() - 1 ); - - return true; - } - } + return true; } } return false; @@ -75,12 +75,12 @@ static bool makeCanonicalFileURL( OUString & rURL ) namespace comphelper { -constexpr OUStringLiteral g_aOfficeBrandDirMacro(u"$(brandbaseurl)"); -constexpr OUStringLiteral g_aUserDirMacro(u"$(userdataurl)"); +constexpr OUString g_aOfficeBrandDirMacro(u"$(brandbaseurl)"_ustr); +constexpr OUString g_aUserDirMacro(u"$(userdataurl)"_ustr); OfficeInstallationDirectories::OfficeInstallationDirectories( - const uno::Reference< uno::XComponentContext > & xCtx ) -: m_xCtx( xCtx ) + uno::Reference< uno::XComponentContext > xCtx ) +: m_xCtx(std::move( xCtx )) { } @@ -211,7 +211,7 @@ void OfficeInstallationDirectories::initDirs() if ( m_xOfficeBrandDir) return; - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( m_xOfficeBrandDir ) return; @@ -236,32 +236,14 @@ void OfficeInstallationDirectories::initDirs() } -namespace { - -struct Instance { - explicit Instance( - css::uno::Reference<css::uno::XComponentContext> const & context): - instance(static_cast<cppu::OWeakObject *>( - new comphelper::OfficeInstallationDirectories(context))) - {} - - rtl::Reference<css::uno::XInterface> instance; -}; - -struct Singleton: - public rtl::StaticWithArg< - Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton> -{}; - -} extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_util_OfficeInstallationDirectories( css::uno::XComponentContext *context, css::uno::Sequence<css::uno::Any> const &) { - return cppu::acquire(static_cast<cppu::OWeakObject *>( - Singleton::get(context).instance.get())); + return cppu::acquire( + new comphelper::OfficeInstallationDirectories(context)); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/officeinstdir/officeinstallationdirectories.hxx b/comphelper/source/officeinstdir/officeinstallationdirectories.hxx index f39f8a380e91..d0d86b76c4d5 100644 --- a/comphelper/source/officeinstdir/officeinstallationdirectories.hxx +++ b/comphelper/source/officeinstdir/officeinstallationdirectories.hxx @@ -19,12 +19,12 @@ #pragma once -#include <osl/mutex.hxx> #include <cppuhelper/implbase.hxx> #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/util/XOfficeInstallationDirectories.hpp> +#include <mutex> #include <optional> namespace com::sun::star::uno { class XComponentContext; } @@ -35,18 +35,13 @@ namespace comphelper { typedef cppu::WeakImplHelper< css::util::XOfficeInstallationDirectories, - css::lang::XServiceInfo > UnoImplBase; + css::lang::XServiceInfo > OfficeInstallationDirectories_Base; -struct mutex_holder -{ - osl::Mutex m_aMutex; -}; - -class OfficeInstallationDirectories : public mutex_holder, public UnoImplBase +class OfficeInstallationDirectories : public OfficeInstallationDirectories_Base { public: explicit OfficeInstallationDirectories( - const css::uno::Reference< css::uno::XComponentContext > & xCtx ); + css::uno::Reference< css::uno::XComponentContext > xCtx ); virtual ~OfficeInstallationDirectories() override; // XOfficeInstallationDirectories @@ -70,6 +65,7 @@ public: private: void initDirs(); + std::mutex m_aMutex; css::uno::Reference< css::uno::XComponentContext > m_xCtx; std::optional<OUString> m_xOfficeBrandDir; std::optional<OUString> m_xUserDir; diff --git a/comphelper/source/processfactory/processfactory.cxx b/comphelper/source/processfactory/processfactory.cxx index 8df1e244ca19..eddff2d45e04 100644 --- a/comphelper/source/processfactory/processfactory.cxx +++ b/comphelper/source/processfactory/processfactory.cxx @@ -17,7 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include <osl/mutex.hxx> +#include <mutex> #include <comphelper/processfactory.hxx> #include <com/sun/star/beans/XPropertySet.hpp> @@ -30,7 +30,6 @@ namespace com::sun::star::uno { class XComponentContext; } using namespace ::com::sun::star; using namespace com::sun::star::uno; using namespace com::sun::star::lang; -using namespace osl; namespace comphelper { @@ -41,19 +40,20 @@ class LocalProcessFactory { public: void set( const Reference< XMultiServiceFactory >& xSMgr ) { - Guard< Mutex > aGuard( Mutex::getGlobalMutex() ); + std::unique_lock aGuard( maMutex ); xProcessFactory = xSMgr; } Reference< XMultiServiceFactory > get() const { - Guard< Mutex > aGuard( Mutex::getGlobalMutex() ); + std::unique_lock aGuard( maMutex ); return xProcessFactory; } private: + mutable std::mutex maMutex; Reference< XMultiServiceFactory > xProcessFactory; }; @@ -86,8 +86,9 @@ Reference< XComponentContext > getComponentContext( Reference< XComponentContext > xRet; uno::Reference<beans::XPropertySet> const xProps( factory, uno::UNO_QUERY ); if (xProps.is()) { + static constexpr OUStringLiteral DEFAULT_CONTEXT = u"DefaultContext"; try { - xRet.set( xProps->getPropertyValue("DefaultContext"), + xRet.set( xProps->getPropertyValue(DEFAULT_CONTEXT), uno::UNO_QUERY ); } catch (beans::UnknownPropertyException & e) { @@ -107,7 +108,8 @@ Reference< XComponentContext > getComponentContext( Reference< XComponentContext > getProcessComponentContext() { - return getComponentContext( getProcessServiceFactory() ); + static const uno::Reference<XComponentContext> processComponentContext = getComponentContext( getProcessServiceFactory() ); + return processComponentContext; } } // namespace comphelper diff --git a/comphelper/source/property/ChainablePropertySet.cxx b/comphelper/source/property/ChainablePropertySet.cxx index 4694a89c527c..0805afe72bcf 100644 --- a/comphelper/source/property/ChainablePropertySet.cxx +++ b/comphelper/source/property/ChainablePropertySet.cxx @@ -23,6 +23,7 @@ #include <memory> +#include <optional> using namespace ::comphelper; using namespace ::com::sun::star; @@ -31,29 +32,29 @@ using namespace ::com::sun::star::lang; using namespace ::com::sun::star::beans; ChainablePropertySet::ChainablePropertySet( comphelper::ChainablePropertySetInfo* pInfo, comphelper::SolarMutex* pMutex ) - throw() + noexcept : mpMutex ( pMutex ) , mxInfo ( pInfo ) { } ChainablePropertySet::~ChainablePropertySet() - throw() + noexcept { } // XPropertySet Reference< XPropertySetInfo > SAL_CALL ChainablePropertySet::getPropertySetInfo( ) { - return mxInfo.get(); + return mxInfo; } void SAL_CALL ChainablePropertySet::setPropertyValue( const OUString& rPropertyName, const Any& rValue ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); PropertyInfoHash::const_iterator aIter = mxInfo->maMap.find ( rPropertyName ); @@ -68,9 +69,9 @@ void SAL_CALL ChainablePropertySet::setPropertyValue( const OUString& rPropertyN Any SAL_CALL ChainablePropertySet::getPropertyValue( const OUString& rPropertyName ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); PropertyInfoHash::const_iterator aIter = mxInfo->maMap.find ( rPropertyName ); @@ -109,9 +110,9 @@ void SAL_CALL ChainablePropertySet::removeVetoableChangeListener( const OUString void SAL_CALL ChainablePropertySet::setPropertyValues(const Sequence< OUString >& rPropertyNames, const Sequence< Any >& rValues) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); const sal_Int32 nCount = rPropertyNames.getLength(); @@ -142,9 +143,9 @@ void SAL_CALL ChainablePropertySet::setPropertyValues(const Sequence< OUString > Sequence< Any > SAL_CALL ChainablePropertySet::getPropertyValues(const Sequence< OUString >& rPropertyNames) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); const sal_Int32 nCount = rPropertyNames.getLength(); diff --git a/comphelper/source/property/ChainablePropertySetInfo.cxx b/comphelper/source/property/ChainablePropertySetInfo.cxx index 26cf2f6e3d70..4515e5c4314b 100644 --- a/comphelper/source/property/ChainablePropertySetInfo.cxx +++ b/comphelper/source/property/ChainablePropertySetInfo.cxx @@ -31,14 +31,14 @@ ChainablePropertySetInfo::ChainablePropertySetInfo( PropertyInfo const * pMap ) for( ; !pMap->maName.isEmpty(); ++pMap ) { SAL_WARN_IF( - maMap.find(pMap->maName) != maMap.end(), + maMap.contains(pMap->maName), "comphelper", "Duplicate property name \"" << pMap->maName << "\""); maMap[pMap->maName] = pMap; } } ChainablePropertySetInfo::~ChainablePropertySetInfo() - throw() + noexcept { } diff --git a/comphelper/source/property/MasterPropertySet.cxx b/comphelper/source/property/MasterPropertySet.cxx index e5e94b5ad46f..922a4c1c69b4 100644 --- a/comphelper/source/property/MasterPropertySet.cxx +++ b/comphelper/source/property/MasterPropertySet.cxx @@ -27,17 +27,18 @@ #include <memory> #include <vector> +#include <optional> namespace { class AutoOGuardArray { - std::vector<std::unique_ptr< osl::Guard< comphelper::SolarMutex > >> maGuardArray; + std::vector<std::optional< osl::Guard< comphelper::SolarMutex > >> maGuardArray; public: explicit AutoOGuardArray( sal_Int32 nNumElements ); - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > & operator[] ( sal_Int32 i ) { return maGuardArray[i]; } + std::optional< osl::Guard< comphelper::SolarMutex > > & operator[] ( sal_Int32 i ) { return maGuardArray[i]; } }; } @@ -61,7 +62,7 @@ SlaveData::SlaveData ( ChainablePropertySet *pSlave) } MasterPropertySet::MasterPropertySet( comphelper::MasterPropertySetInfo* pInfo, comphelper::SolarMutex* pMutex ) - throw() + noexcept : mpMutex ( pMutex ) , mnLastId ( 0 ) , mxInfo ( pInfo ) @@ -69,7 +70,7 @@ MasterPropertySet::MasterPropertySet( comphelper::MasterPropertySetInfo* pInfo, } MasterPropertySet::~MasterPropertySet() - throw() + noexcept { for( const auto& rSlave : maSlaveMap ) delete rSlave.second; @@ -78,11 +79,11 @@ MasterPropertySet::~MasterPropertySet() // XPropertySet Reference< XPropertySetInfo > SAL_CALL MasterPropertySet::getPropertySetInfo( ) { - return mxInfo.get(); + return mxInfo; } void MasterPropertySet::registerSlave ( ChainablePropertySet *pNewSet ) - throw() + noexcept { maSlaveMap [ ++mnLastId ] = new SlaveData ( pNewSet ); mxInfo->add ( pNewSet->mxInfo->maMap, mnLastId ); @@ -91,9 +92,9 @@ void MasterPropertySet::registerSlave ( ChainablePropertySet *pNewSet ) void SAL_CALL MasterPropertySet::setPropertyValue( const OUString& rPropertyName, const Any& rValue ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); PropertyDataHash::const_iterator aIter = mxInfo->maMap.find ( rPropertyName ); @@ -111,9 +112,9 @@ void SAL_CALL MasterPropertySet::setPropertyValue( const OUString& rPropertyName ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mxSlave.get(); // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard2; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard2; if (pSlave->mpMutex) - xMutexGuard2.reset( new osl::Guard< comphelper::SolarMutex >(pSlave->mpMutex) ); + xMutexGuard2.emplace( pSlave->mpMutex ); pSlave->_preSetValues(); pSlave->_setSingleValue( *((*aIter).second->mpInfo), rValue ); @@ -124,9 +125,9 @@ void SAL_CALL MasterPropertySet::setPropertyValue( const OUString& rPropertyName Any SAL_CALL MasterPropertySet::getPropertyValue( const OUString& rPropertyName ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); PropertyDataHash::const_iterator aIter = mxInfo->maMap.find ( rPropertyName ); @@ -145,9 +146,9 @@ Any SAL_CALL MasterPropertySet::getPropertyValue( const OUString& rPropertyName ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mxSlave.get(); // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard2; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard2; if (pSlave->mpMutex) - xMutexGuard2.reset( new osl::Guard< comphelper::SolarMutex >(pSlave->mpMutex) ); + xMutexGuard2.emplace( pSlave->mpMutex ); pSlave->_preGetValues(); pSlave->_getSingleValue( *((*aIter).second->mpInfo), aAny ); @@ -180,9 +181,9 @@ void SAL_CALL MasterPropertySet::removeVetoableChangeListener( const OUString&, void SAL_CALL MasterPropertySet::setPropertyValues( const Sequence< OUString >& aPropertyNames, const Sequence< Any >& aValues ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); const sal_Int32 nCount = aPropertyNames.getLength(); @@ -220,7 +221,7 @@ void SAL_CALL MasterPropertySet::setPropertyValues( const Sequence< OUString >& { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). if (pSlave->mxSlave->mpMutex) - aOGuardArray[i].reset( new osl::Guard< comphelper::SolarMutex >(pSlave->mxSlave->mpMutex) ); + aOGuardArray[i].emplace( pSlave->mxSlave->mpMutex ); pSlave->mxSlave->_preSetValues(); pSlave->SetInit ( true ); @@ -243,9 +244,9 @@ void SAL_CALL MasterPropertySet::setPropertyValues( const Sequence< OUString >& Sequence< Any > SAL_CALL MasterPropertySet::getPropertyValues( const Sequence< OUString >& aPropertyNames ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); const sal_Int32 nCount = aPropertyNames.getLength(); @@ -281,7 +282,7 @@ Sequence< Any > SAL_CALL MasterPropertySet::getPropertyValues( const Sequence< O { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). if (pSlave->mxSlave->mpMutex) - aOGuardArray[i].reset( new osl::Guard< comphelper::SolarMutex >(pSlave->mxSlave->mpMutex) ); + aOGuardArray[i].emplace( pSlave->mxSlave->mpMutex ); pSlave->mxSlave->_preGetValues(); pSlave->SetInit ( true ); @@ -331,9 +332,9 @@ PropertyState SAL_CALL MasterPropertySet::getPropertyState( const OUString& Prop ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mxSlave.get(); // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (pSlave->mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(pSlave->mpMutex) ); + xMutexGuard.emplace( pSlave->mpMutex ); } return PropertyState_AMBIGUOUS_VALUE; diff --git a/comphelper/source/property/MasterPropertySetInfo.cxx b/comphelper/source/property/MasterPropertySetInfo.cxx index 1b1a2249ec08..4040b479a05c 100644 --- a/comphelper/source/property/MasterPropertySetInfo.cxx +++ b/comphelper/source/property/MasterPropertySetInfo.cxx @@ -31,14 +31,14 @@ MasterPropertySetInfo::MasterPropertySetInfo( PropertyInfo const * pMap ) for ( ; !pMap->maName.isEmpty(); ++pMap ) { SAL_WARN_IF( - maMap.find(pMap->maName) != maMap.end(), + maMap.contains(pMap->maName), "comphelper", "Duplicate property name \"" << pMap->maName << "\""); maMap[pMap->maName] = new PropertyData ( 0, pMap ); } } MasterPropertySetInfo::~MasterPropertySetInfo() - throw() + noexcept { for( const auto& rObj : maMap ) delete rObj.second; @@ -52,7 +52,7 @@ void MasterPropertySetInfo::add( PropertyInfoHash &rHash, sal_uInt8 nMapId ) for( const auto& rObj : rHash ) { SAL_WARN_IF( - maMap.find(rObj.first) != maMap.end(), + maMap.contains(rObj.first), "comphelper", "Duplicate property name \"" << rObj.first << "\""); maMap[rObj.first] = new PropertyData ( nMapId, rObj.second ); } diff --git a/comphelper/source/property/genericpropertyset.cxx b/comphelper/source/property/genericpropertyset.cxx index fd591774cdeb..747023d2be87 100644 --- a/comphelper/source/property/genericpropertyset.cxx +++ b/comphelper/source/property/genericpropertyset.cxx @@ -24,15 +24,14 @@ #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/lang/XTypeProvider.hpp> #include <cppuhelper/weakagg.hxx> -#include <cppuhelper/interfacecontainer.hxx> #include <cppuhelper/supportsservice.hxx> +#include <comphelper/multiinterfacecontainer4.hxx> #include <comphelper/propertysethelper.hxx> -#include <osl/mutex.hxx> +#include <mutex> #include <rtl/ref.hxx> #include <comphelper/genericpropertyset.hxx> #include <comphelper/propertysetinfo.hxx> -using namespace ::osl; using namespace ::cppu; using namespace ::comphelper; using namespace ::com::sun::star; @@ -44,33 +43,27 @@ namespace comphelper { namespace { - struct IMPL_GenericPropertySet_MutexContainer - { - Mutex maMutex; - }; - - class GenericPropertySet : public OWeakAggObject, + class GenericPropertySet : public OWeakObject, public XServiceInfo, public XTypeProvider, - public PropertySetHelper, - private IMPL_GenericPropertySet_MutexContainer + public PropertySetHelper { private: std::map<OUString, Any> maAnyMap; - cppu::OMultiTypeInterfaceContainerHelperVar<OUString> m_aListener; + std::mutex maMutex; + comphelper::OMultiTypeInterfaceContainerHelperVar4<OUString, XPropertyChangeListener> m_aListener; protected: virtual void _setPropertyValues( const PropertyMapEntry** ppEntries, const Any* pValues ) override; virtual void _getPropertyValues( const PropertyMapEntry** ppEntries, Any* pValue ) override; public: - explicit GenericPropertySet( PropertySetInfo* pInfo ) throw(); + explicit GenericPropertySet( PropertySetInfo* pInfo ) noexcept; // XInterface - virtual Any SAL_CALL queryAggregation( const Type & rType ) override; virtual Any SAL_CALL queryInterface( const Type & rType ) override; - virtual void SAL_CALL acquire() throw() override; - virtual void SAL_CALL release() throw() override; + virtual void SAL_CALL acquire() noexcept override; + virtual void SAL_CALL release() noexcept override; // XTypeProvider virtual Sequence< Type > SAL_CALL getTypes( ) override; @@ -90,9 +83,8 @@ namespace comphelper } -GenericPropertySet::GenericPropertySet( PropertySetInfo* pInfo ) throw() +GenericPropertySet::GenericPropertySet( PropertySetInfo* pInfo ) noexcept : PropertySetHelper( pInfo ) -,m_aListener(maMutex) { } @@ -102,6 +94,7 @@ void SAL_CALL GenericPropertySet::addPropertyChangeListener( const OUString& aPr if ( !xInfo.is() ) return; + std::unique_lock aGuard(maMutex); if ( aPropertyName.isEmpty() ) { Sequence< Property> aSeq = xInfo->getProperties(); @@ -109,23 +102,22 @@ void SAL_CALL GenericPropertySet::addPropertyChangeListener( const OUString& aPr const Property* pEnd = pIter + aSeq.getLength(); for( ; pIter != pEnd ; ++pIter) { - m_aListener.addInterface(pIter->Name,xListener); + m_aListener.addInterface(aGuard, pIter->Name,xListener); } } else if ( xInfo->hasPropertyByName(aPropertyName) ) - m_aListener.addInterface(aPropertyName,xListener); + m_aListener.addInterface(aGuard, aPropertyName,xListener); else throw UnknownPropertyException( aPropertyName, *this ); } void SAL_CALL GenericPropertySet::removePropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener ) { - ClearableMutexGuard aGuard( maMutex ); Reference < XPropertySetInfo > xInfo = getPropertySetInfo( ); - aGuard.clear(); if ( !xInfo.is() ) return; + std::unique_lock aGuard(maMutex); if ( aPropertyName.isEmpty() ) { Sequence< Property> aSeq = xInfo->getProperties(); @@ -133,22 +125,22 @@ void SAL_CALL GenericPropertySet::removePropertyChangeListener( const OUString& const Property* pEnd = pIter + aSeq.getLength(); for( ; pIter != pEnd ; ++pIter) { - m_aListener.removeInterface(pIter->Name,xListener); + m_aListener.removeInterface(aGuard, pIter->Name,xListener); } } else if ( xInfo->hasPropertyByName(aPropertyName) ) - m_aListener.removeInterface(aPropertyName,xListener); + m_aListener.removeInterface(aGuard, aPropertyName,xListener); else throw UnknownPropertyException( aPropertyName, *this ); } void GenericPropertySet::_setPropertyValues( const PropertyMapEntry** ppEntries, const Any* pValues ) { - ResettableMutexGuard aGuard( maMutex ); + std::unique_lock aGuard(maMutex); while( *ppEntries ) { - OInterfaceContainerHelper * pHelper = m_aListener.getContainer((*ppEntries)->maName); + OInterfaceContainerHelper4<XPropertyChangeListener> * pHelper = m_aListener.getContainer(aGuard, (*ppEntries)->maName); maAnyMap[ (*ppEntries)->maName ] = *pValues; @@ -157,9 +149,7 @@ void GenericPropertySet::_setPropertyValues( const PropertyMapEntry** ppEntries, PropertyChangeEvent aEvt; aEvt.PropertyName = (*ppEntries)->maName; aEvt.NewValue = *pValues; - aGuard.clear(); - pHelper->notifyEach( &XPropertyChangeListener::propertyChange, aEvt ); - aGuard.reset(); + pHelper->notifyEach( aGuard, &XPropertyChangeListener::propertyChange, aEvt ); } ppEntries++; @@ -169,7 +159,7 @@ void GenericPropertySet::_setPropertyValues( const PropertyMapEntry** ppEntries, void GenericPropertySet::_getPropertyValues( const comphelper::PropertyMapEntry** ppEntries, Any* pValue ) { - MutexGuard aGuard( maMutex ); + std::unique_lock aGuard(maMutex); while( *ppEntries ) { @@ -184,11 +174,6 @@ void GenericPropertySet::_getPropertyValues( const comphelper::PropertyMapEntry* Any SAL_CALL GenericPropertySet::queryInterface( const Type & rType ) { - return OWeakAggObject::queryInterface( rType ); -} - -Any SAL_CALL GenericPropertySet::queryAggregation( const Type & rType ) -{ Any aAny; if( rType == cppu::UnoType<XServiceInfo>::get()) @@ -200,19 +185,19 @@ Any SAL_CALL GenericPropertySet::queryAggregation( const Type & rType ) else if( rType == cppu::UnoType<XMultiPropertySet>::get()) aAny <<= Reference< XMultiPropertySet >(this); else - aAny = OWeakAggObject::queryAggregation( rType ); + aAny = OWeakObject::queryInterface( rType ); return aAny; } -void SAL_CALL GenericPropertySet::acquire() throw() +void SAL_CALL GenericPropertySet::acquire() noexcept { - OWeakAggObject::acquire(); + OWeakObject::acquire(); } -void SAL_CALL GenericPropertySet::release() throw() +void SAL_CALL GenericPropertySet::release() noexcept { - OWeakAggObject::release(); + OWeakObject::release(); } uno::Sequence< uno::Type > SAL_CALL GenericPropertySet::getTypes() diff --git a/comphelper/source/property/opropertybag.cxx b/comphelper/source/property/opropertybag.cxx index 62dd474c962f..30201b9ff772 100644 --- a/comphelper/source/property/opropertybag.cxx +++ b/comphelper/source/property/opropertybag.cxx @@ -83,14 +83,14 @@ namespace comphelper && (_rArguments[1] >>= AllowEmptyPropertyName) && (_rArguments[2] >>= AutomaticAddition)) { - m_aAllowedTypes.insert(aTypes.begin(), aTypes.end()); + m_aAllowedTypes.insert(std::cbegin(aTypes), std::cend(aTypes)); m_bAutoAddProperties = AutomaticAddition; } else { ::comphelper::NamedValueCollection aArguments( _rArguments ); if ( aArguments.get_ensureType( "AllowedTypes", aTypes ) ) - m_aAllowedTypes.insert( aTypes.begin(), aTypes.end()); + m_aAllowedTypes.insert(std::cbegin(aTypes), std::cend(aTypes)); aArguments.get_ensureType( "AutomaticAddition", m_bAutoAddProperties ); aArguments.get_ensureType( "AllowEmptyPropertyName", @@ -377,8 +377,8 @@ namespace comphelper // their names Sequence< OUString > aNames( aProperties.getLength() ); std::transform( - aProperties.begin(), - aProperties.end(), + std::cbegin(aProperties), + std::cend(aProperties), aNames.getArray(), TransformPropertyToName< Property >() ); @@ -389,7 +389,7 @@ namespace comphelper { aValues = OPropertyBag_PBase::getPropertyValues( aNames ); if ( aValues.getLength() != aNames.getLength() ) - throw RuntimeException(); + throw RuntimeException("property name and value counts out of sync"); } catch( const RuntimeException& ) { @@ -425,17 +425,18 @@ namespace comphelper { // sort (the XMultiPropertySet interface requires this) Sequence< PropertyValue > aProperties( _rProps ); + auto [begin, end] = asNonConstRange(aProperties); std::sort( - aProperties.begin(), - aProperties.end(), + begin, + end, ComparePropertyValueByName() ); // a sequence of names Sequence< OUString > aNames( aProperties.getLength() ); std::transform( - aProperties.begin(), - aProperties.end(), + std::cbegin(aProperties), + std::cend(aProperties), aNames.getArray(), TransformPropertyToName< PropertyValue >() ); @@ -479,8 +480,8 @@ namespace comphelper // a sequence of values Sequence< Any > aValues( aProperties.getLength() ); std::transform( - aProperties.begin(), - aProperties.end(), + std::cbegin(aProperties), + std::cend(aProperties), aValues.getArray(), ExtractPropertyValue() ); diff --git a/comphelper/source/property/opropertybag.hxx b/comphelper/source/property/opropertybag.hxx index 73957e51a39f..66c38d870c10 100644 --- a/comphelper/source/property/opropertybag.hxx +++ b/comphelper/source/property/opropertybag.hxx @@ -25,8 +25,8 @@ #include <com/sun/star/beans/XPropertyBag.hpp> #include <com/sun/star/container/XSet.hpp> -#include <cppuhelper/implbase5.hxx> -#include <comphelper/interfacecontainer2.hxx> +#include <cppuhelper/implbase.hxx> +#include <comphelper/interfacecontainer3.hxx> #include <comphelper/propstate.hxx> #include <comphelper/broadcasthelper.hxx> #include <comphelper/propertybag.hxx> @@ -55,12 +55,12 @@ namespace comphelper typedef std::map< sal_Int32, css::uno::Any > MapInt2Any; typedef std::set< css::uno::Type, UnoTypeLess > TypeBag; - typedef ::cppu::WeakAggImplHelper5 < css::beans::XPropertyBag - , css::util::XModifiable - , css::lang::XServiceInfo - , css::lang::XInitialization - , css::container::XSet - > OPropertyBag_Base; + typedef ::cppu::WeakImplHelper < css::beans::XPropertyBag + , css::util::XModifiable + , css::lang::XServiceInfo + , css::lang::XInitialization + , css::container::XSet + > OPropertyBag_Base; typedef ::comphelper::OPropertyStateHelper OPropertyBag_PBase; class OPropertyBag final : public ::comphelper::OMutexAndBroadcastHelper // must be before OPropertyBag_PBase @@ -80,7 +80,7 @@ namespace comphelper bool m_bAutoAddProperties; /// for notification - ::comphelper::OInterfaceContainerHelper2 m_NotifyListeners; + ::comphelper::OInterfaceContainerHelper3<css::util::XModifyListener> m_NotifyListeners; /// modify flag bool m_isModified; diff --git a/comphelper/source/property/propagg.cxx b/comphelper/source/property/propagg.cxx index 576621246207..5a0574460cf4 100644 --- a/comphelper/source/property/propagg.cxx +++ b/comphelper/source/property/propagg.cxx @@ -27,6 +27,7 @@ #include <o3tl/sorted_vector.hxx> #include <typeinfo> #include <algorithm> +#include <cstddef> #include <unordered_set> #include <memory> @@ -83,12 +84,13 @@ OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper( std::unordered_set< sal_Int32 > existingHandles; existingHandles.reserve( m_aProperties.size() ); sal_Int32 nAggregateHandle = _nFirstAggregateId; - for ( sal_Int32 nMPLoop = 0; nMPLoop < static_cast< sal_Int32 >( m_aProperties.size() ); ++nMPLoop ) + for ( std::size_t nMPLoop = 0; nMPLoop < m_aProperties.size(); ++nMPLoop ) { auto &prop = m_aProperties[ nMPLoop ]; if ( aDelegatorProps.find( prop.Name ) != aDelegatorProps.end() ) { - m_aPropertyAccessors[ prop.Handle ] = OPropertyAccessor( -1, nMPLoop, false ); + m_aPropertyAccessors.insert_or_assign( + prop.Handle, OPropertyAccessor( -1, nMPLoop, false )); existingHandles.insert( prop.Handle ); } else @@ -111,7 +113,8 @@ OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper( } // remember the accessor for this property - m_aPropertyAccessors[ nHandle ] = OPropertyAccessor( prop.Handle, nMPLoop, true ); + m_aPropertyAccessors.insert_or_assign( + nHandle, OPropertyAccessor( prop.Handle, nMPLoop, true )); prop.Handle = nHandle; } } @@ -126,7 +129,7 @@ OPropertyArrayAggregationHelper::PropertyOrigin OPropertyArrayAggregationHelper: if ( pPropertyDescriptor ) { // look up the handle for this name - ConstPropertyAccessorMapIterator aPos = m_aPropertyAccessors.find( pPropertyDescriptor->Handle ); + auto aPos = m_aPropertyAccessors.find( pPropertyDescriptor->Handle ); OSL_ENSURE( m_aPropertyAccessors.end() != aPos, "OPropertyArrayAggregationHelper::classifyProperty: should have this handle in my map!" ); if ( m_aPropertyAccessors.end() != aPos ) { @@ -170,7 +173,7 @@ sal_Int32 OPropertyArrayAggregationHelper::getHandleByName(const OUString& _rPro sal_Bool OPropertyArrayAggregationHelper::fillPropertyMembersByHandle( OUString* _pPropName, sal_Int16* _pAttributes, sal_Int32 _nHandle) { - ConstPropertyAccessorMapIterator i = m_aPropertyAccessors.find(_nHandle); + auto i = m_aPropertyAccessors.find(_nHandle); bool bRet = i != m_aPropertyAccessors.end(); if (bRet) { @@ -186,7 +189,7 @@ sal_Bool OPropertyArrayAggregationHelper::fillPropertyMembersByHandle( bool OPropertyArrayAggregationHelper::getPropertyByHandle( sal_Int32 _nHandle, Property& _rProperty ) const { - ConstPropertyAccessorMapIterator pos = m_aPropertyAccessors.find(_nHandle); + auto pos = m_aPropertyAccessors.find(_nHandle); if ( pos != m_aPropertyAccessors.end() ) { _rProperty = m_aProperties[ pos->second.nPos ]; @@ -199,7 +202,7 @@ bool OPropertyArrayAggregationHelper::getPropertyByHandle( sal_Int32 _nHandle, P bool OPropertyArrayAggregationHelper::fillAggregatePropertyInfoByHandle( OUString* _pPropName, sal_Int32* _pOriginalHandle, sal_Int32 _nHandle) const { - ConstPropertyAccessorMapIterator i = m_aPropertyAccessors.find(_nHandle); + auto i = m_aPropertyAccessors.find(_nHandle); bool bRet = i != m_aPropertyAccessors.end() && (*i).second.bAggregate; if (bRet) { @@ -207,7 +210,7 @@ bool OPropertyArrayAggregationHelper::fillAggregatePropertyInfoByHandle( *_pOriginalHandle = (*i).second.nOriginalHandle; if (_pPropName) { - OSL_ENSURE((*i).second.nPos < static_cast<sal_Int32>(m_aProperties.size()),"Invalid index for sequence!"); + OSL_ENSURE((*i).second.nPos < m_aProperties.size(),"Invalid index for sequence!"); const css::beans::Property& rProperty = m_aProperties[(*i).second.nPos]; *_pPropName = rProperty.Name; } @@ -264,7 +267,7 @@ namespace internal /** checks whether the forwarder is responsible for the given property */ - bool isResponsibleFor( sal_Int32 _nHandle ); + bool isResponsibleFor( sal_Int32 _nHandle ) const; /// actually forwards a property value to the aggregate /// @@ -288,7 +291,7 @@ namespace internal } - bool PropertyForwarder::isResponsibleFor( sal_Int32 _nHandle ) + bool PropertyForwarder::isResponsibleFor( sal_Int32 _nHandle ) const { return m_aProperties.find( _nHandle ) != m_aProperties.end(); } @@ -586,6 +589,9 @@ void SAL_CALL OPropertySetAggregationHelper::setPropertyValues( OPropertySetHelper::setPropertyValues(_rPropertyNames, _rValues); else if (_rPropertyNames.getLength() == 1) // use the more efficient way { + if (_rValues.getLength() != 1) + throw IllegalArgumentException("lengths do not match", static_cast<XPropertySet*>(this), + -1); try { setPropertyValue( _rPropertyNames[0], _rValues[0] ); @@ -628,6 +634,9 @@ void SAL_CALL OPropertySetAggregationHelper::setPropertyValues( // mixed else { + if (_rValues.getLength() != nLen) + throw IllegalArgumentException("lengths do not match", + static_cast<XPropertySet*>(this), -1); const css::uno::Any* pValues = _rValues.getConstArray(); // dividing the Names and _rValues diff --git a/comphelper/source/property/property.cxx b/comphelper/source/property/property.cxx index 75208c2c51b4..7d57baeb39cb 100644 --- a/comphelper/source/property/property.cxx +++ b/comphelper/source/property/property.cxx @@ -21,6 +21,7 @@ #include <comphelper/sequence.hxx> #include <osl/diagnose.h> #include <sal/log.hxx> +#include <comphelper/diagnose_ex.hxx> #if OSL_DEBUG_LEVEL > 0 #include <cppuhelper/exc_hlp.hxx> @@ -87,10 +88,12 @@ void copyProperties(const Reference<XPropertySet>& _rxSource, catch (Exception&) { #if OSL_DEBUG_LEVEL > 0 - OUStringBuffer aBuffer; - aBuffer.append( "::comphelper::copyProperties: could not copy property '" ); - aBuffer.append(rSourceProp.Name ); - aBuffer.append( "' to the destination set (a '" ); + TOOLS_WARN_EXCEPTION("comphelper", "Caught exception copying properties"); + + OUStringBuffer aBuffer( + "::comphelper::copyProperties: could not copy property '" + + rSourceProp.Name + + "' to the destination set (a '" ); Reference< XServiceInfo > xSI( _rxDest, UNO_QUERY ); if ( xSI.is() ) @@ -99,21 +102,21 @@ void copyProperties(const Reference<XPropertySet>& _rxSource, } else { - aBuffer.append( OUString::createFromAscii(typeid( *_rxDest ).name()) ); + aBuffer.appendAscii( typeid( *_rxDest ).name() ); } aBuffer.append( "' implementation).\n" ); Any aException( ::cppu::getCaughtException() ); - aBuffer.append( "Caught an exception of type '" ); - aBuffer.append( aException.getValueTypeName() ); - aBuffer.append( "'" ); + aBuffer.append( "Caught an exception of type '" + + aException.getValueTypeName() + + "'" ); Exception aBaseException; if ( ( aException >>= aBaseException ) && !aBaseException.Message.isEmpty() ) { - aBuffer.append( ", saying '" ); - aBuffer.append( aBaseException.Message ); - aBuffer.append( "'" ); + aBuffer.append( ", saying '" + + aBaseException.Message + + "'" ); } aBuffer.append( "." ); @@ -138,31 +141,25 @@ bool hasProperty(const OUString& _rName, const Reference<XPropertySet>& _rxSet) void RemoveProperty(Sequence<Property>& _rProps, const OUString& _rPropName) { - sal_Int32 nLen = _rProps.getLength(); - // binary search - const Property* pProperties = _rProps.getConstArray(); Property aNameProp(_rPropName, 0, Type(), 0); - const Property* pResult = std::lower_bound(pProperties, pProperties + nLen, aNameProp, PropertyCompareByName()); + const Property* pResult = std::lower_bound(std::cbegin(_rProps), std::cend(_rProps), aNameProp, PropertyCompareByName()); - if ( pResult != _rProps.end() && pResult->Name == _rPropName ) + if ( pResult != std::cend(_rProps) && pResult->Name == _rPropName) { - OSL_ENSURE(pResult->Name == _rPropName, "::RemoveProperty Properties not sorted"); - removeElementAt(_rProps, pResult - pProperties); + removeElementAt(_rProps, pResult - std::cbegin(_rProps)); } } void ModifyPropertyAttributes(Sequence<Property>& seqProps, const OUString& sPropName, sal_Int16 nAddAttrib, sal_Int16 nRemoveAttrib) { - sal_Int32 nLen = seqProps.getLength(); - // binary search - Property* pProperties = seqProps.getArray(); + auto [begin, end] = asNonConstRange(seqProps); Property aNameProp(sPropName, 0, Type(), 0); - Property* pResult = std::lower_bound(pProperties, pProperties + nLen, aNameProp, PropertyCompareByName()); + Property* pResult = std::lower_bound(begin, end, aNameProp, PropertyCompareByName()); - if ( (pResult != seqProps.end()) && (pResult->Name == sPropName) ) + if ( (pResult != end) && (pResult->Name == sPropName) ) { pResult->Attributes |= nAddAttrib; pResult->Attributes &= ~nRemoveAttrib; diff --git a/comphelper/source/property/propertycontainer.cxx b/comphelper/source/property/propertycontainer.cxx index 2b5685405604..ad24c5f30aa7 100644 --- a/comphelper/source/property/propertycontainer.cxx +++ b/comphelper/source/property/propertycontainer.cxx @@ -26,7 +26,6 @@ namespace comphelper using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::lang; using namespace ::com::sun::star::beans; OPropertyContainer::OPropertyContainer(::cppu::OBroadcastHelper& _rBHelper) diff --git a/comphelper/source/property/propertycontainer2.cxx b/comphelper/source/property/propertycontainer2.cxx new file mode 100644 index 000000000000..5a3bfa4be285 --- /dev/null +++ b/comphelper/source/property/propertycontainer2.cxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <comphelper/propertycontainer2.hxx> +#include <cppuhelper/typeprovider.hxx> + +namespace comphelper +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; + +OPropertyContainer2::OPropertyContainer2() {} + +OPropertyContainer2::~OPropertyContainer2() {} + +Sequence<Type> OPropertyContainer2::getBaseTypes() +{ + // just the types from our one and only base class + ::cppu::OTypeCollection aTypes(cppu::UnoType<XPropertySet>::get(), + cppu::UnoType<XFastPropertySet>::get(), + cppu::UnoType<XMultiPropertySet>::get()); + return aTypes.getTypes(); +} + +bool OPropertyContainer2::convertFastPropertyValue(std::unique_lock<std::mutex>& /*rGuard*/, + Any& _rConvertedValue, Any& _rOldValue, + sal_Int32 _nHandle, const Any& _rValue) +{ + return OPropertyContainerHelper::convertFastPropertyValue(_rConvertedValue, _rOldValue, + _nHandle, _rValue); +} + +void OPropertyContainer2::setFastPropertyValue_NoBroadcast(std::unique_lock<std::mutex>& /*rGuard*/, + sal_Int32 _nHandle, const Any& _rValue) +{ + OPropertyContainerHelper::setFastPropertyValue(_nHandle, _rValue); +} + +void OPropertyContainer2::getFastPropertyValue(std::unique_lock<std::mutex>& /*rGuard*/, + Any& _rValue, sal_Int32 _nHandle) const +{ + OPropertyContainerHelper::getFastPropertyValue(_rValue, _nHandle); +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/property/propertycontainerhelper.cxx b/comphelper/source/property/propertycontainerhelper.cxx index 1ba31ec8258f..ee81100ae617 100644 --- a/comphelper/source/property/propertycontainerhelper.cxx +++ b/comphelper/source/property/propertycontainerhelper.cxx @@ -26,6 +26,7 @@ #include <com/sun/star/beans/UnknownPropertyException.hpp> #include <algorithm> +#include <utility> namespace comphelper @@ -51,7 +52,7 @@ namespace struct PropertyDescriptionNameMatch { OUString const m_rCompare; - explicit PropertyDescriptionNameMatch( const OUString& _rCompare ) : m_rCompare( _rCompare ) { } + explicit PropertyDescriptionNameMatch( OUString _aCompare ) : m_rCompare(std::move( _aCompare )) { } bool operator() (const PropertyDescription& x ) const { @@ -269,7 +270,7 @@ bool OPropertyContainerHelper::convertFastPropertyValue( if (PropertyDescription::LocationType::HoldMyself == aPos->eLocated) { - OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < static_cast<sal_Int32>(m_aHoldProperties.size()), + OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < m_aHoldProperties.size(), "OPropertyContainerHelper::convertFastPropertyValue: invalid position !"); auto aIter = m_aHoldProperties.begin() + aPos->aLocation.nOwnClassVectorIndex; pPropContainer = &(*aIter); @@ -407,7 +408,7 @@ void OPropertyContainerHelper::getFastPropertyValue(Any& _rValue, sal_Int32 _nHa switch (aPos->eLocated) { case PropertyDescription::LocationType::HoldMyself: - OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < static_cast<sal_Int32>(m_aHoldProperties.size()), + OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < m_aHoldProperties.size(), "OPropertyContainerHelper::convertFastPropertyValue: invalid position !"); _rValue = m_aHoldProperties[aPos->aLocation.nOwnClassVectorIndex]; break; @@ -469,15 +470,15 @@ void OPropertyContainerHelper::describeProperties(Sequence< Property >& _rProps) } // as our property vector is sorted by handles, not by name, we have to sort aOwnProps - std::sort(aOwnProps.begin(), aOwnProps.end(), PropertyCompareByName()); + auto [begin, end] = asNonConstRange(aOwnProps); + std::sort(begin, end, PropertyCompareByName()); // unfortunately the STL merge function does not allow the output range to overlap one of the input ranges, // so we need an extra sequence - Sequence< Property > aOutput; - aOutput.realloc(_rProps.getLength() + aOwnProps.getLength()); + Sequence< Property > aOutput(_rProps.getLength() + aOwnProps.getLength()); // do the merge - std::merge( _rProps.begin(), _rProps.end(), // input 1 - aOwnProps.begin(), aOwnProps.end(), // input 2 + std::merge( std::cbegin(_rProps), std::cend(_rProps), // input 1 + std::cbegin(aOwnProps), std::cend(aOwnProps), // input 2 aOutput.getArray(), // output PropertyCompareByName() // compare operator ); diff --git a/comphelper/source/property/propertysethelper.cxx b/comphelper/source/property/propertysethelper.cxx index de6e914cb859..519b0705fadd 100644 --- a/comphelper/source/property/propertysethelper.cxx +++ b/comphelper/source/property/propertysethelper.cxx @@ -23,6 +23,7 @@ #include <rtl/ref.hxx> #include <memory> +#include <utility> using namespace ::comphelper; using namespace ::com::sun::star; @@ -30,7 +31,7 @@ using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::lang; -static PropertyMapEntry const * find( rtl::Reference<PropertySetInfo>& mxInfo, const OUString& aName ) throw() +static PropertyMapEntry const * find( const rtl::Reference<PropertySetInfo>& mxInfo, const OUString& aName ) noexcept { PropertyMap::const_iterator aIter = mxInfo->getPropertyMap().find( aName ); @@ -41,19 +42,19 @@ static PropertyMapEntry const * find( rtl::Reference<PropertySetInfo>& mxInfo, c } -PropertySetHelper::PropertySetHelper( rtl::Reference<comphelper::PropertySetInfo> const & xInfo ) throw() - : mxInfo(xInfo) +PropertySetHelper::PropertySetHelper( rtl::Reference<comphelper::PropertySetInfo> xInfo ) noexcept + : mxInfo(std::move(xInfo)) { } -PropertySetHelper::~PropertySetHelper() throw() +PropertySetHelper::~PropertySetHelper() noexcept { } // XPropertySet Reference< XPropertySetInfo > SAL_CALL PropertySetHelper::getPropertySetInfo( ) { - return mxInfo.get(); + return mxInfo; } void SAL_CALL PropertySetHelper::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) @@ -153,16 +154,15 @@ Sequence< Any > SAL_CALL PropertySetHelper::getPropertyValues(const Sequence< OU bUnknown = nullptr == pEntries[n]; } - if( !bUnknown ) - { - pEntries[nCount] = nullptr; - Sequence< Any > aValues(nCount); - aValues.realloc(nCount); - _getPropertyValues( pEntries.get(), aValues.getArray() ); - return aValues; - } - else + if( bUnknown ) throw RuntimeException( *pNames, static_cast< XPropertySet* >( this ) ); + + pEntries[nCount] = nullptr; + Sequence< Any > aValues(nCount); + aValues.realloc(nCount); + _getPropertyValues( pEntries.get(), aValues.getArray() ); + return aValues; + } void SAL_CALL PropertySetHelper::addPropertiesChangeListener( const Sequence< OUString >&, const Reference< XPropertiesChangeListener >& ) diff --git a/comphelper/source/property/propertysetinfo.cxx b/comphelper/source/property/propertysetinfo.cxx index a77a32799c7d..1d4ad2be8d25 100644 --- a/comphelper/source/property/propertysetinfo.cxx +++ b/comphelper/source/property/propertysetinfo.cxx @@ -20,74 +20,69 @@ #include <comphelper/propertysetinfo.hxx> #include <comphelper/sequence.hxx> -#include <vector> using namespace ::comphelper; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; -using namespace ::com::sun::star::lang; -namespace comphelper +PropertySetInfo::PropertySetInfo() noexcept { -class PropertyMapImpl final -{ -public: - PropertyMapImpl() throw(); - - void add(PropertyMapEntry const * pMap) throw(); - void remove( const OUString& aName ) throw(); - - std::vector< Property > const & getProperties() throw(); - - const PropertyMap& getPropertyMap() const throw() { return maPropertyMap;} +} - /// @throws UnknownPropertyException - Property getPropertyByName( const OUString& aName ); - bool hasPropertyByName( const OUString& aName ) throw(); +PropertySetInfo::PropertySetInfo( std::span<const PropertyMapEntry> pMap ) noexcept +{ + maPropertyMap.reserve(pMap.size()); + for (const auto & rEntry : pMap) + { + // check for duplicates + assert(maPropertyMap.find(rEntry.maName) == maPropertyMap.end()); + // Make sure there are no accidental empty entries left at the end of the array from + // when this method used to take a empty-terminated array. + assert(!rEntry.maName.isEmpty()); -private: - PropertyMap maPropertyMap; - std::vector< Property > maProperties; -}; + maPropertyMap.emplace(rEntry.maName, &rEntry); + } } -PropertyMapImpl::PropertyMapImpl() throw() +PropertySetInfo::~PropertySetInfo() noexcept { } -void PropertyMapImpl::add(PropertyMapEntry const * pMap) throw() +void PropertySetInfo::add( std::span<PropertyMapEntry const> pMap ) noexcept { - while (!pMap->maName.isEmpty()) + maPropertyMap.reserve(maPropertyMap.size() + pMap.size()); + for (const auto & rEntry : pMap) { // check for duplicates - assert(maPropertyMap.find(pMap->maName) == maPropertyMap.end()); - - maPropertyMap[pMap->maName] = pMap; + assert(maPropertyMap.find(rEntry.maName) == maPropertyMap.end()); + // Make sure there are no accidental empty entries left at the end of the array from + // when this method used to take a empty-terminated array. + assert(!rEntry.maName.isEmpty()); - maProperties.clear(); - - pMap = &pMap[1]; + maPropertyMap.emplace(rEntry.maName, &rEntry); } + + // clear cache + maProperties.realloc(0); } -void PropertyMapImpl::remove( const OUString& aName ) throw() +void PropertySetInfo::remove( const OUString& aName ) noexcept { maPropertyMap.erase( aName ); - - maProperties.clear(); + maProperties.realloc(0); } -std::vector< Property > const & PropertyMapImpl::getProperties() throw() +Sequence< css::beans::Property > SAL_CALL PropertySetInfo::getProperties() { // maybe we have to generate the properties after // a change in the property map or at first call // to getProperties if( maProperties.size() != maPropertyMap.size() ) { - maProperties.resize( maPropertyMap.size() ); - auto propIter = maProperties.begin(); + maProperties.realloc( maPropertyMap.size() ); + auto propIter = maProperties.getArray(); for( const auto& rProperty : maPropertyMap ) { @@ -101,12 +96,10 @@ std::vector< Property > const & PropertyMapImpl::getProperties() throw() ++propIter; } } - return maProperties; } - -Property PropertyMapImpl::getPropertyByName( const OUString& aName ) +Property SAL_CALL PropertySetInfo::getPropertyByName( const OUString& aName ) { PropertyMap::iterator aIter = maPropertyMap.find( aName ); @@ -118,73 +111,9 @@ Property PropertyMapImpl::getPropertyByName( const OUString& aName ) return Property( aName, pEntry->mnHandle, pEntry->maType, pEntry->mnAttributes ); } -bool PropertyMapImpl::hasPropertyByName( const OUString& aName ) throw() -{ - return maPropertyMap.find( aName ) != maPropertyMap.end(); -} - - -PropertySetInfo::PropertySetInfo() throw() - : mpImpl(new PropertyMapImpl) -{ -} - -PropertySetInfo::PropertySetInfo( PropertyMapEntry const * pMap ) throw() - : mpImpl(new PropertyMapImpl) -{ - mpImpl->add( pMap ); -} - -PropertySetInfo::PropertySetInfo(uno::Sequence<beans::Property> const& rProps) throw() - : mpImpl(new PropertyMapImpl) -{ - PropertyMapEntry * pEntries(new PropertyMapEntry[rProps.getLength() + 1]); - PropertyMapEntry * pEntry(&pEntries[0]); - for (auto const& it : rProps) - { - pEntry->maName = it.Name; - pEntry->mnHandle = it.Handle; - pEntry->maType = it.Type; - pEntry->mnAttributes = it.Attributes; - pEntry->mnMemberId = 0; - ++pEntry; - } - pEntry->maName = OUString(); - mpImpl->add(pEntries); -} - -PropertySetInfo::~PropertySetInfo() throw() -{ -} - -void PropertySetInfo::add( PropertyMapEntry const * pMap ) throw() -{ - mpImpl->add( pMap ); -} - -void PropertySetInfo::remove( const OUString& aName ) throw() -{ - mpImpl->remove( aName ); -} - -Sequence< css::beans::Property > SAL_CALL PropertySetInfo::getProperties() -{ - return comphelper::containerToSequence(mpImpl->getProperties()); -} - -Property SAL_CALL PropertySetInfo::getPropertyByName( const OUString& aName ) -{ - return mpImpl->getPropertyByName( aName ); -} - -sal_Bool SAL_CALL PropertySetInfo::hasPropertyByName( const OUString& Name ) -{ - return mpImpl->hasPropertyByName( Name ); -} - -const PropertyMap& PropertySetInfo::getPropertyMap() const throw() +sal_Bool SAL_CALL PropertySetInfo::hasPropertyByName( const OUString& aName ) { - return mpImpl->getPropertyMap(); + return maPropertyMap.contains( aName ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/property/propertystatecontainer.cxx b/comphelper/source/property/propertystatecontainer.cxx index e19e78733689..5fbe6252d62b 100644 --- a/comphelper/source/property/propertystatecontainer.cxx +++ b/comphelper/source/property/propertystatecontainer.cxx @@ -30,7 +30,6 @@ namespace comphelper using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; - using namespace ::com::sun::star::lang; namespace { diff --git a/comphelper/source/property/propmultiplex2.cxx b/comphelper/source/property/propmultiplex2.cxx new file mode 100644 index 000000000000..b9d7719c4e1d --- /dev/null +++ b/comphelper/source/property/propmultiplex2.cxx @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <comphelper/propmultiplex2.hxx> +#include <osl/diagnose.h> + +namespace comphelper +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; + +OPropertyChangeListener2::~OPropertyChangeListener2() +{ + if (m_xAdapter.is()) + m_xAdapter->onListenerDestruction(); +} + +void OPropertyChangeListener2::disposeAdapter(std::unique_lock<std::mutex>& rGuard) +{ + if (m_xAdapter.is()) + m_xAdapter->dispose(rGuard); + + // will automatically set a new adapter + OSL_ENSURE(!m_xAdapter.is(), "OPropertyChangeListener::disposeAdapter: what did dispose do?"); +} + +void OPropertyChangeListener2::setAdapter(std::unique_lock<std::mutex>& /*rGuard*/, + OPropertyChangeMultiplexer2* pAdapter) +{ + m_xAdapter = pAdapter; +} + +OPropertyChangeMultiplexer2::OPropertyChangeMultiplexer2(std::mutex& rMutex, + std::unique_lock<std::mutex>& rGuard, + OPropertyChangeListener2* _pListener, + const Reference<XPropertySet>& _rxSet) + : m_rMutex(rMutex) + , m_xSet(_rxSet) + , m_pListener(_pListener) + , m_nLockCount(0) + , m_bListening(false) +{ + m_pListener->setAdapter(rGuard, this); +} + +OPropertyChangeMultiplexer2::~OPropertyChangeMultiplexer2() {} + +void OPropertyChangeMultiplexer2::lock() { ++m_nLockCount; } + +void OPropertyChangeMultiplexer2::unlock() { --m_nLockCount; } + +void OPropertyChangeMultiplexer2::dispose(std::unique_lock<std::mutex>& rGuard) +{ + if (!m_bListening) + return; + + Reference<XPropertyChangeListener> xPreventDelete(this); + + for (const OUString& rProp : m_aProperties) + m_xSet->removePropertyChangeListener(rProp, static_cast<XPropertyChangeListener*>(this)); + + m_pListener->setAdapter(rGuard, nullptr); + + m_pListener = nullptr; + m_bListening = false; + + m_xSet = nullptr; +} + +void OPropertyChangeMultiplexer2::onListenerDestruction() +{ + if (!m_bListening) + return; + + Reference<XPropertyChangeListener> xPreventDelete(this); + + for (const OUString& rProp : m_aProperties) + m_xSet->removePropertyChangeListener(rProp, static_cast<XPropertyChangeListener*>(this)); +} + +// XEventListener + +void SAL_CALL OPropertyChangeMultiplexer2::disposing(const EventObject& /*_rSource*/) +{ + std::unique_lock g(m_rMutex); + if (m_pListener) + { + // disconnect the listener + if (m_pListener) // may have been reset whilst calling into _disposing + m_pListener->setAdapter(g, nullptr); + } + + m_pListener = nullptr; + m_bListening = false; + + m_xSet = nullptr; +} + +// XPropertyChangeListener + +void SAL_CALL OPropertyChangeMultiplexer2::propertyChange(const PropertyChangeEvent& _rEvent) +{ + if (m_pListener && !locked()) + m_pListener->_propertyChanged(_rEvent); +} + +void OPropertyChangeMultiplexer2::addProperty(const OUString& _sPropertyName) +{ + if (m_xSet.is()) + { + m_xSet->addPropertyChangeListener(_sPropertyName, + static_cast<XPropertyChangeListener*>(this)); + m_aProperties.push_back(_sPropertyName); + m_bListening = true; + } +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/property/propshlp.cxx b/comphelper/source/property/propshlp.cxx new file mode 100644 index 000000000000..ca1459582827 --- /dev/null +++ b/comphelper/source/property/propshlp.cxx @@ -0,0 +1,856 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <osl/diagnose.h> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <comphelper/propshlp.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <memory> +#include <sal/log.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace cppu; + +namespace comphelper +{ +extern "C" { + +static int compare_OUString_Property_Impl(const void* arg1, const void* arg2) SAL_THROW_EXTERN_C() +{ + return static_cast<OUString const*>(arg1)->compareTo(static_cast<Property const*>(arg2)->Name); +} +} + +/** + * The class which implements the PropertySetInfo interface. + */ + +namespace +{ +class OPropertySetHelperInfo_Impl : public WeakImplHelper<css::beans::XPropertySetInfo> +{ + Sequence<Property> aInfos; + +public: + explicit OPropertySetHelperInfo_Impl(IPropertyArrayHelper& rHelper_); + + // XPropertySetInfo-methods + virtual Sequence<Property> SAL_CALL getProperties() override; + virtual Property SAL_CALL getPropertyByName(const OUString& PropertyName) override; + virtual sal_Bool SAL_CALL hasPropertyByName(const OUString& PropertyName) override; +}; +} + +/** + * Create an object that implements XPropertySetInfo IPropertyArrayHelper. + */ +OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl(IPropertyArrayHelper& rHelper_) + : aInfos(rHelper_.getProperties()) +{ +} + +/** + * Return the sequence of properties, which are provided through the constructor. + */ +Sequence<Property> OPropertySetHelperInfo_Impl::getProperties() { return aInfos; } + +/** + * Return the sequence of properties, which are provided through the constructor. + */ +Property OPropertySetHelperInfo_Impl::getPropertyByName(const OUString& PropertyName) +{ + Property* pR + = static_cast<Property*>(bsearch(&PropertyName, aInfos.getConstArray(), aInfos.getLength(), + sizeof(Property), compare_OUString_Property_Impl)); + if (!pR) + throw UnknownPropertyException(PropertyName); + + return *pR; +} + +/** + * Return the sequence of properties, which are provided through the constructor. + */ +sal_Bool OPropertySetHelperInfo_Impl::hasPropertyByName(const OUString& PropertyName) +{ + Property* pR + = static_cast<Property*>(bsearch(&PropertyName, aInfos.getConstArray(), aInfos.getLength(), + sizeof(Property), compare_OUString_Property_Impl)); + return pR != nullptr; +} + +OPropertySetHelper::OPropertySetHelper() {} + +OPropertySetHelper::OPropertySetHelper(bool bIgnoreRuntimeExceptionsWhileFiring) + : m_bIgnoreRuntimeExceptionsWhileFiring(bIgnoreRuntimeExceptionsWhileFiring) +{ +} + +/** + * You must call disposing before. + */ +OPropertySetHelper::~OPropertySetHelper() {} + +// XInterface +Any OPropertySetHelper::queryInterface(const css::uno::Type& rType) +{ + return ::cppu::queryInterface(rType, static_cast<XPropertySet*>(this), + static_cast<XMultiPropertySet*>(this), + static_cast<XFastPropertySet*>(this)); +} + +/** + * called from the derivee's XTypeProvider::getTypes implementation + */ +css::uno::Sequence<css::uno::Type> OPropertySetHelper::getTypes() +{ + return { UnoType<css::beans::XPropertySet>::get(), + UnoType<css::beans::XMultiPropertySet>::get(), + UnoType<css::beans::XFastPropertySet>::get() }; +} + +// ComponentHelper +void OPropertySetHelper::disposing(std::unique_lock<std::mutex>& rGuard) +{ + // Create an event with this as sender + Reference<XPropertySet> rSource = this; + EventObject aEvt; + aEvt.Source = rSource; + + // inform all listeners to release this object + // The listener containers are automatically cleared + aBoundLC.disposeAndClear(rGuard, aEvt); + aVetoableLC.disposeAndClear(rGuard, aEvt); +} + +Reference<XPropertySetInfo> +OPropertySetHelper::createPropertySetInfo(IPropertyArrayHelper& rProperties) +{ + return new OPropertySetHelperInfo_Impl(rProperties); +} + +// XPropertySet +void OPropertySetHelper::setPropertyValue(const OUString& rPropertyName, const Any& rValue) +{ + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + // map the name to the handle + sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); + std::unique_lock aGuard(m_aMutex); + setFastPropertyValueImpl(aGuard, nHandle, rValue); +} + +// XPropertySet +Any OPropertySetHelper::getPropertyValue(const OUString& rPropertyName) +{ + std::unique_lock aGuard(m_aMutex); + return getPropertyValueImpl(aGuard, rPropertyName); +} + +Any OPropertySetHelper::getPropertyValueImpl(std::unique_lock<std::mutex>& rGuard, + const OUString& rPropertyName) +{ + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + // map the name to the handle + sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); + // call the method of the XFastPropertySet interface + Any aAny; + getFastPropertyValue(rGuard, aAny, nHandle); + return aAny; +} + +// XPropertySet +void OPropertySetHelper::addPropertyChangeListener( + const OUString& rPropertyName, const Reference<XPropertyChangeListener>& rxListener) +{ + std::unique_lock aGuard(m_aMutex); + OSL_ENSURE(!m_bDisposed, "object is disposed"); + if (m_bDisposed) + return; + + // only add listeners if you are not disposed + // a listener with no name means all properties + if (!rPropertyName.isEmpty()) + { + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + // map the name to the handle + sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); + if (nHandle == -1) + { + // property not known throw exception + throw UnknownPropertyException(rPropertyName); + } + + sal_Int16 nAttributes; + rPH.fillPropertyMembersByHandle(nullptr, &nAttributes, nHandle); + if (!(nAttributes & css::beans::PropertyAttribute::BOUND)) + { + OSL_FAIL("add listener to an unbound property"); + // silent ignore this + return; + } + // add the change listener to the helper container + aBoundLC.addInterface(aGuard, nHandle, rxListener); + } + else + // add the change listener to the helper container + maPropertyChangeListeners.addInterface(aGuard, rxListener); +} + +// XPropertySet +void OPropertySetHelper::removePropertyChangeListener( + const OUString& rPropertyName, const Reference<XPropertyChangeListener>& rxListener) +{ + std::unique_lock aGuard(m_aMutex); + OSL_ENSURE(!m_bDisposed, "object is disposed"); + // all listeners are automatically released in a dispose call + if (m_bDisposed) + return; + + if (!rPropertyName.isEmpty()) + { + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + // map the name to the handle + sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); + if (nHandle == -1) + // property not known throw exception + throw UnknownPropertyException(rPropertyName); + aBoundLC.removeInterface(aGuard, nHandle, rxListener); + } + else + { + // remove the change listener to the helper container + maPropertyChangeListeners.removeInterface(aGuard, rxListener); + } +} + +// XPropertySet +void OPropertySetHelper::addVetoableChangeListener( + const OUString& rPropertyName, const Reference<XVetoableChangeListener>& rxListener) +{ + std::unique_lock aGuard(m_aMutex); + OSL_ENSURE(!m_bDisposed, "object is disposed"); + if (m_bDisposed) + return; + + // only add listeners if you are not disposed + // a listener with no name means all properties + if (!rPropertyName.isEmpty()) + { + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + // map the name to the handle + sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); + if (nHandle == -1) + { + // property not known throw exception + throw UnknownPropertyException(rPropertyName); + } + + sal_Int16 nAttributes; + rPH.fillPropertyMembersByHandle(nullptr, &nAttributes, nHandle); + if (!(nAttributes & PropertyAttribute::CONSTRAINED)) + { + OSL_FAIL("addVetoableChangeListener, and property is not constrained"); + // silent ignore this + return; + } + // add the vetoable listener to the helper container + aVetoableLC.addInterface(aGuard, nHandle, rxListener); + } + else + // add the vetoable listener to the helper container + maVetoableChangeListeners.addInterface(aGuard, rxListener); +} + +// XPropertySet +void OPropertySetHelper::removeVetoableChangeListener( + const OUString& rPropertyName, const Reference<XVetoableChangeListener>& rxListener) +{ + std::unique_lock aGuard(m_aMutex); + OSL_ENSURE(!m_bDisposed, "object is disposed"); + // all listeners are automatically released in a dispose call + if (m_bDisposed) + return; + + if (!rPropertyName.isEmpty()) + { + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + // map the name to the handle + sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); + if (nHandle == -1) + { + // property not known throw exception + throw UnknownPropertyException(rPropertyName); + } + // remove the vetoable listener to the helper container + aVetoableLC.removeInterface(aGuard, nHandle, rxListener); + } + else + // add the vetoable listener to the helper container + maVetoableChangeListeners.removeInterface(aGuard, rxListener); +} + +void OPropertySetHelper::setDependentFastPropertyValue(std::unique_lock<std::mutex>& rGuard, + sal_Int32 i_handle, + const css::uno::Any& i_value) +{ + sal_Int16 nAttributes(0); + IPropertyArrayHelper& rInfo = getInfoHelper(); + if (!rInfo.fillPropertyMembersByHandle(nullptr, &nAttributes, i_handle)) + // unknown property + throw UnknownPropertyException(OUString::number(i_handle)); + + // no need to check for READONLY-ness of the property. The method is intended to be called internally, which + // implies it might be invoked for properties which are read-only to the instance's clients, but well allowed + // to change their value. + + Any aConverted, aOld; + bool bChanged = convertFastPropertyValue(rGuard, aConverted, aOld, i_handle, i_value); + if (!bChanged) + return; + + // don't fire vetoable events. This method is called with our mutex locked, so calling into listeners would not be + // a good idea. The caller is responsible for not invoking this for constrained properties. + OSL_ENSURE((nAttributes & PropertyAttribute::CONSTRAINED) == 0, + "OPropertySetHelper::setDependentFastPropertyValue: not to be used for constrained " + "properties!"); + + // actually set the new value + try + { + setFastPropertyValue_NoBroadcast(rGuard, i_handle, aConverted); + } + catch (const UnknownPropertyException&) + { + throw; /* allowed to leave */ + } + catch (const PropertyVetoException&) + { + throw; /* allowed to leave */ + } + catch (const IllegalArgumentException&) + { + throw; /* allowed to leave */ + } + catch (const WrappedTargetException&) + { + throw; /* allowed to leave */ + } + catch (const RuntimeException&) + { + throw; /* allowed to leave */ + } + catch (const Exception&) + { + // not allowed to leave this method + WrappedTargetException aWrapped; + aWrapped.TargetException = ::cppu::getCaughtException(); + aWrapped.Context = static_cast<XPropertySet*>(this); + throw aWrapped; + } + + // remember the handle/values, for the events to be fired later + m_handles.push_back(i_handle); + m_newValues.push_back( + aConverted); // TODO: setFastPropertyValue notifies the unconverted value here ...? + m_oldValues.push_back(aOld); +} + +// XFastPropertySet +void OPropertySetHelper::setFastPropertyValue(sal_Int32 nHandle, const Any& rValue) +{ + std::unique_lock aGuard(m_aMutex); + setFastPropertyValueImpl(aGuard, nHandle, rValue); +} + +void OPropertySetHelper::setFastPropertyValueImpl(std::unique_lock<std::mutex>& rGuard, + sal_Int32 nHandle, const Any& rValue) +{ + OSL_ENSURE(!m_bDisposed, "object is disposed"); + + IPropertyArrayHelper& rInfo = getInfoHelper(); + sal_Int16 nAttributes; + if (!rInfo.fillPropertyMembersByHandle(nullptr, &nAttributes, nHandle)) + { + // unknown property + throw UnknownPropertyException(OUString::number(nHandle)); + } + if (nAttributes & PropertyAttribute::READONLY) + throw PropertyVetoException(); + + Any aConvertedVal; + Any aOldVal; + + // Will the property change? + bool bChanged = convertFastPropertyValue(rGuard, aConvertedVal, aOldVal, nHandle, rValue); + if (!bChanged) + return; + + // Is it a constrained property? + if (nAttributes & PropertyAttribute::CONSTRAINED) + { + // In aValue is the converted rValue + // fire a constrained event + // second parameter NULL means constrained + fire(rGuard, &nHandle, &rValue, &aOldVal, 1, true); + } + + try + { + // set the property to the new value + setFastPropertyValue_NoBroadcast(rGuard, nHandle, aConvertedVal); + } + catch (const css::beans::UnknownPropertyException&) + { + throw; /* allowed to leave */ + } + catch (const css::beans::PropertyVetoException&) + { + throw; /* allowed to leave */ + } + catch (const css::lang::IllegalArgumentException&) + { + throw; /* allowed to leave */ + } + catch (const css::lang::WrappedTargetException&) + { + throw; /* allowed to leave */ + } + catch (const css::uno::RuntimeException&) + { + throw; /* allowed to leave */ + } + catch (const css::uno::Exception& e) + { + // not allowed to leave this method + css::lang::WrappedTargetException aWrap; + aWrap.Context = static_cast<css::beans::XPropertySet*>(this); + aWrap.TargetException <<= e; + + throw aWrap; + } + + // file a change event, if the value changed + impl_fireAll(rGuard, &nHandle, &rValue, &aOldVal, 1); +} + +// XFastPropertySet +Any OPropertySetHelper::getFastPropertyValue(sal_Int32 nHandle) +{ + IPropertyArrayHelper& rInfo = getInfoHelper(); + if (!rInfo.fillPropertyMembersByHandle(nullptr, nullptr, nHandle)) + // unknown property + throw UnknownPropertyException(OUString::number(nHandle)); + + Any aRet; + std::unique_lock aGuard(m_aMutex); + getFastPropertyValue(aGuard, aRet, nHandle); + return aRet; +} + +void OPropertySetHelper::impl_fireAll(std::unique_lock<std::mutex>& rGuard, sal_Int32* i_handles, + const Any* i_newValues, const Any* i_oldValues, + sal_Int32 i_count) +{ + if (m_handles.empty()) + { + fire(rGuard, i_handles, i_newValues, i_oldValues, i_count, false); + return; + } + + const size_t additionalEvents = m_handles.size(); + OSL_ENSURE(additionalEvents == m_newValues.size() && additionalEvents == m_oldValues.size(), + "OPropertySetHelper::impl_fireAll: inconsistency!"); + + std::vector<sal_Int32> allHandles(additionalEvents + i_count); + std::copy(m_handles.begin(), m_handles.end(), allHandles.begin()); + std::copy(i_handles, i_handles + i_count, allHandles.begin() + additionalEvents); + + std::vector<Any> allNewValues(additionalEvents + i_count); + std::copy(m_newValues.begin(), m_newValues.end(), allNewValues.begin()); + std::copy(i_newValues, i_newValues + i_count, allNewValues.begin() + additionalEvents); + + std::vector<Any> allOldValues(additionalEvents + i_count); + std::copy(m_oldValues.begin(), m_oldValues.end(), allOldValues.begin()); + std::copy(i_oldValues, i_oldValues + i_count, allOldValues.begin() + additionalEvents); + + m_handles.clear(); + m_newValues.clear(); + m_oldValues.clear(); + + fire(rGuard, allHandles.data(), allNewValues.data(), allOldValues.data(), + additionalEvents + i_count, false); +} + +void OPropertySetHelper::fire(std::unique_lock<std::mutex>& rGuard, sal_Int32* pnHandles, + const Any* pNewValues, const Any* pOldValues, + sal_Int32 nHandles, // This is the Count of the array + bool bVetoable) +{ + // Only fire, if one or more properties changed + if (!nHandles) + return; + + // create the event sequence of all changed properties + Sequence<PropertyChangeEvent> aEvts(nHandles); + PropertyChangeEvent* pEvts = aEvts.getArray(); + Reference<XInterface> xSource(static_cast<XPropertySet*>(this), UNO_QUERY); + sal_Int32 i; + sal_Int32 nChangesLen = 0; + // Loop over all changed properties to fill the event struct + for (i = 0; i < nHandles; i++) + { + // Vetoable fire and constrained attribute set or + // Change fire and Changed and bound attribute set + IPropertyArrayHelper& rInfo = getInfoHelper(); + sal_Int16 nAttributes; + OUString aPropName; + rInfo.fillPropertyMembersByHandle(&aPropName, &nAttributes, pnHandles[i]); + + if ((bVetoable && (nAttributes & PropertyAttribute::CONSTRAINED)) + || (!bVetoable && (nAttributes & PropertyAttribute::BOUND))) + { + pEvts[nChangesLen].Source = xSource; + pEvts[nChangesLen].PropertyName = aPropName; + pEvts[nChangesLen].PropertyHandle = pnHandles[i]; + pEvts[nChangesLen].OldValue = pOldValues[i]; + pEvts[nChangesLen].NewValue = pNewValues[i]; + nChangesLen++; + } + } + + bool bIgnoreRuntimeExceptionsWhileFiring = m_bIgnoreRuntimeExceptionsWhileFiring; + + // fire the events for all changed properties + for (i = 0; i < nChangesLen; i++) + { + if (bVetoable) // fire change Events? + fireVetoableChangeListeners( + rGuard, aVetoableLC.getContainer(rGuard, pEvts[i].PropertyHandle), pEvts[i]); + else + // get the listener container for the property name + firePropertyChangeListeners( + rGuard, aBoundLC.getContainer(rGuard, pEvts[i].PropertyHandle), pEvts[i]); + + // broadcast to all listeners with "" property name + if (bVetoable) + // fire change Events? + fireVetoableChangeListeners(rGuard, &maVetoableChangeListeners, pEvts[i]); + else + firePropertyChangeListeners(rGuard, &maPropertyChangeListeners, pEvts[i]); + } + + // reduce array to changed properties + aEvts.realloc(nChangesLen); + + if (bVetoable) + return; + + if (!maPropertiesChangeListeners.getLength(rGuard)) + return; + + // Here is a Bug, unbound properties are also fired + OInterfaceIteratorHelper4 aIt(rGuard, maPropertiesChangeListeners); + rGuard.unlock(); + while (aIt.hasMoreElements()) + { + XPropertiesChangeListener* pL = aIt.next().get(); + try + { + try + { + // fire the whole event sequence to the + // XPropertiesChangeListener's + pL->propertiesChange(aEvts); + } + catch (DisposedException& exc) + { + OSL_ENSURE(exc.Context.is(), "DisposedException without Context!"); + if (exc.Context == pL) + { + rGuard.lock(); + aIt.remove(rGuard); + rGuard.unlock(); + } + else + throw; + } + } + catch (RuntimeException& exc) + { + SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc); + if (!bIgnoreRuntimeExceptionsWhileFiring) + throw; + } + } + rGuard.lock(); +} + +void OPropertySetHelper::fireVetoableChangeListeners( + std::unique_lock<std::mutex>& rGuard, + comphelper::OInterfaceContainerHelper4<css::beans::XVetoableChangeListener>* pListeners, + const css::beans::PropertyChangeEvent& rChangeEvent) +{ + if (!pListeners || !pListeners->getLength(rGuard)) + return; + // Iterate over all listeners and send events + OInterfaceIteratorHelper4 aIt(rGuard, *pListeners); + rGuard.unlock(); + while (aIt.hasMoreElements()) + { + XVetoableChangeListener* pL = aIt.next().get(); + try + { + try + { + pL->vetoableChange(rChangeEvent); + } + catch (DisposedException& exc) + { + OSL_ENSURE(exc.Context.is(), "DisposedException without Context!"); + if (exc.Context == pL) + { + rGuard.lock(); + aIt.remove(rGuard); + rGuard.unlock(); + } + else + throw; + } + } + catch (RuntimeException& exc) + { + SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc); + if (!m_bIgnoreRuntimeExceptionsWhileFiring) + throw; + } + } + rGuard.lock(); +} + +void OPropertySetHelper::firePropertyChangeListeners( + std::unique_lock<std::mutex>& rGuard, + comphelper::OInterfaceContainerHelper4<css::beans::XPropertyChangeListener>* pListeners, + const css::beans::PropertyChangeEvent& rChangeEvent) +{ + if (!pListeners || !pListeners->getLength(rGuard)) + return; + // Iterate over all listeners and send events + OInterfaceIteratorHelper4 aIt(rGuard, *pListeners); + rGuard.unlock(); + while (aIt.hasMoreElements()) + { + XPropertyChangeListener* pL = aIt.next().get(); + try + { + try + { + pL->propertyChange(rChangeEvent); + } + catch (DisposedException& exc) + { + OSL_ENSURE(exc.Context.is(), "DisposedException without Context!"); + if (exc.Context == pL) + { + rGuard.lock(); + aIt.remove(rGuard); + rGuard.unlock(); + } + else + throw; + } + } + catch (RuntimeException& exc) + { + SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc); + if (!m_bIgnoreRuntimeExceptionsWhileFiring) + throw; + } + } + rGuard.lock(); +} + +// OPropertySetHelper +void OPropertySetHelper::setFastPropertyValues(std::unique_lock<std::mutex>& rGuard, + sal_Int32 nSeqLen, sal_Int32* pHandles, + const Any* pValues, sal_Int32 nHitCount) +{ + OSL_ENSURE(!m_bDisposed, "object is disposed"); + + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + + std::unique_ptr<Any[]> pConvertedValues(new Any[nHitCount]); + std::unique_ptr<Any[]> pOldValues(new Any[nHitCount]); + sal_Int32 n = 0; + sal_Int32 i; + + for (i = 0; i < nSeqLen; i++) + { + if (pHandles[i] != -1) + { + sal_Int16 nAttributes; + rPH.fillPropertyMembersByHandle(nullptr, &nAttributes, pHandles[i]); + if (nAttributes & PropertyAttribute::READONLY) + throw PropertyVetoException(); + // Will the property change? + if (convertFastPropertyValue(rGuard, pConvertedValues[n], pOldValues[n], pHandles[i], + pValues[i])) + { + // only increment if the property really change + pHandles[n] = pHandles[i]; + n++; + } + } + } + + // fire vetoable events + fire(rGuard, pHandles, pConvertedValues.get(), pOldValues.get(), n, true); + + // Loop over all changed properties + for (i = 0; i < n; i++) + { + // Will the property change? + setFastPropertyValue_NoBroadcast(rGuard, pHandles[i], pConvertedValues[i]); + } + + // fire change events + impl_fireAll(rGuard, pHandles, pConvertedValues.get(), pOldValues.get(), n); +} + +// XMultiPropertySet +/** + * The sequence may be contain not known properties. The implementation + * must ignore these properties. + */ +void OPropertySetHelper::setPropertyValues(const Sequence<OUString>& rPropertyNames, + const Sequence<Any>& rValues) +{ + sal_Int32 nSeqLen = rPropertyNames.getLength(); + if (nSeqLen != rValues.getLength()) + throw IllegalArgumentException("lengths do not match", static_cast<XPropertySet*>(this), + -1); + std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[nSeqLen]); + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + // fill the handle array + sal_Int32 nHitCount = rPH.fillHandles(pHandles.get(), rPropertyNames); + if (nHitCount == 0) + return; + std::unique_lock aGuard(m_aMutex); + setFastPropertyValues(aGuard, nSeqLen, pHandles.get(), rValues.getConstArray(), nHitCount); +} + +// XMultiPropertySet +Sequence<Any> OPropertySetHelper::getPropertyValues(const Sequence<OUString>& rPropertyNames) +{ + sal_Int32 nSeqLen = rPropertyNames.getLength(); + std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[nSeqLen]); + Sequence<Any> aValues(nSeqLen); + + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + // fill the handle array + rPH.fillHandles(pHandles.get(), rPropertyNames); + + Any* pValues = aValues.getArray(); + + std::unique_lock aGuard(m_aMutex); + // fill the sequence with the values + for (sal_Int32 i = 0; i < nSeqLen; i++) + getFastPropertyValue(aGuard, pValues[i], pHandles[i]); + + return aValues; +} + +// XMultiPropertySet +void OPropertySetHelper::addPropertiesChangeListener( + const Sequence<OUString>&, const Reference<XPropertiesChangeListener>& rListener) +{ + std::unique_lock g(m_aMutex); + maPropertiesChangeListeners.addInterface(g, rListener); +} + +// XMultiPropertySet +void OPropertySetHelper::removePropertiesChangeListener( + const Reference<XPropertiesChangeListener>& rListener) +{ + std::unique_lock g(m_aMutex); + maPropertiesChangeListeners.removeInterface(g, rListener); +} + +// XMultiPropertySet +void OPropertySetHelper::firePropertiesChangeEvent( + const Sequence<OUString>& rPropertyNames, const Reference<XPropertiesChangeListener>& rListener) +{ + sal_Int32 nLen = rPropertyNames.getLength(); + std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[nLen]); + IPropertyArrayHelper& rPH = getInfoHelper(); + rPH.fillHandles(pHandles.get(), rPropertyNames); + const OUString* pNames = rPropertyNames.getConstArray(); + + // get the count of matching properties + sal_Int32 nFireLen = 0; + sal_Int32 i; + for (i = 0; i < nLen; i++) + if (pHandles[i] != -1) + nFireLen++; + + Sequence<PropertyChangeEvent> aChanges(nFireLen); + PropertyChangeEvent* pChanges = aChanges.getArray(); + + { + // must lock the mutex outside the loop. So all values are consistent. + std::unique_lock aGuard(m_aMutex); + Reference<XInterface> xSource(static_cast<XPropertySet*>(this), UNO_QUERY); + sal_Int32 nFirePos = 0; + for (i = 0; i < nLen; i++) + { + if (pHandles[i] != -1) + { + pChanges[nFirePos].Source = xSource; + pChanges[nFirePos].PropertyName = pNames[i]; + pChanges[nFirePos].PropertyHandle = pHandles[i]; + getFastPropertyValue(aGuard, pChanges[nFirePos].OldValue, pHandles[i]); + pChanges[nFirePos].NewValue = pChanges[nFirePos].OldValue; + nFirePos++; + } + } + // release guard to fire events + } + if (nFireLen) + rListener->propertiesChange(aChanges); +} + +UnoImplBase::~UnoImplBase() {} + +} // end namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/property/propstate.cxx b/comphelper/source/property/propstate.cxx index d48a72d094cf..183f51efcedf 100644 --- a/comphelper/source/property/propstate.cxx +++ b/comphelper/source/property/propstate.cxx @@ -210,13 +210,13 @@ namespace comphelper } - void SAL_CALL OStatefulPropertySet::acquire() throw() + void SAL_CALL OStatefulPropertySet::acquire() noexcept { ::cppu::OWeakObject::acquire(); } - void SAL_CALL OStatefulPropertySet::release() throw() + void SAL_CALL OStatefulPropertySet::release() noexcept { ::cppu::OWeakObject::release(); } diff --git a/comphelper/source/streaming/basicio.cxx b/comphelper/source/streaming/basicio.cxx index d86427b7de81..534d8b4cd0a1 100644 --- a/comphelper/source/streaming/basicio.cxx +++ b/comphelper/source/streaming/basicio.cxx @@ -18,6 +18,8 @@ */ #include <comphelper/basicio.hxx> +#include <comphelper/bytereader.hxx> +#include <comphelper/servicehelper.hxx> #include <com/sun/star/awt/FontDescriptor.hpp> namespace comphelper @@ -157,6 +159,9 @@ const css::uno::Reference<css::io::XObjectOutputStream>& operator << (const css: return _rxOutStream; } +ByteReader::~ByteReader() {} + +ByteWriter::~ByteWriter() {} } // namespace comphelper diff --git a/comphelper/source/streaming/memorystream.cxx b/comphelper/source/streaming/memorystream.cxx index b8ff86e03b17..20d0fbd5766a 100644 --- a/comphelper/source/streaming/memorystream.cxx +++ b/comphelper/source/streaming/memorystream.cxx @@ -18,16 +18,23 @@ */ #include <algorithm> +#include <cassert> +#include <memory> + +#include <boost/core/noinit_adaptor.hpp> #include <com/sun/star/lang/IllegalArgumentException.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> #include <com/sun/star/io/IOException.hpp> #include <com/sun/star/io/XStream.hpp> #include <com/sun/star/io/XSeekableInputStream.hpp> #include <com/sun/star/io/XTruncate.hpp> //#include <com/sun/star/uno/XComponentContext.hpp> +#include <comphelper/bytereader.hxx> #include <cppuhelper/implbase.hxx> #include <cppuhelper/supportsservice.hxx> +#include <o3tl/safeint.hxx> #include <osl/diagnose.h> #include <string.h> @@ -40,14 +47,15 @@ using ::cppu::WeakImplHelper; using namespace ::com::sun::star::io; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; -using namespace ::osl; namespace comphelper { namespace { -class UNOMemoryStream : public WeakImplHelper<XServiceInfo, XStream, XSeekableInputStream, XOutputStream, XTruncate> +class UNOMemoryStream : + public WeakImplHelper<XServiceInfo, XStream, XSeekableInputStream, XOutputStream, XTruncate>, + public comphelper::ByteWriter { public: UNOMemoryStream(); @@ -81,8 +89,11 @@ public: // XTruncate virtual void SAL_CALL truncate() override; + // comphelper::ByteWriter + virtual void writeBytes(const sal_Int8* aData, sal_Int32 nBytesToWrite) override; + private: - std::vector< sal_Int8 > maData; + std::vector< sal_Int8, boost::noinit_adaptor<std::allocator<sal_Int8>> > maData; sal_Int32 mnCursor; }; @@ -91,6 +102,7 @@ private: UNOMemoryStream::UNOMemoryStream() : mnCursor(0) { + maData.reserve(1 * 1024 * 1024); } // XServiceInfo @@ -133,7 +145,7 @@ sal_Int32 SAL_CALL UNOMemoryStream::readBytes( Sequence< sal_Int8 >& aData, sal_ { sal_Int8* pData = &(*maData.begin()); sal_Int8* pCursor = &(pData[mnCursor]); - memcpy( static_cast<void*>(aData.getArray()), static_cast<void*>(pCursor), nBytesToRead ); + memcpy( aData.getArray(), pCursor, nBytesToRead ); mnCursor += nBytesToRead; } @@ -171,7 +183,7 @@ void SAL_CALL UNOMemoryStream::seek( sal_Int64 location ) throw IllegalArgumentException("this implementation does not support more than 2GB!", static_cast<OWeakObject*>(this), 0 ); // seek operation should be able to resize the stream - if ( location > static_cast< sal_Int64 >( maData.size() ) ) + if ( o3tl::make_unsigned(location) > maData.size() ) maData.resize( static_cast< sal_Int32 >( location ) ); mnCursor = static_cast< sal_Int32 >( location ); @@ -190,7 +202,12 @@ sal_Int64 SAL_CALL UNOMemoryStream::getLength() // XOutputStream void SAL_CALL UNOMemoryStream::writeBytes( const Sequence< sal_Int8 >& aData ) { - const sal_Int32 nBytesToWrite( aData.getLength() ); + writeBytes(aData.getConstArray(), aData.getLength()); +} + +void UNOMemoryStream::writeBytes( const sal_Int8* pInData, sal_Int32 nBytesToWrite ) +{ + assert(nBytesToWrite >= 0); if( !nBytesToWrite ) return; @@ -201,12 +218,12 @@ void SAL_CALL UNOMemoryStream::writeBytes( const Sequence< sal_Int8 >& aData ) throw IOException("this implementation does not support more than 2GB!", static_cast<OWeakObject*>(this) ); } - if( static_cast< sal_Int32 >( nNewSize ) > static_cast< sal_Int32 >( maData.size() ) ) + if( o3tl::make_unsigned( nNewSize ) > maData.size() ) maData.resize( nNewSize ); sal_Int8* pData = &(*maData.begin()); sal_Int8* pCursor = &(pData[mnCursor]); - memcpy( pCursor, aData.getConstArray(), nBytesToWrite ); + memcpy(pCursor, pInData, nBytesToWrite); mnCursor += nBytesToWrite; } diff --git a/comphelper/source/streaming/oslfile2streamwrap.cxx b/comphelper/source/streaming/oslfile2streamwrap.cxx index eff916a833ff..243634610c2b 100644 --- a/comphelper/source/streaming/oslfile2streamwrap.cxx +++ b/comphelper/source/streaming/oslfile2streamwrap.cxx @@ -51,10 +51,10 @@ sal_Int32 SAL_CALL OSLInputStreamWrapper::readBytes(css::uno::Sequence< sal_Int8 if (nBytesToRead < 0) throw css::io::BufferSizeExceededException(OUString(),static_cast<css::uno::XWeak*>(this)); - ::osl::MutexGuard aGuard( m_aMutex ); - aData.realloc(nBytesToRead); + std::scoped_lock aGuard( m_aMutex ); + sal_uInt64 nRead = 0; FileBase::RC eError = m_pFile->read(static_cast<void*>(aData.getArray()), nBytesToRead, nRead); if (eError != FileBase::E_None) @@ -80,7 +80,7 @@ sal_Int32 SAL_CALL OSLInputStreamWrapper::readSomeBytes(css::uno::Sequence< sal_ void SAL_CALL OSLInputStreamWrapper::skipBytes(sal_Int32 nBytesToSkip) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if (!m_pFile) throw css::io::NotConnectedException(OUString(), static_cast<css::uno::XWeak*>(this)); @@ -97,7 +97,7 @@ void SAL_CALL OSLInputStreamWrapper::skipBytes(sal_Int32 nBytesToSkip) sal_Int32 SAL_CALL OSLInputStreamWrapper::available() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if (!m_pFile) throw css::io::NotConnectedException(OUString(), static_cast<css::uno::XWeak*>(this)); diff --git a/comphelper/source/streaming/seekableinput.cxx b/comphelper/source/streaming/seekableinput.cxx index 905e739e85a1..264feaeb3071 100644 --- a/comphelper/source/streaming/seekableinput.cxx +++ b/comphelper/source/streaming/seekableinput.cxx @@ -24,8 +24,10 @@ #include <com/sun/star/io/TempFile.hpp> #include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> #include <comphelper/seekableinput.hxx> +#include <utility> using namespace ::com::sun::star; @@ -57,13 +59,13 @@ static void copyInputToOutput_Impl( const uno::Reference< io::XInputStream >& xI OSeekableInputWrapper::OSeekableInputWrapper( - const uno::Reference< io::XInputStream >& xInStream, - const uno::Reference< uno::XComponentContext >& rxContext ) -: m_xContext( rxContext ) -, m_xOriginalStream( xInStream ) + uno::Reference< io::XInputStream > xInStream, + uno::Reference< uno::XComponentContext > xContext ) +: m_xContext(std::move( xContext )) +, m_xOriginalStream(std::move( xInStream )) { if ( !m_xContext.is() ) - throw uno::RuntimeException(); + throw lang::IllegalArgumentException("no component context", *this, 1); } @@ -90,7 +92,7 @@ void OSeekableInputWrapper::PrepareCopy_Impl() if ( !m_xCopyInput.is() ) { if ( !m_xContext.is() ) - throw uno::RuntimeException(); + throw uno::RuntimeException("no component context"); uno::Reference< io::XOutputStream > xTempOut( io::TempFile::create(m_xContext), @@ -117,7 +119,7 @@ void OSeekableInputWrapper::PrepareCopy_Impl() sal_Int32 SAL_CALL OSeekableInputWrapper::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOriginalStream.is() ) throw io::NotConnectedException(); @@ -130,7 +132,7 @@ sal_Int32 SAL_CALL OSeekableInputWrapper::readBytes( uno::Sequence< sal_Int8 >& sal_Int32 SAL_CALL OSeekableInputWrapper::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOriginalStream.is() ) throw io::NotConnectedException(); @@ -143,7 +145,7 @@ sal_Int32 SAL_CALL OSeekableInputWrapper::readSomeBytes( uno::Sequence< sal_Int8 void SAL_CALL OSeekableInputWrapper::skipBytes( sal_Int32 nBytesToSkip ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOriginalStream.is() ) throw io::NotConnectedException(); @@ -156,7 +158,7 @@ void SAL_CALL OSeekableInputWrapper::skipBytes( sal_Int32 nBytesToSkip ) sal_Int32 SAL_CALL OSeekableInputWrapper::available() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOriginalStream.is() ) throw io::NotConnectedException(); @@ -169,7 +171,7 @@ sal_Int32 SAL_CALL OSeekableInputWrapper::available() void SAL_CALL OSeekableInputWrapper::closeInput() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOriginalStream.is() ) throw io::NotConnectedException(); @@ -191,7 +193,7 @@ void SAL_CALL OSeekableInputWrapper::closeInput() void SAL_CALL OSeekableInputWrapper::seek( sal_Int64 location ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOriginalStream.is() ) throw io::NotConnectedException(); @@ -204,7 +206,7 @@ void SAL_CALL OSeekableInputWrapper::seek( sal_Int64 location ) sal_Int64 SAL_CALL OSeekableInputWrapper::getPosition() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOriginalStream.is() ) throw io::NotConnectedException(); @@ -217,7 +219,7 @@ sal_Int64 SAL_CALL OSeekableInputWrapper::getPosition() sal_Int64 SAL_CALL OSeekableInputWrapper::getLength() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOriginalStream.is() ) throw io::NotConnectedException(); diff --git a/comphelper/source/streaming/seqinputstreamserv.cxx b/comphelper/source/streaming/seqinputstreamserv.cxx index 2f5c21753b03..22fe8f8f0ea1 100644 --- a/comphelper/source/streaming/seqinputstreamserv.cxx +++ b/comphelper/source/streaming/seqinputstreamserv.cxx @@ -19,7 +19,6 @@ #include <sal/config.h> -#include <osl/mutex.hxx> #include <cppuhelper/implbase.hxx> #include <cppuhelper/supportsservice.hxx> #include <comphelper/seqstream.hxx> @@ -29,6 +28,7 @@ #include <com/sun/star/io/XSeekableInputStream.hpp> #include <com/sun/star/lang/XInitialization.hpp> #include <com/sun/star/frame/DoubleInitializationException.hpp> +#include <mutex> namespace com::sun::star::uno { class XComponentContext; } @@ -73,7 +73,7 @@ private: virtual ~SequenceInputStreamService() override {} - ::osl::Mutex m_aMutex; + std::mutex m_aMutex; bool m_bInitialized; uno::Reference< io::XInputStream > m_xInputStream; uno::Reference< io::XSeekable > m_xSeekable; @@ -102,7 +102,7 @@ uno::Sequence< OUString > SAL_CALL SequenceInputStreamService::getSupportedServi // css::io::XInputStream: ::sal_Int32 SAL_CALL SequenceInputStreamService::readBytes( uno::Sequence< ::sal_Int8 > & aData, ::sal_Int32 nBytesToRead ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xInputStream.is() ) throw io::NotConnectedException(); @@ -111,7 +111,7 @@ uno::Sequence< OUString > SAL_CALL SequenceInputStreamService::getSupportedServi ::sal_Int32 SAL_CALL SequenceInputStreamService::readSomeBytes( uno::Sequence< ::sal_Int8 > & aData, ::sal_Int32 nMaxBytesToRead ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xInputStream.is() ) throw io::NotConnectedException(); @@ -120,7 +120,7 @@ uno::Sequence< OUString > SAL_CALL SequenceInputStreamService::getSupportedServi void SAL_CALL SequenceInputStreamService::skipBytes( ::sal_Int32 nBytesToSkip ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xInputStream.is() ) throw io::NotConnectedException(); @@ -129,7 +129,7 @@ void SAL_CALL SequenceInputStreamService::skipBytes( ::sal_Int32 nBytesToSkip ) ::sal_Int32 SAL_CALL SequenceInputStreamService::available() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xInputStream.is() ) throw io::NotConnectedException(); @@ -138,7 +138,7 @@ void SAL_CALL SequenceInputStreamService::skipBytes( ::sal_Int32 nBytesToSkip ) void SAL_CALL SequenceInputStreamService::closeInput() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xInputStream.is() ) throw io::NotConnectedException(); @@ -150,7 +150,7 @@ void SAL_CALL SequenceInputStreamService::closeInput() // css::io::XSeekable: void SAL_CALL SequenceInputStreamService::seek( ::sal_Int64 location ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xSeekable.is() ) throw io::NotConnectedException(); @@ -159,7 +159,7 @@ void SAL_CALL SequenceInputStreamService::seek( ::sal_Int64 location ) ::sal_Int64 SAL_CALL SequenceInputStreamService::getPosition() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xSeekable.is() ) throw io::NotConnectedException(); @@ -168,7 +168,7 @@ void SAL_CALL SequenceInputStreamService::seek( ::sal_Int64 location ) ::sal_Int64 SAL_CALL SequenceInputStreamService::getLength() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xSeekable.is() ) throw io::NotConnectedException(); @@ -178,7 +178,7 @@ void SAL_CALL SequenceInputStreamService::seek( ::sal_Int64 location ) // css::lang::XInitialization: void SAL_CALL SequenceInputStreamService::initialize( const uno::Sequence< css::uno::Any > & aArguments ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( m_bInitialized ) throw frame::DoubleInitializationException(); @@ -196,9 +196,8 @@ void SAL_CALL SequenceInputStreamService::initialize( const uno::Sequence< css:: uno::Reference< io::XInputStream > xInputStream( static_cast< ::cppu::OWeakObject* >( new ::comphelper::SequenceInputStream( aSeq ) ), uno::UNO_QUERY_THROW ); - uno::Reference< io::XSeekable > xSeekable( xInputStream, uno::UNO_QUERY_THROW ); + m_xSeekable.set(xInputStream, uno::UNO_QUERY_THROW); m_xInputStream = xInputStream; - m_xSeekable = xSeekable; m_bInitialized = true; } diff --git a/comphelper/source/streaming/seqoutputstreamserv.cxx b/comphelper/source/streaming/seqoutputstreamserv.cxx index 477961397413..19ef79002978 100644 --- a/comphelper/source/streaming/seqoutputstreamserv.cxx +++ b/comphelper/source/streaming/seqoutputstreamserv.cxx @@ -19,13 +19,13 @@ #include <sal/config.h> -#include <osl/mutex.hxx> #include <cppuhelper/implbase.hxx> #include <cppuhelper/supportsservice.hxx> #include <comphelper/seqstream.hxx> #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/io/NotConnectedException.hpp> #include <com/sun/star/io/XSequenceOutputStream.hpp> +#include <mutex> namespace com::sun::star::uno { class XComponentContext; } @@ -61,9 +61,10 @@ private: virtual ~SequenceOutputStreamService() override {}; - ::osl::Mutex m_aMutex; - uno::Reference< io::XOutputStream > m_xOutputStream; + std::mutex m_aMutex; + // WARNING: dtor of m_xOutputStream writes into m_aSequence so that must live longer! uno::Sequence< ::sal_Int8 > m_aSequence; + uno::Reference< io::XOutputStream > m_xOutputStream; }; SequenceOutputStreamService::SequenceOutputStreamService() { @@ -89,7 +90,7 @@ uno::Sequence< OUString > SAL_CALL SequenceOutputStreamService::getSupportedServ // css::io::XOutputStream: void SAL_CALL SequenceOutputStreamService::writeBytes( const uno::Sequence< ::sal_Int8 > & aData ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOutputStream.is() ) throw io::NotConnectedException(); @@ -98,7 +99,7 @@ void SAL_CALL SequenceOutputStreamService::writeBytes( const uno::Sequence< ::sa void SAL_CALL SequenceOutputStreamService::flush() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOutputStream.is() ) throw io::NotConnectedException(); @@ -107,10 +108,11 @@ void SAL_CALL SequenceOutputStreamService::flush() void SAL_CALL SequenceOutputStreamService::closeOutput() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOutputStream.is() ) throw io::NotConnectedException(); + m_xOutputStream->flush(); m_xOutputStream->closeOutput(); m_xOutputStream.clear(); } @@ -118,11 +120,14 @@ void SAL_CALL SequenceOutputStreamService::closeOutput() // css::io::XSequenceOutputStream: uno::Sequence< ::sal_Int8 > SAL_CALL SequenceOutputStreamService::getWrittenBytes() { - ::osl::MutexGuard aGuard( m_aMutex ); - if ( !m_xOutputStream.is() ) - throw io::NotConnectedException(); + std::scoped_lock aGuard( m_aMutex ); + + if (m_xOutputStream.is()) + { + m_xOutputStream->flush(); + } + // else: no exception, just return the finished sequence - m_xOutputStream->flush(); return m_aSequence; } diff --git a/comphelper/source/streaming/seqstream.cxx b/comphelper/source/streaming/seqstream.cxx index 7cffb774232f..c7bfde712c74 100644 --- a/comphelper/source/streaming/seqstream.cxx +++ b/comphelper/source/streaming/seqstream.cxx @@ -31,66 +31,83 @@ namespace comphelper using namespace ::com::sun::star::lang; using namespace ::com::sun::star::io; using namespace ::com::sun::star::uno; -using namespace ::osl; -SequenceInputStream::SequenceInputStream( - css::uno::Sequence<sal_Int8> const & rData) -: m_aData(rData) +MemoryInputStream::MemoryInputStream( + const sal_Int8* pData, sal_Int32 nDataLength) +: m_pMemoryData(pData) +, m_nMemoryDataLength(nDataLength) , m_nPos(0) { } // checks if closed, returns available size, not mutex-protected -inline sal_Int32 SequenceInputStream::avail() +inline sal_Int32 MemoryInputStream::avail() { if (m_nPos == -1) throw NotConnectedException(OUString(), *this); - return m_aData.getLength() - m_nPos; + return m_nMemoryDataLength - m_nPos; } // css::io::XInputStream -sal_Int32 SAL_CALL SequenceInputStream::readBytes( Sequence<sal_Int8>& aData, sal_Int32 nBytesToRead ) +sal_Int32 SAL_CALL MemoryInputStream::readBytes( Sequence<sal_Int8>& aData, sal_Int32 nBytesToRead ) { - ::osl::MutexGuard aGuard( m_aMutex ); + if (nBytesToRead < 0) + throw BufferSizeExceededException(OUString(),*this); + + std::scoped_lock aGuard( m_aMutex ); sal_Int32 nAvail = avail(); + if (nAvail < nBytesToRead) + nBytesToRead = nAvail; + + aData.realloc(nBytesToRead); + memcpy(aData.getArray(), m_pMemoryData + m_nPos, nBytesToRead); + m_nPos += nBytesToRead; + + return nBytesToRead; +} + +sal_Int32 MemoryInputStream::readSomeBytes( sal_Int8* pData, sal_Int32 nBytesToRead ) +{ if (nBytesToRead < 0) throw BufferSizeExceededException(OUString(),*this); + std::scoped_lock aGuard( m_aMutex ); + + sal_Int32 nAvail = avail(); + if (nAvail < nBytesToRead) nBytesToRead = nAvail; - aData.realloc(nBytesToRead); - memcpy(aData.getArray(), m_aData.getConstArray() + m_nPos, nBytesToRead); + memcpy(pData, m_pMemoryData + m_nPos, nBytesToRead); m_nPos += nBytesToRead; return nBytesToRead; } - -sal_Int32 SAL_CALL SequenceInputStream::readSomeBytes( Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead ) +sal_Int32 SAL_CALL MemoryInputStream::readSomeBytes( Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead ) { // all data is available at once return readBytes(aData, nMaxBytesToRead); } -void SAL_CALL SequenceInputStream::skipBytes( sal_Int32 nBytesToSkip ) +void SAL_CALL MemoryInputStream::skipBytes( sal_Int32 nBytesToSkip ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - sal_Int32 nAvail = avail(); - if (nBytesToSkip < 0) throw BufferSizeExceededException(OUString(),*this); + std::scoped_lock aGuard( m_aMutex ); + + sal_Int32 nAvail = avail(); + if (nAvail < nBytesToSkip) nBytesToSkip = nAvail; @@ -98,37 +115,49 @@ void SAL_CALL SequenceInputStream::skipBytes( sal_Int32 nBytesToSkip ) } -sal_Int32 SAL_CALL SequenceInputStream::available( ) +sal_Int32 SAL_CALL MemoryInputStream::available( ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); return avail(); } -void SAL_CALL SequenceInputStream::closeInput( ) +void SAL_CALL MemoryInputStream::closeInput( ) { + std::scoped_lock aGuard( m_aMutex ); + if (m_nPos == -1) throw NotConnectedException(OUString(), *this); m_nPos = -1; } -void SAL_CALL SequenceInputStream::seek( sal_Int64 location ) +void SAL_CALL MemoryInputStream::seek( sal_Int64 location ) { - if ( location > m_aData.getLength() || location < 0 || location > SAL_MAX_INT32 ) + if ( location > m_nMemoryDataLength || location < 0 || location > SAL_MAX_INT32 ) throw IllegalArgumentException("bad location", static_cast<cppu::OWeakObject*>(this), 1); + std::scoped_lock aGuard( m_aMutex ); m_nPos = static_cast<sal_Int32>(location); } -sal_Int64 SAL_CALL SequenceInputStream::getPosition() +sal_Int64 SAL_CALL MemoryInputStream::getPosition() { + std::scoped_lock aGuard( m_aMutex ); return m_nPos; } -sal_Int64 SAL_CALL SequenceInputStream::getLength( ) +sal_Int64 SAL_CALL MemoryInputStream::getLength( ) +{ + return m_nMemoryDataLength; +} + + +SequenceInputStream::SequenceInputStream( + css::uno::Sequence<sal_Int8> const & rData) +: MemoryInputStream(rData.getConstArray(), rData.getLength()) +, m_aData(rData) { - return m_aData.getLength(); } @@ -148,7 +177,7 @@ OSequenceOutputStream::OSequenceOutputStream(Sequence< sal_Int8 >& _rSeq, double void SAL_CALL OSequenceOutputStream::writeBytes( const Sequence< sal_Int8 >& _rData ) { - MutexGuard aGuard(m_aMutex); + std::scoped_lock aGuard(m_aMutex); if (!m_bConnected) throw NotConnectedException(); @@ -188,7 +217,7 @@ void SAL_CALL OSequenceOutputStream::writeBytes( const Sequence< sal_Int8 >& _rD void SAL_CALL OSequenceOutputStream::flush( ) { - MutexGuard aGuard(m_aMutex); + std::scoped_lock aGuard(m_aMutex); if (!m_bConnected) throw NotConnectedException(); @@ -198,8 +227,6 @@ void SAL_CALL OSequenceOutputStream::flush( ) void OSequenceOutputStream::finalizeOutput() { - MutexGuard aGuard(m_aMutex); - // cut the sequence to the real size m_rSequence.realloc(m_nSize); // and don't allow any further accesses @@ -208,7 +235,7 @@ void OSequenceOutputStream::finalizeOutput() void SAL_CALL OSequenceOutputStream::closeOutput() { - MutexGuard aGuard(m_aMutex); + std::scoped_lock aGuard(m_aMutex); if (!m_bConnected) throw NotConnectedException(); diff --git a/comphelper/source/windows/windows_process.cxx b/comphelper/source/windows/windows_process.cxx index 7588bae027e5..8e7fd19f0b30 100644 --- a/comphelper/source/windows/windows_process.cxx +++ b/comphelper/source/windows/windows_process.cxx @@ -241,7 +241,7 @@ WinLaunchChild(const wchar_t *exePath, } else { - LPVOID lpMsgBuf = nullptr; + LPWSTR lpMsgBuf = nullptr; FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, diff --git a/comphelper/source/xml/attributelist.cxx b/comphelper/source/xml/attributelist.cxx index d99139c852ea..0b087095aa53 100644 --- a/comphelper/source/xml/attributelist.cxx +++ b/comphelper/source/xml/attributelist.cxx @@ -19,23 +19,14 @@ #include <comphelper/attributelist.hxx> -using namespace osl; +#include <algorithm> +#include <cassert> + using namespace com::sun::star; namespace comphelper { -OUString SAL_CALL AttributeList::getTypeByName( const OUString& sName ) -{ - for (auto const& attribute : mAttributes) - { - if( attribute.sName == sName ) { - return attribute.sType; - } - } - return OUString(); -} - OUString SAL_CALL AttributeList::getValueByName(const OUString& sName) { for (auto const& attribute : mAttributes) @@ -53,10 +44,12 @@ AttributeList::AttributeList() mAttributes.reserve(20); } -AttributeList::AttributeList(const AttributeList &r) - : cppu::WeakImplHelper<XAttributeList, XCloneable>(r) +AttributeList::AttributeList(const uno::Reference< xml::sax::XAttributeList>& rAttrList) { - mAttributes = r.mAttributes; + if (AttributeList* pImpl = dynamic_cast<AttributeList*>(rAttrList.get())) + mAttributes = pImpl->mAttributes; + else + AppendAttributeList(rAttrList); } AttributeList::~AttributeList() @@ -65,8 +58,70 @@ AttributeList::~AttributeList() css::uno::Reference< css::util::XCloneable > AttributeList::createClone() { - AttributeList *p = new AttributeList( *this ); - return css::uno::Reference< css::util::XCloneable > ( static_cast<css::util::XCloneable *>(p) ); + return new AttributeList( *this ); +} + +void AttributeList::AddAttribute(const OUString& sName, const OUString& sValue) +{ + assert(!sName.isEmpty() && "empty attribute name is invalid"); + // Either it's 'namespace_prefix:attribute_name', + // or as in XMLNamespaces::applyNSToAttributeName, it's 'namespace:full:uri^attribute_name'. + assert((std::count(sName.getStr(), sName.getStr() + sName.getLength(), u':') <= 1 + || std::count(sName.getStr(), sName.getStr() + sName.getLength(), u'^') == 1) + && "too many colons"); + // TODO: this assertion fails in tests! +// assert(std::none_of(mAttributes.begin(), mAttributes.end(), +// [&sName](const TagAttribute& a) { return a.sName == sName; })); + mAttributes.push_back({ sName, sValue }); +} + +void AttributeList::RemoveAttribute(const OUString& sName) +{ + auto ii = std::find_if(mAttributes.begin(), mAttributes.end(), + [&sName](const TagAttribute& rAttr) { return rAttr.sName == sName; }); + + if (ii != mAttributes.end()) + mAttributes.erase(ii); +} + +void AttributeList::AppendAttributeList(const uno::Reference<css::xml::sax::XAttributeList>& r) +{ + assert(r.is()); + + sal_Int16 nMax = r->getLength(); + sal_Int16 nTotalSize = mAttributes.size() + nMax; + mAttributes.reserve(nTotalSize); + + for (sal_Int16 i = 0; i < nMax; ++i) + AddAttribute(r->getNameByIndex(i), r->getValueByIndex(i)); + + assert(nTotalSize == getLength()); +} + +void AttributeList::SetValueByIndex(sal_Int16 i, const OUString& rValue) +{ + mAttributes[i].sValue = rValue; +} + +void AttributeList::RemoveAttributeByIndex(sal_Int16 i) +{ + mAttributes.erase(mAttributes.begin() + i); +} + +void AttributeList::RenameAttributeByIndex(sal_Int16 i, const OUString& rNewName) +{ + mAttributes[i].sName = rNewName; +} + +sal_Int16 AttributeList::GetIndexByName(const OUString& rName) const +{ + auto ii = std::find_if(mAttributes.begin(), mAttributes.end(), + [&rName](const TagAttribute& rAttr) { return rAttr.sName == rName; }); + + if (ii != mAttributes.end()) + return static_cast<sal_Int16>(std::distance(mAttributes.begin(), ii)); + + return -1; } } // namespace comphelper diff --git a/comphelper/source/xml/ofopxmlhelper.cxx b/comphelper/source/xml/ofopxmlhelper.cxx index 2da35bdd0a3a..a672bf57a6fb 100644 --- a/comphelper/source/xml/ofopxmlhelper.cxx +++ b/comphelper/source/xml/ofopxmlhelper.cxx @@ -22,6 +22,7 @@ #include <comphelper/attributelist.hxx> #include <cppuhelper/implbase.hxx> +#include <rtl/ref.hxx> #include <com/sun/star/beans/StringPair.hpp> #include <com/sun/star/xml/sax/Parser.hpp> @@ -141,24 +142,20 @@ void WriteRelationsInfoSequence( OUString aRelListElement( "Relationships" ); OUString aRelElement( "Relationship" ); - OUString aCDATAString( "CDATA" ); OUString aWhiteSpace( " " ); // write the namespace - AttributeList* pRootAttrList = new AttributeList; - uno::Reference< css::xml::sax::XAttributeList > xRootAttrList( pRootAttrList ); + rtl::Reference<AttributeList> pRootAttrList = new AttributeList; pRootAttrList->AddAttribute( "xmlns", - aCDATAString, "http://schemas.openxmlformats.org/package/2006/relationships" ); xWriter->startDocument(); - xWriter->startElement( aRelListElement, xRootAttrList ); + xWriter->startElement( aRelListElement, pRootAttrList ); for ( const auto & i : aSequence ) { - AttributeList *pAttrList = new AttributeList; - uno::Reference< css::xml::sax::XAttributeList > xAttrList( pAttrList ); + rtl::Reference<AttributeList> pAttrList = new AttributeList; for( const beans::StringPair & pair : i ) { if ( !(pair.First == "Id" @@ -169,10 +166,10 @@ void WriteRelationsInfoSequence( // TODO/LATER: should the extensions be allowed? throw lang::IllegalArgumentException(); } - pAttrList->AddAttribute( pair.First, aCDATAString, pair.Second ); + pAttrList->AddAttribute( pair.First, pair.Second ); } - xWriter->startElement( aRelElement, xAttrList ); + xWriter->startElement( aRelElement, pAttrList ); xWriter->ignorableWhitespace( aWhiteSpace ); xWriter->endElement( aRelElement ); } @@ -196,44 +193,39 @@ void WriteContentSequence( xWriter->setOutputStream( xOutStream ); - static constexpr OUStringLiteral aTypesElement(u"Types"); - static constexpr OUStringLiteral aDefaultElement(u"Default"); - static constexpr OUStringLiteral aOverrideElement(u"Override"); - static constexpr OUStringLiteral aContentTypeAttr(u"ContentType"); - static constexpr OUStringLiteral aCDATAString(u"CDATA"); - static constexpr OUStringLiteral aWhiteSpace(u" "); + static constexpr OUString aTypesElement(u"Types"_ustr); + static constexpr OUString aDefaultElement(u"Default"_ustr); + static constexpr OUString aOverrideElement(u"Override"_ustr); + static constexpr OUString aContentTypeAttr(u"ContentType"_ustr); + static constexpr OUString aWhiteSpace(u" "_ustr); // write the namespace - AttributeList* pRootAttrList = new AttributeList; - uno::Reference< css::xml::sax::XAttributeList > xRootAttrList( pRootAttrList ); + rtl::Reference<AttributeList> pRootAttrList = new AttributeList; pRootAttrList->AddAttribute( "xmlns", - aCDATAString, "http://schemas.openxmlformats.org/package/2006/content-types" ); xWriter->startDocument(); - xWriter->startElement( aTypesElement, xRootAttrList ); + xWriter->startElement( aTypesElement, pRootAttrList ); for ( const beans::StringPair & pair : aDefaultsSequence ) { - AttributeList *pAttrList = new AttributeList; - uno::Reference< css::xml::sax::XAttributeList > xAttrList( pAttrList ); - pAttrList->AddAttribute( "Extension", aCDATAString, pair.First ); - pAttrList->AddAttribute( aContentTypeAttr, aCDATAString, pair.Second ); + rtl::Reference<AttributeList> pAttrList = new AttributeList; + pAttrList->AddAttribute( "Extension", pair.First ); + pAttrList->AddAttribute( aContentTypeAttr, pair.Second ); - xWriter->startElement( aDefaultElement, xAttrList ); + xWriter->startElement( aDefaultElement, pAttrList ); xWriter->ignorableWhitespace( aWhiteSpace ); xWriter->endElement( aDefaultElement ); } for ( const beans::StringPair & pair : aOverridesSequence ) { - AttributeList *pAttrList = new AttributeList; - uno::Reference< css::xml::sax::XAttributeList > xAttrList( pAttrList ); - pAttrList->AddAttribute( "PartName", aCDATAString, pair.First ); - pAttrList->AddAttribute( aContentTypeAttr, aCDATAString, pair.Second ); + rtl::Reference<AttributeList> pAttrList = new AttributeList; + pAttrList->AddAttribute( "PartName", pair.First ); + pAttrList->AddAttribute( aContentTypeAttr, pair.Second ); - xWriter->startElement( aOverrideElement, xAttrList ); + xWriter->startElement( aOverrideElement, pAttrList ); xWriter->ignorableWhitespace( aWhiteSpace ); xWriter->endElement( aOverrideElement ); } @@ -254,12 +246,11 @@ uno::Sequence< uno::Sequence< beans::StringPair > > ReadSequence_Impl( uno::Reference< css::xml::sax::XParser > xParser = css::xml::sax::Parser::create( rContext ); - OFOPXMLHelper_Impl *const pHelper = new OFOPXMLHelper_Impl( nFormat ); - uno::Reference< css::xml::sax::XDocumentHandler > xHelper( static_cast< css::xml::sax::XDocumentHandler* >( pHelper ) ); + rtl::Reference<OFOPXMLHelper_Impl> pHelper = new OFOPXMLHelper_Impl( nFormat ); css::xml::sax::InputSource aParserInput; aParserInput.aInputStream = xInStream; aParserInput.sSystemId = aStringID; - xParser->setDocumentHandler( xHelper ); + xParser->setDocumentHandler( pHelper ); xParser->parseStream( aParserInput ); xParser->setDocumentHandler( uno::Reference < css::xml::sax::XDocumentHandler > () ); @@ -271,10 +262,10 @@ uno::Sequence< uno::Sequence< beans::StringPair > > ReadSequence_Impl( // Relations info related strings constexpr OUStringLiteral g_aRelListElement(u"Relationships"); constexpr OUStringLiteral g_aRelElement( u"Relationship" ); -constexpr OUStringLiteral g_aIDAttr( u"Id" ); -constexpr OUStringLiteral g_aTypeAttr( u"Type" ); -constexpr OUStringLiteral g_aTargetModeAttr( u"TargetMode" ); -constexpr OUStringLiteral g_aTargetAttr( u"Target" ); +constexpr OUString g_aIDAttr( u"Id"_ustr ); +constexpr OUString g_aTypeAttr( u"Type"_ustr ); +constexpr OUString g_aTargetModeAttr( u"TargetMode"_ustr ); +constexpr OUString g_aTargetAttr( u"Target"_ustr ); // ContentType related strings constexpr OUStringLiteral g_aTypesElement( u"Types" ); @@ -282,7 +273,7 @@ constexpr OUStringLiteral g_aDefaultElement( u"Default" ); constexpr OUStringLiteral g_aOverrideElement( u"Override" ); constexpr OUStringLiteral g_aExtensionAttr( u"Extension" ); constexpr OUStringLiteral g_aPartNameAttr( u"PartName" ); -constexpr OUStringLiteral g_aContentTypeAttr( u"ContentType" ); +constexpr OUString g_aContentTypeAttr( u"ContentType"_ustr ); OFOPXMLHelper_Impl::OFOPXMLHelper_Impl( sal_uInt16 nFormat ) : m_nFormat( nFormat ) @@ -333,8 +324,10 @@ void SAL_CALL OFOPXMLHelper_Impl::startElement( const OUString& aName, const uno sal_Int32 nNewEntryNum = m_aResultSeq.getLength() + 1; m_aResultSeq.realloc( nNewEntryNum ); + auto pResultSeq = m_aResultSeq.getArray(); sal_Int32 nAttrNum = 0; - m_aResultSeq[nNewEntryNum-1].realloc( 4 ); // the maximal expected number of arguments is 4 + pResultSeq[nNewEntryNum-1].realloc( 4 ); // the maximal expected number of arguments is 4 + auto pAttrs = pResultSeq[nNewEntryNum-1].getArray(); OUString aIDValue = xAttribs->getValueByName( g_aIDAttr ); if ( aIDValue.isEmpty() ) @@ -344,28 +337,28 @@ void SAL_CALL OFOPXMLHelper_Impl::startElement( const OUString& aName, const uno OUString aTargetValue = xAttribs->getValueByName( g_aTargetAttr ); OUString aTargetModeValue = xAttribs->getValueByName( g_aTargetModeAttr ); - m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = g_aIDAttr; - m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aIDValue; + pAttrs[++nAttrNum - 1].First = g_aIDAttr; + pAttrs[nAttrNum - 1].Second = aIDValue; if ( !aTypeValue.isEmpty() ) { - m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = g_aTypeAttr; - m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTypeValue; + pAttrs[++nAttrNum - 1].First = g_aTypeAttr; + pAttrs[nAttrNum - 1].Second = aTypeValue; } if ( !aTargetValue.isEmpty() ) { - m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = g_aTargetAttr; - m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTargetValue; + pAttrs[++nAttrNum - 1].First = g_aTargetAttr; + pAttrs[nAttrNum - 1].Second = aTargetValue; } if ( !aTargetModeValue.isEmpty() ) { - m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = g_aTargetModeAttr; - m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTargetModeValue; + pAttrs[++nAttrNum - 1].First = g_aTargetModeAttr; + pAttrs[nAttrNum - 1].Second = aTargetModeValue; } - m_aResultSeq[nNewEntryNum-1].realloc( nAttrNum ); + pResultSeq[nNewEntryNum-1].realloc( nAttrNum ); } else throw css::xml::sax::SAXException(); // TODO: no other elements expected! @@ -400,6 +393,8 @@ void SAL_CALL OFOPXMLHelper_Impl::startElement( const OUString& aName, const uno if ( m_aResultSeq.getLength() != 2 ) throw uno::RuntimeException(); + auto pResultSeq = m_aResultSeq.getArray(); + const OUString aExtensionValue = xAttribs->getValueByName( g_aExtensionAttr ); if ( aExtensionValue.isEmpty() ) throw css::xml::sax::SAXException(); // TODO: the Extension value must present @@ -409,10 +404,11 @@ void SAL_CALL OFOPXMLHelper_Impl::startElement( const OUString& aName, const uno throw css::xml::sax::SAXException(); // TODO: the ContentType value must present const sal_Int32 nNewResultLen = m_aResultSeq[0].getLength() + 1; - m_aResultSeq[0].realloc( nNewResultLen ); + pResultSeq[0].realloc( nNewResultLen ); + auto pSeq = pResultSeq[0].getArray(); - m_aResultSeq[0][nNewResultLen-1].First = aExtensionValue; - m_aResultSeq[0][nNewResultLen-1].Second = aContentTypeValue; + pSeq[nNewResultLen-1].First = aExtensionValue; + pSeq[nNewResultLen-1].Second = aContentTypeValue; } else if ( aName == g_aOverrideElement ) { @@ -428,6 +424,8 @@ void SAL_CALL OFOPXMLHelper_Impl::startElement( const OUString& aName, const uno if ( m_aResultSeq.getLength() != 2 ) throw uno::RuntimeException(); + auto pResultSeq = m_aResultSeq.getArray(); + OUString aPartNameValue = xAttribs->getValueByName( g_aPartNameAttr ); if ( aPartNameValue.isEmpty() ) throw css::xml::sax::SAXException(); // TODO: the PartName value must present @@ -437,10 +435,11 @@ void SAL_CALL OFOPXMLHelper_Impl::startElement( const OUString& aName, const uno throw css::xml::sax::SAXException(); // TODO: the ContentType value must present sal_Int32 nNewResultLen = m_aResultSeq[1].getLength() + 1; - m_aResultSeq[1].realloc( nNewResultLen ); + pResultSeq[1].realloc( nNewResultLen ); + auto pSeq = pResultSeq[1].getArray(); - m_aResultSeq[1][nNewResultLen-1].First = aPartNameValue; - m_aResultSeq[1][nNewResultLen-1].Second = aContentTypeValue; + pSeq[nNewResultLen-1].First = aPartNameValue; + pSeq[nNewResultLen-1].Second = aContentTypeValue; } else throw css::xml::sax::SAXException(); // TODO: no other elements expected! diff --git a/comphelper/source/xml/xmltools.cxx b/comphelper/source/xml/xmltools.cxx index 74ad5faa67e7..6ae8fceed5b9 100644 --- a/comphelper/source/xml/xmltools.cxx +++ b/comphelper/source/xml/xmltools.cxx @@ -9,7 +9,7 @@ #include <comphelper/xmltools.hxx> #include <rtl/random.h> -#include <rtl/uuid.h> +#include <tools/Guid.hxx> #include <vector> using namespace com::sun::star; @@ -71,17 +71,21 @@ namespace namespace comphelper::xml { + // Generate some 'chaff' of varying length to be the body of an + // XML comment to put at the start of encrypted content to make + // document content a little less predictable. + // See SvXMLExport::addChaffWhenEncryptedStorage OString makeXMLChaff() { rtlRandomPool pool = rtl_random_createPool(); sal_Int8 n; - rtl_random_getBytes(pool, &n, 1); + (void)rtl_random_getBytes(pool, &n, 1); sal_Int32 nLength = 1024+n; // coverity[tainted_data] - 1024 deliberate random minus max -127/plus max 128 std::vector<sal_uInt8> aChaff(nLength); - rtl_random_getBytes(pool, aChaff.data(), nLength); + (void)rtl_random_getBytes(pool, aChaff.data(), nLength); rtl_random_destroyPool(pool); @@ -92,15 +96,8 @@ namespace comphelper::xml OString generateGUIDString() { - sal_uInt8 aSeq[16]; - rtl_createUuid(aSeq, nullptr, true); - - char str[39]; - sprintf(str, "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", - aSeq[0], aSeq[1], aSeq[2], aSeq[3], aSeq[4], aSeq[5], aSeq[6], aSeq[7], aSeq[8], - aSeq[9], aSeq[10], aSeq[11], aSeq[12], aSeq[13], aSeq[14], aSeq[15]); - - return str; + tools::Guid aGuid(tools::Guid::Generate); + return aGuid.getString(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |