diff options
Diffstat (limited to 'comphelper/source/misc')
58 files changed, 3769 insertions, 2169 deletions
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..76008b508c68 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); @@ -569,19 +677,16 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( throw uno::RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); ctx->setArmor(false); - const uno::Sequence < beans::NamedValue > *pSequence = rGpgProperties.getConstArray(); - const sal_Int32 nLength = rGpgProperties.getLength(); - for ( sal_Int32 i = 0; i < nLength ; i++, pSequence++ ) + for (auto& rSequence : rGpgProperties) { - const beans::NamedValue *pValues = pSequence->getConstArray(); - if ( pSequence->getLength() == 3 ) + if (rSequence.getLength() == 3) { // take CipherValue and try to decrypt that - stop after // the first successful decryption // ctx is setup now, let's decrypt the lot! uno::Sequence < sal_Int8 > aVector; - pValues[2].Value >>= aVector; + rSequence[2].Value >>= aVector; GpgME::Data cipher( reinterpret_cast<const char*>(aVector.getConstArray()), @@ -612,19 +717,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..647ccb74974d 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; @@ -128,22 +202,18 @@ void SequenceAsHashMap::operator<<(const css::uno::Sequence< css::beans::Propert { clear(); - sal_Int32 c = lSource.getLength(); - const css::beans::PropertyValue* pSource = lSource.getConstArray(); - - for (sal_Int32 i=0; i<c; ++i) - (*this)[pSource[i].Name] = pSource[i].Value; + m_aMap.reserve(lSource.getLength()); + for (auto& rSource : lSource) + (*this)[rSource.Name] = rSource.Value; } void SequenceAsHashMap::operator<<(const css::uno::Sequence< css::beans::NamedValue >& lSource) { clear(); - sal_Int32 c = lSource.getLength(); - const css::beans::NamedValue* pSource = lSource.getConstArray(); - - for (sal_Int32 i=0; i<c; ++i) - (*this)[pSource[i].Name] = pSource[i].Value; + m_aMap.reserve(lSource.getLength()); + for (auto& rSource : lSource) + (*this)[rSource.Name] = rSource.Value; } void SequenceAsHashMap::operator>>(css::uno::Sequence< css::beans::PropertyValue >& lDestination) const @@ -157,7 +227,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 +244,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 +278,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 +295,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..e69f734b2b8b 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()) @@ -284,18 +284,14 @@ vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) OUString GetHexString( const css::uno::Sequence< sal_Int8 >& _rSeq, const char* _pSep, sal_uInt16 _nLineBreak ) { - const sal_Int8* pSerNumSeq = _rSeq.getConstArray(); - int nCnt = _rSeq.getLength(); OUStringBuffer aStr; const char pHexDigs[ 17 ] = "0123456789ABCDEF"; char pBuffer[ 3 ] = " "; - sal_uInt8 nNum; sal_uInt16 nBreakStart = _nLineBreak? _nLineBreak : 1; sal_uInt16 nBreak = nBreakStart; - for( int i = 0 ; i < nCnt ; ++i ) + for (sal_Int8 n : _rSeq) { - nNum = sal_uInt8( pSerNumSeq[ i ] ); - + sal_uInt8 nNum = static_cast<sal_uInt8>(n); // exchange the buffer[0] and buffer[1], which make it consistent with Mozilla and Windows pBuffer[ 1 ] = pHexDigs[ nNum & 0x0F ]; nNum >>= 4; |