diff options
Diffstat (limited to 'comphelper')
123 files changed, 5547 insertions, 2707 deletions
diff --git a/comphelper/CppunitTest_comphelper_parallelsort_test.mk b/comphelper/CppunitTest_comphelper_parallelsort_test.mk index e1d2eab9ec36..1eac7d5276b4 100644 --- a/comphelper/CppunitTest_comphelper_parallelsort_test.mk +++ b/comphelper/CppunitTest_comphelper_parallelsort_test.mk @@ -13,10 +13,6 @@ $(eval $(call gb_CppunitTest_add_exception_objects,comphelper_parallelsort_test, comphelper/qa/unit/parallelsorttest \ )) -$(eval $(call gb_CppunitTest_use_externals,comphelper_parallelsort_test,\ - boost_headers \ -)) - $(eval $(call gb_CppunitTest_use_sdk_api,comphelper_parallelsort_test)) $(eval $(call gb_CppunitTest_use_libraries,comphelper_parallelsort_test, \ @@ -27,4 +23,4 @@ $(eval $(call gb_CppunitTest_use_libraries,comphelper_parallelsort_test, \ tl \ )) -# vim: set noet sw=4 ts=4:
\ No newline at end of file +# vim: set noet sw=4 ts=4: diff --git a/comphelper/CppunitTest_comphelper_syntaxhighlight_test.mk b/comphelper/CppunitTest_comphelper_syntaxhighlight_test.mk index 0ca808051a80..ab2ff0f143b2 100644 --- a/comphelper/CppunitTest_comphelper_syntaxhighlight_test.mk +++ b/comphelper/CppunitTest_comphelper_syntaxhighlight_test.mk @@ -13,10 +13,6 @@ $(eval $(call gb_CppunitTest_add_exception_objects,comphelper_syntaxhighlight_te comphelper/qa/unit/syntaxhighlighttest \ )) -$(eval $(call gb_CppunitTest_use_externals,comphelper_syntaxhighlight_test,\ - boost_headers \ -)) - $(eval $(call gb_CppunitTest_use_sdk_api,comphelper_syntaxhighlight_test)) $(eval $(call gb_CppunitTest_use_libraries,comphelper_syntaxhighlight_test, \ diff --git a/comphelper/CppunitTest_comphelper_test.mk b/comphelper/CppunitTest_comphelper_test.mk index ab2f893a0866..17de701aca26 100644 --- a/comphelper/CppunitTest_comphelper_test.mk +++ b/comphelper/CppunitTest_comphelper_test.mk @@ -11,7 +11,9 @@ $(eval $(call gb_CppunitTest_CppunitTest,comphelper_test)) $(eval $(call gb_CppunitTest_add_exception_objects,comphelper_test, \ comphelper/qa/string/test_string \ + comphelper/qa/string/NaturalStringSortTest \ comphelper/qa/container/testifcontainer \ + comphelper/qa/container/testifcontainer3 \ comphelper/qa/unit/test_hash \ comphelper/qa/unit/base64_test \ comphelper/qa/unit/propertyvalue \ @@ -20,6 +22,7 @@ $(eval $(call gb_CppunitTest_add_exception_objects,comphelper_test, \ comphelper/qa/unit/test_traceevent \ )) +$(eval $(call gb_CppunitTest_use_ure,comphelper_test)) $(eval $(call gb_CppunitTest_use_sdk_api,comphelper_test)) $(eval $(call gb_CppunitTest_use_libraries,comphelper_test, \ @@ -27,6 +30,7 @@ $(eval $(call gb_CppunitTest_use_libraries,comphelper_test, \ cppuhelper \ cppu \ sal \ + unotest \ )) ifeq ($(TLS),NSS) @@ -36,4 +40,8 @@ $(eval $(call gb_CppunitTest_use_externals,comphelper_test,\ )) endif +$(eval $(call gb_CppunitTest_use_components,comphelper_test,\ + i18npool/util/i18npool \ +)) + # vim: set noet sw=4 ts=4: diff --git a/comphelper/CppunitTest_comphelper_threadpool_test.mk b/comphelper/CppunitTest_comphelper_threadpool_test.mk index 24467c898f80..5e2391fdeddb 100644 --- a/comphelper/CppunitTest_comphelper_threadpool_test.mk +++ b/comphelper/CppunitTest_comphelper_threadpool_test.mk @@ -13,10 +13,6 @@ $(eval $(call gb_CppunitTest_add_exception_objects,comphelper_threadpool_test, \ comphelper/qa/unit/threadpooltest \ )) -$(eval $(call gb_CppunitTest_use_externals,comphelper_threadpool_test,\ - boost_headers \ -)) - $(eval $(call gb_CppunitTest_use_sdk_api,comphelper_threadpool_test)) $(eval $(call gb_CppunitTest_use_libraries,comphelper_threadpool_test, \ diff --git a/comphelper/CppunitTest_comphelper_variadictemplates_test.mk b/comphelper/CppunitTest_comphelper_variadictemplates_test.mk index 03ded85270fc..50ee76cacc42 100644 --- a/comphelper/CppunitTest_comphelper_variadictemplates_test.mk +++ b/comphelper/CppunitTest_comphelper_variadictemplates_test.mk @@ -15,10 +15,6 @@ $(eval $(call gb_CppunitTest_add_exception_objects,comphelper_variadictemplates_ $(eval $(call gb_CppunitTest_use_sdk_api,comphelper_variadictemplates_test)) -$(eval $(call gb_CppunitTest_use_externals,comphelper_variadictemplates_test, \ - boost_headers \ -)) - $(eval $(call gb_CppunitTest_use_libraries,comphelper_variadictemplates_test, \ comphelper \ cppuhelper \ diff --git a/comphelper/CppunitTest_comphelper_weakbag_test.mk b/comphelper/CppunitTest_comphelper_weakbag_test.mk new file mode 100644 index 000000000000..3ee86b9b8549 --- /dev/null +++ b/comphelper/CppunitTest_comphelper_weakbag_test.mk @@ -0,0 +1,27 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# +# 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/. + +$(eval $(call gb_CppunitTest_CppunitTest,comphelper_weakbag)) + +$(eval $(call gb_CppunitTest_add_exception_objects,comphelper_weakbag,\ + comphelper/qa/weakbag/test_weakbag \ +)) + +$(eval $(call gb_CppunitTest_use_api,comphelper_weakbag,\ + udkapi \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,comphelper_weakbag,\ + comphelper \ + cppu \ + cppuhelper \ + sal \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/comphelper/IwyuFilter_comphelper.yaml b/comphelper/IwyuFilter_comphelper.yaml index 3e22a187b7e5..9e60203c6750 100644 --- a/comphelper/IwyuFilter_comphelper.yaml +++ b/comphelper/IwyuFilter_comphelper.yaml @@ -68,9 +68,6 @@ excludelist: # Stop warnings about include/ - com/sun/star/beans/PropertyValue.hpp - com/sun/star/beans/NamedValue.hpp - include/comphelper/servicedecl.hxx: - # Stop warnings about include/ - - com/sun/star/uno/XComponentContext.hpp comphelper/source/misc/simplefileaccessinteraction.cxx: # Needed for UnoType template - com/sun/star/task/XInteractionAbort.hpp diff --git a/comphelper/JunitTest_comphelper_complex.mk b/comphelper/JunitTest_comphelper_complex.mk index 1171eb1cd232..e35857b35b07 100644 --- a/comphelper/JunitTest_comphelper_complex.mk +++ b/comphelper/JunitTest_comphelper_complex.mk @@ -23,11 +23,9 @@ $(eval $(call gb_JunitTest_use_unoapi_jars,comphelper_complex)) $(eval $(call gb_JunitTest_add_sourcefiles,comphelper_complex,\ comphelper/qa/complex/comphelper/Map \ - comphelper/qa/complex/comphelper/SequenceOutputStreamUnitTest \ )) $(eval $(call gb_JunitTest_add_classes,comphelper_complex,\ - complex.comphelper.SequenceOutputStreamUnitTest \ complex.comphelper.Map \ )) diff --git a/comphelper/Library_comphelper.mk b/comphelper/Library_comphelper.mk index 1da5e7daa658..2ab1b1bfa5d7 100644 --- a/comphelper/Library_comphelper.mk +++ b/comphelper/Library_comphelper.mk @@ -23,7 +23,7 @@ $(eval $(call gb_Library_use_custom_headers,comphelper,\ officecfg/registry \ )) -$(eval $(call gb_Library_set_componentfile,comphelper,comphelper/util/comphelp)) +$(eval $(call gb_Library_set_componentfile,comphelper,comphelper/util/comphelp,services)) $(eval $(call gb_Library_set_precompiled_header,comphelper,comphelper/inc/pch/precompiled_comphelper)) @@ -77,29 +77,33 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\ comphelper/source/container/namecontainer \ comphelper/source/eventattachermgr/eventattachermgr \ comphelper/source/misc/accessiblecomponenthelper \ - comphelper/source/misc/accessiblecontexthelper \ comphelper/source/misc/accessibleeventnotifier \ comphelper/source/misc/accessiblekeybindinghelper \ comphelper/source/misc/accessibleselectionhelper \ comphelper/source/misc/accessibletexthelper \ comphelper/source/misc/accessiblewrapper \ - comphelper/source/misc/accimplaccess \ comphelper/source/misc/AccessibleImplementationHelper \ + comphelper/source/misc/anycompare \ + comphelper/source/misc/anytohash \ comphelper/source/misc/anytostring \ comphelper/source/misc/asyncnotification \ comphelper/source/misc/asyncquithandler \ comphelper/source/misc/automationinvokedzone \ comphelper/source/misc/backupfilehelper \ comphelper/source/misc/base64 \ + comphelper/source/misc/compbase \ comphelper/source/misc/componentbase \ comphelper/source/misc/configuration \ comphelper/source/misc/configurationhelper \ + comphelper/source/misc/date \ comphelper/source/misc/debuggerinfo \ + comphelper/source/misc/diagnose_ex \ comphelper/source/misc/DirectoryHelper \ comphelper/source/misc/dispatchcommand \ comphelper/source/misc/docpasswordhelper \ comphelper/source/misc/docpasswordrequest \ comphelper/source/misc/documentinfo \ + comphelper/source/misc/errcode \ comphelper/source/misc/evtlistenerhlp \ comphelper/source/misc/evtmethodhelper \ comphelper/source/misc/fileurl \ @@ -108,7 +112,6 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\ comphelper/source/misc/hash \ comphelper/source/misc/instancelocker \ comphelper/source/misc/interaction \ - comphelper/source/misc/listenernotification \ comphelper/source/misc/logging \ comphelper/source/misc/lok \ comphelper/source/misc/mimeconfighelper \ @@ -121,19 +124,16 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\ comphelper/source/misc/random \ comphelper/source/misc/SelectionMultiplex \ comphelper/source/misc/sequenceashashmap \ - comphelper/source/misc/servicedecl \ comphelper/source/misc/sharedmutex \ comphelper/source/misc/simplefileaccessinteraction \ comphelper/source/misc/solarmutex \ comphelper/source/misc/stillreadwriteinteraction \ - comphelper/source/misc/anycompare \ comphelper/source/misc/storagehelper \ comphelper/source/misc/string \ comphelper/source/misc/synchronousdispatch \ comphelper/source/misc/syntaxhighlight \ comphelper/source/misc/threadpool \ comphelper/source/misc/types \ - comphelper/source/misc/weak \ comphelper/source/misc/weakeventlistener \ comphelper/source/misc/xmlsechelper \ comphelper/source/officeinstdir/officeinstallationdirectories \ @@ -147,12 +147,15 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\ comphelper/source/property/propagg \ comphelper/source/property/propertybag \ comphelper/source/property/propertycontainer \ + comphelper/source/property/propertycontainer2 \ comphelper/source/property/propertycontainerhelper \ comphelper/source/property/property \ comphelper/source/property/propertysethelper \ comphelper/source/property/propertysetinfo \ comphelper/source/property/propertystatecontainer \ comphelper/source/property/propmultiplex \ + comphelper/source/property/propmultiplex2 \ + comphelper/source/property/propshlp \ comphelper/source/property/propstate \ comphelper/source/streaming/basicio \ comphelper/source/streaming/memorystream \ diff --git a/comphelper/Module_comphelper.mk b/comphelper/Module_comphelper.mk index 7541a59f1641..2ba6af1198f5 100644 --- a/comphelper/Module_comphelper.mk +++ b/comphelper/Module_comphelper.mk @@ -27,6 +27,7 @@ $(eval $(call gb_Module_add_targets,comphelper,\ $(eval $(call gb_Module_add_subsequentcheck_targets,comphelper,\ JunitTest_comphelper_complex \ + PythonTest_comphelper_python \ )) $(eval $(call gb_Module_add_check_targets,comphelper,\ @@ -36,6 +37,7 @@ $(eval $(call gb_Module_add_check_targets,comphelper,\ CppunitTest_comphelper_variadictemplates_test \ CppunitTest_comphelper_ifcontainer \ CppunitTest_comphelper_test \ + CppunitTest_comphelper_weakbag_test \ )) # vim: set noet sw=4 ts=4: diff --git a/comphelper/PythonTest_comphelper_python.mk b/comphelper/PythonTest_comphelper_python.mk new file mode 100644 index 000000000000..e020deb9899c --- /dev/null +++ b/comphelper/PythonTest_comphelper_python.mk @@ -0,0 +1,13 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# 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/. +# +$(eval $(call gb_PythonTest_PythonTest,comphelper_python)) +$(eval $(call gb_PythonTest_add_modules,comphelper_python,$(SRCDIR)/comphelper/qa/python,\ + test_sequence_output_stream \ +)) +# vim: set noet sw=4 ts=4: diff --git a/comphelper/inc/pch/precompiled_comphelper.hxx b/comphelper/inc/pch/precompiled_comphelper.hxx index fdceecb34853..897773b473f5 100644 --- a/comphelper/inc/pch/precompiled_comphelper.hxx +++ b/comphelper/inc/pch/precompiled_comphelper.hxx @@ -13,7 +13,7 @@ manual changes will be rewritten by the next run of update_pch.sh (which presumably also fixes all possible problems, so it's usually better to use it). - Generated on 2021-04-08 13:55:35 using: + Generated on 2022-08-13 18:00:53 using: ./bin/update_pch comphelper comphelper --cutoff=4 --exclude:system --include:module --include:local If after updating build fails, use the following command to locate conflicting headers: @@ -23,6 +23,7 @@ #include <sal/config.h> #if PCH_LEVEL >= 1 #include <algorithm> +#include <array> #include <cassert> #include <chrono> #include <cmath> @@ -39,7 +40,9 @@ #include <map> #include <math.h> #include <memory> +#include <mutex> #include <new> +#include <numeric> #include <optional> #include <ostream> #include <stddef.h> @@ -50,14 +53,21 @@ #include <unordered_map> #include <utility> #include <vector> +#include <boost/core/noinit_adaptor.hpp> +#include <boost/property_tree/json_parser.hpp> #endif // PCH_LEVEL >= 1 #if PCH_LEVEL >= 2 -#include <osl/conditn.hxx> #include <osl/diagnose.h> +#include <osl/doublecheckedlocking.h> #include <osl/endian.h> +#include <osl/file.h> #include <osl/file.hxx> +#include <osl/getglobalmutex.hxx> #include <osl/interlck.h> +#include <osl/mutex.h> #include <osl/mutex.hxx> +#include <osl/process.h> +#include <osl/security.h> #include <osl/thread.h> #include <osl/time.h> #include <rtl/alloc.h> @@ -78,6 +88,7 @@ #include <rtl/stringutils.hxx> #include <rtl/textcvt.h> #include <rtl/textenc.h> +#include <rtl/uri.hxx> #include <rtl/ustrbuf.hxx> #include <rtl/ustring.h> #include <rtl/ustring.hxx> @@ -92,7 +103,7 @@ #include <vcl/Scanline.hxx> #include <vcl/alpha.hxx> #include <vcl/animate/Animation.hxx> -#include <vcl/animate/AnimationBitmap.hxx> +#include <vcl/animate/AnimationFrame.hxx> #include <vcl/bitmap.hxx> #include <vcl/bitmap/BitmapTypes.hxx> #include <vcl/bitmapex.hxx> @@ -101,7 +112,6 @@ #include <vcl/gfxlink.hxx> #include <vcl/mapmod.hxx> #include <vcl/region.hxx> -#include <vcl/scopedbitmapaccess.hxx> #include <vcl/task.hxx> #include <vcl/timer.hxx> #include <vcl/vectorgraphicdata.hxx> @@ -114,8 +124,11 @@ #include <basegfx/point/b2ipoint.hxx> #include <basegfx/polygon/b2dpolygon.hxx> #include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/range/Range2D.hxx> #include <basegfx/range/b2drange.hxx> #include <basegfx/range/basicrange.hxx> +#include <basegfx/tuple/Tuple2D.hxx> +#include <basegfx/tuple/Tuple3D.hxx> #include <basegfx/tuple/b2dtuple.hxx> #include <basegfx/tuple/b2ituple.hxx> #include <basegfx/tuple/b3dtuple.hxx> @@ -189,9 +202,12 @@ #include <cppuhelper/weakagg.hxx> #include <cppuhelper/weakref.hxx> #include <o3tl/cow_wrapper.hxx> +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> #include <o3tl/strong_int.hxx> #include <o3tl/typed_flags_set.hxx> #include <o3tl/underlyingenumvalue.hxx> +#include <o3tl/unit_conversion.hxx> #include <salhelper/salhelperdllapi.h> #include <salhelper/simplereferenceobject.hxx> #include <salhelper/thread.hxx> @@ -201,10 +217,12 @@ #include <tools/link.hxx> #include <tools/long.hxx> #include <tools/mapunit.hxx> +#include <tools/poly.hxx> #include <tools/solar.h> #include <tools/toolsdllapi.h> #include <typelib/typeclass.h> #include <typelib/typedescription.h> +#include <typelib/typedescription.hxx> #include <typelib/uik.h> #include <ucbhelper/ucbhelperdllapi.h> #include <uno/any2.h> @@ -213,10 +231,11 @@ #endif // PCH_LEVEL >= 3 #if PCH_LEVEL >= 4 #include <comphelper/accessiblecontexthelper.hxx> +#include <comphelper/accessibleeventnotifier.hxx> #include <comphelper/comphelperdllapi.h> -#include <comphelper/interfacecontainer2.hxx> #include <comphelper/processfactory.hxx> #include <comphelper/propertycontainerhelper.hxx> +#include <comphelper/propertyvalue.hxx> #include <comphelper/seqstream.hxx> #include <comphelper/sequence.hxx> #include <comphelper/solarmutex.hxx> diff --git a/comphelper/qa/complex/comphelper/Map.java b/comphelper/qa/complex/comphelper/Map.java index d01d1bef362b..51f731732071 100644 --- a/comphelper/qa/complex/comphelper/Map.java +++ b/comphelper/qa/complex/comphelper/Map.java @@ -461,23 +461,23 @@ public class Map @Test public void testSpecialValues() throws com.sun.star.uno.Exception { - final Double[] keys = new Double[] { new Double( 0 ), Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY }; - final Double[] values = new Double[] { Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, new Double( 0 ) }; + final Double[] keys = new Double[] { Double.valueOf( 0 ), Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY }; + final Double[] values = new Double[] { Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.valueOf( 0 ) }; XEnumerableMap map = com.sun.star.container.EnumerableMap.create( connection.getComponentContext(), new Type( Double.class ), new Type( Double.class ) ); impl_putAll( map, keys, values ); assertTrue( "containsKey( Double.+INF failed", map.containsKey( Double.POSITIVE_INFINITY ) ); assertTrue( "containsKey( Double.-INF failed", map.containsKey( Double.NEGATIVE_INFINITY ) ); - assertTrue( "containsKey( 0 ) failed", map.containsKey( new Double( 0 ) ) ); + assertTrue( "containsKey( 0 ) failed", map.containsKey( Double.valueOf( 0 ) ) ); assertTrue( "containsValue( Double.+INF ) failed", map.containsValue( Double.POSITIVE_INFINITY ) ); assertTrue( "containsValue( Double.-INF ) failed", map.containsValue( Double.NEGATIVE_INFINITY ) ); - assertTrue( "containsValue( 0 ) failed", map.containsValue( new Double( 0 ) ) ); + assertTrue( "containsValue( 0 ) failed", map.containsValue( Double.valueOf( 0 ) ) ); // put and containsKey should reject Double.NaN as key //? assureException( "Double.NaN should not be allowed as key in a call to 'put'", map, "put", -//? new Class[] { Object.class, Object.class }, new Object[] { Double.NaN, new Double( 0 ) }, +//? new Class[] { Object.class, Object.class }, new Object[] { Double.NaN, Double.valueOf( 0 ) }, //? com.sun.star.lang.IllegalArgumentException.class ); //? assureException( "Double.NaN should not be allowed as key in a call to 'containsKey'", map, "containsKey", //? new Class[] { Object.class }, new Object[] { Double.NaN }, @@ -485,7 +485,7 @@ public class Map // ditto for put and containsValue //? assureException( "Double.NaN should not be allowed as value in a call to 'put'", map, "put", -//? new Class[] { Object.class, Object.class }, new Object[] { new Double( 0 ), Double.NaN }, +//? new Class[] { Object.class, Object.class }, new Object[] { Double.valueOf( 0 ), Double.NaN }, //? com.sun.star.lang.IllegalArgumentException.class ); //? assureException( "Double.NaN should not be allowed as key in a call to 'containsValue'", map, "containsValue", //? new Class[] { Object.class }, new Object[] { Double.NaN }, diff --git a/comphelper/qa/complex/comphelper/SequenceOutputStreamUnitTest.java b/comphelper/qa/complex/comphelper/SequenceOutputStreamUnitTest.java deleted file mode 100644 index 03906134b9f7..000000000000 --- a/comphelper/qa/complex/comphelper/SequenceOutputStreamUnitTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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 . - */ -package complex.comphelper; - -import com.sun.star.lang.XMultiServiceFactory; -import com.sun.star.uno.UnoRuntime; - -import com.sun.star.io.XSequenceOutputStream; -import com.sun.star.io.XSeekableInputStream; - -import java.util.Random; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.openoffice.test.OfficeConnection; -import static org.junit.Assert.*; - -/* Document. - */ - -public class SequenceOutputStreamUnitTest -{ - private XMultiServiceFactory m_xMSF = null; - - @Before public void before() { - try { - m_xMSF = getMSF(); - } catch (Exception e) { - fail ("Cannot create service factory!"); - } - if (m_xMSF==null) { - fail ("Cannot create service factory!"); - } - } - - @After public void after() { - m_xMSF = null; - } - - @Test public void test () { - try { - final int nBytesCnt = 20; - - //create SequenceOutputStream - Object oSequenceOutputStream = m_xMSF.createInstance ( - "com.sun.star.io.SequenceOutputStream" ); - XSequenceOutputStream xSeqOutStream = - UnoRuntime.queryInterface ( - XSequenceOutputStream.class, oSequenceOutputStream ); - - //write something to the stream - byte pBytesOriginal[] = new byte [nBytesCnt]; - Random oRandom = new Random(); - oRandom.nextBytes (pBytesOriginal); - xSeqOutStream.writeBytes (pBytesOriginal); - - // Append the same content once again - xSeqOutStream.writeBytes (pBytesOriginal); - - byte pBytesWritten[] = xSeqOutStream.getWrittenBytes (); - assertTrue( "SequenceOutputStream::getWrittenBytes() - wrong amount of bytes returned", - pBytesWritten.length == nBytesCnt * 2 ); - - //create SequenceInputstream - Object pArgs[] = new Object[1]; - pArgs[0] = pBytesWritten; - Object oSequenceInputStream = m_xMSF.createInstanceWithArguments ( - "com.sun.star.io.SequenceInputStream", pArgs ); - XSeekableInputStream xSeekableInStream = - UnoRuntime.queryInterface ( - XSeekableInputStream.class, oSequenceInputStream ); - - //read from the stream - byte pBytesRead[][] = new byte [1][nBytesCnt*2]; - int nBytesCountRead = xSeekableInStream.readBytes ( pBytesRead, pBytesRead[0].length + 1 ); - - assertTrue( "SequenceInputStream::readBytes() - wrong amount of bytes returned " + pBytesRead[0].length + " vs " + (nBytesCountRead), - pBytesRead[0].length == nBytesCountRead); - - //close the streams - xSeqOutStream.closeOutput (); - xSeekableInStream.closeInput (); - - //compare the original, written and read arrays - for ( int i = 0; i < nBytesCnt * 2; ++i ) { - assertTrue( "Written array not identical to original array. Position: " + i, - pBytesOriginal[i % nBytesCnt] == pBytesWritten[i] ); - assertTrue( "Read array not identical to original array. Position: " + i, - pBytesOriginal[i % nBytesCnt] == pBytesRead[0][i] ); - } - } catch ( Exception e ) { - fail ( "Exception: " + e ); - } - } - - private static XMultiServiceFactory getMSF() - { - return UnoRuntime.queryInterface(XMultiServiceFactory.class, connection.getComponentContext().getServiceManager()); - } - - // setup and close connections - @BeforeClass public static void setUpConnection() throws Exception { - System.out.println("setUpConnection()"); - connection.setUp(); - } - - @AfterClass public static void tearDownConnection() - throws InterruptedException, com.sun.star.uno.Exception - { - System.out.println("tearDownConnection()"); - connection.tearDown(); - } - - private static final OfficeConnection connection = new OfficeConnection(); -} diff --git a/comphelper/qa/complex/comphelper_all.sce b/comphelper/qa/complex/comphelper_all.sce index 5ee5f941f94a..656850ab0712 100644 --- a/comphelper/qa/complex/comphelper_all.sce +++ b/comphelper/qa/complex/comphelper_all.sce @@ -15,5 +15,4 @@ # except in compliance with the License. You may obtain a copy of # the License at http://www.apache.org/licenses/LICENSE-2.0 . # --o complex.comphelper.SequenceOutputStreamUnitTest -o complex.comphelper.Map diff --git a/comphelper/qa/container/comphelper_ifcontainer.cxx b/comphelper/qa/container/comphelper_ifcontainer.cxx index ed92aa692f4e..db904e2fbaf6 100644 --- a/comphelper/qa/container/comphelper_ifcontainer.cxx +++ b/comphelper/qa/container/comphelper_ifcontainer.cxx @@ -114,7 +114,7 @@ namespace comphelper_ifcontainer CPPUNIT_ASSERT_EQUAL_MESSAGE("query contents", nTests, static_cast<int>(aElements.size())); - if (static_cast<int>(aElements.size()) == nTests) + if (aElements.size() == nTests) { for (i = 0; i < nTests; i++) { diff --git a/comphelper/qa/container/testifcontainer3.cxx b/comphelper/qa/container/testifcontainer3.cxx new file mode 100644 index 000000000000..e300adeda12e --- /dev/null +++ b/comphelper/qa/container/testifcontainer3.cxx @@ -0,0 +1,170 @@ +/* -*- 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 <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <osl/mutex.hxx> +#include <comphelper/interfacecontainer3.hxx> +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/beans/XVetoableChangeListener.hpp> + +using namespace ::osl; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; + +namespace +{ +class TestInterfaceContainer3 : public CppUnit::TestFixture +{ +public: + void test1(); + + CPPUNIT_TEST_SUITE(TestInterfaceContainer3); + CPPUNIT_TEST(test1); + CPPUNIT_TEST_SUITE_END(); +}; + +class TestListener : public cppu::WeakImplHelper<XVetoableChangeListener> +{ +public: + // Methods + virtual void SAL_CALL disposing(const css::lang::EventObject& /*Source*/) override {} + + virtual void SAL_CALL vetoableChange(const css::beans::PropertyChangeEvent& /*aEvent*/) override + { + } +}; + +void TestInterfaceContainer3::test1() +{ + Mutex mutex; + + { + comphelper::OInterfaceContainerHelper3<XVetoableChangeListener> helper(mutex); + + Reference<XVetoableChangeListener> r1 = new TestListener; + Reference<XVetoableChangeListener> r2 = new TestListener; + Reference<XVetoableChangeListener> r3 = new TestListener; + + helper.addInterface(r1); + helper.addInterface(r2); + helper.addInterface(r3); + + helper.disposeAndClear(EventObject()); + } + + { + comphelper::OInterfaceContainerHelper3<XVetoableChangeListener> helper(mutex); + + Reference<XVetoableChangeListener> r1 = new TestListener; + Reference<XVetoableChangeListener> r2 = new TestListener; + Reference<XVetoableChangeListener> r3 = new TestListener; + + helper.addInterface(r1); + helper.addInterface(r2); + helper.addInterface(r3); + + comphelper::OInterfaceIteratorHelper3 iterator(helper); + + while (iterator.hasMoreElements()) + iterator.next()->vetoableChange(PropertyChangeEvent()); + + helper.disposeAndClear(EventObject()); + } + + { + comphelper::OInterfaceContainerHelper3<XVetoableChangeListener> helper(mutex); + + Reference<XVetoableChangeListener> r1 = new TestListener; + Reference<XVetoableChangeListener> r2 = new TestListener; + Reference<XVetoableChangeListener> r3 = new TestListener; + + helper.addInterface(r1); + helper.addInterface(r2); + helper.addInterface(r3); + + comphelper::OInterfaceIteratorHelper3 iterator(helper); + + iterator.next()->vetoableChange(PropertyChangeEvent()); + iterator.remove(); + iterator.next()->vetoableChange(PropertyChangeEvent()); + iterator.remove(); + iterator.next()->vetoableChange(PropertyChangeEvent()); + iterator.remove(); + + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), helper.getLength()); + helper.disposeAndClear(EventObject()); + } + + { + comphelper::OInterfaceContainerHelper3<XVetoableChangeListener> helper(mutex); + + Reference<XVetoableChangeListener> r1 = new TestListener; + Reference<XVetoableChangeListener> r2 = new TestListener; + Reference<XVetoableChangeListener> r3 = new TestListener; + + helper.addInterface(r1); + helper.addInterface(r2); + helper.addInterface(r3); + + { + comphelper::OInterfaceIteratorHelper3 iterator(helper); + while (iterator.hasMoreElements()) + { + Reference<XVetoableChangeListener> r = iterator.next(); + if (r == r1) + iterator.remove(); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), helper.getLength()); + { + comphelper::OInterfaceIteratorHelper3 iterator(helper); + while (iterator.hasMoreElements()) + { + Reference<XVetoableChangeListener> r = iterator.next(); + CPPUNIT_ASSERT(r != r1); + CPPUNIT_ASSERT(r == r2 || r == r3); + } + } + + helper.disposeAndClear(EventObject()); + } + + { + comphelper::OInterfaceContainerHelper3<XVetoableChangeListener> helper(mutex); + + Reference<XVetoableChangeListener> r1 = new TestListener; + + helper.addInterface(r1); + + { + comphelper::OInterfaceIteratorHelper3 iterator(helper); + iterator.next(); + iterator.remove(); + } + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), helper.getLength()); + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TestInterfaceContainer3); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/python/test_sequence_output_stream.py b/comphelper/qa/python/test_sequence_output_stream.py new file mode 100644 index 000000000000..6f1294960e29 --- /dev/null +++ b/comphelper/qa/python/test_sequence_output_stream.py @@ -0,0 +1,84 @@ +#! /usr/bin/env python +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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/. +# + +import unittest +import uno + +from org.libreoffice.unotest import UnoInProcess + + +class TestSequenceOutputStream(unittest.TestCase): + """Test com.sun.star.io.SequenceOutputStream""" + + @classmethod + def setUpClass(cls): + cls._uno = UnoInProcess() + cls._uno.setUp() + + @classmethod + def tearDownClass(cls): + cls._uno.tearDown() + + def setUp(self): + self.data = uno.ByteSequence(b"some data") + try: + self.service_manager = self._uno.getContext().getServiceManager() + except: + raise RuntimeError("Cannot create service factory!") + if self.service_manager is None: + raise RuntimeError("Cannot create service factory!") + + def test_stream(self): + try: + seq_output_stream = self.service_manager.createInstance( + "com.sun.star.io.SequenceOutputStream" + ) + seq_output_stream.writeBytes(self.data) + + # Append the same content once again + seq_output_stream.writeBytes(self.data) + + written_bytes = seq_output_stream.getWrittenBytes() + + self.assertEqual( + len(self.data) * 2, + len(written_bytes), + "SequenceOutputStream::getWrittenBytes() - wrong amount of bytes returned", + ) + + # create SequenceInputstream + seq_input_stream = self.service_manager.createInstanceWithArguments( + "com.sun.star.io.SequenceInputStream", (written_bytes,) + ) + + # read from the stream + nbytes_read, read_bytes = seq_input_stream.readBytes(None, len(self.data) * 2 + 1) + self.assertEqual( + len(self.data) * 2, + nbytes_read, + "SequenceInputStream::readBytes() - " + f"wrong amount of bytes returned {len(self.data) * 2} vs {nbytes_read}", + ) + + # close the streams + seq_output_stream.closeOutput() + seq_input_stream.closeInput() + + expected = uno.ByteSequence(self.data.value * 2) + self.assertEqual(expected, written_bytes, "Written array not identical to original.") + self.assertEqual(expected, read_bytes, "Read array not identical to original.") + except Exception as e: + self.fail(f"Exception: {e}") + + +if __name__ == "__main__": + unittest.main() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/comphelper/qa/string/NaturalStringSortTest.cxx b/comphelper/qa/string/NaturalStringSortTest.cxx new file mode 100644 index 000000000000..bfdcaff6e13c --- /dev/null +++ b/comphelper/qa/string/NaturalStringSortTest.cxx @@ -0,0 +1,95 @@ +/* -*- 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/string.hxx> +#include <comphelper/processfactory.hxx> +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/i18n/CharType.hpp> +#include <com/sun/star/i18n/XBreakIterator.hpp> +#include <com/sun/star/i18n/XCollator.hpp> + +#include <unotest/bootstrapfixturebase.hxx> +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> +#include <rtl/ustring.hxx> + +using namespace css; + +namespace +{ +class TestStringNaturalCompare : public test::BootstrapFixtureBase +{ +public: + void testNatural() + { + lang::Locale aLocale; + aLocale.Language = "en"; + aLocale.Country = "US"; + + comphelper::string::NaturalStringSorter aSorter(comphelper::getProcessComponentContext(), + aLocale); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(+0), aSorter.compare("ABC", "ABC")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare("ABC", "abc")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare("abc", "ABC")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare("alongstring", "alongerstring")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare("alongerstring", "alongstring")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare("Heading 9", "Heading 10")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare("Heading 10", "Heading 9")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare("July, the 4th", "July, the 10th")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare("July, the 10th", "July, the 4th")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare("abc08", "abc010")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare("abc010", "abc08")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+0), aSorter.compare("apple10apple", "apple10apple")); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare("KA1", "KA0")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+0), aSorter.compare("KA1", "KA1")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare("KA1", "KA2")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare("KA50", "KA5")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare("KA50", "KA100")); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare("1", "0")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+0), aSorter.compare("1", "1")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare("1", "2")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare("11", "1")); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare("50", "100")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare("0", "100000")); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare("0", "A")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare("A", "0")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare("A", "99")); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare("00ABC2", "00ABC1")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare("00ABC1", "00ABC2")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare("00ABC11", "00ABC2")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare("00ABC2", "00ABC11")); + } + + CPPUNIT_TEST_SUITE(TestStringNaturalCompare); + CPPUNIT_TEST(testNatural); + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(TestStringNaturalCompare); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/string/test_string.cxx b/comphelper/qa/string/test_string.cxx index 0619b873e0fb..ac79148a4c48 100644 --- a/comphelper/qa/string/test_string.cxx +++ b/comphelper/qa/string/test_string.cxx @@ -17,6 +17,10 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <sal/config.h> + +#include <iterator> + #include <comphelper/string.hxx> #include <cppuhelper/implbase.hxx> #include <com/sun/star/i18n/CharType.hpp> @@ -35,7 +39,6 @@ namespace { class TestString: public CppUnit::TestFixture { public: - void testNatural(); void testStripStart(); void testStripEnd(); void testStrip(); @@ -44,11 +47,11 @@ public: void testDecimalStringToNumber(); void testIsdigitAsciiString(); void testReverseString(); + void testReverseCodePoints(); void testSplit(); void testRemoveAny(); CPPUNIT_TEST_SUITE(TestString); - CPPUNIT_TEST(testNatural); CPPUNIT_TEST(testStripStart); CPPUNIT_TEST(testStripEnd); CPPUNIT_TEST(testStrip); @@ -57,6 +60,7 @@ public: CPPUNIT_TEST(testDecimalStringToNumber); CPPUNIT_TEST(testIsdigitAsciiString); CPPUNIT_TEST(testReverseString); + CPPUNIT_TEST(testReverseCodePoints); CPPUNIT_TEST(testSplit); CPPUNIT_TEST(testRemoveAny); CPPUNIT_TEST_SUITE_END(); @@ -69,7 +73,7 @@ void TestString::testDecimalStringToNumber() s1 += u"\u07C6"; CPPUNIT_ASSERT_EQUAL(sal_uInt32(12346), comphelper::string::decimalStringToNumber(s1)); // Codepoints on 2 16bits words - s1 = u"\U0001D7FE\U0001D7F7"; // MATHEMATICAL MONOSPACE DIGIT EIGHT and ONE + s1 = u"\U0001D7FE\U0001D7F7"_ustr; // MATHEMATICAL MONOSPACE DIGIT EIGHT and ONE CPPUNIT_ASSERT_EQUAL(sal_uInt32(81), comphelper::string::decimalStringToNumber(s1)); } @@ -82,268 +86,82 @@ void TestString::testIsdigitAsciiString() CPPUNIT_ASSERT_EQUAL(true, comphelper::string::isdigitAsciiString("")); } -using namespace ::com::sun::star; - -class testCollator : public cppu::WeakImplHelper< i18n::XCollator > -{ -public: - virtual sal_Int32 SAL_CALL compareSubstring( - const OUString& str1, sal_Int32 off1, sal_Int32 len1, - const OUString& str2, sal_Int32 off2, sal_Int32 len2) override - { - return str1.copy(off1, len1).compareTo(str2.subView(off2, len2)); - } - virtual sal_Int32 SAL_CALL compareString( - const OUString& str1, - const OUString& str2) override - { - return str1.compareTo(str2); - } - virtual sal_Int32 SAL_CALL loadDefaultCollator(const lang::Locale&, sal_Int32) override {return 0;} - virtual sal_Int32 SAL_CALL loadCollatorAlgorithm(const OUString&, - const lang::Locale&, sal_Int32) override {return 0;} - virtual void SAL_CALL loadCollatorAlgorithmWithEndUserOption(const OUString&, - const lang::Locale&, const uno::Sequence< sal_Int32 >&) override {} - virtual uno::Sequence< OUString > SAL_CALL listCollatorAlgorithms(const lang::Locale&) override - { - return uno::Sequence< OUString >(); - } - virtual uno::Sequence< sal_Int32 > SAL_CALL listCollatorOptions(const OUString&) override - { - return uno::Sequence< sal_Int32 >(); - } -}; - -#define IS_DIGIT(CHAR) (((CHAR) >= 48) && ((CHAR <= 57))) - -class testBreakIterator : public cppu::WeakImplHelper< i18n::XBreakIterator > -{ -public: - virtual sal_Int32 SAL_CALL nextCharacters( const OUString&, sal_Int32, - const lang::Locale&, sal_Int16, sal_Int32, sal_Int32& ) override {return -1;} - virtual sal_Int32 SAL_CALL previousCharacters( const OUString&, sal_Int32, - const lang::Locale&, sal_Int16, sal_Int32, sal_Int32& ) override {return -1;} - - virtual i18n::Boundary SAL_CALL previousWord( const OUString&, sal_Int32, - const lang::Locale&, sal_Int16) override - { return i18n::Boundary(); } - virtual i18n::Boundary SAL_CALL nextWord( const OUString&, sal_Int32, - const lang::Locale&, sal_Int16) override - { return i18n::Boundary(); } - virtual i18n::Boundary SAL_CALL getWordBoundary( const OUString&, sal_Int32, - const lang::Locale&, sal_Int16, sal_Bool ) override - { return i18n::Boundary(); } - - virtual sal_Bool SAL_CALL isBeginWord( const OUString&, sal_Int32, - const lang::Locale&, sal_Int16 ) override - { return false; } - virtual sal_Bool SAL_CALL isEndWord( const OUString&, sal_Int32, - const lang::Locale& , sal_Int16 ) override - { return false; } - virtual sal_Int16 SAL_CALL getWordType( const OUString&, sal_Int32, - const lang::Locale& ) override - { return 0; } - - virtual sal_Int32 SAL_CALL beginOfSentence( const OUString&, sal_Int32, - const lang::Locale& ) override - { return 0; } - virtual sal_Int32 SAL_CALL endOfSentence( const OUString& rText, sal_Int32, - const lang::Locale& ) override - { return rText.getLength(); } - - virtual i18n::LineBreakResults SAL_CALL getLineBreak( const OUString&, sal_Int32, - const lang::Locale&, sal_Int32, - const i18n::LineBreakHyphenationOptions&, - const i18n::LineBreakUserOptions&) override - { - return i18n::LineBreakResults(); - } - - virtual sal_Int16 SAL_CALL getScriptType( const OUString&, sal_Int32 ) override { return -1; } - virtual sal_Int32 SAL_CALL beginOfScript( const OUString&, sal_Int32, - sal_Int16 ) override { return -1; } - virtual sal_Int32 SAL_CALL endOfScript( const OUString&, sal_Int32, - sal_Int16 ) override { return -1; } - virtual sal_Int32 SAL_CALL previousScript( const OUString&, sal_Int32, - sal_Int16 ) override { return -1; } - virtual sal_Int32 SAL_CALL nextScript( const OUString&, sal_Int32, - sal_Int16 ) override { return -1; } - - virtual sal_Int32 SAL_CALL beginOfCharBlock( const OUString&, sal_Int32, - const lang::Locale&, sal_Int16 ) override { return -1; } - virtual sal_Int32 SAL_CALL endOfCharBlock( const OUString& rText, sal_Int32 nStartPos, - const lang::Locale&, sal_Int16 CharType ) override - { - const sal_Unicode *pStr = rText.getStr()+nStartPos; - for (sal_Int32 nI = nStartPos; nI < rText.getLength(); ++nI) - { - if (CharType == i18n::CharType::DECIMAL_DIGIT_NUMBER && !IS_DIGIT(*pStr)) - return nI; - else if (CharType != i18n::CharType::DECIMAL_DIGIT_NUMBER && IS_DIGIT(*pStr)) - return nI; - ++pStr; - } - return -1; - } - virtual sal_Int32 SAL_CALL previousCharBlock( const OUString&, sal_Int32, - const lang::Locale&, sal_Int16 ) override { return -1; } - virtual sal_Int32 SAL_CALL nextCharBlock( const OUString& rText, sal_Int32 nStartPos, - const lang::Locale&, sal_Int16 CharType ) override - { - const sal_Unicode *pStr = rText.getStr()+nStartPos; - for (sal_Int32 nI = nStartPos; nI < rText.getLength(); ++nI) - { - if (CharType == i18n::CharType::DECIMAL_DIGIT_NUMBER && IS_DIGIT(*pStr)) - return nI; - else if (CharType != i18n::CharType::DECIMAL_DIGIT_NUMBER && !IS_DIGIT(*pStr)) - return nI; - ++pStr; - } - return -1; - } -}; - -void TestString::testNatural() -{ - using namespace comphelper::string; - - uno::Reference< i18n::XCollator > xCollator(new testCollator); - uno::Reference< i18n::XBreakIterator > xBI(new testBreakIterator); - -// --- Some generic tests to ensure we do not alter original behavior -// outside what we want - CPPUNIT_ASSERT_EQUAL( - static_cast<sal_Int32>(0), compareNatural("ABC", "ABC", xCollator, xBI, lang::Locale()) - ); - // Case sensitivity - CPPUNIT_ASSERT( - compareNatural("ABC", "abc", xCollator, xBI, lang::Locale()) < 0 - ); - // Reverse - CPPUNIT_ASSERT( - compareNatural("abc", "ABC", xCollator, xBI, lang::Locale()) > 0 - ); - // First shorter - CPPUNIT_ASSERT( - compareNatural("alongstring", "alongerstring", xCollator, xBI, lang::Locale()) > 0 - ); - // Second shorter - CPPUNIT_ASSERT( - compareNatural("alongerstring", "alongstring", xCollator, xBI, lang::Locale()) < 0 - ); -// -- Here we go on natural order, each one is followed by classic compare and the reverse comparison - // That's why we originally made the patch - CPPUNIT_ASSERT( - compareNatural("Heading 9", "Heading 10", xCollator, xBI, lang::Locale()) < 0 - ); - // Original behavior - CPPUNIT_ASSERT( - OUString("Heading 9").compareTo(u"Heading 10") > 0 - ); - CPPUNIT_ASSERT( - compareNatural("Heading 10", "Heading 9", xCollator, xBI, lang::Locale()) > 0 - ); - // Harder - CPPUNIT_ASSERT( - compareNatural("July, the 4th", "July, the 10th", xCollator, xBI, lang::Locale()) < 0 - ); - CPPUNIT_ASSERT( - OUString("July, the 4th").compareTo(u"July, the 10th") > 0 - ); - CPPUNIT_ASSERT( - compareNatural("July, the 10th", "July, the 4th", xCollator, xBI, lang::Locale()) > 0 - ); - // Hardest - CPPUNIT_ASSERT( - compareNatural("abc08", "abc010", xCollator, xBI, lang::Locale()) < 0 - ); - CPPUNIT_ASSERT( - OUString("abc08").compareTo(u"abc010") > 0 - ); - CPPUNIT_ASSERT( - compareNatural("abc010", "abc08", xCollator, xBI, lang::Locale()) > 0 - ); - CPPUNIT_ASSERT_EQUAL( - static_cast<sal_Int32>(0), compareNatural("apple10apple", "apple10apple", xCollator, xBI, lang::Locale()) - ); -} - void TestString::testStripStart() { - OString aIn("abc"); + OString aIn("abc"_ostr); OString aOut; aOut = ::comphelper::string::stripStart(aIn, 'b'); - CPPUNIT_ASSERT_EQUAL(OString("abc"), aOut); + CPPUNIT_ASSERT_EQUAL("abc"_ostr, aOut); aOut = ::comphelper::string::stripStart(aIn, 'a'); - CPPUNIT_ASSERT_EQUAL(OString("bc"), aOut); + CPPUNIT_ASSERT_EQUAL("bc"_ostr, aOut); - aIn = "aaa"; + aIn = "aaa"_ostr; aOut = ::comphelper::string::stripStart(aIn, 'a'); CPPUNIT_ASSERT(aOut.isEmpty()); - aIn = "aba"; + aIn = "aba"_ostr; aOut = ::comphelper::string::stripStart(aIn, 'a'); - CPPUNIT_ASSERT_EQUAL(OString("ba"), aOut); + CPPUNIT_ASSERT_EQUAL("ba"_ostr, aOut); } void TestString::testStripEnd() { - OString aIn("abc"); + OString aIn("abc"_ostr); OString aOut; aOut = ::comphelper::string::stripEnd(aIn, 'b'); - CPPUNIT_ASSERT_EQUAL(OString("abc"), aOut); + CPPUNIT_ASSERT_EQUAL("abc"_ostr, aOut); aOut = ::comphelper::string::stripEnd(aIn, 'c'); - CPPUNIT_ASSERT_EQUAL(OString("ab"), aOut); + CPPUNIT_ASSERT_EQUAL("ab"_ostr, aOut); - aIn = "aaa"; + aIn = "aaa"_ostr; aOut = ::comphelper::string::stripEnd(aIn, 'a'); CPPUNIT_ASSERT(aOut.isEmpty()); - aIn = "aba"; + aIn = "aba"_ostr; aOut = ::comphelper::string::stripEnd(aIn, 'a'); - CPPUNIT_ASSERT_EQUAL(OString("ab"), aOut); + CPPUNIT_ASSERT_EQUAL("ab"_ostr, aOut); } void TestString::testStrip() { - OString aIn("abc"); + OString aIn("abc"_ostr); OString aOut; aOut = ::comphelper::string::strip(aIn, 'b'); - CPPUNIT_ASSERT_EQUAL(OString("abc"), aOut); + CPPUNIT_ASSERT_EQUAL("abc"_ostr, aOut); aOut = ::comphelper::string::strip(aIn, 'c'); - CPPUNIT_ASSERT_EQUAL(OString("ab"), aOut); + CPPUNIT_ASSERT_EQUAL("ab"_ostr, aOut); - aIn = "aaa"; + aIn = "aaa"_ostr; aOut = ::comphelper::string::strip(aIn, 'a'); CPPUNIT_ASSERT(aOut.isEmpty()); - aIn = "aba"; + aIn = "aba"_ostr; aOut = ::comphelper::string::strip(aIn, 'a'); - CPPUNIT_ASSERT_EQUAL(OString("b"), aOut); + CPPUNIT_ASSERT_EQUAL("b"_ostr, aOut); } void TestString::testToken() { - OString aIn("10.11.12"); + OString aIn("10.11.12"_ostr); OString aOut; aOut = aIn.getToken(-1, '.'); CPPUNIT_ASSERT(aOut.isEmpty()); aOut = aIn.getToken(0, '.'); - CPPUNIT_ASSERT_EQUAL(OString("10"), aOut); + CPPUNIT_ASSERT_EQUAL("10"_ostr, aOut); aOut = aIn.getToken(1, '.'); - CPPUNIT_ASSERT_EQUAL(OString("11"), aOut); + CPPUNIT_ASSERT_EQUAL("11"_ostr, aOut); aOut = aIn.getToken(2, '.'); - CPPUNIT_ASSERT_EQUAL(OString("12"), aOut); + CPPUNIT_ASSERT_EQUAL("12"_ostr, aOut); aOut = aIn.getToken(3, '.'); CPPUNIT_ASSERT(aOut.isEmpty()); @@ -351,7 +169,7 @@ void TestString::testToken() void TestString::testTokenCount() { - OString aIn("10.11.12"); + OString aIn("10.11.12"_ostr); sal_Int32 nOut; nOut = ::comphelper::string::getTokenCount(aIn, '.'); @@ -366,14 +184,33 @@ void TestString::testTokenCount() void TestString::testReverseString() { - OString aOut = ::comphelper::string::reverseString("ABC"); + CPPUNIT_ASSERT_EQUAL(OUString(), comphelper::string::reverseString(u"")); + CPPUNIT_ASSERT_EQUAL(OUString("cba"), comphelper::string::reverseString(u"abc")); + static sal_Unicode const rev[] = {'w', 0xDFFF, 0xDBFF, 'v', 0xDC00, 0xD800, 'u'}; + CPPUNIT_ASSERT_EQUAL( + OUString(rev, std::size(rev)), + comphelper::string::reverseString(u"u\U00010000v\U0010FFFFw")); + static sal_Unicode const malformed[] = {0xDC00, 0xD800}; + CPPUNIT_ASSERT_EQUAL( + u"\U00010000"_ustr, + comphelper::string::reverseString(std::u16string_view(malformed, std::size(malformed)))); +} - CPPUNIT_ASSERT_EQUAL(OString("CBA"), aOut); +void TestString::testReverseCodePoints() { + CPPUNIT_ASSERT_EQUAL(OUString(), comphelper::string::reverseCodePoints(u"")); + CPPUNIT_ASSERT_EQUAL(OUString("cba"), comphelper::string::reverseCodePoints(u"abc")); + CPPUNIT_ASSERT_EQUAL( + u"w\U0010FFFFv\U00010000u"_ustr, + comphelper::string::reverseCodePoints(u"u\U00010000v\U0010FFFFw")); + static sal_Unicode const malformed[] = {0xDC00, 0xD800}; + CPPUNIT_ASSERT_EQUAL( + u"\U00010000"_ustr, + comphelper::string::reverseCodePoints(std::u16string_view(malformed, std::size(malformed)))); } void TestString::testSplit() { - std::vector<OUString> aRet = ::comphelper::string::split("CTRL+ALT+F1", '+'); + std::vector<OUString> aRet = ::comphelper::string::split(u"CTRL+ALT+F1", '+'); CPPUNIT_ASSERT_EQUAL(size_t(3), aRet.size()); CPPUNIT_ASSERT_EQUAL(OUString("CTRL"), aRet[0]); CPPUNIT_ASSERT_EQUAL(OUString("ALT"), aRet[1]); diff --git a/comphelper/qa/unit/base64_test.cxx b/comphelper/qa/unit/base64_test.cxx index 31e865a370a6..dc637f63f709 100644 --- a/comphelper/qa/unit/base64_test.cxx +++ b/comphelper/qa/unit/base64_test.cxx @@ -71,17 +71,17 @@ void Base64Test::testBase64Decode() uno::Sequence<sal_Int8> decodedSequence; uno::Sequence<sal_Int8> expectedSequence = { 0, 0, 0, 0, 0, 1, 2, 3 }; - comphelper::Base64::decode(decodedSequence, "AAAAAAABAgM="); + comphelper::Base64::decode(decodedSequence, u"AAAAAAABAgM="); CPPUNIT_ASSERT(std::equal(std::cbegin(expectedSequence), std::cend(expectedSequence), std::cbegin(decodedSequence))); expectedSequence = { 5, 2, 3, 0, 0, 1, 2, 3 }; - comphelper::Base64::decode(decodedSequence, "BQIDAAABAgM="); + comphelper::Base64::decode(decodedSequence, u"BQIDAAABAgM="); CPPUNIT_ASSERT(std::equal(std::cbegin(expectedSequence), std::cend(expectedSequence), std::cbegin(decodedSequence))); expectedSequence = { sal_Int8(sal_uInt8(200)), 31, 77, 111, 0, 1, 2, 3 }; - comphelper::Base64::decode(decodedSequence, "yB9NbwABAgM="); + comphelper::Base64::decode(decodedSequence, u"yB9NbwABAgM="); CPPUNIT_ASSERT(std::equal(std::cbegin(expectedSequence), std::cend(expectedSequence), std::cbegin(decodedSequence))); } @@ -93,17 +93,17 @@ void Base64Test::testBase64EncodeForOStringBuffer() inputSequence = { 0, 0, 0, 0, 0, 1, 2, 3 }; comphelper::Base64::encode(aBuffer, inputSequence); - CPPUNIT_ASSERT_EQUAL(OString("AAAAAAABAgM="), aBuffer.toString()); + CPPUNIT_ASSERT_EQUAL("AAAAAAABAgM="_ostr, aBuffer.toString()); aBuffer.setLength(0); inputSequence = { 5, 2, 3, 0, 0, 1, 2, 3 }; comphelper::Base64::encode(aBuffer, inputSequence); - CPPUNIT_ASSERT_EQUAL(OString("BQIDAAABAgM="), aBuffer.toString()); + CPPUNIT_ASSERT_EQUAL("BQIDAAABAgM="_ostr, aBuffer.toString()); aBuffer.setLength(0); inputSequence = { sal_Int8(sal_uInt8(200)), 31, 77, 111, 0, 1, 2, 3 }; comphelper::Base64::encode(aBuffer, inputSequence); - CPPUNIT_ASSERT_EQUAL(OString("yB9NbwABAgM="), aBuffer.makeStringAndClear()); + CPPUNIT_ASSERT_EQUAL("yB9NbwABAgM="_ostr, aBuffer.makeStringAndClear()); } CPPUNIT_TEST_SUITE_REGISTRATION(Base64Test); diff --git a/comphelper/qa/unit/propertyvalue.cxx b/comphelper/qa/unit/propertyvalue.cxx index 40f60bb0463d..4470b28f503a 100644 --- a/comphelper/qa/unit/propertyvalue.cxx +++ b/comphelper/qa/unit/propertyvalue.cxx @@ -14,9 +14,12 @@ #include <cppunit/extensions/HelperMacros.h> #include <comphelper/propertyvalue.hxx> +#include <comphelper/propertysequence.hxx> #include <cppu/unotype.hxx> #include <o3tl/any.hxx> +using namespace com::sun::star; + namespace { class MakePropertyValueTest : public CppUnit::TestFixture @@ -25,6 +28,7 @@ class MakePropertyValueTest : public CppUnit::TestFixture CPPUNIT_TEST(testLvalue); CPPUNIT_TEST(testRvalue); CPPUNIT_TEST(testBitField); + CPPUNIT_TEST(testJson); CPPUNIT_TEST_SUITE_END(); void testLvalue() @@ -52,6 +56,73 @@ class MakePropertyValueTest : public CppUnit::TestFixture CPPUNIT_ASSERT_EQUAL(cppu::UnoType<bool>::get(), v.Value.getValueType()); CPPUNIT_ASSERT_EQUAL(false, *o3tl::doAccess<bool>(v.Value)); } + + void testJson() + { + std::vector<beans::PropertyValue> aRet = comphelper::JsonToPropertyValues(R"json( +{ + "FieldType": { + "type": "string", + "value": "vnd.oasis.opendocument.field.UNHANDLED" + }, + "FieldCommandPrefix": { + "type": "string", + "value": "ADDIN ZOTERO_ITEM" + }, + "Fields": { + "type": "[][]com.sun.star.beans.PropertyValue", + "value": [ + { + "FieldType": { + "type": "string", + "value": "vnd.oasis.opendocument.field.UNHANDLED" + }, + "FieldCommand": { + "type": "string", + "value": "ADDIN ZOTERO_ITEM new command 1" + }, + "Fields": { + "type": "string", + "value": "new result 1" + } + }, + { + "FieldType": { + "type": "string", + "value": "vnd.oasis.opendocument.field.UNHANDLED" + }, + "FieldCommandPrefix": { + "type": "string", + "value": "ADDIN ZOTERO_ITEM new command 2" + }, + "Fields": { + "type": "string", + "value": "new result 2" + } + } + ] + } +} +)json"_ostr); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aRet.size()); + beans::PropertyValue aFirst = aRet[0]; + CPPUNIT_ASSERT_EQUAL(OUString("FieldType"), aFirst.Name); + CPPUNIT_ASSERT_EQUAL(OUString("vnd.oasis.opendocument.field.UNHANDLED"), + aFirst.Value.get<OUString>()); + beans::PropertyValue aSecond = aRet[1]; + CPPUNIT_ASSERT_EQUAL(OUString("FieldCommandPrefix"), aSecond.Name); + CPPUNIT_ASSERT_EQUAL(OUString("ADDIN ZOTERO_ITEM"), aSecond.Value.get<OUString>()); + beans::PropertyValue aThird = aRet[2]; + CPPUNIT_ASSERT_EQUAL(OUString("Fields"), aThird.Name); + uno::Sequence<uno::Sequence<beans::PropertyValue>> aSeqs; + aThird.Value >>= aSeqs; + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), aSeqs.getLength()); + uno::Sequence<beans::PropertyValue> aFirstSeq = aSeqs[0]; + CPPUNIT_ASSERT_EQUAL(OUString("FieldType"), aFirstSeq[0].Name); + CPPUNIT_ASSERT_EQUAL(OUString("FieldCommand"), aFirstSeq[1].Name); + CPPUNIT_ASSERT_EQUAL(OUString("ADDIN ZOTERO_ITEM new command 1"), + aFirstSeq[1].Value.get<OUString>()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(MakePropertyValueTest); diff --git a/comphelper/qa/unit/syntaxhighlighttest.cxx b/comphelper/qa/unit/syntaxhighlighttest.cxx index c28941339085..eab382b85a65 100644 --- a/comphelper/qa/unit/syntaxhighlighttest.cxx +++ b/comphelper/qa/unit/syntaxhighlighttest.cxx @@ -38,7 +38,7 @@ public: void SyntaxHighlightTest::testBasicString() { std::vector<HighlightPortion> ps; - SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions("\"foo\"", ps); + SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions(u"\"foo\"", ps); CPPUNIT_ASSERT_EQUAL( static_cast<std::vector<HighlightPortion>::size_type>(1), ps.size()); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), ps[0].nBegin); @@ -48,7 +48,7 @@ void SyntaxHighlightTest::testBasicString() { void SyntaxHighlightTest::testBasicComment() { std::vector<HighlightPortion> ps; - SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions("' foo", ps); + SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions(u"' foo", ps); CPPUNIT_ASSERT_EQUAL( static_cast<std::vector<HighlightPortion>::size_type>(1), ps.size()); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), ps[0].nBegin); @@ -58,7 +58,7 @@ void SyntaxHighlightTest::testBasicComment() { void SyntaxHighlightTest::testBasicCommentNewline() { std::vector<HighlightPortion> ps; - SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions("' foo\n", ps); + SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions(u"' foo\n", ps); CPPUNIT_ASSERT_EQUAL( static_cast<std::vector<HighlightPortion>::size_type>(2), ps.size()); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), ps[0].nBegin); @@ -71,7 +71,7 @@ void SyntaxHighlightTest::testBasicCommentNewline() { void SyntaxHighlightTest::testBasicEmptyComment() { std::vector<HighlightPortion> ps; - SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions("'", ps); + SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions(u"'", ps); CPPUNIT_ASSERT_EQUAL( static_cast<std::vector<HighlightPortion>::size_type>(1), ps.size()); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), ps[0].nBegin); @@ -81,7 +81,7 @@ void SyntaxHighlightTest::testBasicEmptyComment() { void SyntaxHighlightTest::testBasicEmptyCommentNewline() { std::vector<HighlightPortion> ps; - SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions("'\n", ps); + SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions(u"'\n", ps); CPPUNIT_ASSERT_EQUAL( static_cast<std::vector<HighlightPortion>::size_type>(2), ps.size()); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), ps[0].nBegin); diff --git a/comphelper/qa/unit/test_guards.cxx b/comphelper/qa/unit/test_guards.cxx index 02daffaa521b..83034a2dcc6a 100644 --- a/comphelper/qa/unit/test_guards.cxx +++ b/comphelper/qa/unit/test_guards.cxx @@ -10,42 +10,50 @@ #include <comphelper/flagguard.hxx> #include <unotest/bootstrapfixturebase.hxx> -CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, test_comphelperGuards) +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testScopeGuard) { + // Test that comphelper::ScopeGuard executes its parameter on destruction + + // initial value "true", out-of-scope ScopeGuard function executes and changes the value to "false" bool bFlag = true; { - // Test that comphelper::ScopeGuard executes its parameter on destruction comphelper::ScopeGuard aGuard([&bFlag] { bFlag = false; }); CPPUNIT_ASSERT(bFlag); } CPPUNIT_ASSERT(!bFlag); +} + +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testFlagGuard) +{ + // Test that comphelper::FlagGuard properly sets and resets the flag + // initial value "false", change to "true", out-of-scope change to "false" + bool bFlag = false; { - // Test that comphelper::FlagGuard properly sets and resets the flag comphelper::FlagGuard aGuard(bFlag); CPPUNIT_ASSERT(bFlag); } + // comphelper::FlagGuard must reset flag to false on destruction unconditionally CPPUNIT_ASSERT(!bFlag); + // initial value "true", retain the value at "true", out-of-scope change to "false" bFlag = true; { - // Test that comphelper::FlagGuard properly sets and resets the flag comphelper::FlagGuard aGuard(bFlag); CPPUNIT_ASSERT(bFlag); } // comphelper::FlagGuard must reset flag to false on destruction unconditionally CPPUNIT_ASSERT(!bFlag); +} - { - // Test that comphelper::FlagRestorationGuard properly sets and resets the flag - comphelper::FlagRestorationGuard aGuard(bFlag, true); - CPPUNIT_ASSERT(bFlag); - } - CPPUNIT_ASSERT(!bFlag); +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testFlagRestorationGuard) +{ + // Test that comphelper::FlagRestorationGuard properly sets and resets the flag - bFlag = true; + // initial value "true", change to "false", out-of-scope change to "true" + + bool bFlag = true; { - // Test that comphelper::FlagRestorationGuard properly sets and resets the flag comphelper::FlagRestorationGuard aGuard(bFlag, false); CPPUNIT_ASSERT(!bFlag); } @@ -53,4 +61,28 @@ CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, test_comphelperGuards) CPPUNIT_ASSERT(bFlag); } +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testValueRestorationGuard) +{ + // Test that comphelper::ValueRestorationGuard properly sets and resets the (int) value + + int value = 199; + + // set value and restore after scope ends + { + CPPUNIT_ASSERT_EQUAL(199, value); + comphelper::ValueRestorationGuard aGuard(value, 100); + CPPUNIT_ASSERT_EQUAL(100, value); + } + CPPUNIT_ASSERT_EQUAL(199, value); + + // set value, manually setto another value and restore after scope ends + { + CPPUNIT_ASSERT_EQUAL(199, value); + comphelper::ValueRestorationGuard aGuard(value, 100); + CPPUNIT_ASSERT_EQUAL(100, value); + value = 200; + } + CPPUNIT_ASSERT_EQUAL(199, value); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/unit/test_hash.cxx b/comphelper/qa/unit/test_hash.cxx index 0bcc3f8ed56c..64815ee56dc8 100644 --- a/comphelper/qa/unit/test_hash.cxx +++ b/comphelper/qa/unit/test_hash.cxx @@ -120,7 +120,7 @@ void TestHash::testSHA512_NoSaltNoSpin() // tdf#104250 https://bugs.documentfoundation.org/attachment.cgi?id=129104 void TestHash::testSHA512_saltspin() { - const OUString aHash = comphelper::DocPasswordHelper::GetOoxHashAsBase64( "pwd", "876MLoKTq42+/DLp415iZQ==", 100000, + const OUString aHash = comphelper::DocPasswordHelper::GetOoxHashAsBase64( "pwd", u"876MLoKTq42+/DLp415iZQ==", 100000, comphelper::Hash::IterCount::APPEND, u"SHA-512"); CPPUNIT_ASSERT_EQUAL(OUString("5l3mgNHXpWiFaBPv5Yso1Xd/UifWvQWmlDnl/hsCYbFT2sJCzorjRmBCQ/3qeDu6Q/4+GIE8a1DsdaTwYh1q2g=="), aHash); } diff --git a/comphelper/qa/unit/test_traceevent.cxx b/comphelper/qa/unit/test_traceevent.cxx index 46c1cef5be25..34d10f519d2b 100644 --- a/comphelper/qa/unit/test_traceevent.cxx +++ b/comphelper/qa/unit/test_traceevent.cxx @@ -31,8 +31,6 @@ namespace { void trace_event_test() { - std::shared_ptr<comphelper::AsyncEvent> pAsync7Locked; - { // When we start recording is off and this will not generate any 'X' event when we leave the scope comphelper::ProfileZone aZone0("test0"); diff --git a/comphelper/qa/unit/threadpooltest.cxx b/comphelper/qa/unit/threadpooltest.cxx index 14da59988ef4..13eaf210a18b 100644 --- a/comphelper/qa/unit/threadpooltest.cxx +++ b/comphelper/qa/unit/threadpooltest.cxx @@ -17,6 +17,7 @@ #include <stdlib.h> #include <atomic> +#include <cstddef> #include <thread> #include <mutex> @@ -42,7 +43,7 @@ void ThreadPoolTest::testPreferredConcurrency() { // Check default. auto nThreads = comphelper::ThreadPool::getPreferredConcurrency(); - sal_Int32 nExpected = 4; // UTs are capped to 4. + std::size_t nExpected = 4; // UTs are capped to 4. CPPUNIT_ASSERT_MESSAGE("Expected no more than 4 threads", nExpected >= nThreads); #ifndef _WIN32 @@ -51,7 +52,7 @@ void ThreadPoolTest::testPreferredConcurrency() setenv("MAX_CONCURRENCY", std::to_string(nThreads).c_str(), true); nThreads = comphelper::ThreadPool::getPreferredConcurrency(); CPPUNIT_ASSERT_MESSAGE("Expected no more than hardware threads", - nThreads <= static_cast<sal_Int32>(std::thread::hardware_concurrency())); + nThreads <= std::thread::hardware_concurrency()); // Revert and check. Again, nothing should change. unsetenv("MAX_CONCURRENCY"); diff --git a/comphelper/qa/unit/types_test.cxx b/comphelper/qa/unit/types_test.cxx index a0f136a5f49f..c69b07199127 100644 --- a/comphelper/qa/unit/types_test.cxx +++ b/comphelper/qa/unit/types_test.cxx @@ -42,7 +42,7 @@ public: void TypesTest::testGetINT64() { - CPPUNIT_ASSERT_EQUAL(sal_Int64(1337), ::comphelper::getINT64(uno::makeAny(sal_Int64(1337)))); + CPPUNIT_ASSERT_EQUAL(sal_Int64(1337), ::comphelper::getINT64(uno::Any(sal_Int64(1337)))); uno::Any aValue; CPPUNIT_ASSERT_EQUAL(sal_Int64(0), ::comphelper::getINT64(aValue)); @@ -50,7 +50,7 @@ void TypesTest::testGetINT64() void TypesTest::testGetINT32() { - CPPUNIT_ASSERT_EQUAL(sal_Int32(1337), ::comphelper::getINT32(uno::makeAny(sal_Int32(1337)))); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1337), ::comphelper::getINT32(uno::Any(sal_Int32(1337)))); uno::Any aValue; CPPUNIT_ASSERT_EQUAL(sal_Int32(0), ::comphelper::getINT32(aValue)); @@ -58,7 +58,7 @@ void TypesTest::testGetINT32() void TypesTest::testGetINT16() { - CPPUNIT_ASSERT_EQUAL(sal_Int16(1337), ::comphelper::getINT16(uno::makeAny(sal_Int16(1337)))); + CPPUNIT_ASSERT_EQUAL(sal_Int16(1337), ::comphelper::getINT16(uno::Any(sal_Int16(1337)))); uno::Any aValue; CPPUNIT_ASSERT_EQUAL(sal_Int16(0), ::comphelper::getINT16(aValue)); @@ -66,7 +66,7 @@ void TypesTest::testGetINT16() void TypesTest::testGetDouble() { - CPPUNIT_ASSERT_EQUAL(1337.1337, ::comphelper::getDouble(uno::makeAny(1337.1337))); + CPPUNIT_ASSERT_EQUAL(1337.1337, ::comphelper::getDouble(uno::Any(1337.1337))); uno::Any aValue; CPPUNIT_ASSERT_EQUAL(0.0, ::comphelper::getDouble(aValue)); @@ -75,7 +75,7 @@ void TypesTest::testGetDouble() void TypesTest::testGetFloat() { CPPUNIT_ASSERT_EQUAL(static_cast<float>(1337.0), - ::comphelper::getFloat(uno::makeAny(static_cast<float>(1337.0)))); + ::comphelper::getFloat(uno::Any(static_cast<float>(1337.0)))); uno::Any aValue; CPPUNIT_ASSERT_EQUAL(static_cast<float>(0.0), ::comphelper::getFloat(aValue)); @@ -83,7 +83,7 @@ void TypesTest::testGetFloat() void TypesTest::testGetString() { - CPPUNIT_ASSERT_EQUAL(OUString("1337"), ::comphelper::getString(uno::makeAny(OUString("1337")))); + CPPUNIT_ASSERT_EQUAL(OUString("1337"), ::comphelper::getString(uno::Any(OUString("1337")))); uno::Any aValue; CPPUNIT_ASSERT_EQUAL(OUString(""), ::comphelper::getString(aValue)); diff --git a/comphelper/qa/unit/variadictemplates.cxx b/comphelper/qa/unit/variadictemplates.cxx index e729d76b24ed..6b62204f487c 100644 --- a/comphelper/qa/unit/variadictemplates.cxx +++ b/comphelper/qa/unit/variadictemplates.cxx @@ -91,22 +91,22 @@ void VariadicTemplatesTest::testUnwrapArgs() { sal_Int32 tmp2 = 42; sal_uInt32 tmp3 = 42; ::com::sun::star::uno::Any tmp6( - ::com::sun::star::uno::makeAny( tmp1 ) + tmp1 ); ::com::sun::star::uno::Any tmp7( - ::com::sun::star::uno::makeAny( tmp2 ) + tmp2 ); ::com::sun::star::uno::Any tmp8( - ::com::sun::star::uno::makeAny( tmp3 ) + tmp3 ); ::com::sun::star::uno::Any tmp9( - ::com::sun::star::uno::makeAny( OUString("Test2") ) + OUString("Test2") ); ::std::optional< ::com::sun::star::uno::Any > tmp10( - ::com::sun::star::uno::makeAny( OUString("Test3") ) + OUString("Test3") ); ::std::optional< ::com::sun::star::uno::Any > tmp11( - ::com::sun::star::uno::makeAny( tmp1 ) + tmp1 ); // test equality with the baseline and template specialization with diff --git a/comphelper/qa/weakbag/makefile.mk b/comphelper/qa/weakbag/makefile.mk deleted file mode 100644 index 495c68f5063d..000000000000 --- a/comphelper/qa/weakbag/makefile.mk +++ /dev/null @@ -1,44 +0,0 @@ -# -# 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 . -# - -PRJ := ..$/.. -PRJNAME := comphelper -TARGET := qa_weakbag - -ENABLE_EXCEPTIONS := TRUE - -.INCLUDE: settings.mk -.INCLUDE : $(PRJ)$/version.mk - -CFLAGSCXX += $(CPPUNIT_CFLAGS) - -DLLPRE = # no leading "lib" on .so files - -INCPRE += $(MISC)$/$(TARGET)$/inc - -SHL1TARGET = $(TARGET)_weakbag -SHL1OBJS = $(SLO)$/test_weakbag.obj $(SLO)$/test_weakbag_noadditional.obj -SHL1STDLIBS = $(CPPUHELPERLIB) $(CPPULIB) $(CPPUNITLIB) $(SALLIB) $(COMPHELPERLIB) -SHL1VERSIONMAP = ..$/version.map -SHL1IMPLIB = i$(SHL1TARGET) -DEF1NAME = $(SHL1TARGET) - -SLOFILES = $(SHL1OBJS) - -.INCLUDE: target.mk -.INCLUDE: _cppunit.mk diff --git a/comphelper/qa/weakbag/test_weakbag.cxx b/comphelper/qa/weakbag/test_weakbag.cxx index b646ca7aef42..10e10cd7da85 100644 --- a/comphelper/qa/weakbag/test_weakbag.cxx +++ b/comphelper/qa/weakbag/test_weakbag.cxx @@ -28,7 +28,8 @@ namespace { -class Test : public CppUnit::TestFixture +// Tests the behaviour of comphelper::WeakBag +class WeakBagTest : public CppUnit::TestFixture { public: void test() @@ -36,7 +37,9 @@ public: css::uno::Reference<css::uno::XInterface> ref1(new cppu::OWeakObject); css::uno::Reference<css::uno::XInterface> ref2(new cppu::OWeakObject); css::uno::Reference<css::uno::XInterface> ref3(new cppu::OWeakObject); + comphelper::WeakBag<css::uno::XInterface> bag; + bag.add(ref1); bag.add(ref1); bag.add(ref2); @@ -44,18 +47,21 @@ public: ref1.clear(); bag.add(ref3); ref3.clear(); - CPPUNIT_ASSERT_MESSAGE("remove first ref2", bag.remove() == ref2); - CPPUNIT_ASSERT_MESSAGE("remove second ref2", bag.remove() == ref2); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("remove first ref2", bag.remove(), ref2); + CPPUNIT_ASSERT_EQUAL_MESSAGE("remove second ref2", bag.remove(), ref2); CPPUNIT_ASSERT_MESSAGE("remove first null", !bag.remove().is()); CPPUNIT_ASSERT_MESSAGE("remove second null", !bag.remove().is()); } - CPPUNIT_TEST_SUITE(Test); + CPPUNIT_TEST_SUITE(WeakBagTest); CPPUNIT_TEST(test); CPPUNIT_TEST_SUITE_END(); }; -CPPUNIT_TEST_SUITE_REGISTRATION(Test); +CPPUNIT_TEST_SUITE_REGISTRATION(WeakBagTest); } +CPPUNIT_PLUGIN_IMPLEMENT(); + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/weakbag/test_weakbag_noadditional.cxx b/comphelper/qa/weakbag/test_weakbag_noadditional.cxx deleted file mode 100644 index d2d66a61ea93..000000000000 --- a/comphelper/qa/weakbag/test_weakbag_noadditional.cxx +++ /dev/null @@ -1,25 +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 <sal/types.h> -#include <cppunit/plugin/TestPlugIn.h> - -CPPUNIT_PLUGIN_IMPLEMENT(); - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/container/IndexedPropertyValuesContainer.cxx b/comphelper/source/container/IndexedPropertyValuesContainer.cxx index c0086061b033..f5b7358d64c4 100644 --- a/comphelper/source/container/IndexedPropertyValuesContainer.cxx +++ b/comphelper/source/container/IndexedPropertyValuesContainer.cxx @@ -17,55 +17,19 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include <com/sun/star/container/XIndexContainer.hpp> -#include <com/sun/star/uno/Sequence.h> -#include <com/sun/star/beans/PropertyValue.hpp> -#include <cppuhelper/implbase.hxx> #include <com/sun/star/lang/IllegalArgumentException.hpp> #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> -#include <com/sun/star/lang/XServiceInfo.hpp> +#include <comphelper/indexedpropertyvalues.hxx> #include <cppuhelper/supportsservice.hxx> - -#include <vector> +#include <o3tl/safeint.hxx> namespace com::sun::star::uno { class XComponentContext; } using namespace com::sun::star; -typedef std::vector < uno::Sequence< beans::PropertyValue > > IndexedPropertyValues; - -namespace { - -class IndexedPropertyValuesContainer : public cppu::WeakImplHelper< container::XIndexContainer, lang::XServiceInfo > -{ -public: - IndexedPropertyValuesContainer() noexcept; - - // XIndexContainer - virtual void SAL_CALL insertByIndex( sal_Int32 nIndex, const css::uno::Any& aElement ) override; - virtual void SAL_CALL removeByIndex( sal_Int32 nIndex ) override; - - // XIndexReplace - virtual void SAL_CALL replaceByIndex( sal_Int32 nIndex, const css::uno::Any& aElement ) override; - // XIndexAccess - virtual sal_Int32 SAL_CALL getCount( ) override; - virtual css::uno::Any SAL_CALL getByIndex( sal_Int32 nIndex ) override; +namespace comphelper { - // XElementAccess - virtual css::uno::Type SAL_CALL getElementType( ) override; - virtual sal_Bool SAL_CALL hasElements( ) override; - - //XServiceInfo - virtual OUString SAL_CALL getImplementationName( ) override; - virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; - virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; - -private: - IndexedPropertyValues maProperties; -}; - -} IndexedPropertyValuesContainer::IndexedPropertyValuesContainer() noexcept { @@ -89,7 +53,7 @@ void SAL_CALL IndexedPropertyValuesContainer::insertByIndex( sal_Int32 nIndex, c void SAL_CALL IndexedPropertyValuesContainer::removeByIndex( sal_Int32 nIndex ) { - if ((nIndex >= sal_Int32(maProperties.size())) || (nIndex < 0)) + if ((nIndex < 0) || (o3tl::make_unsigned(nIndex) >= maProperties.size())) throw lang::IndexOutOfBoundsException(); maProperties.erase(maProperties.begin() + nIndex); @@ -150,12 +114,14 @@ css::uno::Sequence< OUString > SAL_CALL IndexedPropertyValuesContainer::getSuppo return { "com.sun.star.document.IndexedPropertyValues" }; } +} // namespace comphelper + extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * IndexedPropertyValuesContainer_get_implementation( css::uno::XComponentContext *, css::uno::Sequence<css::uno::Any> const &) { - return cppu::acquire(new IndexedPropertyValuesContainer()); + return cppu::acquire(new comphelper::IndexedPropertyValuesContainer()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/container/container.cxx b/comphelper/source/container/container.cxx index 1a6132e0d65a..7b2432723360 100644 --- a/comphelper/source/container/container.cxx +++ b/comphelper/source/container/container.cxx @@ -22,6 +22,7 @@ #include <com/sun/star/container/XChild.hpp> #include <comphelper/container.hxx> #include <o3tl/any.hxx> +#include <utility> #include <osl/diagnose.h> @@ -29,8 +30,8 @@ namespace comphelper { -IndexAccessIterator::IndexAccessIterator(css::uno::Reference< css::uno::XInterface> const & xStartingPoint) - :m_xStartingPoint(xStartingPoint) +IndexAccessIterator::IndexAccessIterator(css::uno::Reference< css::uno::XInterface> xStartingPoint) + :m_xStartingPoint(std::move(xStartingPoint)) { OSL_ENSURE(m_xStartingPoint.is(), "IndexAccessIterator::IndexAccessIterator : no starting point !"); } diff --git a/comphelper/source/container/embeddedobjectcontainer.cxx b/comphelper/source/container/embeddedobjectcontainer.cxx index ac85e9cfdc70..56b50c964823 100644 --- a/comphelper/source/container/embeddedobjectcontainer.cxx +++ b/comphelper/source/container/embeddedobjectcontainer.cxx @@ -46,6 +46,8 @@ #include <cppuhelper/weakref.hxx> #include <sal/log.hxx> +#include <officecfg/Office/Common.hxx> + #include <algorithm> #include <unordered_map> @@ -135,31 +137,31 @@ void EmbeddedObjectContainer::SwitchPersistence( const uno::Reference < embed::X bool EmbeddedObjectContainer::CommitImageSubStorage() { - if ( pImpl->mxImageStorage.is() ) + if ( !pImpl->mxImageStorage ) + return true; + + try { - try + bool bReadOnlyMode = true; + uno::Reference < beans::XPropertySet > xSet(pImpl->mxImageStorage,uno::UNO_QUERY); + if ( xSet.is() ) { - bool bReadOnlyMode = true; - uno::Reference < beans::XPropertySet > xSet(pImpl->mxImageStorage,uno::UNO_QUERY); - if ( xSet.is() ) - { - // get the open mode from the parent storage - sal_Int32 nMode = 0; - uno::Any aAny = xSet->getPropertyValue("OpenMode"); - if ( aAny >>= nMode ) - bReadOnlyMode = !(nMode & embed::ElementModes::WRITE ); - } // if ( xSet.is() ) - if ( !bReadOnlyMode ) - { - uno::Reference< embed::XTransactedObject > xTransact( pImpl->mxImageStorage, uno::UNO_QUERY_THROW ); - xTransact->commit(); - } - } - catch (const uno::Exception&) + // get the open mode from the parent storage + sal_Int32 nMode = 0; + uno::Any aAny = xSet->getPropertyValue("OpenMode"); + if ( aAny >>= nMode ) + bReadOnlyMode = !(nMode & embed::ElementModes::WRITE ); + } // if ( xSet.is() ) + if ( !bReadOnlyMode ) { - return false; + uno::Reference< embed::XTransactedObject > xTransact( pImpl->mxImageStorage, uno::UNO_QUERY_THROW ); + xTransact->commit(); } } + catch (const uno::Exception&) + { + return false; + } return true; } @@ -236,8 +238,7 @@ bool EmbeddedObjectContainer::HasEmbeddedObjects() const bool EmbeddedObjectContainer::HasEmbeddedObject( const OUString& rName ) { - auto aIt = pImpl->maNameToObjectMap.find( rName ); - if (aIt != pImpl->maNameToObjectMap.end()) + if (pImpl->maNameToObjectMap.contains(rName)) return true; if (!pImpl->mxStorage.is()) return false; @@ -246,7 +247,7 @@ bool EmbeddedObjectContainer::HasEmbeddedObject( const OUString& rName ) bool EmbeddedObjectContainer::HasEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj ) const { - return pImpl->maObjectToNameMap.find(xObj) != pImpl->maObjectToNameMap.end(); + return pImpl->maObjectToNameMap.contains(xObj); } bool EmbeddedObjectContainer::HasInstantiatedEmbeddedObject( const OUString& rName ) @@ -254,8 +255,7 @@ bool EmbeddedObjectContainer::HasInstantiatedEmbeddedObject( const OUString& rNa // allows to detect whether the object was already instantiated // currently the filter instantiate it on loading, so this method allows // to avoid objects pointing to the same persistence - auto aIt = pImpl->maNameToObjectMap.find( rName ); - return ( aIt != pImpl->maNameToObjectMap.end() ); + return pImpl->maNameToObjectMap.contains(rName); } OUString EmbeddedObjectContainer::GetEmbeddedObjectName( const css::uno::Reference < css::embed::XEmbeddedObject >& xObj ) const @@ -913,7 +913,7 @@ bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed // the media type will be provided with object insertion OUString aOrigStorMediaType; uno::Reference< beans::XPropertySet > xStorProps( pImpl->mxStorage, uno::UNO_QUERY_THROW ); - static constexpr OUStringLiteral s_sMediaType(u"MediaType"); + static constexpr OUString s_sMediaType(u"MediaType"_ustr); xStorProps->getPropertyValue( s_sMediaType ) >>= aOrigStorMediaType; SAL_WARN_IF( aOrigStorMediaType.isEmpty(), "comphelper.container", "No valuable media type in the storage!" ); @@ -969,26 +969,26 @@ bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed else SAL_WARN( "comphelper.container", "Object not found for removal!" ); - if ( xPersist.is() && bKeepToTempStorage ) // #i119941# - { - // remove replacement image (if there is one) - RemoveGraphicStream( aName ); + if ( !xPersist || !bKeepToTempStorage ) // #i119941# + return true; - // now it's time to remove the storage from the container storage - try - { + // remove replacement image (if there is one) + RemoveGraphicStream( aName ); + + // now it's time to remove the storage from the container storage + try + { #if OSL_DEBUG_LEVEL > 1 - // if the object has a persistence and the object is not a link than it must have persistence entry in storage - OSL_ENSURE( bIsNotEmbedded || pImpl->mxStorage->hasByName( aName ), "The object has no persistence entry in the storage!" ); + // if the object has a persistence and the object is not a link than it must have persistence entry in storage + OSL_ENSURE( bIsNotEmbedded || pImpl->mxStorage->hasByName( aName ), "The object has no persistence entry in the storage!" ); #endif - if ( xPersist.is() && pImpl->mxStorage->hasByName( aName ) ) - pImpl->mxStorage->removeElement( aName ); - } - catch (const uno::Exception&) - { - SAL_WARN( "comphelper.container", "Failed to remove object from storage!" ); - return false; - } + if ( xPersist.is() && pImpl->mxStorage->hasByName( aName ) ) + pImpl->mxStorage->removeElement( aName ); + } + catch (const uno::Exception&) + { + SAL_WARN( "comphelper.container", "Failed to remove object from storage!" ); + return false; } return true; @@ -1158,18 +1158,16 @@ namespace { } -bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEmbedded,const uno::Reference < embed::XStorage >& _xStorage) +bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEmbedded, bool _bAutoSaveEvent, + const uno::Reference < embed::XStorage >& _xStorage) { bool bResult = false; try { comphelper::EmbeddedObjectContainer aCnt( _xStorage ); - const uno::Sequence < OUString > aNames = GetObjectNames(); - const OUString* pIter = aNames.getConstArray(); - const OUString* pEnd = pIter + aNames.getLength(); - for(;pIter != pEnd;++pIter) + for (auto& name : GetObjectNames()) { - uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter ); + uno::Reference<embed::XEmbeddedObject> xObj = GetEmbeddedObject(name); SAL_WARN_IF( !xObj.is(), "comphelper.container", "An empty entry in the embedded objects list!" ); if ( xObj.is() ) { @@ -1208,13 +1206,13 @@ bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEm { // if it is an embedded object or the optimized inserting fails the normal inserting should be done if ( _bCreateEmbedded - || !aCnt.InsertGraphicStreamDirectly( xStream, *pIter, aMediaType ) ) - aCnt.InsertGraphicStream( xStream, *pIter, aMediaType ); + || !aCnt.InsertGraphicStreamDirectly(xStream, name, aMediaType)) + aCnt.InsertGraphicStream(xStream, name, aMediaType); } else { // it is a linked object exported into SO7 format - InsertStreamIntoPicturesStorage_Impl( _xStorage, xStream, *pIter ); + InsertStreamIntoPicturesStorage_Impl(_xStorage, xStream, name); } } } @@ -1222,7 +1220,7 @@ bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEm uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); if ( xPersist.is() ) { - uno::Sequence< beans::PropertyValue > aArgs( _bOasisFormat ? 2 : 3 ); + uno::Sequence< beans::PropertyValue > aArgs( _bOasisFormat ? 3 : 4 ); auto pArgs = aArgs.getArray(); pArgs[0].Name = "StoreVisualReplacement"; pArgs[0].Value <<= !_bOasisFormat; @@ -1230,11 +1228,15 @@ bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEm // if it is an embedded object or the optimized inserting fails the normal inserting should be done pArgs[1].Name = "CanTryOptimization"; pArgs[1].Value <<= !_bCreateEmbedded; + + pArgs[2].Name = "AutoSaveEvent"; + pArgs[2].Value <<= _bAutoSaveEvent; + if ( !_bOasisFormat ) { // if object has no cached replacement it will use this one - pArgs[2].Name = "VisualReplacement"; - pArgs[2].Value <<= xStream; + pArgs[3].Name = "VisualReplacement"; + pArgs[3].Value <<= xStream; } try @@ -1243,7 +1245,7 @@ bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEm } catch (const embed::WrongStateException&) { - SAL_WARN("comphelper.container", "failed to store '" << *pIter << "'"); + SAL_WARN("comphelper.container", "failed to store '" << name << "'"); } } @@ -1285,14 +1287,11 @@ bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEm bool EmbeddedObjectContainer::StoreChildren(bool _bOasisFormat,bool _bObjectsOnly) { bool bResult = true; - const uno::Sequence < OUString > aNames = GetObjectNames(); - const OUString* pIter = aNames.getConstArray(); - const OUString* pEnd = pIter + aNames.getLength(); - for(;pIter != pEnd;++pIter) + for (auto& name : GetObjectNames()) { try { - uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter ); + uno::Reference<embed::XEmbeddedObject> xObj = GetEmbeddedObject(name); SAL_WARN_IF( !xObj.is(), "comphelper.container", "An empty entry in the embedded objects list!" ); if ( xObj.is() ) { @@ -1311,8 +1310,8 @@ bool EmbeddedObjectContainer::StoreChildren(bool _bOasisFormat,bool _bObjectsOnl &aMediaType ); if ( xStream.is() ) { - if ( !InsertGraphicStreamDirectly( xStream, *pIter, aMediaType ) ) - InsertGraphicStream( xStream, *pIter, aMediaType ); + if (!InsertGraphicStreamDirectly(xStream, name, aMediaType)) + InsertGraphicStream(xStream, name, aMediaType); } } @@ -1336,7 +1335,7 @@ bool EmbeddedObjectContainer::StoreChildren(bool _bOasisFormat,bool _bObjectsOnl // '_bObjectsOnly' mean we are storing to alien formats. // 'isStorageElement' mean current object is NOT a MS OLE format. (may also include in future), i120168 if (_bObjectsOnly && (nCurState == embed::EmbedStates::LOADED || nCurState == embed::EmbedStates::RUNNING) - && (pImpl->mxStorage->isStorageElement( *pIter ) )) + && (pImpl->mxStorage->isStorageElement(name))) { uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY ); if ( xModifiable.is() && xModifiable->isModified()) @@ -1373,7 +1372,7 @@ bool EmbeddedObjectContainer::StoreChildren(bool _bOasisFormat,bool _bObjectsOnl OUString aMediaType; uno::Reference < io::XInputStream > xInStream = GetGraphicStream( xObj, &aMediaType ); if ( xInStream.is() ) - InsertStreamIntoPicturesStorage_Impl( pImpl->mxStorage, xInStream, *pIter ); + InsertStreamIntoPicturesStorage_Impl( pImpl->mxStorage, xInStream, name ); } } catch (const uno::Exception&) @@ -1439,12 +1438,9 @@ uno::Reference< io::XInputStream > EmbeddedObjectContainer::GetGraphicReplacemen bool EmbeddedObjectContainer::SetPersistentEntries(const uno::Reference< embed::XStorage >& _xStorage,bool _bClearModifiedFlag) { bool bError = false; - const uno::Sequence < OUString > aNames = GetObjectNames(); - const OUString* pIter = aNames.getConstArray(); - const OUString* pEnd = pIter + aNames.getLength(); - for(;pIter != pEnd;++pIter) + for (auto& name : GetObjectNames()) { - uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter ); + uno::Reference<embed::XEmbeddedObject> xObj = GetEmbeddedObject(name); SAL_WARN_IF( !xObj.is(), "comphelper.container", "An empty entry in the embedded objects list!" ); if ( xObj.is() ) { @@ -1454,7 +1450,7 @@ bool EmbeddedObjectContainer::SetPersistentEntries(const uno::Reference< embed:: try { xPersist->setPersistentEntry( _xStorage, - *pIter, + name, embed::EntryInitModes::NO_INIT, uno::Sequence< beans::PropertyValue >(), uno::Sequence< beans::PropertyValue >() ); @@ -1487,6 +1483,8 @@ bool EmbeddedObjectContainer::SetPersistentEntries(const uno::Reference< embed:: bool EmbeddedObjectContainer::getUserAllowsLinkUpdate() const { + if (officecfg::Office::Common::Security::Scripting::DisableActiveContent::get()) + return false; return pImpl->mbUserAllowsLinkUpdate; } diff --git a/comphelper/source/container/enumerablemap.cxx b/comphelper/source/container/enumerablemap.cxx index 6ca7c36d2d25..031bd86c3aee 100644 --- a/comphelper/source/container/enumerablemap.cxx +++ b/comphelper/source/container/enumerablemap.cxx @@ -31,7 +31,7 @@ #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/uno/XComponentContext.hpp> -#include <cppuhelper/compbase3.hxx> +#include <cppuhelper/compbase.hxx> #include <cppuhelper/implbase.hxx> #include <cppuhelper/supportsservice.hxx> #include <typelib/typedescription.hxx> @@ -143,7 +143,7 @@ namespace comphelper // EnumerableMap - typedef ::cppu::WeakAggComponentImplHelper3 < XInitialization + typedef ::cppu::WeakComponentImplHelper < XInitialization , XEnumerableMap , XServiceInfo > Map_IFace; @@ -372,12 +372,10 @@ namespace comphelper if (!m_aData.m_pValues || !m_aData.m_pValues->empty()) throw RuntimeException(); - const Pair< Any, Any >* mapping = _initialValues.getConstArray(); - const Pair< Any, Any >* mappingEnd = mapping + _initialValues.getLength(); - for ( ; mapping != mappingEnd; ++mapping ) + for (auto& mapping : _initialValues) { - impl_checkValue_throw( mapping->Second ); - (*m_aData.m_pValues)[ mapping->First ] = mapping->Second; + impl_checkValue_throw(mapping.Second); + (*m_aData.m_pValues)[mapping.First] = mapping.Second; } } diff --git a/comphelper/source/container/enumhelper.cxx b/comphelper/source/container/enumhelper.cxx index 2487d3adf234..3390fef86444 100644 --- a/comphelper/source/container/enumhelper.cxx +++ b/comphelper/source/container/enumhelper.cxx @@ -21,13 +21,14 @@ #include <com/sun/star/lang/XComponent.hpp> #include <com/sun/star/container/XIndexAccess.hpp> #include <com/sun/star/container/XNameAccess.hpp> +#include <utility> namespace comphelper { -OEnumerationByName::OEnumerationByName(const css::uno::Reference<css::container::XNameAccess>& _rxAccess) - :m_aNames(_rxAccess->getElementNames()) - ,m_xAccess(_rxAccess) +OEnumerationByName::OEnumerationByName(css::uno::Reference<css::container::XNameAccess> _xAccess) + :m_aNames(_xAccess->getElementNames()) + ,m_xAccess(_xAccess) ,m_nPos(0) ,m_bListening(false) { @@ -35,17 +36,16 @@ OEnumerationByName::OEnumerationByName(const css::uno::Reference<css::container: } -OEnumerationByName::OEnumerationByName(const css::uno::Reference<css::container::XNameAccess>& _rxAccess, - const css::uno::Sequence< OUString >& _aNames ) - :m_aNames(_aNames) - ,m_xAccess(_rxAccess) +OEnumerationByName::OEnumerationByName(css::uno::Reference<css::container::XNameAccess> _xAccess, + std::vector<OUString> _aNames ) + :m_aNames(std::move(_aNames)) + ,m_xAccess(std::move(_xAccess)) ,m_nPos(0) ,m_bListening(false) { impl_startDisposeListening(); } - OEnumerationByName::~OEnumerationByName() { std::lock_guard aLock(m_aLock); @@ -58,7 +58,7 @@ sal_Bool SAL_CALL OEnumerationByName::hasMoreElements( ) { std::lock_guard aLock(m_aLock); - if (m_xAccess.is() && m_aNames.getLength() > m_nPos) + if (m_xAccess.is() && getLength() > m_nPos) return true; if (m_xAccess.is()) @@ -76,10 +76,10 @@ css::uno::Any SAL_CALL OEnumerationByName::nextElement( ) std::lock_guard aLock(m_aLock); css::uno::Any aRes; - if (m_xAccess.is() && m_nPos < m_aNames.getLength()) - aRes = m_xAccess->getByName(m_aNames.getConstArray()[m_nPos++]); + if (m_xAccess.is() && m_nPos < getLength()) + aRes = m_xAccess->getByName(getElement(m_nPos++)); - if (m_xAccess.is() && m_nPos >= m_aNames.getLength()) + if (m_xAccess.is() && m_nPos >= getLength()) { impl_stopDisposeListening(); m_xAccess.clear(); @@ -91,7 +91,6 @@ css::uno::Any SAL_CALL OEnumerationByName::nextElement( ) return aRes; } - void SAL_CALL OEnumerationByName::disposing(const css::lang::EventObject& aEvent) { std::lock_guard aLock(m_aLock); @@ -132,8 +131,25 @@ void OEnumerationByName::impl_stopDisposeListening() osl_atomic_decrement(&m_refCount); } -OEnumerationByIndex::OEnumerationByIndex(const css::uno::Reference< css::container::XIndexAccess >& _rxAccess) - :m_xAccess(_rxAccess) +sal_Int32 OEnumerationByName::getLength() const +{ + if (m_aNames.index() == 0) + return std::get<css::uno::Sequence<OUString>>(m_aNames).getLength(); + else + return std::get<std::vector<OUString>>(m_aNames).size(); +} + +const OUString& OEnumerationByName::getElement(sal_Int32 nIndex) const +{ + if (m_aNames.index() == 0) + return std::get<css::uno::Sequence<OUString>>(m_aNames)[nIndex]; + else + return std::get<std::vector<OUString>>(m_aNames)[nIndex]; +} + + +OEnumerationByIndex::OEnumerationByIndex(css::uno::Reference< css::container::XIndexAccess > _xAccess) + :m_xAccess(std::move(_xAccess)) ,m_nPos(0) ,m_bListening(false) { diff --git a/comphelper/source/container/interfacecontainer2.cxx b/comphelper/source/container/interfacecontainer2.cxx index 0881ccbe44cf..a2e2119be0d2 100644 --- a/comphelper/source/container/interfacecontainer2.cxx +++ b/comphelper/source/container/interfacecontainer2.cxx @@ -21,6 +21,7 @@ #include <comphelper/interfacecontainer2.hxx> #include <comphelper/multicontainer2.hxx> +#include <o3tl/safeint.hxx> #include <osl/diagnose.h> #include <osl/mutex.hxx> @@ -103,7 +104,7 @@ void OInterfaceIteratorHelper2::remove() if( bIsList ) { OSL_ASSERT( nRemain >= 0 && - nRemain < static_cast<sal_Int32>(aData.pAsVector->size()) ); + o3tl::make_unsigned(nRemain) < aData.pAsVector->size() ); rCont.removeInterface( (*aData.pAsVector)[nRemain] ); } else @@ -171,6 +172,9 @@ void OInterfaceContainerHelper2::copyAndResetInUse() sal_Int32 OInterfaceContainerHelper2::addInterface( const Reference<XInterface> & rListener ) { OSL_ASSERT( rListener.is() ); + if ( !rListener.is() ) + return 0; + MutexGuard aGuard( rMutex ); if( bInUse ) copyAndResetInUse(); @@ -244,14 +248,10 @@ Reference<XInterface> OInterfaceContainerHelper2::getInterface( sal_Int32 nIndex { MutexGuard aGuard( rMutex ); - if( bIsList ) + if (bIsList) return (*aData.pAsVector)[nIndex]; - else if( aData.pAsInterface ) - { - if (nIndex == 0) - return aData.pAsInterface; - } - throw std::out_of_range("index out of range"); + assert(aData.pAsInterface && nIndex == 0); + return aData.pAsInterface; } void OInterfaceContainerHelper2::disposeAndClear( const EventObject & rEvt ) diff --git a/comphelper/source/container/namecontainer.cxx b/comphelper/source/container/namecontainer.cxx index c13ee7486e80..cfa958a0272b 100644 --- a/comphelper/source/container/namecontainer.cxx +++ b/comphelper/source/container/namecontainer.cxx @@ -66,7 +66,6 @@ namespace comphelper } using namespace ::comphelper; -using namespace ::osl; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::container; using namespace ::com::sun::star::lang; diff --git a/comphelper/source/eventattachermgr/eventattachermgr.cxx b/comphelper/source/eventattachermgr/eventattachermgr.cxx index 35e90a8379b0..af2c7bbc3edb 100644 --- a/comphelper/source/eventattachermgr/eventattachermgr.cxx +++ b/comphelper/source/eventattachermgr/eventattachermgr.cxx @@ -21,7 +21,6 @@ #include <o3tl/any.hxx> #include <o3tl/safeint.hxx> -#include <osl/mutex.hxx> #include <osl/diagnose.h> #include <comphelper/eventattachermgr.hxx> #include <comphelper/sequence.hxx> @@ -42,13 +41,15 @@ #include <com/sun/star/script/XEventAttacherManager.hpp> #include <com/sun/star/script/XScriptListener.hpp> #include <cppuhelper/weak.hxx> -#include <comphelper/interfacecontainer3.hxx> +#include <comphelper/interfacecontainer4.hxx> #include <cppuhelper/exc_hlp.hxx> #include <cppuhelper/implbase.hxx> #include <rtl/ref.hxx> #include <deque> +#include <mutex> #include <algorithm> +#include <utility> using namespace com::sun::star::uno; using namespace com::sun::star::io; @@ -57,7 +58,6 @@ using namespace com::sun::star::beans; using namespace com::sun::star::script; using namespace com::sun::star::reflection; using namespace cppu; -using namespace osl; namespace comphelper @@ -84,9 +84,9 @@ class ImplEventAttacherManager { friend class AttacherAllListener_Impl; std::deque< AttacherIndex_Impl > aIndex; - Mutex aLock; + std::mutex m_aMutex; // Container for the ScriptListener - OInterfaceContainerHelper3<XScriptListener> aScriptListeners; + OInterfaceContainerHelper4<XScriptListener> aScriptListeners; // Instance of EventAttacher Reference< XEventAttacher2 > xAttacher; Reference< XComponentContext > mxContext; @@ -116,8 +116,14 @@ public: virtual void SAL_CALL read(const Reference< XObjectInputStream >& InStream) override; private: + void registerScriptEvent(std::unique_lock<std::mutex>&, sal_Int32 Index, const ScriptEventDescriptor& ScriptEvent); + void registerScriptEvents(std::unique_lock<std::mutex>&, sal_Int32 Index, const Sequence< ScriptEventDescriptor >& ScriptEvents); + void attach(std::unique_lock<std::mutex>&, sal_Int32 Index, const Reference< XInterface >& Object, const Any& Helper); + void detach(std::unique_lock<std::mutex>&, sal_Int32 nIndex, const Reference< XInterface >& xObject); + void insertEntry(std::unique_lock<std::mutex>&, sal_Int32 Index); + /// @throws Exception - Reference< XIdlReflection > getReflection(); + Reference< XIdlReflection > getReflection(std::unique_lock<std::mutex>&); /** checks if <arg>_nIndex</arg> is a valid index, throws an <type>IllegalArgumentException</type> if not @param _nIndex @@ -140,8 +146,8 @@ class AttacherAllListener_Impl : public WeakImplHelper< XAllListener > /// @throws CannotConvertException void convertToEventReturn( Any & rRet, const Type & rRetType ); public: - AttacherAllListener_Impl( ImplEventAttacherManager* pManager_, const OUString &rScriptType_, - const OUString & rScriptCode_ ); + AttacherAllListener_Impl( ImplEventAttacherManager* pManager_, OUString aScriptType_, + OUString aScriptCode_ ); // Methods of XAllListener virtual void SAL_CALL firing(const AllEventObject& Event) override; @@ -156,12 +162,12 @@ public: AttacherAllListener_Impl::AttacherAllListener_Impl ( ImplEventAttacherManager* pManager_, - const OUString & rScriptType_, - const OUString & rScriptCode_ + OUString aScriptType_, + OUString aScriptCode_ ) : mxManager( pManager_ ) - , aScriptType( rScriptType_ ) - , aScriptCode( rScriptCode_ ) + , aScriptType(std::move( aScriptType_ )) + , aScriptCode(std::move( aScriptCode_ )) { } @@ -179,9 +185,8 @@ void SAL_CALL AttacherAllListener_Impl::firing(const AllEventObject& Event) aScriptEvent.ScriptCode = aScriptCode; // Iterate over all listeners and pass events. - OInterfaceIteratorHelper3 aIt( mxManager->aScriptListeners ); - while( aIt.hasMoreElements() ) - aIt.next()->firing( aScriptEvent ); + std::unique_lock l(mxManager->m_aMutex); + mxManager->aScriptListeners.notifyEach( l, &XScriptListener::firing, aScriptEvent ); } @@ -242,13 +247,17 @@ Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Even Any aRet; // Iterate over all listeners and pass events. - OInterfaceIteratorHelper3 aIt( mxManager->aScriptListeners ); + std::unique_lock l(mxManager->m_aMutex); + OInterfaceIteratorHelper4 aIt( l, mxManager->aScriptListeners ); while( aIt.hasMoreElements() ) { + // cannot hold lock over call to approveFiring, since it might recurse back into us + l.unlock(); aRet = aIt.next()->approveFiring( aScriptEvent ); + l.lock(); try { - Reference< XIdlClass > xListenerType = mxManager->getReflection()-> + Reference< XIdlClass > xListenerType = mxManager->getReflection(l)-> forName( Event.ListenerType.getTypeName() ); Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName ); if( xMeth.is() ) @@ -299,7 +308,7 @@ Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Even catch (const CannotConvertException&) { // silent ignore conversions errors from a script call - Reference< XIdlClass > xListenerType = mxManager->getReflection()-> + Reference< XIdlClass > xListenerType = mxManager->getReflection(l)-> forName( Event.ListenerType.getTypeName() ); Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName ); if( xMeth.is() ) @@ -340,8 +349,7 @@ Reference< XEventAttacherManager > createEventAttacherManager( const Reference< ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospection > & rIntrospection, const Reference< XComponentContext >& rContext ) - : aScriptListeners( aLock ) - , mxContext( rContext ) + : mxContext( rContext ) , nVersion(0) { if ( rContext.is() ) @@ -362,9 +370,8 @@ ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospect } } -Reference< XIdlReflection > ImplEventAttacherManager::getReflection() +Reference< XIdlReflection > ImplEventAttacherManager::getReflection(std::unique_lock<std::mutex>&) { - Guard< Mutex > aGuard( aLock ); // Do we already have a service? If not, create one. if( !mxCoreReflection.is() ) { @@ -390,8 +397,17 @@ void SAL_CALL ImplEventAttacherManager::registerScriptEvent const ScriptEventDescriptor& ScriptEvent ) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); + registerScriptEvent(l, nIndex, ScriptEvent); +} +void ImplEventAttacherManager::registerScriptEvent +( + std::unique_lock<std::mutex>&, + sal_Int32 nIndex, + const ScriptEventDescriptor& ScriptEvent +) +{ // Examine the index and apply the array std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); @@ -425,20 +441,28 @@ void SAL_CALL ImplEventAttacherManager::registerScriptEvents const Sequence< ScriptEventDescriptor >& ScriptEvents ) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); + registerScriptEvents(l, nIndex, ScriptEvents); +} +void ImplEventAttacherManager::registerScriptEvents +( + std::unique_lock<std::mutex>& l, + sal_Int32 nIndex, + const Sequence< ScriptEventDescriptor >& ScriptEvents +) +{ // Examine the index and apply the array std::deque< AttachedObject_Impl > aList = implCheckIndex( nIndex )->aObjList; for( const auto& rObj : aList ) - detach( nIndex, rObj.xTarget ); + detach( l, nIndex, rObj.xTarget ); - const ScriptEventDescriptor* pArray = ScriptEvents.getConstArray(); sal_Int32 nLen = ScriptEvents.getLength(); for( sal_Int32 i = 0 ; i < nLen ; i++ ) - registerScriptEvent( nIndex, pArray[ i ] ); + registerScriptEvent(l, nIndex, ScriptEvents[i]); for( const auto& rObj : aList ) - attach( nIndex, rObj.xTarget, rObj.aHelper ); + attach( l, nIndex, rObj.xTarget, rObj.aHelper ); } @@ -450,18 +474,18 @@ void SAL_CALL ImplEventAttacherManager::revokeScriptEvent const OUString& ToRemoveListenerParam ) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); std::deque< AttachedObject_Impl > aList = aIt->aObjList; for( const auto& rObj : aList ) - detach( nIndex, rObj.xTarget ); + detach( l, nIndex, rObj.xTarget ); - OUString aLstType = ListenerType; - sal_Int32 nLastDot = aLstType.lastIndexOf('.'); - if (nLastDot != -1) - aLstType = aLstType.copy(nLastDot+1); + std::u16string_view aLstType = ListenerType; + size_t nLastDot = aLstType.rfind('.'); + if (nLastDot != std::u16string_view::npos) + aLstType = aLstType.substr(nLastDot+1); auto aEvtIt = std::find_if(aIt->aEventList.begin(), aIt->aEventList.end(), [&aLstType, &EventMethod, &ToRemoveListenerParam](const ScriptEventDescriptor& rEvent) { @@ -473,30 +497,35 @@ void SAL_CALL ImplEventAttacherManager::revokeScriptEvent aIt->aEventList.erase( aEvtIt ); for( const auto& rObj : aList ) - attach( nIndex, rObj.xTarget, rObj.aHelper ); + attach( l, nIndex, rObj.xTarget, rObj.aHelper ); } void SAL_CALL ImplEventAttacherManager::revokeScriptEvents(sal_Int32 nIndex ) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); std::deque< AttachedObject_Impl > aList = aIt->aObjList; for( const auto& rObj : aList ) - detach( nIndex, rObj.xTarget ); + detach( l, nIndex, rObj.xTarget ); aIt->aEventList.clear(); for( const auto& rObj : aList ) - attach( nIndex, rObj.xTarget, rObj.aHelper ); + attach( l, nIndex, rObj.xTarget, rObj.aHelper ); } void SAL_CALL ImplEventAttacherManager::insertEntry(sal_Int32 nIndex) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); if( nIndex < 0 ) throw IllegalArgumentException("negative index", static_cast<cppu::OWeakObject*>(this), 1); + insertEntry(l, nIndex); +} + +void ImplEventAttacherManager::insertEntry(std::unique_lock<std::mutex>&, sal_Int32 nIndex) +{ if ( o3tl::make_unsigned(nIndex) >= aIndex.size() ) aIndex.resize(nIndex+1); @@ -504,15 +533,14 @@ void SAL_CALL ImplEventAttacherManager::insertEntry(sal_Int32 nIndex) aIndex.insert( aIndex.begin() + nIndex, aTmp ); } - void SAL_CALL ImplEventAttacherManager::removeEntry(sal_Int32 nIndex) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); std::deque< AttachedObject_Impl > aList = aIt->aObjList; for( const auto& rObj : aList ) - detach( nIndex, rObj.xTarget ); + detach( l, nIndex, rObj.xTarget ); aIndex.erase( aIt ); } @@ -520,7 +548,7 @@ void SAL_CALL ImplEventAttacherManager::removeEntry(sal_Int32 nIndex) Sequence< ScriptEventDescriptor > SAL_CALL ImplEventAttacherManager::getScriptEvents(sal_Int32 nIndex) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); return comphelper::containerToSequence(aIt->aEventList); } @@ -528,17 +556,21 @@ Sequence< ScriptEventDescriptor > SAL_CALL ImplEventAttacherManager::getScriptEv void SAL_CALL ImplEventAttacherManager::attach(sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); if( nIndex < 0 || !xObject.is() ) throw IllegalArgumentException("negative index, or null object", static_cast<cppu::OWeakObject*>(this), -1); + attach(l, nIndex, xObject, Helper); +} +void ImplEventAttacherManager::attach(std::unique_lock<std::mutex>& l, sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper) +{ if( o3tl::make_unsigned(nIndex) >= aIndex.size() ) { // read older files if( nVersion != 1 ) throw IllegalArgumentException(); - insertEntry( nIndex ); - attach( nIndex, xObject, Helper ); + insertEntry( l, nIndex ); + attach( l, nIndex, xObject, Helper ); return; } @@ -584,11 +616,15 @@ void SAL_CALL ImplEventAttacherManager::attach(sal_Int32 nIndex, const Reference void SAL_CALL ImplEventAttacherManager::detach(sal_Int32 nIndex, const Reference< XInterface >& xObject) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); //return; if( nIndex < 0 || o3tl::make_unsigned(nIndex) >= aIndex.size() || !xObject.is() ) throw IllegalArgumentException("bad index or null object", static_cast<cppu::OWeakObject*>(this), 1); + detach(l, nIndex, xObject); +} +void ImplEventAttacherManager::detach(std::unique_lock<std::mutex>&, sal_Int32 nIndex, const Reference< XInterface >& xObject) +{ std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex; auto aObjIt = std::find_if(aCurrentPosition->aObjList.begin(), aCurrentPosition->aObjList.end(), [&xObject](const AttachedObject_Impl& rObj) { return rObj.xTarget == xObject; }); @@ -616,14 +652,14 @@ void SAL_CALL ImplEventAttacherManager::detach(sal_Int32 nIndex, const Reference void SAL_CALL ImplEventAttacherManager::addScriptListener(const Reference< XScriptListener >& aListener) { - Guard< Mutex > aGuard( aLock ); - aScriptListeners.addInterface( aListener ); + std::unique_lock l(m_aMutex); + aScriptListeners.addInterface( l, aListener ); } void SAL_CALL ImplEventAttacherManager::removeScriptListener(const Reference< XScriptListener >& aListener) { - Guard< Mutex > aGuard( aLock ); - aScriptListeners.removeInterface( aListener ); + std::unique_lock l(m_aMutex); + aScriptListeners.removeInterface( l, aListener ); } @@ -635,7 +671,7 @@ OUString SAL_CALL ImplEventAttacherManager::getServiceName() void SAL_CALL ImplEventAttacherManager::write(const Reference< XObjectOutputStream >& OutStream) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); // Don't run without XMarkableStream Reference< XMarkableStream > xMarkStream( OutStream, UNO_QUERY ); if( !xMarkStream.is() ) @@ -674,7 +710,7 @@ void SAL_CALL ImplEventAttacherManager::write(const Reference< XObjectOutputStre void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream >& InStream) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); // Don't run without XMarkableStream Reference< XMarkableStream > xMarkStream( InStream, UNO_QUERY ); if( !xMarkStream.is() ) @@ -695,7 +731,7 @@ void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream for( sal_Int32 i = 0 ; i < nItemCount ; i++ ) { - insertEntry( i ); + insertEntry( l, i ); // Read the length of the sequence sal_Int32 nSeqLen = InStream->readLong(); @@ -711,7 +747,7 @@ void SAL_CALL ImplEventAttacherManager::read(const Reference< XObjectInputStream rDesc.ScriptType = InStream->readUTF(); rDesc.ScriptCode = InStream->readUTF(); } - registerScriptEvents( i, aSEDSeq ); + registerScriptEvents( l, i, aSEDSeq ); } // Have we read the specified length? diff --git a/comphelper/source/misc/AccessibleImplementationHelper.cxx b/comphelper/source/misc/AccessibleImplementationHelper.cxx index a45b6e5f3cd7..a02f4380dd33 100644 --- a/comphelper/source/misc/AccessibleImplementationHelper.cxx +++ b/comphelper/source/misc/AccessibleImplementationHelper.cxx @@ -33,8 +33,7 @@ OUString GetkeyBindingStrByXkeyBinding(const Sequence<KeyStroke>& keySet) OUStringBuffer buf; for (const auto& k : keySet) { - buf.append('\n'); - buf.append(k.KeyChar); + buf.append("\n" + OUStringChar(k.KeyChar)); } return buf.makeStringAndClear(); } diff --git a/comphelper/source/misc/DirectoryHelper.cxx b/comphelper/source/misc/DirectoryHelper.cxx index 248e7af185b7..badfe9b62d80 100644 --- a/comphelper/source/misc/DirectoryHelper.cxx +++ b/comphelper/source/misc/DirectoryHelper.cxx @@ -19,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); } } @@ -210,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 ad2c63b1a1c0..000000000000 --- a/comphelper/source/misc/accessiblecontexthelper.cxx +++ /dev/null @@ -1,248 +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; - - OAccessibleContextHelper::OAccessibleContextHelper( ) - :OAccessibleContextHelper_Base( GetMutex() ) - ,m_nClientId( 0 ) - { - } - - - 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_nClientId ) - { - AccessibleEventNotifier::revokeClientNotifyDisposing( m_nClientId, *this ); - m_nClientId=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_nClientId ) - m_nClientId = AccessibleEventNotifier::registerClient( ); - - AccessibleEventNotifier::addEventListener( m_nClientId, _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_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 OAccessibleContextHelper::NotifyAccessibleEvent( const sal_Int16 _nEventId, - const Any& _rOldValue, const Any& _rNewValue ) - { - 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; - aEvent.Source = *this; - aEvent.EventId = _nEventId; - aEvent.OldValue = _rOldValue; - aEvent.NewValue = _rNewValue; - - // let the notifier handle this event - AccessibleEventNotifier::addEvent( m_nClientId, 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_aCreator = _rxAccessible; - } - - - Reference< XAccessible > OAccessibleContextHelper::getAccessibleCreator( ) const - { - return m_aCreator; - } - - - 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_aCreator); - - 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 c1e26c35bdd9..9c3b55126bc6 100644 --- a/comphelper/source/misc/accessibleeventnotifier.cxx +++ b/comphelper/source/misc/accessibleeventnotifier.cxx @@ -21,9 +21,10 @@ #include <com/sun/star/accessibility/XAccessibleEventListener.hpp> #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,7 +37,7 @@ typedef std::pair< AccessibleEventNotifier::TClientId, AccessibleEventObject > ClientEvent; typedef ::comphelper::OInterfaceContainerHelper4<XAccessibleEventListener> ListenerContainer; -typedef std::map< AccessibleEventNotifier::TClientId, ListenerContainer* > ClientMap; +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, @@ -154,10 +155,8 @@ AccessibleEventNotifier::TClientId AccessibleEventNotifier::registerClient() // generate a new client id TClientId nNewClientId = generateId( ); - // the event listeners for the new client - ListenerContainer * pNewListeners = new ListenerContainer(); // add the client - gaClients.emplace( nNewClientId, pNewListeners ); + gaClients.emplace( nNewClientId, ListenerContainer{} ); // outta here return nNewClientId; @@ -173,7 +172,6 @@ void AccessibleEventNotifier::revokeClient( const TClientId _nClient ) return; // remove it from the clients map - delete aClientPos->second; gaClients.erase( aClientPos ); releaseId(_nClient); } @@ -189,7 +187,7 @@ void AccessibleEventNotifier::revokeClientNotifyDisposing( return; // notify the listeners - std::unique_ptr<ListenerContainer> pListeners(aClientPos->second); + 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 @@ -203,13 +201,13 @@ void AccessibleEventNotifier::revokeClientNotifyDisposing( aDisposalEvent.Source = _rxEventSource; // now really do the notification - pListeners->disposeAndClear( aGuard, aDisposalEvent ); + aListeners.disposeAndClear( aGuard, aDisposalEvent ); } sal_Int32 AccessibleEventNotifier::addEventListener( const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) { - std::scoped_lock aGuard( GetLocalMutex() ); + std::unique_lock aGuard( GetLocalMutex() ); ClientMap::iterator aClientPos; if ( !implLookupClient( _nClient, aClientPos ) ) @@ -217,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 ) { - std::scoped_lock aGuard( GetLocalMutex() ); + std::unique_lock aGuard( GetLocalMutex() ); ClientMap::iterator aClientPos; if ( !implLookupClient( _nClient, aClientPos ) ) @@ -233,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< XAccessibleEventListener > > aListeners; - - { - std::scoped_lock aGuard( GetLocalMutex() ); - - ClientMap::iterator aClientPos; - if ( !implLookupClient( _nClient, aClientPos ) ) - // already asserted in implLookupClient - return; + std::unique_lock aGuard( GetLocalMutex() ); - // 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 { - rListener->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 @@ -269,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 cf16f157c5e3..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 @@ -83,7 +84,7 @@ namespace comphelper { 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 9aa1b48e2f1e..3e356f434faa 100644 --- a/comphelper/source/misc/accessiblewrapper.cxx +++ b/comphelper/source/misc/accessiblewrapper.cxx @@ -79,14 +79,14 @@ namespace comphelper xComp->removeEventListener( this ); } // clear the map - AccessibleMap().swap(m_aChildrenMap); + m_aChildrenMap.clear(); } Reference< XAccessible > OWrappedAccessibleChildrenManager::getAccessibleWrapperFor( const Reference< XAccessible >& _rxKey ) { - Reference< XAccessible > xValue; + rtl::Reference< OAccessibleWrapper > xValue; if( !_rxKey.is() ) { @@ -140,14 +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().swap(m_aChildrenMap); + m_aChildrenMap.clear(); } @@ -345,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 ); } @@ -389,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 ); @@ -417,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 ) @@ -495,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 ); } @@ -513,7 +512,7 @@ namespace comphelper } - sal_Int32 SAL_CALL OAccessibleContextWrapper::getAccessibleIndexInParent( ) + sal_Int64 SAL_CALL OAccessibleContextWrapper::getAccessibleIndexInParent( ) { return m_xInnerContext->getAccessibleIndexInParent(); } @@ -543,7 +542,7 @@ namespace comphelper } - Reference< XAccessibleStateSet > SAL_CALL OAccessibleContextWrapper::getAccessibleStateSet( ) + sal_Int64 SAL_CALL OAccessibleContextWrapper::getAccessibleStateSet( ) { return m_xInnerContext->getAccessibleStateSet(); } @@ -586,7 +585,7 @@ namespace comphelper } - void SAL_CALL OAccessibleContextWrapper::disposing() + void OAccessibleContextWrapper::implDisposing(const css::lang::EventObject* pEvent) { AccessibleEventNotifier::TClientId nClientId( 0 ); @@ -604,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/anycompare.cxx b/comphelper/source/misc/anycompare.cxx index d802024e7502..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,56 +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); - case TypeClass_BYTE: - return ScalarPredicateLess< sal_Int8 >().isLess(lhs, rhs); - case TypeClass_SHORT: - return ScalarPredicateLess< sal_Int16 >().isLess(lhs, rhs); - case TypeClass_UNSIGNED_SHORT: - return ScalarPredicateLess< sal_uInt16 >().isLess(lhs, rhs); - case TypeClass_LONG: - return ScalarPredicateLess< sal_Int32 >().isLess(lhs, rhs); - case TypeClass_UNSIGNED_LONG: - return ScalarPredicateLess< sal_uInt32 >().isLess(lhs, rhs); - case TypeClass_HYPER: - return ScalarPredicateLess< sal_Int64 >().isLess(lhs, rhs); - case TypeClass_UNSIGNED_HYPER: - return ScalarPredicateLess< sal_uInt64 >().isLess(lhs, rhs); - case TypeClass_FLOAT: - return ScalarPredicateLess< float >().isLess(lhs, rhs); - case TypeClass_DOUBLE: - return ScalarPredicateLess< double >().isLess(lhs, rhs); - case TypeClass_STRING: - return StringPredicateLess().isLess(lhs, rhs); - case TypeClass_TYPE: - return TypePredicateLess().isLess(lhs, rhs); - case TypeClass_ENUM: - return EnumPredicateLess( lhs.getValueType() ).isLess(lhs, rhs); - case TypeClass_INTERFACE: - return InterfacePredicateLess().isLess(lhs, rhs); - 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 4e068cec9acd..ebc338b0b4be 100644 --- a/comphelper/source/misc/anytostring.cxx +++ b/comphelper/source/misc/anytostring.cxx @@ -20,10 +20,14 @@ #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 { @@ -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 e2c5691899d3..72c6414e7281 100644 --- a/comphelper/source/misc/asyncnotification.cxx +++ b/comphelper/source/misc/asyncnotification.cxx @@ -18,9 +18,9 @@ */ #include <comphelper/asyncnotification.hxx> +#include <comphelper/scopeguard.hxx> #include <mutex> #include <condition_variable> -#include <osl/mutex.hxx> #include <cassert> #include <stdexcept> @@ -91,7 +91,7 @@ namespace comphelper 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 ) ); } @@ -231,16 +231,20 @@ namespace comphelper { // see salhelper::Thread::launch xThis->m_xImpl->pKeepThisAlive = xThis; + 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 + comphelper::ScopeGuard g([this] { onTerminated(); }); setName(m_xImpl->name); execute(); + g.dismiss(); } void AsyncEventNotifierAutoJoin::onTerminated() diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx index d03662381939..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> @@ -222,8 +222,8 @@ namespace { } - ExtensionInfoEntry(const OString& rName, bool bEnabled) - : maName(rName), + ExtensionInfoEntry(OString aName, bool bEnabled) + : maName(std::move(aName)), maRepository(USER), mbEnabled(bEnabled) { @@ -354,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 { @@ -411,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) { @@ -629,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 @@ -637,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)) @@ -664,8 +661,8 @@ namespace const ExtensionInfoEntryVector& rToBeEnabled, const ExtensionInfoEntryVector& rToBeDisabled) { - static const OUStringLiteral aRegPathFront(u"/uno_packages/cache/registry/com.sun.star.comp.deployment."); - static const OUStringLiteral aRegPathBack(u".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); @@ -806,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()); - z_stream zstream; - memset(&zstream, 0, sizeof(zstream)); + if (!maFile || osl::File::E_None != maFile->open(osl_File_OpenFlag_Read)) + return false; - if (Z_OK == deflateInit(&zstream, 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, 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, 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); + deflateEnd(&zstream); #else - z_deflateEnd(&zstream); + z_deflateEnd(&zstream); #endif - } } + } - maFile->close(); - - // get compressed size and add to entry - if (mnFullFileSize == mnPackFileSize && mnFullFileSize == zstream.total_in) - { - mnPackFileSize = zstream.total_out; - } + maFile->close(); - 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()); - z_stream zstream; - memset(&zstream, 0, sizeof(zstream)); + if (!maFile || osl::File::E_None != maFile->open(osl_File_OpenFlag_Read)) + return false; + + 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)) + 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, Z_NO_FLUSH)); + const sal_Int64 nRetval(inflate(&zstream, Z_NO_FLUSH)); #else - const sal_Int64 nRetval(z_inflate(&zstream, 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); + deflateEnd(&zstream); #else - z_deflateEnd(&zstream); + z_deflateEnd(&zstream); #endif - } } - - maFile->close(); - return (0 == nSize); } - return false; + maFile->close(); + return (0 == nSize); } @@ -1005,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) { } @@ -1253,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 @@ -1421,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) @@ -1478,7 +1467,7 @@ namespace comphelper // points to registrymodifications.xcu OUString conf("${CONFIGURATION_LAYERS}"); rtl::Bootstrap::expandMacros(conf); - static const OUStringLiteral aTokenUser(u"user:"); + static constexpr OUString aTokenUser(u"user:"_ustr); sal_Int32 nStart(conf.indexOf(aTokenUser)); if (-1 != nStart) @@ -1523,7 +1512,7 @@ namespace comphelper const OUString& BackupFileHelper::getSafeModeName() { - static const OUString aSafeMode("SafeMode"); + static constexpr OUString aSafeMode(u"SafeMode"_ustr); return aSafeMode; } @@ -1931,9 +1920,7 @@ namespace comphelper 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"); - aUrl >>= aTempURL; + aTempURL = xTempFile->getUri(); } // copy back file @@ -2227,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 /////////////////////// @@ -2319,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 (!aToBeDisabled.empty() || !aToBeEnabled.empty()) + if (nullptr != pLoadedInfo) + { + // loaded info contains information about the Extension rCurrentInfo + const bool bCurrentEnabled(rCurrentInfo.isEnabled()); + const bool bLoadedEnabled(pLoadedInfo->isEnabled()); + + 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 67009cd9f864..b7d97bbb6533 100644 --- a/comphelper/source/misc/configuration.cxx +++ b/comphelper/source/misc/configuration.cxx @@ -38,12 +38,6 @@ namespace com::sun::star::uno { class XComponentContext; } namespace { -comphelper::detail::ConfigurationWrapper& GetTheConfigurationWrapper(const css::uno::Reference< css::uno::XComponentContext >& xContext) -{ - static comphelper::detail::ConfigurationWrapper WRAPPER(xContext); - return WRAPPER; -} - 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 GetTheConfigurationWrapper(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 GetTheConfigurationWrapper(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,18 +125,21 @@ 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 { + // 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.lastIndexOf("/"); + sal_Int32 idx = path.rfind('/'); assert(idx!=-1); - OUString parentPath = path.copy(0, idx); - OUString childName = path.copy(idx+1); + OUString parentPath(path.substr(0, idx)); + OUString childName(path.substr(idx+1)); std::scoped_lock aGuard(gMutex); @@ -252,6 +250,7 @@ void comphelper::ConfigurationListener::dispose() listener->dispose(); } maListeners.clear(); + mxConfig.clear(); mbDisposed = true; } @@ -284,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/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 71f92db48d00..76008b508c68 100644 --- a/comphelper/source/misc/docpasswordhelper.cxx +++ b/comphelper/source/misc/docpasswordhelper.cxx @@ -51,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; @@ -111,22 +110,82 @@ DocPasswordHelper::GenerateNewModifyPasswordInfoOOXML(std::u16string_view aPassw { uno::Sequence<beans::PropertyValue> aResult; - uno::Sequence<sal_Int8> aSalt = GenerateRandomByteSequence(16); - OUStringBuffer aBuffer; - comphelper::Base64::encode(aBuffer, aSalt); - OUString sSalt = aBuffer.toString(); + 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; +} - sal_Int32 const nIterationCount = 100000; - OUString sAlgorithm("SHA-512"); - const OUString sHash(GetOoxHashAsBase64(OUString(aPassword), sSalt, nIterationCount, - comphelper::Hash::IterCount::APPEND, sAlgorithm)); +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 (!sHash.isEmpty()) + 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", nIterationCount), + comphelper::makePropertyValue("iteration-count", nCount), comphelper::makePropertyValue("hash", sHash) }; } @@ -194,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 @@ -233,7 +292,7 @@ sal_uInt32 DocPasswordHelper::GetWordHashAsUINT32( }; sal_uInt32 nResult = 0; - sal_uInt32 nLen = aUString.getLength(); + size_t nLen = aUString.size(); if ( nLen ) { @@ -243,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 @@ -314,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") @@ -327,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); @@ -347,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) @@ -366,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 ); } @@ -562,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 @@ -614,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()), diff --git a/comphelper/source/misc/documentinfo.cxx b/comphelper/source/misc/documentinfo.cxx index 0a1c04347c84..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; 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 4448c832971f..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> @@ -53,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), @@ -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 28d655223062..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" @@ -73,7 +73,6 @@ void SAL_CALL OInstanceLocker::dispose() lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) ); m_aListenersContainer.disposeAndClear( aGuard, aSource ); - aGuard.lock(); if ( m_xLockListener.is() ) { auto tmp = std::move(m_xLockListener); @@ -88,18 +87,18 @@ void SAL_CALL OInstanceLocker::dispose() void SAL_CALL OInstanceLocker::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) { - std::scoped_lock aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); // TODO - m_aListenersContainer.addInterface( xListener ); + m_aListenersContainer.addInterface( aGuard, xListener ); } void SAL_CALL OInstanceLocker::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) { - std::scoped_lock aGuard( m_aMutex ); - m_aListenersContainer.removeInterface( xListener ); + std::unique_lock aGuard( m_aMutex ); + m_aListenersContainer.removeInterface( aGuard, xListener ); } // XInitialization @@ -190,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 ) @@ -217,6 +216,7 @@ void OLockListener::Dispose() return; auto xInstance = std::move(m_xInstance); + auto xApproval = std::move(m_xApproval); auto nMode = m_nMode; m_bDisposed = true; aGuard.unlock(); diff --git a/comphelper/source/misc/instancelocker.hxx b/comphelper/source/misc/instancelocker.hxx index c5420b6ff931..6a050c7f437c 100644 --- a/comphelper/source/misc/instancelocker.hxx +++ b/comphelper/source/misc/instancelocker.hxx @@ -28,7 +28,6 @@ #include <cppuhelper/weakref.hxx> #include <cppuhelper/implbase.hxx> #include <rtl/ref.hxx> -#include <memory> #include <mutex> namespace com::sun::star::embed { class XActionsApproval; } @@ -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 e1fd64d9b04b..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,14 +31,14 @@ 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, + OInteractionRequest::OInteractionRequest(Any aRequestDescription, std::vector<Reference<XInteractionContinuation>>&& rContinuations) - : m_aRequest(rRequestDescription) + : 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 b656389def83..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; @@ -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 45037f862bd7..c042b0c626e5 100644 --- a/comphelper/source/misc/lok.cxx +++ b/comphelper/source/misc/lok.cxx @@ -8,9 +8,9 @@ */ #include <comphelper/lok.hxx> +#include <osl/process.h> #include <i18nlangtag/languagetag.hxx> #include <sal/log.hxx> -#include <algorithm> #include <iostream> @@ -19,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); @@ -98,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; @@ -182,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); @@ -230,7 +244,7 @@ bool isAllowlistedLanguage(const OUString& lang) continue; std::cerr << s << " "; - aList.emplace_back(OStringToOUString(s.c_str(), RTL_TEXTENCODING_UTF8)); + aList.emplace_back(OStringToOUString(s, RTL_TEXTENCODING_UTF8)); } std::cerr << std::endl; } @@ -256,6 +270,24 @@ bool isAllowlistedLanguage(const OUString& lang) #endif } +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); diff --git a/comphelper/source/misc/mimeconfighelper.cxx b/comphelper/source/misc/mimeconfighelper.cxx index 4bc4410c225c..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"); } @@ -81,18 +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++] ); @@ -114,12 +115,6 @@ uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassIDRepresentat } -uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetConfigurationByPath( const OUString& aPath ) -{ - std::unique_lock aGuard( m_aMutex ); - return GetConfigurationByPathImpl(aPath); -} - uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetConfigurationByPathImpl( const OUString& aPath ) { uno::Reference< container::XNameAccess > xConfig; @@ -208,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; } @@ -239,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" @@ -273,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; @@ -316,12 +315,12 @@ uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjPropsFromConfi { 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], aVerbDescriptorsRange[nVerbI] ) ) - throw uno::RuntimeException(); + throw uno::RuntimeException("Failed to get verb descriptor by shortcut"); pResult[nInd+1].Value <<= aVerbDescriptors; } @@ -566,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; @@ -582,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; @@ -605,7 +604,7 @@ 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 ) ) { @@ -629,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; @@ -730,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 @@ -745,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 } diff --git a/comphelper/source/misc/namedvaluecollection.cxx b/comphelper/source/misc/namedvaluecollection.cxx index c56e6979a3a0..11ef15b30854 100644 --- a/comphelper/source/misc/namedvaluecollection.cxx +++ b/comphelper/source/misc/namedvaluecollection.cxx @@ -179,33 +179,76 @@ 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; } + // static + const css::uno::Any& NamedValueCollection::get( const css::uno::Sequence<css::beans::PropertyValue>& rPropSeq, + std::u16string_view _rValueName ) + { + 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 Any theEmptyDefault; + static const Any theEmptyDefault; auto pos = maValues.find( _rValueName ); if ( pos != maValues.end() ) return pos->second; diff --git a/comphelper/source/misc/numberedcollection.cxx b/comphelper/source/misc/numberedcollection.cxx index 0a771a333251..9dec18e66a06 100644 --- a/comphelper/source/misc/numberedcollection.cxx +++ b/comphelper/source/misc/numberedcollection.cxx @@ -24,11 +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 () { } @@ -41,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; @@ -52,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; @@ -63,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); @@ -98,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; @@ -135,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); @@ -157,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; @@ -179,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 ad6e308d2819..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; 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/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 48c99598fac5..8cd77af7d693 100644 --- a/comphelper/source/misc/simplefileaccessinteraction.cxx +++ b/comphelper/source/misc/simplefileaccessinteraction.cxx @@ -32,38 +32,26 @@ 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(std::move(lInterceptions)); 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 d9333f389166..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; diff --git a/comphelper/source/misc/storagehelper.cxx b/comphelper/source/misc/storagehelper.cxx index 13e9eb3aa288..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,6 +46,8 @@ #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> @@ -56,6 +56,7 @@ #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> @@ -172,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 ); } @@ -360,21 +372,19 @@ 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()); ++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, @@ -431,7 +441,10 @@ 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); @@ -457,13 +470,18 @@ 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(); @@ -485,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); @@ -527,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 '?': @@ -553,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; } } @@ -561,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; } @@ -606,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( @@ -630,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; @@ -640,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 a3ee9bc58521..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> @@ -61,16 +66,43 @@ namespace return rIn.substr(i); } + template <typename T, typename C> T tmpl_stripStartString(const T &rIn, + const C cRemove) + { + if (rIn.isEmpty()) + return rIn; + + sal_Int32 i = 0; + + while (i < rIn.getLength()) + { + if (rIn[i] != cRemove) + break; + ++i; + } + + return rIn.copy(i); + } +} + +OString stripStart(const OString& rIn, char c) +{ + return tmpl_stripStartString<OString, char>(rIn, c); } -OString stripStart(std::string_view rIn, char c) +std::string_view stripStart(std::string_view rIn, char c) { - return OString(tmpl_stripStart<std::string_view, char>(rIn, c)); + return tmpl_stripStart<std::string_view, char>(rIn, c); } -OUString stripStart(std::u16string_view rIn, sal_Unicode c) +OUString stripStart(const OUString& rIn, sal_Unicode c) { - return OUString(tmpl_stripStart<std::u16string_view, sal_Unicode>(rIn, 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 @@ -92,28 +124,114 @@ namespace return rIn.substr(0, i); } + template <typename T, typename C> T tmpl_stripEndString(const T &rIn, + const C cRemove) + { + if (rIn.isEmpty()) + return rIn; + + sal_Int32 i = rIn.getLength(); + + while (i > 0) + { + if (rIn[i-1] != cRemove) + break; + --i; + } + + return rIn.copy(0, i); + } } -OString stripEnd(std::string_view rIn, char c) +OString stripEnd(const OString& rIn, char c) { - return OString(tmpl_stripEnd<std::string_view, char>(rIn, c)); + return tmpl_stripEndString<OString, char>(rIn, c); } -OUString stripEnd(std::u16string_view rIn, sal_Unicode c) +std::string_view stripEnd(std::string_view rIn, char c) { - return OUString(tmpl_stripEnd<std::u16string_view, sal_Unicode>(rIn, c)); + return tmpl_stripEnd<std::string_view, char>(rIn, c); } -OString strip(std::string_view rIn, char c) +OUString stripEnd(const OUString& rIn, sal_Unicode c) { - auto x = tmpl_stripStart<std::string_view, char>(rIn, c); - return stripEnd(x, c); + return tmpl_stripEndString<OUString, sal_Unicode>(rIn, c); } -OUString strip(std::u16string_view rIn, sal_Unicode c) +std::u16string_view stripEnd(std::u16string_view rIn, sal_Unicode c) { - auto x = tmpl_stripStart<std::u16string_view, sal_Unicode>(rIn, c); - return stripEnd(x, 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_stripString<OString, char>(rIn, c); +} + +std::string_view strip(std::string_view rIn, char c) +{ + return tmpl_strip<std::string_view, char>(rIn, c); +} + +OUString strip(const OUString& rIn, sal_Unicode c) +{ + return tmpl_stripString<OUString, sal_Unicode>(rIn, c); +} + +std::u16string_view strip(std::u16string_view rIn, sal_Unicode c) +{ + return tmpl_strip<std::u16string_view, sal_Unicode>(rIn, c); } namespace @@ -145,13 +263,12 @@ sal_Int32 getTokenCount(std::u16string_view rIn, sal_Unicode 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; @@ -242,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 @@ -262,27 +373,26 @@ 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); @@ -312,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) @@ -350,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) { @@ -365,7 +492,7 @@ 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); @@ -386,29 +513,25 @@ bool isdigitAsciiString(std::u16string_view rString) [](sal_Unicode c){ return rtl::isAsciiDigit(c); }); } -namespace -{ - template <typename T, typename I, typename O> T tmpl_reverseString(I rIn) - { - if (rIn.empty()) - return T(); - - typename I::size_type i = rIn.size(); - O sBuf(static_cast<sal_Int32>(i)); - while (i) - sBuf.append(rIn[--i]); - return sBuf.makeStringAndClear(); - } -} - OUString reverseString(std::u16string_view rStr) { - return tmpl_reverseString<OUString, std::u16string_view, 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(std::string_view rStr) -{ - return tmpl_reverseString<OString, std::string_view, 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(std::u16string_view rIn, @@ -494,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 48ff4af2d7c6..f0a71eb05168 100644 --- a/comphelper/source/misc/threadpool.cxx +++ b/comphelper/source/misc/threadpool.cxx @@ -11,6 +11,7 @@ #include <com/sun/star/uno/Exception.hpp> #include <config_options.h> +#include <o3tl/safeint.hxx> #include <sal/config.h> #include <sal/log.hxx> #include <salhelper/thread.hxx> @@ -18,7 +19,9 @@ #include <memory> #include <thread> #include <chrono> +#include <cstddef> #include <comphelper/debuggerinfo.hxx> +#include <utility> #if defined HAVE_VALGRIND_HEADERS #include <valgrind/memcheck.h> @@ -90,7 +93,7 @@ public: } }; -ThreadPool::ThreadPool(sal_Int32 nWorkers) +ThreadPool::ThreadPool(std::size_t nWorkers) : mbTerminate(true) , mnMaxWorkers(nWorkers) , mnBusyWorkers(0) @@ -115,7 +118,7 @@ std::shared_ptr< ThreadPool >& GetStaticThreadPool() static std::shared_ptr< ThreadPool > POOL = []() { - const sal_Int32 nThreads = ThreadPool::getPreferredConcurrency(); + const std::size_t nThreads = ThreadPool::getPreferredConcurrency(); return std::make_shared< ThreadPool >( nThreads ); }(); return POOL; @@ -128,21 +131,22 @@ ThreadPool& ThreadPool::getSharedOptimalPool() 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; @@ -304,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 index 8b1a9c09427a..1296404ebd32 100644 --- a/comphelper/source/misc/traceevent.cxx +++ b/comphelper/source/misc/traceevent.cxx @@ -10,8 +10,8 @@ #include <sal/config.h> #include <atomic> +#include <mutex> #include <iostream> -#include <string_view> #include <comphelper/profilezone.hxx> #include <comphelper/sequence.hxx> @@ -35,20 +35,21 @@ static thread_local int nProfileZoneNesting = 0; // Level of Nested Profile Zone namespace { std::vector<OUString> g_aRecording; // recorded data -osl::Mutex g_aMutex; +std::mutex g_aMutex; } void TraceEvent::addRecording(const OUString& sObject) { - osl::MutexGuard aGuard(g_aMutex); + bool bEmitCallback; + { + std::lock_guard aGuard(g_aMutex); - g_aRecording.emplace_back(sObject); + g_aRecording.emplace_back(sObject); - if (s_nBufferSize > 0 && g_aRecording.size() >= s_nBufferSize) - { - if (s_pBufferFullCallback != nullptr) - (*s_pBufferFullCallback)(); + 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) @@ -77,7 +78,7 @@ void TraceEvent::addInstantEvent(const char* sName, const std::map<OUString, OUS void TraceEvent::startRecording() { - osl::MutexGuard aGuard(g_aMutex); + std::lock_guard aGuard(g_aMutex); s_bRecording = true; } @@ -94,7 +95,7 @@ std::vector<OUString> TraceEvent::getEventVectorAndClear() bool bRecording; std::vector<OUString> aRecording; { - osl::MutexGuard aGuard(g_aMutex); + std::lock_guard aGuard(g_aMutex); bRecording = s_bRecording; stopRecording(); aRecording.swap(g_aRecording); diff --git a/comphelper/source/misc/accimplaccess.cxx b/comphelper/source/misc/typedescriptionref.hxx index be8065725636..f4580cb2e4cb 100644 --- a/comphelper/source/misc/accimplaccess.cxx +++ b/comphelper/source/misc/typedescriptionref.hxx @@ -17,40 +17,35 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include <comphelper/accimplaccess.hxx> -#include <comphelper/servicehelper.hxx> +#pragma once -#include <string.h> +#include <typelib/typedescription.h> - -namespace comphelper +namespace comphelper::detail { - - - using ::com::sun::star::uno::Sequence; - - OAccessibleImplementationAccess::OAccessibleImplementationAccess( ) - { - } - - - OAccessibleImplementationAccess::~OAccessibleImplementationAccess( ) - { - } - - Sequence<sal_Int8> OAccessibleImplementationAccess::getUnoTunnelId() +// 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 +{ +public: + TypeDescriptionRef(typelib_TypeDescriptionReference* typeDef) { - static const comphelper::UnoIdInit implID; - return implID.getSeq(); + TYPELIB_DANGER_GET(&typeDescr, typeDef); } - - - sal_Int64 SAL_CALL OAccessibleImplementationAccess::getSomething( const Sequence< sal_Int8 >& _rIdentifier ) + ~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 comphelper::getSomethingImpl(_rIdentifier, this); + return typeDescr && other.typeDescr + && typelib_typedescription_equals(typeDescr, other.typeDescr); } -} // namespace comphelper +private: + typelib_TypeDescription* typeDescr = nullptr; +}; +} // namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/weak.cxx b/comphelper/source/misc/weak.cxx deleted file mode 100644 index 02cf40e2b646..000000000000 --- a/comphelper/source/misc/weak.cxx +++ /dev/null @@ -1,57 +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/weak.hxx> - -using namespace com::sun::star::uno; -using namespace com::sun::star::lang; - -namespace comphelper -{ - -OWeakTypeObject::OWeakTypeObject() -{ -} - -OWeakTypeObject::~OWeakTypeObject() -{ -} - -Any SAL_CALL OWeakTypeObject::queryInterface(const Type & rType ) -{ - 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 >(); -} - -} - -/* 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 bc2cb280a710..e69f734b2b8b 100644 --- a/comphelper/source/misc/xmlsechelper.cxx +++ b/comphelper/source/misc/xmlsechelper.cxx @@ -21,6 +21,7 @@ #include <rtl/ustrbuf.hxx> #include <osl/diagnose.h> +#include <o3tl/string_view.hxx> #include <utility> #include <vector> @@ -48,7 +49,7 @@ 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. */ - std::pair< OUString, OUString> GetDNForCertDetailsView( const OUString & rRawString) + std::pair< OUString, OUString> GetDNForCertDetailsView( std::u16string_view rRawString) { std::vector< std::pair< OUString, OUString > > vecAttrValueOfDN = parseDN(rRawString); OUStringBuffer s1, s2; @@ -72,18 +73,18 @@ namespace comphelper::xmlsec they are escaped with a double quote. This function removes the escape characters. */ #ifdef _WIN32 -std::vector< std::pair< OUString, OUString> > parseDN(const OUString& rRawString) +std::vector< std::pair< OUString, OUString> > parseDN(std::u16string_view rRawString) { 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]; @@ -91,8 +92,8 @@ std::vector< std::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 @@ -128,9 +129,9 @@ std::vector< std::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(std::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; @@ -151,13 +152,13 @@ std::vector< std::pair< OUString, OUString> > parseDN(const OUString& rRawString } if (sbufValue.getLength()) { - OSL_ASSERT(!sType.isEmpty()); - retVal.push_back(std::make_pair(sType, sbufValue.makeStringAndClear())); + OSL_ASSERT(!sType.empty()); + retVal.emplace_back(OUString(sType), sbufValue.makeStringAndClear()); } return retVal; } #else -std::vector< std::pair< OUString, OUString> > parseDN(const OUString& rRawString) +std::vector< std::pair< OUString, OUString> > parseDN(std::u16string_view rRawString) { std::vector< std::pair<OUString, OUString> > retVal; //bInEscape == true means that the preceding character is an escape character @@ -165,11 +166,11 @@ std::vector< std::pair< OUString, OUString> > parseDN(const OUString& rRawString 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]; @@ -177,8 +178,8 @@ std::vector< std::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 @@ -223,9 +224,9 @@ std::vector< std::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; @@ -249,7 +250,7 @@ std::vector< std::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; @@ -283,18 +284,14 @@ std::vector< std::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; diff --git a/comphelper/source/officeinstdir/officeinstallationdirectories.cxx b/comphelper/source/officeinstdir/officeinstallationdirectories.cxx index 385f61680e1c..010655964dcc 100644 --- a/comphelper/source/officeinstdir/officeinstallationdirectories.cxx +++ b/comphelper/source/officeinstdir/officeinstallationdirectories.cxx @@ -28,9 +28,9 @@ *************************************************************************/ #include <osl/file.hxx> -#include <rtl/ref.hxx> #include <com/sun/star/util/theMacroExpander.hpp> #include <comphelper/fileurl.hxx> +#include <utility> #include "officeinstallationdirectories.hxx" @@ -44,30 +44,30 @@ static bool makeCanonicalFileURL( OUString & rURL ) if ( osl::FileBase::getAbsoluteFileURL( OUString(), rURL, aNormalizedURL ) + != osl::DirectoryItem::E_None ) + return false; + + osl::DirectoryItem aDirItem; + if ( osl::DirectoryItem::get( aNormalizedURL, aDirItem ) + != osl::DirectoryItem::E_None ) + return false; + + osl::FileStatus aFileStatus( osl_FileStatus_Mask_FileURL ); + + if ( aDirItem.getFileStatus( aFileStatus ) == osl::DirectoryItem::E_None ) { - osl::DirectoryItem aDirItem; - if ( osl::DirectoryItem::get( aNormalizedURL, aDirItem ) - == osl::DirectoryItem::E_None ) + aNormalizedURL = aFileStatus.getFileURL(); + + if ( !aNormalizedURL.isEmpty() ) { - osl::FileStatus aFileStatus( osl_FileStatus_Mask_FileURL ); + if ( !aNormalizedURL.endsWith("/") ) + rURL = aNormalizedURL; + else + rURL = aNormalizedURL + .copy( 0, aNormalizedURL.getLength() - 1 ); - if ( aDirItem.getFileStatus( aFileStatus ) - == osl::DirectoryItem::E_None ) - { - aNormalizedURL = aFileStatus.getFileURL(); - - if ( !aNormalizedURL.isEmpty() ) - { - if ( !aNormalizedURL.endsWith("/") ) - rURL = aNormalizedURL; - else - rURL = aNormalizedURL - .copy( 0, aNormalizedURL.getLength() - 1 ); - - return true; - } - } + return true; } } return false; @@ -75,12 +75,12 @@ static bool makeCanonicalFileURL( OUString & rURL ) namespace comphelper { -constexpr OUStringLiteral g_aOfficeBrandDirMacro(u"$(brandbaseurl)"); -constexpr OUStringLiteral g_aUserDirMacro(u"$(userdataurl)"); +constexpr OUString g_aOfficeBrandDirMacro(u"$(brandbaseurl)"_ustr); +constexpr OUString g_aUserDirMacro(u"$(userdataurl)"_ustr); OfficeInstallationDirectories::OfficeInstallationDirectories( - const uno::Reference< uno::XComponentContext > & xCtx ) -: m_xCtx( xCtx ) + uno::Reference< uno::XComponentContext > xCtx ) +: m_xCtx(std::move( xCtx )) { } @@ -211,7 +211,7 @@ void OfficeInstallationDirectories::initDirs() if ( m_xOfficeBrandDir) return; - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( m_xOfficeBrandDir ) return; diff --git a/comphelper/source/officeinstdir/officeinstallationdirectories.hxx b/comphelper/source/officeinstdir/officeinstallationdirectories.hxx index f39f8a380e91..d0d86b76c4d5 100644 --- a/comphelper/source/officeinstdir/officeinstallationdirectories.hxx +++ b/comphelper/source/officeinstdir/officeinstallationdirectories.hxx @@ -19,12 +19,12 @@ #pragma once -#include <osl/mutex.hxx> #include <cppuhelper/implbase.hxx> #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/util/XOfficeInstallationDirectories.hpp> +#include <mutex> #include <optional> namespace com::sun::star::uno { class XComponentContext; } @@ -35,18 +35,13 @@ namespace comphelper { typedef cppu::WeakImplHelper< css::util::XOfficeInstallationDirectories, - css::lang::XServiceInfo > UnoImplBase; + css::lang::XServiceInfo > OfficeInstallationDirectories_Base; -struct mutex_holder -{ - osl::Mutex m_aMutex; -}; - -class OfficeInstallationDirectories : public mutex_holder, public UnoImplBase +class OfficeInstallationDirectories : public OfficeInstallationDirectories_Base { public: explicit OfficeInstallationDirectories( - const css::uno::Reference< css::uno::XComponentContext > & xCtx ); + css::uno::Reference< css::uno::XComponentContext > xCtx ); virtual ~OfficeInstallationDirectories() override; // XOfficeInstallationDirectories @@ -70,6 +65,7 @@ public: private: void initDirs(); + std::mutex m_aMutex; css::uno::Reference< css::uno::XComponentContext > m_xCtx; std::optional<OUString> m_xOfficeBrandDir; std::optional<OUString> m_xUserDir; diff --git a/comphelper/source/processfactory/processfactory.cxx b/comphelper/source/processfactory/processfactory.cxx index ea5595646e4c..eddff2d45e04 100644 --- a/comphelper/source/processfactory/processfactory.cxx +++ b/comphelper/source/processfactory/processfactory.cxx @@ -17,7 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include <osl/mutex.hxx> +#include <mutex> #include <comphelper/processfactory.hxx> #include <com/sun/star/beans/XPropertySet.hpp> @@ -30,7 +30,6 @@ namespace com::sun::star::uno { class XComponentContext; } using namespace ::com::sun::star; using namespace com::sun::star::uno; using namespace com::sun::star::lang; -using namespace osl; namespace comphelper { @@ -41,19 +40,20 @@ class LocalProcessFactory { public: void set( const Reference< XMultiServiceFactory >& xSMgr ) { - Guard< Mutex > aGuard( Mutex::getGlobalMutex() ); + std::unique_lock aGuard( maMutex ); xProcessFactory = xSMgr; } Reference< XMultiServiceFactory > get() const { - Guard< Mutex > aGuard( Mutex::getGlobalMutex() ); + std::unique_lock aGuard( maMutex ); return xProcessFactory; } private: + mutable std::mutex maMutex; Reference< XMultiServiceFactory > xProcessFactory; }; @@ -108,7 +108,8 @@ Reference< XComponentContext > getComponentContext( Reference< XComponentContext > getProcessComponentContext() { - return getComponentContext( getProcessServiceFactory() ); + static const uno::Reference<XComponentContext> processComponentContext = getComponentContext( getProcessServiceFactory() ); + return processComponentContext; } } // namespace comphelper diff --git a/comphelper/source/property/ChainablePropertySet.cxx b/comphelper/source/property/ChainablePropertySet.cxx index 65a53e62479f..d2e7122996ed 100644 --- a/comphelper/source/property/ChainablePropertySet.cxx +++ b/comphelper/source/property/ChainablePropertySet.cxx @@ -23,6 +23,7 @@ #include <memory> +#include <optional> using namespace ::comphelper; using namespace ::com::sun::star; @@ -51,9 +52,9 @@ Reference< XPropertySetInfo > SAL_CALL ChainablePropertySet::getPropertySetInfo( void SAL_CALL ChainablePropertySet::setPropertyValue( const OUString& rPropertyName, const Any& rValue ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); PropertyInfoHash::const_iterator aIter = mxInfo->maMap.find ( rPropertyName ); @@ -68,9 +69,9 @@ void SAL_CALL ChainablePropertySet::setPropertyValue( const OUString& rPropertyN Any SAL_CALL ChainablePropertySet::getPropertyValue( const OUString& rPropertyName ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); PropertyInfoHash::const_iterator aIter = mxInfo->maMap.find ( rPropertyName ); @@ -109,9 +110,9 @@ void SAL_CALL ChainablePropertySet::removeVetoableChangeListener( const OUString void SAL_CALL ChainablePropertySet::setPropertyValues(const Sequence< OUString >& rPropertyNames, const Sequence< Any >& rValues) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); const sal_Int32 nCount = rPropertyNames.getLength(); @@ -123,17 +124,13 @@ void SAL_CALL ChainablePropertySet::setPropertyValues(const Sequence< OUString > _preSetValues(); - const Any * pAny = rValues.getConstArray(); - const OUString * pString = rPropertyNames.getConstArray(); - PropertyInfoHash::const_iterator aEnd = mxInfo->maMap.end(), aIter; - - for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pAny ) + for (sal_Int32 i = 0; i < nCount; ++i) { - aIter = mxInfo->maMap.find ( *pString ); - if ( aIter == aEnd ) - throw RuntimeException( *pString, static_cast< XPropertySet* >( this ) ); + auto aIter = mxInfo->maMap.find(rPropertyNames[i]); + if (aIter == mxInfo->maMap.end()) + throw RuntimeException(rPropertyNames[i], static_cast<XPropertySet*>(this)); - _setSingleValue ( *((*aIter).second), *pAny ); + _setSingleValue(*((*aIter).second), rValues[i]); } _postSetValues(); @@ -142,9 +139,9 @@ void SAL_CALL ChainablePropertySet::setPropertyValues(const Sequence< OUString > Sequence< Any > SAL_CALL ChainablePropertySet::getPropertyValues(const Sequence< OUString >& rPropertyNames) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); const sal_Int32 nCount = rPropertyNames.getLength(); @@ -155,16 +152,13 @@ Sequence< Any > SAL_CALL ChainablePropertySet::getPropertyValues(const Sequence< _preGetValues(); Any * pAny = aValues.getArray(); - const OUString * pString = rPropertyNames.getConstArray(); - PropertyInfoHash::const_iterator aEnd = mxInfo->maMap.end(), aIter; - - for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pAny ) + for (sal_Int32 i = 0; i < nCount; ++i) { - aIter = mxInfo->maMap.find ( *pString ); - if ( aIter == aEnd ) - throw RuntimeException( *pString, static_cast< XPropertySet* >( this ) ); + auto aIter = mxInfo->maMap.find(rPropertyNames[i]); + if (aIter == mxInfo->maMap.end()) + throw RuntimeException(rPropertyNames[i], static_cast<XPropertySet*>(this)); - _getSingleValue ( *((*aIter).second), *pAny ); + _getSingleValue(*((*aIter).second), pAny[i]); } _postGetValues(); @@ -205,14 +199,15 @@ Sequence< PropertyState > SAL_CALL ChainablePropertySet::getPropertyStates( cons if( nCount ) { PropertyState * pState = aStates.getArray(); - const OUString * pString = rPropertyNames.getConstArray(); PropertyInfoHash::const_iterator aEnd = mxInfo->maMap.end(), aIter; - for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pState ) + for (sal_Int32 i = 0; i < nCount; ++i) { - aIter = mxInfo->maMap.find ( *pString ); + aIter = mxInfo->maMap.find(rPropertyNames[i]); if ( aIter == aEnd ) - throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) ); + throw UnknownPropertyException(rPropertyNames[i], static_cast<XPropertySet*>(this)); + + pState[i] = PropertyState_AMBIGUOUS_VALUE; } } return aStates; diff --git a/comphelper/source/property/ChainablePropertySetInfo.cxx b/comphelper/source/property/ChainablePropertySetInfo.cxx index 10b4d5fda622..4515e5c4314b 100644 --- a/comphelper/source/property/ChainablePropertySetInfo.cxx +++ b/comphelper/source/property/ChainablePropertySetInfo.cxx @@ -31,7 +31,7 @@ ChainablePropertySetInfo::ChainablePropertySetInfo( PropertyInfo const * pMap ) for( ; !pMap->maName.isEmpty(); ++pMap ) { SAL_WARN_IF( - maMap.find(pMap->maName) != maMap.end(), + maMap.contains(pMap->maName), "comphelper", "Duplicate property name \"" << pMap->maName << "\""); maMap[pMap->maName] = pMap; } diff --git a/comphelper/source/property/MasterPropertySet.cxx b/comphelper/source/property/MasterPropertySet.cxx index 3f6f0119dbb6..bd5ce83eaa16 100644 --- a/comphelper/source/property/MasterPropertySet.cxx +++ b/comphelper/source/property/MasterPropertySet.cxx @@ -27,17 +27,18 @@ #include <memory> #include <vector> +#include <optional> namespace { class AutoOGuardArray { - std::vector<std::unique_ptr< osl::Guard< comphelper::SolarMutex > >> maGuardArray; + std::vector<std::optional< osl::Guard< comphelper::SolarMutex > >> maGuardArray; public: explicit AutoOGuardArray( sal_Int32 nNumElements ); - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > & operator[] ( sal_Int32 i ) { return maGuardArray[i]; } + std::optional< osl::Guard< comphelper::SolarMutex > > & operator[] ( sal_Int32 i ) { return maGuardArray[i]; } }; } @@ -91,9 +92,9 @@ void MasterPropertySet::registerSlave ( ChainablePropertySet *pNewSet ) void SAL_CALL MasterPropertySet::setPropertyValue( const OUString& rPropertyName, const Any& rValue ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); PropertyDataHash::const_iterator aIter = mxInfo->maMap.find ( rPropertyName ); @@ -111,9 +112,9 @@ void SAL_CALL MasterPropertySet::setPropertyValue( const OUString& rPropertyName ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mxSlave.get(); // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard2; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard2; if (pSlave->mpMutex) - xMutexGuard2.reset( new osl::Guard< comphelper::SolarMutex >(pSlave->mpMutex) ); + xMutexGuard2.emplace( pSlave->mpMutex ); pSlave->_preSetValues(); pSlave->_setSingleValue( *((*aIter).second->mpInfo), rValue ); @@ -124,9 +125,9 @@ void SAL_CALL MasterPropertySet::setPropertyValue( const OUString& rPropertyName Any SAL_CALL MasterPropertySet::getPropertyValue( const OUString& rPropertyName ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); PropertyDataHash::const_iterator aIter = mxInfo->maMap.find ( rPropertyName ); @@ -145,9 +146,9 @@ Any SAL_CALL MasterPropertySet::getPropertyValue( const OUString& rPropertyName ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mxSlave.get(); // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard2; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard2; if (pSlave->mpMutex) - xMutexGuard2.reset( new osl::Guard< comphelper::SolarMutex >(pSlave->mpMutex) ); + xMutexGuard2.emplace( pSlave->mpMutex ); pSlave->_preGetValues(); pSlave->_getSingleValue( *((*aIter).second->mpInfo), aAny ); @@ -180,9 +181,9 @@ void SAL_CALL MasterPropertySet::removeVetoableChangeListener( const OUString&, void SAL_CALL MasterPropertySet::setPropertyValues( const Sequence< OUString >& aPropertyNames, const Sequence< Any >& aValues ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); const sal_Int32 nCount = aPropertyNames.getLength(); @@ -194,8 +195,6 @@ void SAL_CALL MasterPropertySet::setPropertyValues( const Sequence< OUString >& _preSetValues(); - const Any * pAny = aValues.getConstArray(); - const OUString * pString = aPropertyNames.getConstArray(); PropertyDataHash::const_iterator aEnd = mxInfo->maMap.end(), aIter; //!! have a unique_ptr to an array of OGuards in order to have the @@ -205,14 +204,14 @@ void SAL_CALL MasterPropertySet::setPropertyValues( const Sequence< OUString >& //!! the acquired locks properly released. AutoOGuardArray aOGuardArray( nCount ); - for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pAny ) + for (sal_Int32 i = 0; i < nCount; ++i) { - aIter = mxInfo->maMap.find ( *pString ); + aIter = mxInfo->maMap.find(aPropertyNames[i]); if ( aIter == aEnd ) - throw RuntimeException( *pString, static_cast< XPropertySet* >( this ) ); + throw RuntimeException(aPropertyNames[i], static_cast<XPropertySet*>(this)); if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours ! - _setSingleValue( *((*aIter).second->mpInfo), *pAny ); + _setSingleValue(*((*aIter).second->mpInfo), aValues[i]); else { SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]; @@ -220,12 +219,12 @@ void SAL_CALL MasterPropertySet::setPropertyValues( const Sequence< OUString >& { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). if (pSlave->mxSlave->mpMutex) - aOGuardArray[i].reset( new osl::Guard< comphelper::SolarMutex >(pSlave->mxSlave->mpMutex) ); + aOGuardArray[i].emplace( pSlave->mxSlave->mpMutex ); pSlave->mxSlave->_preSetValues(); pSlave->SetInit ( true ); } - pSlave->mxSlave->_setSingleValue( *((*aIter).second->mpInfo), *pAny ); + pSlave->mxSlave->_setSingleValue(*((*aIter).second->mpInfo), aValues[i]); } } @@ -243,9 +242,9 @@ void SAL_CALL MasterPropertySet::setPropertyValues( const Sequence< OUString >& Sequence< Any > SAL_CALL MasterPropertySet::getPropertyValues( const Sequence< OUString >& aPropertyNames ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); const sal_Int32 nCount = aPropertyNames.getLength(); @@ -256,7 +255,6 @@ Sequence< Any > SAL_CALL MasterPropertySet::getPropertyValues( const Sequence< O _preGetValues(); Any * pAny = aValues.getArray(); - const OUString * pString = aPropertyNames.getConstArray(); PropertyDataHash::const_iterator aEnd = mxInfo->maMap.end(), aIter; //!! have a unique_ptr to an array of OGuards in order to have the @@ -266,14 +264,14 @@ Sequence< Any > SAL_CALL MasterPropertySet::getPropertyValues( const Sequence< O //!! the acquired locks properly released. AutoOGuardArray aOGuardArray( nCount ); - for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pAny ) + for (sal_Int32 i = 0; i < nCount; ++i) { - aIter = mxInfo->maMap.find ( *pString ); + aIter = mxInfo->maMap.find(aPropertyNames[i]); if ( aIter == aEnd ) - throw RuntimeException( *pString, static_cast< XPropertySet* >( this ) ); + throw RuntimeException(aPropertyNames[i], static_cast<XPropertySet*>(this)); if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours ! - _getSingleValue( *((*aIter).second->mpInfo), *pAny ); + _getSingleValue(*((*aIter).second->mpInfo), pAny[i]); else { SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]; @@ -281,12 +279,12 @@ Sequence< Any > SAL_CALL MasterPropertySet::getPropertyValues( const Sequence< O { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). if (pSlave->mxSlave->mpMutex) - aOGuardArray[i].reset( new osl::Guard< comphelper::SolarMutex >(pSlave->mxSlave->mpMutex) ); + aOGuardArray[i].emplace( pSlave->mxSlave->mpMutex ); pSlave->mxSlave->_preGetValues(); pSlave->SetInit ( true ); } - pSlave->mxSlave->_getSingleValue( *((*aIter).second->mpInfo), *pAny ); + pSlave->mxSlave->_getSingleValue(*((*aIter).second->mpInfo), pAny[i]); } } @@ -331,9 +329,9 @@ PropertyState SAL_CALL MasterPropertySet::getPropertyState( const OUString& Prop ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mxSlave.get(); // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (pSlave->mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(pSlave->mpMutex) ); + xMutexGuard.emplace( pSlave->mpMutex ); } return PropertyState_AMBIGUOUS_VALUE; @@ -347,14 +345,13 @@ Sequence< PropertyState > SAL_CALL MasterPropertySet::getPropertyStates( const S if( nCount ) { PropertyState * pState = aStates.getArray(); - const OUString * pString = rPropertyNames.getConstArray(); PropertyDataHash::const_iterator aEnd = mxInfo->maMap.end(), aIter; - for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pState ) + for (sal_Int32 i = 0; i < nCount; ++i) { - aIter = mxInfo->maMap.find ( *pString ); + aIter = mxInfo->maMap.find(rPropertyNames[i]); if ( aIter == aEnd ) - throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) ); + throw UnknownPropertyException(rPropertyNames[i], static_cast<XPropertySet*>(this)); // 0 means it's one of ours ! if ( (*aIter).second->mnMapId != 0 ) @@ -365,6 +362,8 @@ Sequence< PropertyState > SAL_CALL MasterPropertySet::getPropertyStates( const S pSlave->SetInit ( true ); } } + + pState[i] = PropertyState_AMBIGUOUS_VALUE; } for( const auto& rSlave : maSlaveMap ) { diff --git a/comphelper/source/property/MasterPropertySetInfo.cxx b/comphelper/source/property/MasterPropertySetInfo.cxx index db8ddb769975..4040b479a05c 100644 --- a/comphelper/source/property/MasterPropertySetInfo.cxx +++ b/comphelper/source/property/MasterPropertySetInfo.cxx @@ -31,7 +31,7 @@ MasterPropertySetInfo::MasterPropertySetInfo( PropertyInfo const * pMap ) for ( ; !pMap->maName.isEmpty(); ++pMap ) { SAL_WARN_IF( - maMap.find(pMap->maName) != maMap.end(), + maMap.contains(pMap->maName), "comphelper", "Duplicate property name \"" << pMap->maName << "\""); maMap[pMap->maName] = new PropertyData ( 0, pMap ); } @@ -52,7 +52,7 @@ void MasterPropertySetInfo::add( PropertyInfoHash &rHash, sal_uInt8 nMapId ) for( const auto& rObj : rHash ) { SAL_WARN_IF( - maMap.find(rObj.first) != maMap.end(), + maMap.contains(rObj.first), "comphelper", "Duplicate property name \"" << rObj.first << "\""); maMap[rObj.first] = new PropertyData ( nMapId, rObj.second ); } diff --git a/comphelper/source/property/genericpropertyset.cxx b/comphelper/source/property/genericpropertyset.cxx index 68ae7a3353b4..a6392ec757db 100644 --- a/comphelper/source/property/genericpropertyset.cxx +++ b/comphelper/source/property/genericpropertyset.cxx @@ -25,14 +25,13 @@ #include <com/sun/star/lang/XTypeProvider.hpp> #include <cppuhelper/weakagg.hxx> #include <cppuhelper/supportsservice.hxx> -#include <comphelper/multiinterfacecontainer2.hxx> +#include <comphelper/multiinterfacecontainer4.hxx> #include <comphelper/propertysethelper.hxx> -#include <osl/mutex.hxx> +#include <mutex> #include <rtl/ref.hxx> #include <comphelper/genericpropertyset.hxx> #include <comphelper/propertysetinfo.hxx> -using namespace ::osl; using namespace ::cppu; using namespace ::comphelper; using namespace ::com::sun::star; @@ -44,20 +43,15 @@ namespace comphelper { namespace { - struct IMPL_GenericPropertySet_MutexContainer - { - Mutex maMutex; - }; - - class GenericPropertySet : public OWeakAggObject, + class GenericPropertySet : public OWeakObject, public XServiceInfo, public XTypeProvider, - public PropertySetHelper, - private IMPL_GenericPropertySet_MutexContainer + public PropertySetHelper { private: std::map<OUString, Any> maAnyMap; - comphelper::OMultiTypeInterfaceContainerHelperVar2<OUString> m_aListener; + std::mutex maMutex; + comphelper::OMultiTypeInterfaceContainerHelperVar4<OUString, XPropertyChangeListener> m_aListener; protected: virtual void _setPropertyValues( const PropertyMapEntry** ppEntries, const Any* pValues ) override; @@ -67,7 +61,6 @@ namespace comphelper explicit GenericPropertySet( PropertySetInfo* pInfo ) noexcept; // XInterface - virtual Any SAL_CALL queryAggregation( const Type & rType ) override; virtual Any SAL_CALL queryInterface( const Type & rType ) override; virtual void SAL_CALL acquire() noexcept override; virtual void SAL_CALL release() noexcept override; @@ -92,7 +85,6 @@ namespace comphelper GenericPropertySet::GenericPropertySet( PropertySetInfo* pInfo ) noexcept : PropertySetHelper( pInfo ) -,m_aListener(maMutex) { } @@ -102,53 +94,47 @@ void SAL_CALL GenericPropertySet::addPropertyChangeListener( const OUString& aPr if ( !xInfo.is() ) return; + std::unique_lock aGuard(maMutex); if ( aPropertyName.isEmpty() ) { - Sequence< Property> aSeq = xInfo->getProperties(); - const Property* pIter = aSeq.getConstArray(); - const Property* pEnd = pIter + aSeq.getLength(); - for( ; pIter != pEnd ; ++pIter) + for (auto& prop : xInfo->getProperties()) { - m_aListener.addInterface(pIter->Name,xListener); + m_aListener.addInterface(aGuard, prop.Name, xListener); } } else if ( xInfo->hasPropertyByName(aPropertyName) ) - m_aListener.addInterface(aPropertyName,xListener); + m_aListener.addInterface(aGuard, aPropertyName,xListener); else throw UnknownPropertyException( aPropertyName, *this ); } void SAL_CALL GenericPropertySet::removePropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener ) { - ClearableMutexGuard aGuard( maMutex ); Reference < XPropertySetInfo > xInfo = getPropertySetInfo( ); - aGuard.clear(); if ( !xInfo.is() ) return; + std::unique_lock aGuard(maMutex); if ( aPropertyName.isEmpty() ) { - Sequence< Property> aSeq = xInfo->getProperties(); - const Property* pIter = aSeq.getConstArray(); - const Property* pEnd = pIter + aSeq.getLength(); - for( ; pIter != pEnd ; ++pIter) + for (auto& prop : xInfo->getProperties()) { - m_aListener.removeInterface(pIter->Name,xListener); + m_aListener.removeInterface(aGuard, prop.Name, xListener); } } else if ( xInfo->hasPropertyByName(aPropertyName) ) - m_aListener.removeInterface(aPropertyName,xListener); + m_aListener.removeInterface(aGuard, aPropertyName,xListener); else throw UnknownPropertyException( aPropertyName, *this ); } void GenericPropertySet::_setPropertyValues( const PropertyMapEntry** ppEntries, const Any* pValues ) { - ResettableMutexGuard aGuard( maMutex ); + std::unique_lock aGuard(maMutex); while( *ppEntries ) { - OInterfaceContainerHelper2 * pHelper = m_aListener.getContainer((*ppEntries)->maName); + OInterfaceContainerHelper4<XPropertyChangeListener> * pHelper = m_aListener.getContainer(aGuard, (*ppEntries)->maName); maAnyMap[ (*ppEntries)->maName ] = *pValues; @@ -157,9 +143,7 @@ void GenericPropertySet::_setPropertyValues( const PropertyMapEntry** ppEntries, PropertyChangeEvent aEvt; aEvt.PropertyName = (*ppEntries)->maName; aEvt.NewValue = *pValues; - aGuard.clear(); - pHelper->notifyEach( &XPropertyChangeListener::propertyChange, aEvt ); - aGuard.reset(); + pHelper->notifyEach( aGuard, &XPropertyChangeListener::propertyChange, aEvt ); } ppEntries++; @@ -169,7 +153,7 @@ void GenericPropertySet::_setPropertyValues( const PropertyMapEntry** ppEntries, void GenericPropertySet::_getPropertyValues( const comphelper::PropertyMapEntry** ppEntries, Any* pValue ) { - MutexGuard aGuard( maMutex ); + std::unique_lock aGuard(maMutex); while( *ppEntries ) { @@ -184,11 +168,6 @@ void GenericPropertySet::_getPropertyValues( const comphelper::PropertyMapEntry* Any SAL_CALL GenericPropertySet::queryInterface( const Type & rType ) { - return OWeakAggObject::queryInterface( rType ); -} - -Any SAL_CALL GenericPropertySet::queryAggregation( const Type & rType ) -{ Any aAny; if( rType == cppu::UnoType<XServiceInfo>::get()) @@ -200,19 +179,19 @@ Any SAL_CALL GenericPropertySet::queryAggregation( const Type & rType ) else if( rType == cppu::UnoType<XMultiPropertySet>::get()) aAny <<= Reference< XMultiPropertySet >(this); else - aAny = OWeakAggObject::queryAggregation( rType ); + aAny = OWeakObject::queryInterface( rType ); return aAny; } void SAL_CALL GenericPropertySet::acquire() noexcept { - OWeakAggObject::acquire(); + OWeakObject::acquire(); } void SAL_CALL GenericPropertySet::release() noexcept { - OWeakAggObject::release(); + OWeakObject::release(); } uno::Sequence< uno::Type > SAL_CALL GenericPropertySet::getTypes() diff --git a/comphelper/source/property/opropertybag.cxx b/comphelper/source/property/opropertybag.cxx index e0b389c19199..3b4a0498dcef 100644 --- a/comphelper/source/property/opropertybag.cxx +++ b/comphelper/source/property/opropertybag.cxx @@ -389,7 +389,7 @@ namespace comphelper { aValues = OPropertyBag_PBase::getPropertyValues( aNames ); if ( aValues.getLength() != aNames.getLength() ) - throw RuntimeException(); + throw RuntimeException("property name and value counts out of sync"); } catch( const RuntimeException& ) { @@ -404,17 +404,14 @@ namespace comphelper ::cppu::IPropertyArrayHelper& rPropInfo = getInfoHelper(); Sequence< PropertyValue > aPropertyValues( aNames.getLength() ); - const OUString* pName = aNames.getConstArray(); - const OUString* pNamesEnd = aNames.getConstArray() + aNames.getLength(); - const Any* pValue = aValues.getArray(); PropertyValue* pPropertyValue = aPropertyValues.getArray(); - for ( ; pName != pNamesEnd; ++pName, ++pValue, ++pPropertyValue ) + for (sal_Int32 i = 0; i < aNames.getLength(); ++i) { - pPropertyValue->Name = *pName; - pPropertyValue->Handle = rPropInfo.getHandleByName( *pName ); - pPropertyValue->Value = *pValue; - pPropertyValue->State = getPropertyStateByHandle( pPropertyValue->Handle ); + pPropertyValue[i].Name = aNames[i]; + pPropertyValue[i].Handle = rPropInfo.getHandleByName(aNames[i]); + pPropertyValue[i].Value = aValues[i]; + pPropertyValue[i].State = getPropertyStateByHandle(pPropertyValue[i].Handle); } return aPropertyValues; @@ -452,16 +449,12 @@ namespace comphelper sal_Int32 nCount = aNames.getLength(); Sequence< sal_Int32 > aHandles( nCount ); - sal_Int32* pHandle = aHandles.getArray(); - const PropertyValue* pProperty = aProperties.getConstArray(); - for ( const OUString* pName = aNames.getConstArray(); - pName != aNames.getConstArray() + aNames.getLength(); - ++pName, ++pHandle, ++pProperty - ) + sal_Int32* pHandles = aHandles.getArray(); + for (sal_Int32 i = 0; i < nCount; ++i) { ::cppu::IPropertyArrayHelper& rPropInfo = getInfoHelper(); - *pHandle = rPropInfo.getHandleByName( *pName ); - if ( *pHandle != -1 ) + pHandles[i] = rPropInfo.getHandleByName(aNames[i]); + if (pHandles[i] != -1) continue; // there's a property requested which we do not know @@ -469,12 +462,12 @@ namespace comphelper { // add the property sal_Int16 const nAttributes = PropertyAttribute::BOUND | PropertyAttribute::REMOVABLE | PropertyAttribute::MAYBEDEFAULT; - addProperty( *pName, nAttributes, pProperty->Value ); + addProperty(aNames[i], nAttributes, aProperties[i].Value); continue; } // no way out - throw UnknownPropertyException( *pName, *this ); + throw UnknownPropertyException(aNames[i], *this); } // a sequence of values @@ -486,7 +479,7 @@ namespace comphelper ExtractPropertyValue() ); - setFastPropertyValues( nCount, aHandles.getArray(), aValues.getConstArray(), nCount ); + setFastPropertyValues(nCount, pHandles, aValues.getConstArray(), nCount); } catch( const PropertyVetoException& ) { throw; } catch( const IllegalArgumentException& ) { throw; } diff --git a/comphelper/source/property/opropertybag.hxx b/comphelper/source/property/opropertybag.hxx index 28333901c2e3..66c38d870c10 100644 --- a/comphelper/source/property/opropertybag.hxx +++ b/comphelper/source/property/opropertybag.hxx @@ -25,7 +25,7 @@ #include <com/sun/star/beans/XPropertyBag.hpp> #include <com/sun/star/container/XSet.hpp> -#include <cppuhelper/implbase5.hxx> +#include <cppuhelper/implbase.hxx> #include <comphelper/interfacecontainer3.hxx> #include <comphelper/propstate.hxx> #include <comphelper/broadcasthelper.hxx> @@ -55,12 +55,12 @@ namespace comphelper typedef std::map< sal_Int32, css::uno::Any > MapInt2Any; typedef std::set< css::uno::Type, UnoTypeLess > TypeBag; - typedef ::cppu::WeakAggImplHelper5 < css::beans::XPropertyBag - , css::util::XModifiable - , css::lang::XServiceInfo - , css::lang::XInitialization - , css::container::XSet - > OPropertyBag_Base; + typedef ::cppu::WeakImplHelper < css::beans::XPropertyBag + , css::util::XModifiable + , css::lang::XServiceInfo + , css::lang::XInitialization + , css::container::XSet + > OPropertyBag_Base; typedef ::comphelper::OPropertyStateHelper OPropertyBag_PBase; class OPropertyBag final : public ::comphelper::OMutexAndBroadcastHelper // must be before OPropertyBag_PBase diff --git a/comphelper/source/property/propagg.cxx b/comphelper/source/property/propagg.cxx index a93c82c98fae..5acf8a1dc2d5 100644 --- a/comphelper/source/property/propagg.cxx +++ b/comphelper/source/property/propagg.cxx @@ -27,6 +27,7 @@ #include <o3tl/sorted_vector.hxx> #include <typeinfo> #include <algorithm> +#include <cstddef> #include <unordered_set> #include <memory> @@ -83,12 +84,13 @@ OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper( std::unordered_set< sal_Int32 > existingHandles; existingHandles.reserve( m_aProperties.size() ); sal_Int32 nAggregateHandle = _nFirstAggregateId; - for ( sal_Int32 nMPLoop = 0; nMPLoop < static_cast< sal_Int32 >( m_aProperties.size() ); ++nMPLoop ) + for ( std::size_t nMPLoop = 0; nMPLoop < m_aProperties.size(); ++nMPLoop ) { auto &prop = m_aProperties[ nMPLoop ]; if ( aDelegatorProps.find( prop.Name ) != aDelegatorProps.end() ) { - m_aPropertyAccessors[ prop.Handle ] = OPropertyAccessor( -1, nMPLoop, false ); + m_aPropertyAccessors.insert_or_assign( + prop.Handle, OPropertyAccessor( -1, nMPLoop, false )); existingHandles.insert( prop.Handle ); } else @@ -111,7 +113,8 @@ OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper( } // remember the accessor for this property - m_aPropertyAccessors[ nHandle ] = OPropertyAccessor( prop.Handle, nMPLoop, true ); + m_aPropertyAccessors.insert_or_assign( + nHandle, OPropertyAccessor( prop.Handle, nMPLoop, true )); prop.Handle = nHandle; } } @@ -126,7 +129,7 @@ OPropertyArrayAggregationHelper::PropertyOrigin OPropertyArrayAggregationHelper: if ( pPropertyDescriptor ) { // look up the handle for this name - ConstPropertyAccessorMapIterator aPos = m_aPropertyAccessors.find( pPropertyDescriptor->Handle ); + auto aPos = m_aPropertyAccessors.find( pPropertyDescriptor->Handle ); OSL_ENSURE( m_aPropertyAccessors.end() != aPos, "OPropertyArrayAggregationHelper::classifyProperty: should have this handle in my map!" ); if ( m_aPropertyAccessors.end() != aPos ) { @@ -170,7 +173,7 @@ sal_Int32 OPropertyArrayAggregationHelper::getHandleByName(const OUString& _rPro sal_Bool OPropertyArrayAggregationHelper::fillPropertyMembersByHandle( OUString* _pPropName, sal_Int16* _pAttributes, sal_Int32 _nHandle) { - ConstPropertyAccessorMapIterator i = m_aPropertyAccessors.find(_nHandle); + auto i = m_aPropertyAccessors.find(_nHandle); bool bRet = i != m_aPropertyAccessors.end(); if (bRet) { @@ -186,7 +189,7 @@ sal_Bool OPropertyArrayAggregationHelper::fillPropertyMembersByHandle( bool OPropertyArrayAggregationHelper::getPropertyByHandle( sal_Int32 _nHandle, Property& _rProperty ) const { - ConstPropertyAccessorMapIterator pos = m_aPropertyAccessors.find(_nHandle); + auto pos = m_aPropertyAccessors.find(_nHandle); if ( pos != m_aPropertyAccessors.end() ) { _rProperty = m_aProperties[ pos->second.nPos ]; @@ -199,7 +202,7 @@ bool OPropertyArrayAggregationHelper::getPropertyByHandle( sal_Int32 _nHandle, P bool OPropertyArrayAggregationHelper::fillAggregatePropertyInfoByHandle( OUString* _pPropName, sal_Int32* _pOriginalHandle, sal_Int32 _nHandle) const { - ConstPropertyAccessorMapIterator i = m_aPropertyAccessors.find(_nHandle); + auto i = m_aPropertyAccessors.find(_nHandle); bool bRet = i != m_aPropertyAccessors.end() && (*i).second.bAggregate; if (bRet) { @@ -207,7 +210,7 @@ bool OPropertyArrayAggregationHelper::fillAggregatePropertyInfoByHandle( *_pOriginalHandle = (*i).second.nOriginalHandle; if (_pPropName) { - OSL_ENSURE((*i).second.nPos < static_cast<sal_Int32>(m_aProperties.size()),"Invalid index for sequence!"); + OSL_ENSURE((*i).second.nPos < m_aProperties.size(),"Invalid index for sequence!"); const css::beans::Property& rProperty = m_aProperties[(*i).second.nPos]; *_pPropName = rProperty.Name; } @@ -226,15 +229,13 @@ sal_Int32 OPropertyArrayAggregationHelper::fillHandles( sal_Int32* _pHandles, const css::uno::Sequence< OUString >& _rPropNames ) { sal_Int32 nHitCount = 0; - const OUString* pReqProps = _rPropNames.getConstArray(); - sal_Int32 nReqLen = _rPropNames.getLength(); Property aNameProp; - for( sal_Int32 i = 0; i < nReqLen; ++i ) + for (sal_Int32 i = 0; i < _rPropNames.getLength(); ++i) { - aNameProp.Name = pReqProps[i]; + aNameProp.Name = _rPropNames[i]; auto findIter = std::lower_bound(m_aProperties.begin(), m_aProperties.end(), aNameProp, PropertyCompareByName()); - if ( findIter != m_aProperties.end() && findIter->Name == pReqProps[i] ) + if (findIter != m_aProperties.end() && findIter->Name == _rPropNames[i]) { _pHandles[i] = findIter->Handle; nHitCount++; @@ -383,7 +384,7 @@ void SAL_CALL OPropertySetAggregationHelper::propertiesChange(const css::uno::Se if (1 == nLen) { - const css::beans::PropertyChangeEvent& evt = _rEvents.getConstArray()[0]; + const css::beans::PropertyChangeEvent& evt = _rEvents[0]; OSL_ENSURE(!evt.PropertyName.isEmpty(), "OPropertySetAggregationHelper::propertiesChange : invalid event !"); // we had a bug where this assertion would have us saved a whole day :) (72514) sal_Int32 nHandle = rPH.getHandleByName( evt.PropertyName ); @@ -586,6 +587,9 @@ void SAL_CALL OPropertySetAggregationHelper::setPropertyValues( OPropertySetHelper::setPropertyValues(_rPropertyNames, _rValues); else if (_rPropertyNames.getLength() == 1) // use the more efficient way { + if (_rValues.getLength() != 1) + throw IllegalArgumentException("lengths do not match", static_cast<XPropertySet*>(this), + -1); try { setPropertyValue( _rPropertyNames[0], _rValues[0] ); @@ -628,9 +632,9 @@ void SAL_CALL OPropertySetAggregationHelper::setPropertyValues( // mixed else { - const css::uno::Any* pValues = _rValues.getConstArray(); - - // dividing the Names and _rValues + if (_rValues.getLength() != nLen) + throw IllegalArgumentException("lengths do not match", + static_cast<XPropertySet*>(this), -1); // aggregate's names Sequence< OUString > AggPropertyNames( nAggCount ); @@ -647,23 +651,20 @@ void SAL_CALL OPropertySetAggregationHelper::setPropertyValues( Sequence< Any > DelValues( nLen - nAggCount ); Any* pDelValues = DelValues.getArray(); - for ( const OUString& rName : _rPropertyNames ) + for (sal_Int32 i = 0; i < nLen; ++i) { - if ( OPropertyArrayAggregationHelper::PropertyOrigin::Aggregate == rPH.classifyProperty( rName ) ) + if ( OPropertyArrayAggregationHelper::PropertyOrigin::Aggregate == rPH.classifyProperty( _rPropertyNames[i] ) ) { - *pAggNames++ = rName; - *pAggValues++ = *pValues++; + *pAggNames++ = _rPropertyNames[i]; + *pAggValues++ = _rValues[i]; } else { - *pDelNames++ = rName; - *pDelValues++ = *pValues++; + *pDelNames++ = _rPropertyNames[i]; + *pDelValues++ = _rValues[i]; } } - // reset, needed below - pDelValues = DelValues.getArray(); - std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[ nLen - nAggCount ]); // get the map table @@ -691,7 +692,7 @@ void SAL_CALL OPropertySetAggregationHelper::setPropertyValues( throw css::beans::PropertyVetoException(); // Will the property change? if( convertFastPropertyValue( pConvertedValues[ nHitCount ], pOldValues[nHitCount], - pHandles[i], pDelValues[i] ) ) + pHandles[i], DelValues[i] ) ) { // only increment if the property really change pHandles[nHitCount] = pHandles[i]; diff --git a/comphelper/source/property/property.cxx b/comphelper/source/property/property.cxx index 49a7a108f09a..7d57baeb39cb 100644 --- a/comphelper/source/property/property.cxx +++ b/comphelper/source/property/property.cxx @@ -21,6 +21,7 @@ #include <comphelper/sequence.hxx> #include <osl/diagnose.h> #include <sal/log.hxx> +#include <comphelper/diagnose_ex.hxx> #if OSL_DEBUG_LEVEL > 0 #include <cppuhelper/exc_hlp.hxx> @@ -87,10 +88,12 @@ void copyProperties(const Reference<XPropertySet>& _rxSource, catch (Exception&) { #if OSL_DEBUG_LEVEL > 0 - OUStringBuffer aBuffer; - aBuffer.append( "::comphelper::copyProperties: could not copy property '" ); - aBuffer.append(rSourceProp.Name ); - aBuffer.append( "' to the destination set (a '" ); + TOOLS_WARN_EXCEPTION("comphelper", "Caught exception copying properties"); + + OUStringBuffer aBuffer( + "::comphelper::copyProperties: could not copy property '" + + rSourceProp.Name + + "' to the destination set (a '" ); Reference< XServiceInfo > xSI( _rxDest, UNO_QUERY ); if ( xSI.is() ) @@ -99,21 +102,21 @@ void copyProperties(const Reference<XPropertySet>& _rxSource, } else { - aBuffer.append( OUString::createFromAscii(typeid( *_rxDest ).name()) ); + aBuffer.appendAscii( typeid( *_rxDest ).name() ); } aBuffer.append( "' implementation).\n" ); Any aException( ::cppu::getCaughtException() ); - aBuffer.append( "Caught an exception of type '" ); - aBuffer.append( aException.getValueTypeName() ); - aBuffer.append( "'" ); + aBuffer.append( "Caught an exception of type '" + + aException.getValueTypeName() + + "'" ); Exception aBaseException; if ( ( aException >>= aBaseException ) && !aBaseException.Message.isEmpty() ) { - aBuffer.append( ", saying '" ); - aBuffer.append( aBaseException.Message ); - aBuffer.append( "'" ); + aBuffer.append( ", saying '" + + aBaseException.Message + + "'" ); } aBuffer.append( "." ); diff --git a/comphelper/source/property/propertycontainer.cxx b/comphelper/source/property/propertycontainer.cxx index 2b5685405604..ad24c5f30aa7 100644 --- a/comphelper/source/property/propertycontainer.cxx +++ b/comphelper/source/property/propertycontainer.cxx @@ -26,7 +26,6 @@ namespace comphelper using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::lang; using namespace ::com::sun::star::beans; OPropertyContainer::OPropertyContainer(::cppu::OBroadcastHelper& _rBHelper) diff --git a/comphelper/source/property/propertycontainer2.cxx b/comphelper/source/property/propertycontainer2.cxx new file mode 100644 index 000000000000..5a3bfa4be285 --- /dev/null +++ b/comphelper/source/property/propertycontainer2.cxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <comphelper/propertycontainer2.hxx> +#include <cppuhelper/typeprovider.hxx> + +namespace comphelper +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; + +OPropertyContainer2::OPropertyContainer2() {} + +OPropertyContainer2::~OPropertyContainer2() {} + +Sequence<Type> OPropertyContainer2::getBaseTypes() +{ + // just the types from our one and only base class + ::cppu::OTypeCollection aTypes(cppu::UnoType<XPropertySet>::get(), + cppu::UnoType<XFastPropertySet>::get(), + cppu::UnoType<XMultiPropertySet>::get()); + return aTypes.getTypes(); +} + +bool OPropertyContainer2::convertFastPropertyValue(std::unique_lock<std::mutex>& /*rGuard*/, + Any& _rConvertedValue, Any& _rOldValue, + sal_Int32 _nHandle, const Any& _rValue) +{ + return OPropertyContainerHelper::convertFastPropertyValue(_rConvertedValue, _rOldValue, + _nHandle, _rValue); +} + +void OPropertyContainer2::setFastPropertyValue_NoBroadcast(std::unique_lock<std::mutex>& /*rGuard*/, + sal_Int32 _nHandle, const Any& _rValue) +{ + OPropertyContainerHelper::setFastPropertyValue(_nHandle, _rValue); +} + +void OPropertyContainer2::getFastPropertyValue(std::unique_lock<std::mutex>& /*rGuard*/, + Any& _rValue, sal_Int32 _nHandle) const +{ + OPropertyContainerHelper::getFastPropertyValue(_rValue, _nHandle); +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/property/propertycontainerhelper.cxx b/comphelper/source/property/propertycontainerhelper.cxx index 5fd6053ce100..ee81100ae617 100644 --- a/comphelper/source/property/propertycontainerhelper.cxx +++ b/comphelper/source/property/propertycontainerhelper.cxx @@ -26,6 +26,7 @@ #include <com/sun/star/beans/UnknownPropertyException.hpp> #include <algorithm> +#include <utility> namespace comphelper @@ -51,7 +52,7 @@ namespace struct PropertyDescriptionNameMatch { OUString const m_rCompare; - explicit PropertyDescriptionNameMatch( const OUString& _rCompare ) : m_rCompare( _rCompare ) { } + explicit PropertyDescriptionNameMatch( OUString _aCompare ) : m_rCompare(std::move( _aCompare )) { } bool operator() (const PropertyDescription& x ) const { @@ -269,7 +270,7 @@ bool OPropertyContainerHelper::convertFastPropertyValue( if (PropertyDescription::LocationType::HoldMyself == aPos->eLocated) { - OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < static_cast<sal_Int32>(m_aHoldProperties.size()), + OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < m_aHoldProperties.size(), "OPropertyContainerHelper::convertFastPropertyValue: invalid position !"); auto aIter = m_aHoldProperties.begin() + aPos->aLocation.nOwnClassVectorIndex; pPropContainer = &(*aIter); @@ -407,7 +408,7 @@ void OPropertyContainerHelper::getFastPropertyValue(Any& _rValue, sal_Int32 _nHa switch (aPos->eLocated) { case PropertyDescription::LocationType::HoldMyself: - OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < static_cast<sal_Int32>(m_aHoldProperties.size()), + OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < m_aHoldProperties.size(), "OPropertyContainerHelper::convertFastPropertyValue: invalid position !"); _rValue = m_aHoldProperties[aPos->aLocation.nOwnClassVectorIndex]; break; diff --git a/comphelper/source/property/propertysethelper.cxx b/comphelper/source/property/propertysethelper.cxx index 1568aca9b49d..5172fbb17b8f 100644 --- a/comphelper/source/property/propertysethelper.cxx +++ b/comphelper/source/property/propertysethelper.cxx @@ -23,6 +23,7 @@ #include <rtl/ref.hxx> #include <memory> +#include <utility> using namespace ::comphelper; using namespace ::com::sun::star; @@ -41,8 +42,8 @@ static PropertyMapEntry const * find( const rtl::Reference<PropertySetInfo>& mxI } -PropertySetHelper::PropertySetHelper( rtl::Reference<comphelper::PropertySetInfo> const & xInfo ) noexcept - : mxInfo(xInfo) +PropertySetHelper::PropertySetHelper( rtl::Reference<comphelper::PropertySetInfo> xInfo ) noexcept + : mxInfo(std::move(xInfo)) { } @@ -111,28 +112,22 @@ void SAL_CALL PropertySetHelper::setPropertyValues( const Sequence< OUString >& const sal_Int32 nCount = rPropertyNames.getLength(); if( nCount != rValues.getLength() ) - throw IllegalArgumentException("lengths do not match", uno::Reference<uno::XInterface>(), -1); + throw IllegalArgumentException("lengths do not match", static_cast<XPropertySet*>(this), -1); if( !nCount ) return; std::unique_ptr<PropertyMapEntry const *[]> pEntries(new PropertyMapEntry const *[nCount+1]); pEntries[nCount] = nullptr; - const OUString* pNames = rPropertyNames.getConstArray(); - bool bUnknown = false; - sal_Int32 n; - for( n = 0; !bUnknown && ( n < nCount ); n++, pNames++ ) + for (sal_Int32 n = 0; n < nCount; n++) { - pEntries[n] = find( mxInfo, *pNames ); - bUnknown = nullptr == pEntries[n]; + pEntries[n] = find(mxInfo, rPropertyNames[n]); + if (!pEntries[n]) + throw UnknownPropertyException(rPropertyNames[n], static_cast<XPropertySet*>(this)); } - if( !bUnknown ) - _setPropertyValues( pEntries.get(), rValues.getConstArray() ); - - if( bUnknown ) - throw RuntimeException( *pNames, static_cast< XPropertySet* >( this ) ); + _setPropertyValues(pEntries.get(), rValues.getConstArray()); } Sequence< Any > SAL_CALL PropertySetHelper::getPropertyValues(const Sequence< OUString >& rPropertyNames) @@ -143,22 +138,16 @@ Sequence< Any > SAL_CALL PropertySetHelper::getPropertyValues(const Sequence< OU return Sequence< Any >(); std::unique_ptr<PropertyMapEntry const *[]> pEntries(new PropertyMapEntry const *[nCount+1]); - const OUString* pNames = rPropertyNames.getConstArray(); - bool bUnknown = false; - sal_Int32 n; - for( n = 0; !bUnknown && ( n < nCount ); n++, pNames++ ) + for (sal_Int32 n = 0; n < nCount; n++) { - pEntries[n] = find( mxInfo, *pNames ); - bUnknown = nullptr == pEntries[n]; + pEntries[n] = find(mxInfo, rPropertyNames[n]); + if (!pEntries[n]) + throw UnknownPropertyException(rPropertyNames[n], static_cast<XPropertySet*>(this)); } - if( bUnknown ) - throw RuntimeException( *pNames, static_cast< XPropertySet* >( this ) ); - pEntries[nCount] = nullptr; Sequence< Any > aValues(nCount); - aValues.realloc(nCount); _getPropertyValues( pEntries.get(), aValues.getArray() ); return aValues; @@ -204,26 +193,19 @@ Sequence< PropertyState > SAL_CALL PropertySetHelper::getPropertyStates( const S if( nCount ) { - const OUString* pNames = aPropertyName.getConstArray(); - - bool bUnknown = false; - std::unique_ptr<PropertyMapEntry const *[]> pEntries(new PropertyMapEntry const *[nCount+1]); sal_Int32 n; - for( n = 0; !bUnknown && (n < nCount); n++, pNames++ ) + for (n = 0; n < nCount; n++) { - pEntries[n] = find( mxInfo, *pNames ); - bUnknown = nullptr == pEntries[n]; + pEntries[n] = find(mxInfo, aPropertyName[n]); + if (!pEntries[n]) + throw UnknownPropertyException(aPropertyName[n], static_cast<XPropertySet*>(this)); } pEntries[nCount] = nullptr; - if( !bUnknown ) - _getPropertyStates( pEntries.get(), aStates.getArray() ); - - if( bUnknown ) - throw UnknownPropertyException( *pNames, static_cast< XPropertySet* >( this ) ); + _getPropertyStates(pEntries.get(), aStates.getArray()); } return aStates; diff --git a/comphelper/source/property/propertysetinfo.cxx b/comphelper/source/property/propertysetinfo.cxx index f21afe3951cd..1d4ad2be8d25 100644 --- a/comphelper/source/property/propertysetinfo.cxx +++ b/comphelper/source/property/propertysetinfo.cxx @@ -20,78 +20,58 @@ #include <comphelper/propertysetinfo.hxx> #include <comphelper/sequence.hxx> -#include <vector> using namespace ::comphelper; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; -using namespace ::com::sun::star::lang; - -void PropertySetInfo::addImpl(PropertyMapEntry const * pMap) noexcept -{ - while (!pMap->maName.isEmpty()) - { - // check for duplicates - assert(maPropertyMap.find(pMap->maName) == maPropertyMap.end()); - - maPropertyMap[pMap->maName] = pMap; - - maProperties.clear(); - - ++pMap; - } -} PropertySetInfo::PropertySetInfo() noexcept { } -PropertySetInfo::PropertySetInfo( PropertyMapEntry const * pMap ) noexcept +PropertySetInfo::PropertySetInfo( std::span<const PropertyMapEntry> pMap ) noexcept { - while (!pMap->maName.isEmpty()) + maPropertyMap.reserve(pMap.size()); + for (const auto & rEntry : pMap) { // check for duplicates - assert(maPropertyMap.find(pMap->maName) == maPropertyMap.end()); + assert(maPropertyMap.find(rEntry.maName) == maPropertyMap.end()); + // Make sure there are no accidental empty entries left at the end of the array from + // when this method used to take a empty-terminated array. + assert(!rEntry.maName.isEmpty()); - maPropertyMap[pMap->maName] = pMap; - - ++pMap; + maPropertyMap.emplace(rEntry.maName, &rEntry); } } -PropertySetInfo::PropertySetInfo(uno::Sequence<beans::Property> const& rProps) noexcept -{ - PropertyMapEntry * pEntries(new PropertyMapEntry[rProps.getLength() + 1]); - PropertyMapEntry * pEntry(&pEntries[0]); - for (auto const& it : rProps) - { - pEntry->maName = it.Name; - pEntry->mnHandle = it.Handle; - pEntry->maType = it.Type; - pEntry->mnAttributes = it.Attributes; - pEntry->mnMemberId = 0; - ++pEntry; - } - pEntry->maName = OUString(); - - addImpl(pEntries); -} - PropertySetInfo::~PropertySetInfo() noexcept { } -void PropertySetInfo::add( PropertyMapEntry const * pMap ) noexcept +void PropertySetInfo::add( std::span<PropertyMapEntry const> pMap ) noexcept { - addImpl( pMap ); + maPropertyMap.reserve(maPropertyMap.size() + pMap.size()); + for (const auto & rEntry : pMap) + { + // check for duplicates + assert(maPropertyMap.find(rEntry.maName) == maPropertyMap.end()); + // Make sure there are no accidental empty entries left at the end of the array from + // when this method used to take a empty-terminated array. + assert(!rEntry.maName.isEmpty()); + + maPropertyMap.emplace(rEntry.maName, &rEntry); + } + + // clear cache + maProperties.realloc(0); } void PropertySetInfo::remove( const OUString& aName ) noexcept { maPropertyMap.erase( aName ); - maProperties.clear(); + maProperties.realloc(0); } Sequence< css::beans::Property > SAL_CALL PropertySetInfo::getProperties() @@ -101,8 +81,8 @@ Sequence< css::beans::Property > SAL_CALL PropertySetInfo::getProperties() // to getProperties if( maProperties.size() != maPropertyMap.size() ) { - maProperties.resize( maPropertyMap.size() ); - auto propIter = maProperties.begin(); + maProperties.realloc( maPropertyMap.size() ); + auto propIter = maProperties.getArray(); for( const auto& rProperty : maPropertyMap ) { @@ -116,7 +96,7 @@ Sequence< css::beans::Property > SAL_CALL PropertySetInfo::getProperties() ++propIter; } } - return comphelper::containerToSequence(maProperties); + return maProperties; } Property SAL_CALL PropertySetInfo::getPropertyByName( const OUString& aName ) @@ -133,7 +113,7 @@ Property SAL_CALL PropertySetInfo::getPropertyByName( const OUString& aName ) sal_Bool SAL_CALL PropertySetInfo::hasPropertyByName( const OUString& aName ) { - return maPropertyMap.find( aName ) != maPropertyMap.end(); + return maPropertyMap.contains( aName ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/property/propertystatecontainer.cxx b/comphelper/source/property/propertystatecontainer.cxx index e19e78733689..9ab7f534dc02 100644 --- a/comphelper/source/property/propertystatecontainer.cxx +++ b/comphelper/source/property/propertystatecontainer.cxx @@ -30,7 +30,6 @@ namespace comphelper using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; - using namespace ::com::sun::star::lang; namespace { @@ -90,46 +89,34 @@ namespace comphelper #ifdef DBG_UTIL // precondition: property sequence is sorted (the algorithm below relies on this) - { - const OUString* pNames = _rPropertyNames.getConstArray(); - const OUString* pNamesCompare = pNames + 1; - const OUString* pNamesEnd = _rPropertyNames.getConstArray() + _rPropertyNames.getLength(); - for ( ; pNamesCompare != pNamesEnd; ++pNames, ++pNamesCompare ) - OSL_PRECOND( pNames->compareTo( *pNamesCompare ) < 0, + OSL_PRECOND(std::is_sorted(_rPropertyNames.begin(), _rPropertyNames.end(), + [](auto& lhs, auto& rhs) { return lhs.compareTo(rhs) < 0; }), "OPropertyStateContainer::getPropertyStates: property sequence not sorted!" ); - } #endif - const OUString* pLookup = _rPropertyNames.getConstArray(); - const OUString* pLookupEnd = pLookup + nProperties; PropertyState* pStates = aStates.getArray(); cppu::IPropertyArrayHelper& rHelper = getInfoHelper(); Sequence< Property> aAllProperties = rHelper.getProperties(); - sal_Int32 nAllProperties = aAllProperties.getLength(); - const Property* pAllProperties = aAllProperties.getConstArray(); - const Property* pAllPropertiesEnd = pAllProperties + nAllProperties; +#ifdef DBG_UTIL + OSL_ENSURE(std::is_sorted(aAllProperties.begin(), aAllProperties.end(), + [](auto& lhs, auto& rhs) + { return lhs.Name.compareTo(rhs.Name) < 0; }), + "OPropertyStateContainer::getPropertyStates: all-properties not sorted!"); +#endif + auto it = aAllProperties.begin(); + const auto end = aAllProperties.end(); osl::MutexGuard aGuard( rBHelper.rMutex ); - for ( ; ( pAllProperties != pAllPropertiesEnd ) && ( pLookup != pLookupEnd ); ++pAllProperties ) + for (auto& propName : _rPropertyNames) { -#ifdef DBG_UTIL - if ( pAllProperties < pAllPropertiesEnd - 1 ) - OSL_ENSURE( pAllProperties->Name.compareTo( (pAllProperties + 1)->Name ) < 0, - "OPropertyStateContainer::getPropertyStates: all-properties not sorted!" ); -#endif - if ( pAllProperties->Name == *pLookup ) - { - *pStates++ = getPropertyState( *pLookup ); - ++pLookup; - } + it = std::find_if(it, end, [&propName](auto& prop) { return prop.Name == propName; }); + if (it == end) + throw UnknownPropertyException(lcl_getUnknownPropertyErrorMessage(propName), + static_cast<XPropertyState*>(this)); + *pStates++ = getPropertyStateByHandle(it->Handle); } - if ( pLookup != pLookupEnd ) - // we run out of properties from the IPropertyArrayHelper, but still have properties to lookup - // -> we were asked for a nonexistent property - throw UnknownPropertyException( lcl_getUnknownPropertyErrorMessage( *pLookup ), static_cast< XPropertyState* >( this ) ); - return aStates; } diff --git a/comphelper/source/property/propmultiplex2.cxx b/comphelper/source/property/propmultiplex2.cxx new file mode 100644 index 000000000000..b9d7719c4e1d --- /dev/null +++ b/comphelper/source/property/propmultiplex2.cxx @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <comphelper/propmultiplex2.hxx> +#include <osl/diagnose.h> + +namespace comphelper +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; + +OPropertyChangeListener2::~OPropertyChangeListener2() +{ + if (m_xAdapter.is()) + m_xAdapter->onListenerDestruction(); +} + +void OPropertyChangeListener2::disposeAdapter(std::unique_lock<std::mutex>& rGuard) +{ + if (m_xAdapter.is()) + m_xAdapter->dispose(rGuard); + + // will automatically set a new adapter + OSL_ENSURE(!m_xAdapter.is(), "OPropertyChangeListener::disposeAdapter: what did dispose do?"); +} + +void OPropertyChangeListener2::setAdapter(std::unique_lock<std::mutex>& /*rGuard*/, + OPropertyChangeMultiplexer2* pAdapter) +{ + m_xAdapter = pAdapter; +} + +OPropertyChangeMultiplexer2::OPropertyChangeMultiplexer2(std::mutex& rMutex, + std::unique_lock<std::mutex>& rGuard, + OPropertyChangeListener2* _pListener, + const Reference<XPropertySet>& _rxSet) + : m_rMutex(rMutex) + , m_xSet(_rxSet) + , m_pListener(_pListener) + , m_nLockCount(0) + , m_bListening(false) +{ + m_pListener->setAdapter(rGuard, this); +} + +OPropertyChangeMultiplexer2::~OPropertyChangeMultiplexer2() {} + +void OPropertyChangeMultiplexer2::lock() { ++m_nLockCount; } + +void OPropertyChangeMultiplexer2::unlock() { --m_nLockCount; } + +void OPropertyChangeMultiplexer2::dispose(std::unique_lock<std::mutex>& rGuard) +{ + if (!m_bListening) + return; + + Reference<XPropertyChangeListener> xPreventDelete(this); + + for (const OUString& rProp : m_aProperties) + m_xSet->removePropertyChangeListener(rProp, static_cast<XPropertyChangeListener*>(this)); + + m_pListener->setAdapter(rGuard, nullptr); + + m_pListener = nullptr; + m_bListening = false; + + m_xSet = nullptr; +} + +void OPropertyChangeMultiplexer2::onListenerDestruction() +{ + if (!m_bListening) + return; + + Reference<XPropertyChangeListener> xPreventDelete(this); + + for (const OUString& rProp : m_aProperties) + m_xSet->removePropertyChangeListener(rProp, static_cast<XPropertyChangeListener*>(this)); +} + +// XEventListener + +void SAL_CALL OPropertyChangeMultiplexer2::disposing(const EventObject& /*_rSource*/) +{ + std::unique_lock g(m_rMutex); + if (m_pListener) + { + // disconnect the listener + if (m_pListener) // may have been reset whilst calling into _disposing + m_pListener->setAdapter(g, nullptr); + } + + m_pListener = nullptr; + m_bListening = false; + + m_xSet = nullptr; +} + +// XPropertyChangeListener + +void SAL_CALL OPropertyChangeMultiplexer2::propertyChange(const PropertyChangeEvent& _rEvent) +{ + if (m_pListener && !locked()) + m_pListener->_propertyChanged(_rEvent); +} + +void OPropertyChangeMultiplexer2::addProperty(const OUString& _sPropertyName) +{ + if (m_xSet.is()) + { + m_xSet->addPropertyChangeListener(_sPropertyName, + static_cast<XPropertyChangeListener*>(this)); + m_aProperties.push_back(_sPropertyName); + m_bListening = true; + } +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/property/propshlp.cxx b/comphelper/source/property/propshlp.cxx new file mode 100644 index 000000000000..307f48a42cbc --- /dev/null +++ b/comphelper/source/property/propshlp.cxx @@ -0,0 +1,855 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <osl/diagnose.h> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <comphelper/propshlp.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <memory> +#include <sal/log.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace cppu; + +namespace comphelper +{ +extern "C" { + +static int compare_OUString_Property_Impl(const void* arg1, const void* arg2) SAL_THROW_EXTERN_C() +{ + return static_cast<OUString const*>(arg1)->compareTo(static_cast<Property const*>(arg2)->Name); +} +} + +/** + * The class which implements the PropertySetInfo interface. + */ + +namespace +{ +class OPropertySetHelperInfo_Impl : public WeakImplHelper<css::beans::XPropertySetInfo> +{ + Sequence<Property> aInfos; + +public: + explicit OPropertySetHelperInfo_Impl(IPropertyArrayHelper& rHelper_); + + // XPropertySetInfo-methods + virtual Sequence<Property> SAL_CALL getProperties() override; + virtual Property SAL_CALL getPropertyByName(const OUString& PropertyName) override; + virtual sal_Bool SAL_CALL hasPropertyByName(const OUString& PropertyName) override; +}; +} + +/** + * Create an object that implements XPropertySetInfo IPropertyArrayHelper. + */ +OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl(IPropertyArrayHelper& rHelper_) + : aInfos(rHelper_.getProperties()) +{ +} + +/** + * Return the sequence of properties, which are provided through the constructor. + */ +Sequence<Property> OPropertySetHelperInfo_Impl::getProperties() { return aInfos; } + +/** + * Return the sequence of properties, which are provided through the constructor. + */ +Property OPropertySetHelperInfo_Impl::getPropertyByName(const OUString& PropertyName) +{ + Property* pR + = static_cast<Property*>(bsearch(&PropertyName, aInfos.getConstArray(), aInfos.getLength(), + sizeof(Property), compare_OUString_Property_Impl)); + if (!pR) + throw UnknownPropertyException(PropertyName); + + return *pR; +} + +/** + * Return the sequence of properties, which are provided through the constructor. + */ +sal_Bool OPropertySetHelperInfo_Impl::hasPropertyByName(const OUString& PropertyName) +{ + Property* pR + = static_cast<Property*>(bsearch(&PropertyName, aInfos.getConstArray(), aInfos.getLength(), + sizeof(Property), compare_OUString_Property_Impl)); + return pR != nullptr; +} + +OPropertySetHelper::OPropertySetHelper() {} + +OPropertySetHelper::OPropertySetHelper(bool bIgnoreRuntimeExceptionsWhileFiring) + : m_bIgnoreRuntimeExceptionsWhileFiring(bIgnoreRuntimeExceptionsWhileFiring) +{ +} + +/** + * You must call disposing before. + */ +OPropertySetHelper::~OPropertySetHelper() {} + +// XInterface +Any OPropertySetHelper::queryInterface(const css::uno::Type& rType) +{ + return ::cppu::queryInterface(rType, static_cast<XPropertySet*>(this), + static_cast<XMultiPropertySet*>(this), + static_cast<XFastPropertySet*>(this)); +} + +/** + * called from the derivee's XTypeProvider::getTypes implementation + */ +css::uno::Sequence<css::uno::Type> OPropertySetHelper::getTypes() +{ + return { UnoType<css::beans::XPropertySet>::get(), + UnoType<css::beans::XMultiPropertySet>::get(), + UnoType<css::beans::XFastPropertySet>::get() }; +} + +// ComponentHelper +void OPropertySetHelper::disposing(std::unique_lock<std::mutex>& rGuard) +{ + // Create an event with this as sender + Reference<XPropertySet> rSource = this; + EventObject aEvt; + aEvt.Source = rSource; + + // inform all listeners to release this object + // The listener containers are automatically cleared + aBoundLC.disposeAndClear(rGuard, aEvt); + aVetoableLC.disposeAndClear(rGuard, aEvt); +} + +Reference<XPropertySetInfo> +OPropertySetHelper::createPropertySetInfo(IPropertyArrayHelper& rProperties) +{ + return new OPropertySetHelperInfo_Impl(rProperties); +} + +// XPropertySet +void OPropertySetHelper::setPropertyValue(const OUString& rPropertyName, const Any& rValue) +{ + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + // map the name to the handle + sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); + std::unique_lock aGuard(m_aMutex); + setFastPropertyValueImpl(aGuard, nHandle, rValue); +} + +// XPropertySet +Any OPropertySetHelper::getPropertyValue(const OUString& rPropertyName) +{ + std::unique_lock aGuard(m_aMutex); + return getPropertyValueImpl(aGuard, rPropertyName); +} + +Any OPropertySetHelper::getPropertyValueImpl(std::unique_lock<std::mutex>& rGuard, + const OUString& rPropertyName) +{ + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + // map the name to the handle + sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); + // call the method of the XFastPropertySet interface + Any aAny; + getFastPropertyValue(rGuard, aAny, nHandle); + return aAny; +} + +// XPropertySet +void OPropertySetHelper::addPropertyChangeListener( + const OUString& rPropertyName, const Reference<XPropertyChangeListener>& rxListener) +{ + std::unique_lock aGuard(m_aMutex); + OSL_ENSURE(!m_bDisposed, "object is disposed"); + if (m_bDisposed) + return; + + // only add listeners if you are not disposed + // a listener with no name means all properties + if (!rPropertyName.isEmpty()) + { + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + // map the name to the handle + sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); + if (nHandle == -1) + { + // property not known throw exception + throw UnknownPropertyException(rPropertyName); + } + + sal_Int16 nAttributes; + rPH.fillPropertyMembersByHandle(nullptr, &nAttributes, nHandle); + if (!(nAttributes & css::beans::PropertyAttribute::BOUND)) + { + OSL_FAIL("add listener to an unbound property"); + // silent ignore this + return; + } + // add the change listener to the helper container + aBoundLC.addInterface(aGuard, nHandle, rxListener); + } + else + // add the change listener to the helper container + maPropertyChangeListeners.addInterface(aGuard, rxListener); +} + +// XPropertySet +void OPropertySetHelper::removePropertyChangeListener( + const OUString& rPropertyName, const Reference<XPropertyChangeListener>& rxListener) +{ + std::unique_lock aGuard(m_aMutex); + OSL_ENSURE(!m_bDisposed, "object is disposed"); + // all listeners are automatically released in a dispose call + if (m_bDisposed) + return; + + if (!rPropertyName.isEmpty()) + { + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + // map the name to the handle + sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); + if (nHandle == -1) + // property not known throw exception + throw UnknownPropertyException(rPropertyName); + aBoundLC.removeInterface(aGuard, nHandle, rxListener); + } + else + { + // remove the change listener to the helper container + maPropertyChangeListeners.removeInterface(aGuard, rxListener); + } +} + +// XPropertySet +void OPropertySetHelper::addVetoableChangeListener( + const OUString& rPropertyName, const Reference<XVetoableChangeListener>& rxListener) +{ + std::unique_lock aGuard(m_aMutex); + OSL_ENSURE(!m_bDisposed, "object is disposed"); + if (m_bDisposed) + return; + + // only add listeners if you are not disposed + // a listener with no name means all properties + if (!rPropertyName.isEmpty()) + { + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + // map the name to the handle + sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); + if (nHandle == -1) + { + // property not known throw exception + throw UnknownPropertyException(rPropertyName); + } + + sal_Int16 nAttributes; + rPH.fillPropertyMembersByHandle(nullptr, &nAttributes, nHandle); + if (!(nAttributes & PropertyAttribute::CONSTRAINED)) + { + OSL_FAIL("addVetoableChangeListener, and property is not constrained"); + // silent ignore this + return; + } + // add the vetoable listener to the helper container + aVetoableLC.addInterface(aGuard, nHandle, rxListener); + } + else + // add the vetoable listener to the helper container + maVetoableChangeListeners.addInterface(aGuard, rxListener); +} + +// XPropertySet +void OPropertySetHelper::removeVetoableChangeListener( + const OUString& rPropertyName, const Reference<XVetoableChangeListener>& rxListener) +{ + std::unique_lock aGuard(m_aMutex); + OSL_ENSURE(!m_bDisposed, "object is disposed"); + // all listeners are automatically released in a dispose call + if (m_bDisposed) + return; + + if (!rPropertyName.isEmpty()) + { + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + // map the name to the handle + sal_Int32 nHandle = rPH.getHandleByName(rPropertyName); + if (nHandle == -1) + { + // property not known throw exception + throw UnknownPropertyException(rPropertyName); + } + // remove the vetoable listener to the helper container + aVetoableLC.removeInterface(aGuard, nHandle, rxListener); + } + else + // add the vetoable listener to the helper container + maVetoableChangeListeners.removeInterface(aGuard, rxListener); +} + +void OPropertySetHelper::setDependentFastPropertyValue(std::unique_lock<std::mutex>& rGuard, + sal_Int32 i_handle, + const css::uno::Any& i_value) +{ + sal_Int16 nAttributes(0); + IPropertyArrayHelper& rInfo = getInfoHelper(); + if (!rInfo.fillPropertyMembersByHandle(nullptr, &nAttributes, i_handle)) + // unknown property + throw UnknownPropertyException(OUString::number(i_handle)); + + // no need to check for READONLY-ness of the property. The method is intended to be called internally, which + // implies it might be invoked for properties which are read-only to the instance's clients, but well allowed + // to change their value. + + Any aConverted, aOld; + bool bChanged = convertFastPropertyValue(rGuard, aConverted, aOld, i_handle, i_value); + if (!bChanged) + return; + + // don't fire vetoable events. This method is called with our mutex locked, so calling into listeners would not be + // a good idea. The caller is responsible for not invoking this for constrained properties. + OSL_ENSURE((nAttributes & PropertyAttribute::CONSTRAINED) == 0, + "OPropertySetHelper::setDependentFastPropertyValue: not to be used for constrained " + "properties!"); + + // actually set the new value + try + { + setFastPropertyValue_NoBroadcast(rGuard, i_handle, aConverted); + } + catch (const UnknownPropertyException&) + { + throw; /* allowed to leave */ + } + catch (const PropertyVetoException&) + { + throw; /* allowed to leave */ + } + catch (const IllegalArgumentException&) + { + throw; /* allowed to leave */ + } + catch (const WrappedTargetException&) + { + throw; /* allowed to leave */ + } + catch (const RuntimeException&) + { + throw; /* allowed to leave */ + } + catch (const Exception&) + { + // not allowed to leave this method + WrappedTargetException aWrapped; + aWrapped.TargetException = ::cppu::getCaughtException(); + aWrapped.Context = static_cast<XPropertySet*>(this); + throw aWrapped; + } + + // remember the handle/values, for the events to be fired later + m_handles.push_back(i_handle); + m_newValues.push_back( + aConverted); // TODO: setFastPropertyValue notifies the unconverted value here ...? + m_oldValues.push_back(aOld); +} + +// XFastPropertySet +void OPropertySetHelper::setFastPropertyValue(sal_Int32 nHandle, const Any& rValue) +{ + std::unique_lock aGuard(m_aMutex); + setFastPropertyValueImpl(aGuard, nHandle, rValue); +} + +void OPropertySetHelper::setFastPropertyValueImpl(std::unique_lock<std::mutex>& rGuard, + sal_Int32 nHandle, const Any& rValue) +{ + OSL_ENSURE(!m_bDisposed, "object is disposed"); + + IPropertyArrayHelper& rInfo = getInfoHelper(); + sal_Int16 nAttributes; + if (!rInfo.fillPropertyMembersByHandle(nullptr, &nAttributes, nHandle)) + { + // unknown property + throw UnknownPropertyException(OUString::number(nHandle)); + } + if (nAttributes & PropertyAttribute::READONLY) + throw PropertyVetoException(); + + Any aConvertedVal; + Any aOldVal; + + // Will the property change? + bool bChanged = convertFastPropertyValue(rGuard, aConvertedVal, aOldVal, nHandle, rValue); + if (!bChanged) + return; + + // Is it a constrained property? + if (nAttributes & PropertyAttribute::CONSTRAINED) + { + // In aValue is the converted rValue + // fire a constrained event + // second parameter NULL means constrained + fire(rGuard, &nHandle, &rValue, &aOldVal, 1, true); + } + + try + { + // set the property to the new value + setFastPropertyValue_NoBroadcast(rGuard, nHandle, aConvertedVal); + } + catch (const css::beans::UnknownPropertyException&) + { + throw; /* allowed to leave */ + } + catch (const css::beans::PropertyVetoException&) + { + throw; /* allowed to leave */ + } + catch (const css::lang::IllegalArgumentException&) + { + throw; /* allowed to leave */ + } + catch (const css::lang::WrappedTargetException&) + { + throw; /* allowed to leave */ + } + catch (const css::uno::RuntimeException&) + { + throw; /* allowed to leave */ + } + catch (const css::uno::Exception& e) + { + // not allowed to leave this method + css::lang::WrappedTargetException aWrap; + aWrap.Context = static_cast<css::beans::XPropertySet*>(this); + aWrap.TargetException <<= e; + + throw aWrap; + } + + // file a change event, if the value changed + impl_fireAll(rGuard, &nHandle, &rValue, &aOldVal, 1); +} + +// XFastPropertySet +Any OPropertySetHelper::getFastPropertyValue(sal_Int32 nHandle) +{ + IPropertyArrayHelper& rInfo = getInfoHelper(); + if (!rInfo.fillPropertyMembersByHandle(nullptr, nullptr, nHandle)) + // unknown property + throw UnknownPropertyException(OUString::number(nHandle)); + + Any aRet; + std::unique_lock aGuard(m_aMutex); + getFastPropertyValue(aGuard, aRet, nHandle); + return aRet; +} + +void OPropertySetHelper::impl_fireAll(std::unique_lock<std::mutex>& rGuard, sal_Int32* i_handles, + const Any* i_newValues, const Any* i_oldValues, + sal_Int32 i_count) +{ + if (m_handles.empty()) + { + fire(rGuard, i_handles, i_newValues, i_oldValues, i_count, false); + return; + } + + const size_t additionalEvents = m_handles.size(); + OSL_ENSURE(additionalEvents == m_newValues.size() && additionalEvents == m_oldValues.size(), + "OPropertySetHelper::impl_fireAll: inconsistency!"); + + std::vector<sal_Int32> allHandles(additionalEvents + i_count); + std::copy(m_handles.begin(), m_handles.end(), allHandles.begin()); + std::copy(i_handles, i_handles + i_count, allHandles.begin() + additionalEvents); + + std::vector<Any> allNewValues(additionalEvents + i_count); + std::copy(m_newValues.begin(), m_newValues.end(), allNewValues.begin()); + std::copy(i_newValues, i_newValues + i_count, allNewValues.begin() + additionalEvents); + + std::vector<Any> allOldValues(additionalEvents + i_count); + std::copy(m_oldValues.begin(), m_oldValues.end(), allOldValues.begin()); + std::copy(i_oldValues, i_oldValues + i_count, allOldValues.begin() + additionalEvents); + + m_handles.clear(); + m_newValues.clear(); + m_oldValues.clear(); + + fire(rGuard, allHandles.data(), allNewValues.data(), allOldValues.data(), + additionalEvents + i_count, false); +} + +void OPropertySetHelper::fire(std::unique_lock<std::mutex>& rGuard, sal_Int32* pnHandles, + const Any* pNewValues, const Any* pOldValues, + sal_Int32 nHandles, // This is the Count of the array + bool bVetoable) +{ + // Only fire, if one or more properties changed + if (!nHandles) + return; + + // create the event sequence of all changed properties + Sequence<PropertyChangeEvent> aEvts(nHandles); + PropertyChangeEvent* pEvts = aEvts.getArray(); + Reference<XInterface> xSource(static_cast<XPropertySet*>(this), UNO_QUERY); + sal_Int32 i; + sal_Int32 nChangesLen = 0; + // Loop over all changed properties to fill the event struct + for (i = 0; i < nHandles; i++) + { + // Vetoable fire and constrained attribute set or + // Change fire and Changed and bound attribute set + IPropertyArrayHelper& rInfo = getInfoHelper(); + sal_Int16 nAttributes; + OUString aPropName; + rInfo.fillPropertyMembersByHandle(&aPropName, &nAttributes, pnHandles[i]); + + if ((bVetoable && (nAttributes & PropertyAttribute::CONSTRAINED)) + || (!bVetoable && (nAttributes & PropertyAttribute::BOUND))) + { + pEvts[nChangesLen].Source = xSource; + pEvts[nChangesLen].PropertyName = aPropName; + pEvts[nChangesLen].PropertyHandle = pnHandles[i]; + pEvts[nChangesLen].OldValue = pOldValues[i]; + pEvts[nChangesLen].NewValue = pNewValues[i]; + nChangesLen++; + } + } + + bool bIgnoreRuntimeExceptionsWhileFiring = m_bIgnoreRuntimeExceptionsWhileFiring; + + // fire the events for all changed properties + for (i = 0; i < nChangesLen; i++) + { + if (bVetoable) // fire change Events? + fireVetoableChangeListeners( + rGuard, aVetoableLC.getContainer(rGuard, pEvts[i].PropertyHandle), pEvts[i]); + else + // get the listener container for the property name + firePropertyChangeListeners( + rGuard, aBoundLC.getContainer(rGuard, pEvts[i].PropertyHandle), pEvts[i]); + + // broadcast to all listeners with "" property name + if (bVetoable) + // fire change Events? + fireVetoableChangeListeners(rGuard, &maVetoableChangeListeners, pEvts[i]); + else + firePropertyChangeListeners(rGuard, &maPropertyChangeListeners, pEvts[i]); + } + + // reduce array to changed properties + aEvts.realloc(nChangesLen); + + if (bVetoable) + return; + + if (!maPropertiesChangeListeners.getLength(rGuard)) + return; + + // Here is a Bug, unbound properties are also fired + OInterfaceIteratorHelper4 aIt(rGuard, maPropertiesChangeListeners); + rGuard.unlock(); + while (aIt.hasMoreElements()) + { + XPropertiesChangeListener* pL = aIt.next().get(); + try + { + try + { + // fire the whole event sequence to the + // XPropertiesChangeListener's + pL->propertiesChange(aEvts); + } + catch (DisposedException& exc) + { + OSL_ENSURE(exc.Context.is(), "DisposedException without Context!"); + if (exc.Context == pL) + { + rGuard.lock(); + aIt.remove(rGuard); + rGuard.unlock(); + } + else + throw; + } + } + catch (RuntimeException& exc) + { + SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc); + if (!bIgnoreRuntimeExceptionsWhileFiring) + throw; + } + } + rGuard.lock(); +} + +void OPropertySetHelper::fireVetoableChangeListeners( + std::unique_lock<std::mutex>& rGuard, + comphelper::OInterfaceContainerHelper4<css::beans::XVetoableChangeListener>* pListeners, + const css::beans::PropertyChangeEvent& rChangeEvent) +{ + if (!pListeners || !pListeners->getLength(rGuard)) + return; + // Iterate over all listeners and send events + OInterfaceIteratorHelper4 aIt(rGuard, *pListeners); + rGuard.unlock(); + while (aIt.hasMoreElements()) + { + XVetoableChangeListener* pL = aIt.next().get(); + try + { + try + { + pL->vetoableChange(rChangeEvent); + } + catch (DisposedException& exc) + { + OSL_ENSURE(exc.Context.is(), "DisposedException without Context!"); + if (exc.Context == pL) + { + rGuard.lock(); + aIt.remove(rGuard); + rGuard.unlock(); + } + else + throw; + } + } + catch (RuntimeException& exc) + { + SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc); + if (!m_bIgnoreRuntimeExceptionsWhileFiring) + throw; + } + } + rGuard.lock(); +} + +void OPropertySetHelper::firePropertyChangeListeners( + std::unique_lock<std::mutex>& rGuard, + comphelper::OInterfaceContainerHelper4<css::beans::XPropertyChangeListener>* pListeners, + const css::beans::PropertyChangeEvent& rChangeEvent) +{ + if (!pListeners || !pListeners->getLength(rGuard)) + return; + // Iterate over all listeners and send events + OInterfaceIteratorHelper4 aIt(rGuard, *pListeners); + rGuard.unlock(); + while (aIt.hasMoreElements()) + { + XPropertyChangeListener* pL = aIt.next().get(); + try + { + try + { + pL->propertyChange(rChangeEvent); + } + catch (DisposedException& exc) + { + OSL_ENSURE(exc.Context.is(), "DisposedException without Context!"); + if (exc.Context == pL) + { + rGuard.lock(); + aIt.remove(rGuard); + rGuard.unlock(); + } + else + throw; + } + } + catch (RuntimeException& exc) + { + SAL_INFO("cppuhelper", "caught RuntimeException while firing listeners: " << exc); + if (!m_bIgnoreRuntimeExceptionsWhileFiring) + throw; + } + } + rGuard.lock(); +} + +// OPropertySetHelper +void OPropertySetHelper::setFastPropertyValues(std::unique_lock<std::mutex>& rGuard, + sal_Int32 nSeqLen, sal_Int32* pHandles, + const Any* pValues, sal_Int32 nHitCount) +{ + OSL_ENSURE(!m_bDisposed, "object is disposed"); + + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + + std::unique_ptr<Any[]> pConvertedValues(new Any[nHitCount]); + std::unique_ptr<Any[]> pOldValues(new Any[nHitCount]); + sal_Int32 n = 0; + sal_Int32 i; + + for (i = 0; i < nSeqLen; i++) + { + if (pHandles[i] != -1) + { + sal_Int16 nAttributes; + rPH.fillPropertyMembersByHandle(nullptr, &nAttributes, pHandles[i]); + if (nAttributes & PropertyAttribute::READONLY) + throw PropertyVetoException(); + // Will the property change? + if (convertFastPropertyValue(rGuard, pConvertedValues[n], pOldValues[n], pHandles[i], + pValues[i])) + { + // only increment if the property really change + pHandles[n] = pHandles[i]; + n++; + } + } + } + + // fire vetoable events + fire(rGuard, pHandles, pConvertedValues.get(), pOldValues.get(), n, true); + + // Loop over all changed properties + for (i = 0; i < n; i++) + { + // Will the property change? + setFastPropertyValue_NoBroadcast(rGuard, pHandles[i], pConvertedValues[i]); + } + + // fire change events + impl_fireAll(rGuard, pHandles, pConvertedValues.get(), pOldValues.get(), n); +} + +// XMultiPropertySet +/** + * The sequence may be contain not known properties. The implementation + * must ignore these properties. + */ +void OPropertySetHelper::setPropertyValues(const Sequence<OUString>& rPropertyNames, + const Sequence<Any>& rValues) +{ + sal_Int32 nSeqLen = rPropertyNames.getLength(); + if (nSeqLen != rValues.getLength()) + throw IllegalArgumentException("lengths do not match", static_cast<XPropertySet*>(this), + -1); + std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[nSeqLen]); + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + // fill the handle array + sal_Int32 nHitCount = rPH.fillHandles(pHandles.get(), rPropertyNames); + if (nHitCount == 0) + return; + std::unique_lock aGuard(m_aMutex); + setFastPropertyValues(aGuard, nSeqLen, pHandles.get(), rValues.getConstArray(), nHitCount); +} + +// XMultiPropertySet +Sequence<Any> OPropertySetHelper::getPropertyValues(const Sequence<OUString>& rPropertyNames) +{ + sal_Int32 nSeqLen = rPropertyNames.getLength(); + std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[nSeqLen]); + Sequence<Any> aValues(nSeqLen); + + // get the map table + IPropertyArrayHelper& rPH = getInfoHelper(); + // fill the handle array + rPH.fillHandles(pHandles.get(), rPropertyNames); + + Any* pValues = aValues.getArray(); + + std::unique_lock aGuard(m_aMutex); + // fill the sequence with the values + for (sal_Int32 i = 0; i < nSeqLen; i++) + getFastPropertyValue(aGuard, pValues[i], pHandles[i]); + + return aValues; +} + +// XMultiPropertySet +void OPropertySetHelper::addPropertiesChangeListener( + const Sequence<OUString>&, const Reference<XPropertiesChangeListener>& rListener) +{ + std::unique_lock g(m_aMutex); + maPropertiesChangeListeners.addInterface(g, rListener); +} + +// XMultiPropertySet +void OPropertySetHelper::removePropertiesChangeListener( + const Reference<XPropertiesChangeListener>& rListener) +{ + std::unique_lock g(m_aMutex); + maPropertiesChangeListeners.removeInterface(g, rListener); +} + +// XMultiPropertySet +void OPropertySetHelper::firePropertiesChangeEvent( + const Sequence<OUString>& rPropertyNames, const Reference<XPropertiesChangeListener>& rListener) +{ + sal_Int32 nLen = rPropertyNames.getLength(); + std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[nLen]); + IPropertyArrayHelper& rPH = getInfoHelper(); + rPH.fillHandles(pHandles.get(), rPropertyNames); + + // get the count of matching properties + sal_Int32 nFireLen = 0; + sal_Int32 i; + for (i = 0; i < nLen; i++) + if (pHandles[i] != -1) + nFireLen++; + + Sequence<PropertyChangeEvent> aChanges(nFireLen); + PropertyChangeEvent* pChanges = aChanges.getArray(); + + { + // must lock the mutex outside the loop. So all values are consistent. + std::unique_lock aGuard(m_aMutex); + Reference<XInterface> xSource(static_cast<XPropertySet*>(this), UNO_QUERY); + sal_Int32 nFirePos = 0; + for (i = 0; i < nLen; i++) + { + if (pHandles[i] != -1) + { + pChanges[nFirePos].Source = xSource; + pChanges[nFirePos].PropertyName = rPropertyNames[i]; + pChanges[nFirePos].PropertyHandle = pHandles[i]; + getFastPropertyValue(aGuard, pChanges[nFirePos].OldValue, pHandles[i]); + pChanges[nFirePos].NewValue = pChanges[nFirePos].OldValue; + nFirePos++; + } + } + // release guard to fire events + } + if (nFireLen) + rListener->propertiesChange(aChanges); +} + +UnoImplBase::~UnoImplBase() {} + +} // end namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/property/propstate.cxx b/comphelper/source/property/propstate.cxx index 183f51efcedf..20deab1963ee 100644 --- a/comphelper/source/property/propstate.cxx +++ b/comphelper/source/property/propstate.cxx @@ -115,25 +115,22 @@ namespace comphelper sal_Int32 nLen = _rPropertyNames.getLength(); css::uno::Sequence< css::beans::PropertyState> aRet(nLen); css::beans::PropertyState* pValues = aRet.getArray(); - const OUString* pNames = _rPropertyNames.getConstArray(); cppu::IPropertyArrayHelper& rHelper = getInfoHelper(); css::uno::Sequence< css::beans::Property> aProps = rHelper.getProperties(); - const css::beans::Property* pProps = aProps.getConstArray(); - sal_Int32 nPropCount = aProps.getLength(); + auto it = aProps.begin(); + const auto end = aProps.end(); osl::MutexGuard aGuard(rBHelper.rMutex); - for (sal_Int32 i=0, j=0; i<nPropCount && j<nLen; ++i, ++pProps) + // Assumption is that both _rPropertyNames and aProps are sorted + for (auto& propName : _rPropertyNames) { // get the values only for valid properties - if (pProps->Name == *pNames) - { - *pValues = getPropertyState(*pNames); - ++pValues; - ++pNames; - ++j; - } + it = std::find_if(it, end, [&propName](auto& prop) { return prop.Name == propName; }); + if (it == end) + break; + *pValues++ = getPropertyStateByHandle(it->Handle); } return aRet; diff --git a/comphelper/source/streaming/basicio.cxx b/comphelper/source/streaming/basicio.cxx index d86427b7de81..534d8b4cd0a1 100644 --- a/comphelper/source/streaming/basicio.cxx +++ b/comphelper/source/streaming/basicio.cxx @@ -18,6 +18,8 @@ */ #include <comphelper/basicio.hxx> +#include <comphelper/bytereader.hxx> +#include <comphelper/servicehelper.hxx> #include <com/sun/star/awt/FontDescriptor.hpp> namespace comphelper @@ -157,6 +159,9 @@ const css::uno::Reference<css::io::XObjectOutputStream>& operator << (const css: return _rxOutStream; } +ByteReader::~ByteReader() {} + +ByteWriter::~ByteWriter() {} } // namespace comphelper diff --git a/comphelper/source/streaming/memorystream.cxx b/comphelper/source/streaming/memorystream.cxx index b8ff86e03b17..20d0fbd5766a 100644 --- a/comphelper/source/streaming/memorystream.cxx +++ b/comphelper/source/streaming/memorystream.cxx @@ -18,16 +18,23 @@ */ #include <algorithm> +#include <cassert> +#include <memory> + +#include <boost/core/noinit_adaptor.hpp> #include <com/sun/star/lang/IllegalArgumentException.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> #include <com/sun/star/io/IOException.hpp> #include <com/sun/star/io/XStream.hpp> #include <com/sun/star/io/XSeekableInputStream.hpp> #include <com/sun/star/io/XTruncate.hpp> //#include <com/sun/star/uno/XComponentContext.hpp> +#include <comphelper/bytereader.hxx> #include <cppuhelper/implbase.hxx> #include <cppuhelper/supportsservice.hxx> +#include <o3tl/safeint.hxx> #include <osl/diagnose.h> #include <string.h> @@ -40,14 +47,15 @@ using ::cppu::WeakImplHelper; using namespace ::com::sun::star::io; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; -using namespace ::osl; namespace comphelper { namespace { -class UNOMemoryStream : public WeakImplHelper<XServiceInfo, XStream, XSeekableInputStream, XOutputStream, XTruncate> +class UNOMemoryStream : + public WeakImplHelper<XServiceInfo, XStream, XSeekableInputStream, XOutputStream, XTruncate>, + public comphelper::ByteWriter { public: UNOMemoryStream(); @@ -81,8 +89,11 @@ public: // XTruncate virtual void SAL_CALL truncate() override; + // comphelper::ByteWriter + virtual void writeBytes(const sal_Int8* aData, sal_Int32 nBytesToWrite) override; + private: - std::vector< sal_Int8 > maData; + std::vector< sal_Int8, boost::noinit_adaptor<std::allocator<sal_Int8>> > maData; sal_Int32 mnCursor; }; @@ -91,6 +102,7 @@ private: UNOMemoryStream::UNOMemoryStream() : mnCursor(0) { + maData.reserve(1 * 1024 * 1024); } // XServiceInfo @@ -133,7 +145,7 @@ sal_Int32 SAL_CALL UNOMemoryStream::readBytes( Sequence< sal_Int8 >& aData, sal_ { sal_Int8* pData = &(*maData.begin()); sal_Int8* pCursor = &(pData[mnCursor]); - memcpy( static_cast<void*>(aData.getArray()), static_cast<void*>(pCursor), nBytesToRead ); + memcpy( aData.getArray(), pCursor, nBytesToRead ); mnCursor += nBytesToRead; } @@ -171,7 +183,7 @@ void SAL_CALL UNOMemoryStream::seek( sal_Int64 location ) throw IllegalArgumentException("this implementation does not support more than 2GB!", static_cast<OWeakObject*>(this), 0 ); // seek operation should be able to resize the stream - if ( location > static_cast< sal_Int64 >( maData.size() ) ) + if ( o3tl::make_unsigned(location) > maData.size() ) maData.resize( static_cast< sal_Int32 >( location ) ); mnCursor = static_cast< sal_Int32 >( location ); @@ -190,7 +202,12 @@ sal_Int64 SAL_CALL UNOMemoryStream::getLength() // XOutputStream void SAL_CALL UNOMemoryStream::writeBytes( const Sequence< sal_Int8 >& aData ) { - const sal_Int32 nBytesToWrite( aData.getLength() ); + writeBytes(aData.getConstArray(), aData.getLength()); +} + +void UNOMemoryStream::writeBytes( const sal_Int8* pInData, sal_Int32 nBytesToWrite ) +{ + assert(nBytesToWrite >= 0); if( !nBytesToWrite ) return; @@ -201,12 +218,12 @@ void SAL_CALL UNOMemoryStream::writeBytes( const Sequence< sal_Int8 >& aData ) throw IOException("this implementation does not support more than 2GB!", static_cast<OWeakObject*>(this) ); } - if( static_cast< sal_Int32 >( nNewSize ) > static_cast< sal_Int32 >( maData.size() ) ) + if( o3tl::make_unsigned( nNewSize ) > maData.size() ) maData.resize( nNewSize ); sal_Int8* pData = &(*maData.begin()); sal_Int8* pCursor = &(pData[mnCursor]); - memcpy( pCursor, aData.getConstArray(), nBytesToWrite ); + memcpy(pCursor, pInData, nBytesToWrite); mnCursor += nBytesToWrite; } diff --git a/comphelper/source/streaming/seekableinput.cxx b/comphelper/source/streaming/seekableinput.cxx index bd30aa354620..264feaeb3071 100644 --- a/comphelper/source/streaming/seekableinput.cxx +++ b/comphelper/source/streaming/seekableinput.cxx @@ -24,8 +24,10 @@ #include <com/sun/star/io/TempFile.hpp> #include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> #include <comphelper/seekableinput.hxx> +#include <utility> using namespace ::com::sun::star; @@ -57,13 +59,13 @@ static void copyInputToOutput_Impl( const uno::Reference< io::XInputStream >& xI OSeekableInputWrapper::OSeekableInputWrapper( - const uno::Reference< io::XInputStream >& xInStream, - const uno::Reference< uno::XComponentContext >& rxContext ) -: m_xContext( rxContext ) -, m_xOriginalStream( xInStream ) + uno::Reference< io::XInputStream > xInStream, + uno::Reference< uno::XComponentContext > xContext ) +: m_xContext(std::move( xContext )) +, m_xOriginalStream(std::move( xInStream )) { if ( !m_xContext.is() ) - throw uno::RuntimeException(); + throw lang::IllegalArgumentException("no component context", *this, 1); } @@ -90,7 +92,7 @@ void OSeekableInputWrapper::PrepareCopy_Impl() if ( !m_xCopyInput.is() ) { if ( !m_xContext.is() ) - throw uno::RuntimeException(); + throw uno::RuntimeException("no component context"); uno::Reference< io::XOutputStream > xTempOut( io::TempFile::create(m_xContext), diff --git a/comphelper/source/streaming/seqinputstreamserv.cxx b/comphelper/source/streaming/seqinputstreamserv.cxx index 25596f17473c..22fe8f8f0ea1 100644 --- a/comphelper/source/streaming/seqinputstreamserv.cxx +++ b/comphelper/source/streaming/seqinputstreamserv.cxx @@ -19,7 +19,6 @@ #include <sal/config.h> -#include <osl/mutex.hxx> #include <cppuhelper/implbase.hxx> #include <cppuhelper/supportsservice.hxx> #include <comphelper/seqstream.hxx> @@ -197,9 +196,8 @@ void SAL_CALL SequenceInputStreamService::initialize( const uno::Sequence< css:: uno::Reference< io::XInputStream > xInputStream( static_cast< ::cppu::OWeakObject* >( new ::comphelper::SequenceInputStream( aSeq ) ), uno::UNO_QUERY_THROW ); - uno::Reference< io::XSeekable > xSeekable( xInputStream, uno::UNO_QUERY_THROW ); + m_xSeekable.set(xInputStream, uno::UNO_QUERY_THROW); m_xInputStream = xInputStream; - m_xSeekable = xSeekable; m_bInitialized = true; } diff --git a/comphelper/source/streaming/seqoutputstreamserv.cxx b/comphelper/source/streaming/seqoutputstreamserv.cxx index 84900014aad4..19ef79002978 100644 --- a/comphelper/source/streaming/seqoutputstreamserv.cxx +++ b/comphelper/source/streaming/seqoutputstreamserv.cxx @@ -19,7 +19,6 @@ #include <sal/config.h> -#include <osl/mutex.hxx> #include <cppuhelper/implbase.hxx> #include <cppuhelper/supportsservice.hxx> #include <comphelper/seqstream.hxx> @@ -63,8 +62,9 @@ private: std::mutex m_aMutex; - uno::Reference< io::XOutputStream > m_xOutputStream; + // WARNING: dtor of m_xOutputStream writes into m_aSequence so that must live longer! uno::Sequence< ::sal_Int8 > m_aSequence; + uno::Reference< io::XOutputStream > m_xOutputStream; }; SequenceOutputStreamService::SequenceOutputStreamService() { diff --git a/comphelper/source/streaming/seqstream.cxx b/comphelper/source/streaming/seqstream.cxx index db39a1dc30e8..c7bfde712c74 100644 --- a/comphelper/source/streaming/seqstream.cxx +++ b/comphelper/source/streaming/seqstream.cxx @@ -31,31 +31,31 @@ namespace comphelper using namespace ::com::sun::star::lang; using namespace ::com::sun::star::io; using namespace ::com::sun::star::uno; -using namespace ::osl; -SequenceInputStream::SequenceInputStream( - css::uno::Sequence<sal_Int8> const & rData) -: m_aData(rData) +MemoryInputStream::MemoryInputStream( + const sal_Int8* pData, sal_Int32 nDataLength) +: m_pMemoryData(pData) +, m_nMemoryDataLength(nDataLength) , m_nPos(0) { } // checks if closed, returns available size, not mutex-protected -inline sal_Int32 SequenceInputStream::avail() +inline sal_Int32 MemoryInputStream::avail() { if (m_nPos == -1) throw NotConnectedException(OUString(), *this); - return m_aData.getLength() - m_nPos; + return m_nMemoryDataLength - m_nPos; } // css::io::XInputStream -sal_Int32 SAL_CALL SequenceInputStream::readBytes( Sequence<sal_Int8>& aData, sal_Int32 nBytesToRead ) +sal_Int32 SAL_CALL MemoryInputStream::readBytes( Sequence<sal_Int8>& aData, sal_Int32 nBytesToRead ) { if (nBytesToRead < 0) throw BufferSizeExceededException(OUString(),*this); @@ -68,21 +68,38 @@ sal_Int32 SAL_CALL SequenceInputStream::readBytes( Sequence<sal_Int8>& aData, sa nBytesToRead = nAvail; aData.realloc(nBytesToRead); - memcpy(aData.getArray(), m_aData.getConstArray() + m_nPos, nBytesToRead); + memcpy(aData.getArray(), m_pMemoryData + m_nPos, nBytesToRead); m_nPos += nBytesToRead; return nBytesToRead; } +sal_Int32 MemoryInputStream::readSomeBytes( sal_Int8* pData, sal_Int32 nBytesToRead ) +{ + if (nBytesToRead < 0) + throw BufferSizeExceededException(OUString(),*this); + + std::scoped_lock aGuard( m_aMutex ); + + sal_Int32 nAvail = avail(); + + if (nAvail < nBytesToRead) + nBytesToRead = nAvail; + + memcpy(pData, m_pMemoryData + m_nPos, nBytesToRead); + m_nPos += nBytesToRead; + + return nBytesToRead; +} -sal_Int32 SAL_CALL SequenceInputStream::readSomeBytes( Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead ) +sal_Int32 SAL_CALL MemoryInputStream::readSomeBytes( Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead ) { // all data is available at once return readBytes(aData, nMaxBytesToRead); } -void SAL_CALL SequenceInputStream::skipBytes( sal_Int32 nBytesToSkip ) +void SAL_CALL MemoryInputStream::skipBytes( sal_Int32 nBytesToSkip ) { if (nBytesToSkip < 0) throw BufferSizeExceededException(OUString(),*this); @@ -98,7 +115,7 @@ void SAL_CALL SequenceInputStream::skipBytes( sal_Int32 nBytesToSkip ) } -sal_Int32 SAL_CALL SequenceInputStream::available( ) +sal_Int32 SAL_CALL MemoryInputStream::available( ) { std::scoped_lock aGuard( m_aMutex ); @@ -106,7 +123,7 @@ sal_Int32 SAL_CALL SequenceInputStream::available( ) } -void SAL_CALL SequenceInputStream::closeInput( ) +void SAL_CALL MemoryInputStream::closeInput( ) { std::scoped_lock aGuard( m_aMutex ); @@ -116,24 +133,31 @@ void SAL_CALL SequenceInputStream::closeInput( ) m_nPos = -1; } -void SAL_CALL SequenceInputStream::seek( sal_Int64 location ) +void SAL_CALL MemoryInputStream::seek( sal_Int64 location ) { - if ( location > m_aData.getLength() || location < 0 || location > SAL_MAX_INT32 ) + if ( location > m_nMemoryDataLength || location < 0 || location > SAL_MAX_INT32 ) throw IllegalArgumentException("bad location", static_cast<cppu::OWeakObject*>(this), 1); std::scoped_lock aGuard( m_aMutex ); m_nPos = static_cast<sal_Int32>(location); } -sal_Int64 SAL_CALL SequenceInputStream::getPosition() +sal_Int64 SAL_CALL MemoryInputStream::getPosition() { std::scoped_lock aGuard( m_aMutex ); return m_nPos; } -sal_Int64 SAL_CALL SequenceInputStream::getLength( ) +sal_Int64 SAL_CALL MemoryInputStream::getLength( ) +{ + return m_nMemoryDataLength; +} + + +SequenceInputStream::SequenceInputStream( + css::uno::Sequence<sal_Int8> const & rData) +: MemoryInputStream(rData.getConstArray(), rData.getLength()) +, m_aData(rData) { - std::scoped_lock aGuard( m_aMutex ); - return m_aData.getLength(); } diff --git a/comphelper/source/windows/windows_process.cxx b/comphelper/source/windows/windows_process.cxx index 7588bae027e5..8e7fd19f0b30 100644 --- a/comphelper/source/windows/windows_process.cxx +++ b/comphelper/source/windows/windows_process.cxx @@ -241,7 +241,7 @@ WinLaunchChild(const wchar_t *exePath, } else { - LPVOID lpMsgBuf = nullptr; + LPWSTR lpMsgBuf = nullptr; FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, diff --git a/comphelper/source/xml/attributelist.cxx b/comphelper/source/xml/attributelist.cxx index a02c82f69465..0b087095aa53 100644 --- a/comphelper/source/xml/attributelist.cxx +++ b/comphelper/source/xml/attributelist.cxx @@ -19,23 +19,14 @@ #include <comphelper/attributelist.hxx> -using namespace osl; +#include <algorithm> +#include <cassert> + using namespace com::sun::star; namespace comphelper { -OUString SAL_CALL AttributeList::getTypeByName( const OUString& sName ) -{ - for (auto const& attribute : mAttributes) - { - if( attribute.sName == sName ) { - return attribute.sType; - } - } - return OUString(); -} - OUString SAL_CALL AttributeList::getValueByName(const OUString& sName) { for (auto const& attribute : mAttributes) @@ -53,10 +44,12 @@ AttributeList::AttributeList() mAttributes.reserve(20); } -AttributeList::AttributeList(const AttributeList &r) - : cppu::WeakImplHelper<XAttributeList, XCloneable>(r) +AttributeList::AttributeList(const uno::Reference< xml::sax::XAttributeList>& rAttrList) { - mAttributes = r.mAttributes; + if (AttributeList* pImpl = dynamic_cast<AttributeList*>(rAttrList.get())) + mAttributes = pImpl->mAttributes; + else + AppendAttributeList(rAttrList); } AttributeList::~AttributeList() @@ -68,6 +61,69 @@ css::uno::Reference< css::util::XCloneable > AttributeList::createClone() return new AttributeList( *this ); } +void AttributeList::AddAttribute(const OUString& sName, const OUString& sValue) +{ + assert(!sName.isEmpty() && "empty attribute name is invalid"); + // Either it's 'namespace_prefix:attribute_name', + // or as in XMLNamespaces::applyNSToAttributeName, it's 'namespace:full:uri^attribute_name'. + assert((std::count(sName.getStr(), sName.getStr() + sName.getLength(), u':') <= 1 + || std::count(sName.getStr(), sName.getStr() + sName.getLength(), u'^') == 1) + && "too many colons"); + // TODO: this assertion fails in tests! +// assert(std::none_of(mAttributes.begin(), mAttributes.end(), +// [&sName](const TagAttribute& a) { return a.sName == sName; })); + mAttributes.push_back({ sName, sValue }); +} + +void AttributeList::RemoveAttribute(const OUString& sName) +{ + auto ii = std::find_if(mAttributes.begin(), mAttributes.end(), + [&sName](const TagAttribute& rAttr) { return rAttr.sName == sName; }); + + if (ii != mAttributes.end()) + mAttributes.erase(ii); +} + +void AttributeList::AppendAttributeList(const uno::Reference<css::xml::sax::XAttributeList>& r) +{ + assert(r.is()); + + sal_Int16 nMax = r->getLength(); + sal_Int16 nTotalSize = mAttributes.size() + nMax; + mAttributes.reserve(nTotalSize); + + for (sal_Int16 i = 0; i < nMax; ++i) + AddAttribute(r->getNameByIndex(i), r->getValueByIndex(i)); + + assert(nTotalSize == getLength()); +} + +void AttributeList::SetValueByIndex(sal_Int16 i, const OUString& rValue) +{ + mAttributes[i].sValue = rValue; +} + +void AttributeList::RemoveAttributeByIndex(sal_Int16 i) +{ + mAttributes.erase(mAttributes.begin() + i); +} + +void AttributeList::RenameAttributeByIndex(sal_Int16 i, const OUString& rNewName) +{ + mAttributes[i].sName = rNewName; +} + +sal_Int16 AttributeList::GetIndexByName(const OUString& rName) const +{ + auto ii = std::find_if(mAttributes.begin(), mAttributes.end(), + [&rName](const TagAttribute& rAttr) { return rAttr.sName == rName; }); + + if (ii != mAttributes.end()) + return static_cast<sal_Int16>(std::distance(mAttributes.begin(), ii)); + + return -1; +} + } // namespace comphelper /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/xml/ofopxmlhelper.cxx b/comphelper/source/xml/ofopxmlhelper.cxx index 52f6c63568a9..a672bf57a6fb 100644 --- a/comphelper/source/xml/ofopxmlhelper.cxx +++ b/comphelper/source/xml/ofopxmlhelper.cxx @@ -142,14 +142,12 @@ void WriteRelationsInfoSequence( OUString aRelListElement( "Relationships" ); OUString aRelElement( "Relationship" ); - OUString aCDATAString( "CDATA" ); OUString aWhiteSpace( " " ); // write the namespace rtl::Reference<AttributeList> pRootAttrList = new AttributeList; pRootAttrList->AddAttribute( "xmlns", - aCDATAString, "http://schemas.openxmlformats.org/package/2006/relationships" ); xWriter->startDocument(); @@ -168,7 +166,7 @@ void WriteRelationsInfoSequence( // TODO/LATER: should the extensions be allowed? throw lang::IllegalArgumentException(); } - pAttrList->AddAttribute( pair.First, aCDATAString, pair.Second ); + pAttrList->AddAttribute( pair.First, pair.Second ); } xWriter->startElement( aRelElement, pAttrList ); @@ -195,18 +193,16 @@ void WriteContentSequence( xWriter->setOutputStream( xOutStream ); - static constexpr OUStringLiteral aTypesElement(u"Types"); - static constexpr OUStringLiteral aDefaultElement(u"Default"); - static constexpr OUStringLiteral aOverrideElement(u"Override"); - static constexpr OUStringLiteral aContentTypeAttr(u"ContentType"); - static constexpr OUStringLiteral aCDATAString(u"CDATA"); - static constexpr OUStringLiteral aWhiteSpace(u" "); + static constexpr OUString aTypesElement(u"Types"_ustr); + static constexpr OUString aDefaultElement(u"Default"_ustr); + static constexpr OUString aOverrideElement(u"Override"_ustr); + static constexpr OUString aContentTypeAttr(u"ContentType"_ustr); + static constexpr OUString aWhiteSpace(u" "_ustr); // write the namespace rtl::Reference<AttributeList> pRootAttrList = new AttributeList; pRootAttrList->AddAttribute( "xmlns", - aCDATAString, "http://schemas.openxmlformats.org/package/2006/content-types" ); xWriter->startDocument(); @@ -215,8 +211,8 @@ void WriteContentSequence( for ( const beans::StringPair & pair : aDefaultsSequence ) { rtl::Reference<AttributeList> pAttrList = new AttributeList; - pAttrList->AddAttribute( "Extension", aCDATAString, pair.First ); - pAttrList->AddAttribute( aContentTypeAttr, aCDATAString, pair.Second ); + pAttrList->AddAttribute( "Extension", pair.First ); + pAttrList->AddAttribute( aContentTypeAttr, pair.Second ); xWriter->startElement( aDefaultElement, pAttrList ); xWriter->ignorableWhitespace( aWhiteSpace ); @@ -226,8 +222,8 @@ void WriteContentSequence( for ( const beans::StringPair & pair : aOverridesSequence ) { rtl::Reference<AttributeList> pAttrList = new AttributeList; - pAttrList->AddAttribute( "PartName", aCDATAString, pair.First ); - pAttrList->AddAttribute( aContentTypeAttr, aCDATAString, pair.Second ); + pAttrList->AddAttribute( "PartName", pair.First ); + pAttrList->AddAttribute( aContentTypeAttr, pair.Second ); xWriter->startElement( aOverrideElement, pAttrList ); xWriter->ignorableWhitespace( aWhiteSpace ); @@ -266,10 +262,10 @@ uno::Sequence< uno::Sequence< beans::StringPair > > ReadSequence_Impl( // Relations info related strings constexpr OUStringLiteral g_aRelListElement(u"Relationships"); constexpr OUStringLiteral g_aRelElement( u"Relationship" ); -constexpr OUStringLiteral g_aIDAttr( u"Id" ); -constexpr OUStringLiteral g_aTypeAttr( u"Type" ); -constexpr OUStringLiteral g_aTargetModeAttr( u"TargetMode" ); -constexpr OUStringLiteral g_aTargetAttr( u"Target" ); +constexpr OUString g_aIDAttr( u"Id"_ustr ); +constexpr OUString g_aTypeAttr( u"Type"_ustr ); +constexpr OUString g_aTargetModeAttr( u"TargetMode"_ustr ); +constexpr OUString g_aTargetAttr( u"Target"_ustr ); // ContentType related strings constexpr OUStringLiteral g_aTypesElement( u"Types" ); @@ -277,7 +273,7 @@ constexpr OUStringLiteral g_aDefaultElement( u"Default" ); constexpr OUStringLiteral g_aOverrideElement( u"Override" ); constexpr OUStringLiteral g_aExtensionAttr( u"Extension" ); constexpr OUStringLiteral g_aPartNameAttr( u"PartName" ); -constexpr OUStringLiteral g_aContentTypeAttr( u"ContentType" ); +constexpr OUString g_aContentTypeAttr( u"ContentType"_ustr ); OFOPXMLHelper_Impl::OFOPXMLHelper_Impl( sal_uInt16 nFormat ) : m_nFormat( nFormat ) diff --git a/comphelper/source/xml/xmltools.cxx b/comphelper/source/xml/xmltools.cxx index 366321076bad..6ae8fceed5b9 100644 --- a/comphelper/source/xml/xmltools.cxx +++ b/comphelper/source/xml/xmltools.cxx @@ -9,7 +9,7 @@ #include <comphelper/xmltools.hxx> #include <rtl/random.h> -#include <rtl/uuid.h> +#include <tools/Guid.hxx> #include <vector> using namespace com::sun::star; @@ -71,17 +71,21 @@ namespace namespace comphelper::xml { + // Generate some 'chaff' of varying length to be the body of an + // XML comment to put at the start of encrypted content to make + // document content a little less predictable. + // See SvXMLExport::addChaffWhenEncryptedStorage OString makeXMLChaff() { rtlRandomPool pool = rtl_random_createPool(); sal_Int8 n; - rtl_random_getBytes(pool, &n, 1); + (void)rtl_random_getBytes(pool, &n, 1); sal_Int32 nLength = 1024+n; // coverity[tainted_data] - 1024 deliberate random minus max -127/plus max 128 std::vector<sal_uInt8> aChaff(nLength); - rtl_random_getBytes(pool, aChaff.data(), nLength); + (void)rtl_random_getBytes(pool, aChaff.data(), nLength); rtl_random_destroyPool(pool); @@ -92,15 +96,8 @@ namespace comphelper::xml OString generateGUIDString() { - sal_uInt8 aSeq[16]; - rtl_createUuid(aSeq, nullptr, true); - - char str[39]; - sprintf(str, "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", - aSeq[0], aSeq[1], aSeq[2], aSeq[3], aSeq[4], aSeq[5], aSeq[6], aSeq[7], aSeq[8], - aSeq[9], aSeq[10], aSeq[11], aSeq[12], aSeq[13], aSeq[14], aSeq[15]); - - return OString(str); + tools::Guid aGuid(tools::Guid::Generate); + return aGuid.getString(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |