diff options
Diffstat (limited to 'comphelper')
143 files changed, 7415 insertions, 4375 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 ef795f1664d1..17de701aca26 100644 --- a/comphelper/CppunitTest_comphelper_test.mk +++ b/comphelper/CppunitTest_comphelper_test.mk @@ -11,13 +11,18 @@ $(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 \ comphelper/qa/unit/types_test \ comphelper/qa/unit/test_guards \ + 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, \ @@ -25,6 +30,7 @@ $(eval $(call gb_CppunitTest_use_libraries,comphelper_test, \ cppuhelper \ cppu \ sal \ + unotest \ )) ifeq ($(TLS),NSS) @@ -34,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 16bbd6fff69b..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, \ @@ -24,6 +20,7 @@ $(eval $(call gb_CppunitTest_use_libraries,comphelper_threadpool_test, \ cppuhelper \ cppu \ sal \ + tl \ )) # vim: set noet sw=4 ts=4: 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 6d6ec0903716..9e60203c6750 100644 --- a/comphelper/IwyuFilter_comphelper.yaml +++ b/comphelper/IwyuFilter_comphelper.yaml @@ -19,6 +19,12 @@ excludelist: # Base class has to be a complete type - com/sun/star/lang/XServiceInfo.hpp - com/sun/star/util/XOfficeInstallationDirectories.hpp + comphelper/qa/unit/test_guards.cxx: + # Keep for system-cppunit; see also commit 456d61ec526e250fd1af894e109d5914ac9c9e6e + - unotest/bootstrapfixturebase.hxx + comphelper/source/container/embeddedobjectcontainer.cxx: + # Keep for OSL_DEBUG_LEVEL > 1 + - com/sun/star/container/XNameAccess.hpp comphelper/source/container/IndexedPropertyValuesContainer.cxx: # Needed for typedef - com/sun/star/beans/PropertyValue.hpp @@ -37,6 +43,9 @@ excludelist: comphelper/source/misc/fileurl.cxx: # Needed for linker visibility - comphelper/fileurl.hxx + comphelper/source/misc/AccessibleImplementationHelper.cxx: + # Needed for template + - com/sun/star/uno/Sequence.hxx comphelper/source/misc/getexpandeduri.cxx: # Needed for linker visibility - comphelper/getexpandeduri.hxx @@ -46,6 +55,9 @@ excludelist: comphelper/source/misc/hash.cxx: # OSL_BIGENDIAN is being checked - osl/endian.h + comphelper/source/misc/instancelocker.cxx: + # Needed for template + - com/sun/star/embed/XActionsApproval.hpp include/comphelper/interaction.hxx: # Stop warnings about include/ - com/sun/star/task/XInteractionApprove.hpp @@ -56,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 9a814e17d5bf..2ab1b1bfa5d7 100644 --- a/comphelper/Library_comphelper.mk +++ b/comphelper/Library_comphelper.mk @@ -23,12 +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_include,comphelper,\ - -I$(SRCDIR)/comphelper/source/inc \ - $$(INCLUDE) \ -)) +$(eval $(call gb_Library_set_componentfile,comphelper,comphelper/util/comphelp,services)) $(eval $(call gb_Library_set_precompiled_header,comphelper,comphelper/inc/pch/precompiled_comphelper)) @@ -82,31 +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/comphelper_module \ + comphelper/source/misc/compbase \ comphelper/source/misc/componentbase \ - comphelper/source/misc/componentmodule \ 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 \ @@ -115,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 \ @@ -123,24 +119,21 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\ comphelper/source/misc/numberedcollection \ comphelper/source/misc/numbers \ comphelper/source/misc/officerestartmanager \ - comphelper/source/misc/profilezone \ + comphelper/source/misc/traceevent \ comphelper/source/misc/proxyaggregation \ 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 \ @@ -154,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/README b/comphelper/README deleted file mode 100644 index e27793533e9a..000000000000 --- a/comphelper/README +++ /dev/null @@ -1,4 +0,0 @@ -Helper functionality for implementing UNO components - -...anything not generic/mature enough to end up in URE's stable interface at -cppuhelper etc. diff --git a/comphelper/README.md b/comphelper/README.md new file mode 100644 index 000000000000..5369639e9885 --- /dev/null +++ b/comphelper/README.md @@ -0,0 +1,4 @@ +# Helpers for Implementing UNO Components + +Here goes anything not generic / mature enough to end up in URE's stable interface +at `cppuhelper`, etc. diff --git a/comphelper/inc/pch/precompiled_comphelper.hxx b/comphelper/inc/pch/precompiled_comphelper.hxx index aff3397332e4..897773b473f5 100644 --- a/comphelper/inc/pch/precompiled_comphelper.hxx +++ b/comphelper/inc/pch/precompiled_comphelper.hxx @@ -13,18 +13,22 @@ 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 2020-07-09 17:06:16 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: ./bin/update_pch_bisect ./comphelper/inc/pch/precompiled_comphelper.hxx "make comphelper.build" --find-conflicts */ +#include <sal/config.h> #if PCH_LEVEL >= 1 #include <algorithm> +#include <array> #include <cassert> +#include <chrono> #include <cmath> #include <cstddef> +#include <cstdlib> #include <cstring> #include <deque> #include <float.h> @@ -36,7 +40,9 @@ #include <map> #include <math.h> #include <memory> +#include <mutex> #include <new> +#include <numeric> #include <optional> #include <ostream> #include <stddef.h> @@ -47,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> @@ -65,7 +78,6 @@ #include <rtl/instance.hxx> #include <rtl/locale.h> #include <rtl/math.h> -#include <rtl/math.hxx> #include <rtl/random.h> #include <rtl/ref.hxx> #include <rtl/strbuf.h> @@ -76,30 +88,30 @@ #include <rtl/stringutils.hxx> #include <rtl/textcvt.h> #include <rtl/textenc.h> -#include <rtl/unload.h> +#include <rtl/uri.hxx> #include <rtl/ustrbuf.hxx> #include <rtl/ustring.h> #include <rtl/ustring.hxx> #include <rtl/uuid.h> -#include <sal/config.h> #include <sal/log.hxx> #include <sal/macros.h> #include <sal/saldllapi.h> #include <sal/types.h> #include <sal/typesizes.h> +#include <vcl/BinaryDataContainer.hxx> #include <vcl/GraphicExternalLink.hxx> #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> #include <vcl/checksum.hxx> #include <vcl/dllapi.h> #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> @@ -112,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> @@ -187,20 +202,27 @@ #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> -#include <tools/UnitConversion.hxx> #include <tools/color.hxx> +#include <tools/degree.hxx> #include <tools/gen.hxx> #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> @@ -209,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..32519d7534e6 --- /dev/null +++ b/comphelper/qa/string/NaturalStringSortTest.cxx @@ -0,0 +1,100 @@ +/* -*- 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(u"ABC"_ustr, u"ABC"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare(u"ABC"_ustr, u"abc"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare(u"abc"_ustr, u"ABC"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), + aSorter.compare(u"alongstring"_ustr, u"alongerstring"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), + aSorter.compare(u"alongerstring"_ustr, u"alongstring"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare(u"Heading 9"_ustr, u"Heading 10"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare(u"Heading 10"_ustr, u"Heading 9"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), + aSorter.compare(u"July, the 4th"_ustr, u"July, the 10th"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), + aSorter.compare(u"July, the 10th"_ustr, u"July, the 4th"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare(u"abc08"_ustr, u"abc010"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare(u"abc010"_ustr, u"abc08"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+0), + aSorter.compare(u"apple10apple"_ustr, u"apple10apple"_ustr)); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare(u"KA1"_ustr, u"KA0"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+0), aSorter.compare(u"KA1"_ustr, u"KA1"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare(u"KA1"_ustr, u"KA2"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare(u"KA50"_ustr, u"KA5"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare(u"KA50"_ustr, u"KA100"_ustr)); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare(u"1"_ustr, u"0"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+0), aSorter.compare(u"1"_ustr, u"1"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare(u"1"_ustr, u"2"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare(u"11"_ustr, u"1"_ustr)); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare(u"50"_ustr, u"100"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare(u"0"_ustr, u"100000"_ustr)); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare(u"0"_ustr, u"A"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare(u"A"_ustr, u"0"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare(u"A"_ustr, u"99"_ustr)); + + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare(u"00ABC2"_ustr, u"00ABC1"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare(u"00ABC1"_ustr, u"00ABC2"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(+1), aSorter.compare(u"00ABC11"_ustr, u"00ABC2"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aSorter.compare(u"00ABC2"_ustr, u"00ABC11"_ustr)); + } + + 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 abccec85691c..93d2965941c9 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(); @@ -64,290 +68,100 @@ public: void TestString::testDecimalStringToNumber() { - OUString s1("1234"); + OUString s1(u"1234"_ustr); CPPUNIT_ASSERT_EQUAL(sal_uInt32(1234), comphelper::string::decimalStringToNumber(s1)); s1 += u"\u07C6"; CPPUNIT_ASSERT_EQUAL(sal_uInt32(12346), comphelper::string::decimalStringToNumber(s1)); // Codepoints on 2 16bits words - sal_uInt32 utf16String[] = { 0x1D7FE /* 8 */, 0x1D7F7 /* 1 */}; - s1 = OUString(utf16String, 2); + s1 = u"\U0001D7FE\U0001D7F7"_ustr; // MATHEMATICAL MONOSPACE DIGIT EIGHT and ONE CPPUNIT_ASSERT_EQUAL(sal_uInt32(81), comphelper::string::decimalStringToNumber(s1)); } void TestString::testIsdigitAsciiString() { - OString s1("1234"); - CPPUNIT_ASSERT_EQUAL(true, comphelper::string::isdigitAsciiString(s1)); - - OString s2("1A34"); - CPPUNIT_ASSERT_EQUAL(false, comphelper::string::isdigitAsciiString(s2)); - - OString s3; - CPPUNIT_ASSERT_EQUAL(true, comphelper::string::isdigitAsciiString(s3)); -} - -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.copy(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; + CPPUNIT_ASSERT_EQUAL(true, comphelper::string::isdigitAsciiString("1234")); - uno::Reference< i18n::XCollator > xCollator(new testCollator); - uno::Reference< i18n::XBreakIterator > xBI(new testBreakIterator); + CPPUNIT_ASSERT_EQUAL(false, comphelper::string::isdigitAsciiString("1A34")); -// --- 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("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("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("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()) - ); + CPPUNIT_ASSERT_EQUAL(true, comphelper::string::isdigitAsciiString("")); } 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()); @@ -355,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, '.'); @@ -364,41 +178,59 @@ void TestString::testTokenCount() nOut = ::comphelper::string::getTokenCount(aIn, 'X'); CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), nOut); - nOut = ::comphelper::string::getTokenCount(OString(), 'X'); + nOut = ::comphelper::string::getTokenCount("", 'X'); CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), nOut); } void TestString::testReverseString() { - OString aIn("ABC"); - OString aOut = ::comphelper::string::reverseString(aIn); + CPPUNIT_ASSERT_EQUAL(OUString(), comphelper::string::reverseString(u"")); + CPPUNIT_ASSERT_EQUAL(u"cba"_ustr, 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(u"cba"_ustr, 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]); - CPPUNIT_ASSERT_EQUAL(OUString("F1"), aRet[2]); + CPPUNIT_ASSERT_EQUAL(u"CTRL"_ustr, aRet[0]); + CPPUNIT_ASSERT_EQUAL(u"ALT"_ustr, aRet[1]); + CPPUNIT_ASSERT_EQUAL(u"F1"_ustr, aRet[2]); } void TestString::testRemoveAny() { using namespace ::comphelper::string; - OUString in("abcAAAbbC"); + OUString in(u"abcAAAbbC"_ustr); sal_Unicode const test1 [] = { 'a', 0 }; - CPPUNIT_ASSERT_EQUAL(OUString("bcAAAbbC"), removeAny(in, test1)); + CPPUNIT_ASSERT_EQUAL(u"bcAAAbbC"_ustr, removeAny(in, test1)); sal_Unicode const test2 [] = { 0 }; CPPUNIT_ASSERT_EQUAL(in, removeAny(in, test2)); sal_Unicode const test3 [] = { 'A', 0 }; - CPPUNIT_ASSERT_EQUAL(OUString("abcbbC"), removeAny(in, test3)); + CPPUNIT_ASSERT_EQUAL(u"abcbbC"_ustr, removeAny(in, test3)); sal_Unicode const test4 [] = { 'A', 'a', 0 }; - CPPUNIT_ASSERT_EQUAL(OUString("bcbbC"), removeAny(in, test4)); + CPPUNIT_ASSERT_EQUAL(u"bcbbC"_ustr, removeAny(in, test4)); sal_Unicode const test5 [] = { 'C', 0 }; - CPPUNIT_ASSERT_EQUAL(OUString("abcAAAbb"), removeAny(in, test5)); + CPPUNIT_ASSERT_EQUAL(u"abcAAAbb"_ustr, removeAny(in, test5)); sal_Unicode const test6 [] = { 'X', 0 }; CPPUNIT_ASSERT_EQUAL(in, removeAny(in, test6)); sal_Unicode const test7 [] = { 'A', 'B', 'C', 'a', 'b', 'c', 0 }; diff --git a/comphelper/qa/unit/base64_test.cxx b/comphelper/qa/unit/base64_test.cxx index 97f7b78aae7a..f589e1809dd0 100644 --- a/comphelper/qa/unit/base64_test.cxx +++ b/comphelper/qa/unit/base64_test.cxx @@ -30,12 +30,11 @@ using namespace css; -namespace { - +namespace +{ class Base64Test : public CppUnit::TestFixture { public: - void testBase64Encode(); void testBase64Decode(); void testBase64EncodeForOStringBuffer(); @@ -54,17 +53,17 @@ void Base64Test::testBase64Encode() inputSequence = { 0, 0, 0, 0, 0, 1, 2, 3 }; comphelper::Base64::encode(aBuffer, inputSequence); - CPPUNIT_ASSERT_EQUAL(OUString("AAAAAAABAgM="), aBuffer.toString()); + CPPUNIT_ASSERT_EQUAL(u"AAAAAAABAgM="_ustr, aBuffer.toString()); aBuffer.setLength(0); inputSequence = { 5, 2, 3, 0, 0, 1, 2, 3 }; comphelper::Base64::encode(aBuffer, inputSequence); - CPPUNIT_ASSERT_EQUAL(OUString("BQIDAAABAgM="), aBuffer.toString()); + CPPUNIT_ASSERT_EQUAL(u"BQIDAAABAgM="_ustr, 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(OUString("yB9NbwABAgM="), aBuffer.makeStringAndClear()); + CPPUNIT_ASSERT_EQUAL(u"yB9NbwABAgM="_ustr, aBuffer.makeStringAndClear()); } void Base64Test::testBase64Decode() @@ -72,16 +71,19 @@ 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="); - CPPUNIT_ASSERT(std::equal(expectedSequence.begin(), expectedSequence.end(), decodedSequence.begin())); + 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="); - CPPUNIT_ASSERT(std::equal(expectedSequence.begin(), expectedSequence.end(), decodedSequence.begin())); + 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="); - CPPUNIT_ASSERT(std::equal(expectedSequence.begin(), expectedSequence.end(), decodedSequence.begin())); + comphelper::Base64::decode(decodedSequence, u"yB9NbwABAgM="); + CPPUNIT_ASSERT(std::equal(std::cbegin(expectedSequence), std::cend(expectedSequence), + std::cbegin(decodedSequence))); } void Base64Test::testBase64EncodeForOStringBuffer() @@ -91,21 +93,20 @@ 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); - } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/unit/parallelsorttest.cxx b/comphelper/qa/unit/parallelsorttest.cxx index 90dcb3c235ba..a3618244ab8d 100644 --- a/comphelper/qa/unit/parallelsorttest.cxx +++ b/comphelper/qa/unit/parallelsorttest.cxx @@ -53,7 +53,7 @@ void ParallelSortTest::setUp() void ParallelSortTest::tearDown() { if (pThreadPool) - pThreadPool->joinAll(); + pThreadPool->joinThreadsIfIdle(); } void ParallelSortTest::fillRandomUptoN(std::vector<size_t>& rVector, size_t N) diff --git a/comphelper/qa/unit/propertyvalue.cxx b/comphelper/qa/unit/propertyvalue.cxx new file mode 100644 index 000000000000..877a964478ac --- /dev/null +++ b/comphelper/qa/unit/propertyvalue.cxx @@ -0,0 +1,131 @@ +/* -*- 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 <sal/config.h> + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#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 +{ + CPPUNIT_TEST_SUITE(MakePropertyValueTest); + CPPUNIT_TEST(testLvalue); + CPPUNIT_TEST(testRvalue); + CPPUNIT_TEST(testBitField); + CPPUNIT_TEST(testJson); + CPPUNIT_TEST_SUITE_END(); + + void testLvalue() + { + sal_Int32 const i = 123; + auto const v = comphelper::makePropertyValue(u"test"_ustr, i); + CPPUNIT_ASSERT_EQUAL(cppu::UnoType<sal_Int32>::get(), v.Value.getValueType()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(123), *o3tl::doAccess<sal_Int32>(v.Value)); + } + + void testRvalue() + { + auto const v = comphelper::makePropertyValue(u"test"_ustr, sal_Int32(456)); + CPPUNIT_ASSERT_EQUAL(cppu::UnoType<sal_Int32>::get(), v.Value.getValueType()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(456), *o3tl::doAccess<sal_Int32>(v.Value)); + } + + void testBitField() + { + struct + { + bool b : 1; + } s = { false }; + auto const v = comphelper::makePropertyValue(u"test"_ustr, s.b); + 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(u"FieldType"_ustr, aFirst.Name); + CPPUNIT_ASSERT_EQUAL(u"vnd.oasis.opendocument.field.UNHANDLED"_ustr, + aFirst.Value.get<OUString>()); + beans::PropertyValue aSecond = aRet[1]; + CPPUNIT_ASSERT_EQUAL(u"FieldCommandPrefix"_ustr, aSecond.Name); + CPPUNIT_ASSERT_EQUAL(u"ADDIN ZOTERO_ITEM"_ustr, aSecond.Value.get<OUString>()); + beans::PropertyValue aThird = aRet[2]; + CPPUNIT_ASSERT_EQUAL(u"Fields"_ustr, 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(u"FieldType"_ustr, aFirstSeq[0].Name); + CPPUNIT_ASSERT_EQUAL(u"FieldCommand"_ustr, aFirstSeq[1].Name); + CPPUNIT_ASSERT_EQUAL(u"ADDIN ZOTERO_ITEM new command 1"_ustr, + aFirstSeq[1].Value.get<OUString>()); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(MakePropertyValueTest); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/comphelper/qa/unit/syntaxhighlighttest.cxx b/comphelper/qa/unit/syntaxhighlighttest.cxx index c28941339085..e838c0c9886d 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); @@ -94,7 +94,7 @@ void SyntaxHighlightTest::testBasicEmptyCommentNewline() { void SyntaxHighlightTest::testBasic() { - OUString aBasicString(" if Mid(sText,iRun,1 )<> \" \" then Mid( sText ,iRun, 1, Chr( 1 + Asc( Mid(sText,iRun,1 )) ) '"); + OUString aBasicString(u" if Mid(sText,iRun,1 )<> \" \" then Mid( sText ,iRun, 1, Chr( 1 + Asc( Mid(sText,iRun,1 )) ) '"_ustr); std::vector<HighlightPortion> aPortions; SyntaxHighlighter(HighlighterLanguage::Basic).getHighlightPortions( diff --git a/comphelper/qa/unit/test_guards.cxx b/comphelper/qa/unit/test_guards.cxx index 1d2b5f209daa..83034a2dcc6a 100644 --- a/comphelper/qa/unit/test_guards.cxx +++ b/comphelper/qa/unit/test_guards.cxx @@ -7,46 +7,53 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include <sal/types.h> #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); } @@ -54,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 8b6e5a393d23..dc96a03318ef 100644 --- a/comphelper/qa/unit/test_hash.cxx +++ b/comphelper/qa/unit/test_hash.cxx @@ -120,9 +120,9 @@ 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, - comphelper::Hash::IterCount::APPEND, "SHA-512"); - CPPUNIT_ASSERT_EQUAL(OUString("5l3mgNHXpWiFaBPv5Yso1Xd/UifWvQWmlDnl/hsCYbFT2sJCzorjRmBCQ/3qeDu6Q/4+GIE8a1DsdaTwYh1q2g=="), aHash); + const OUString aHash = comphelper::DocPasswordHelper::GetOoxHashAsBase64( u"pwd"_ustr, u"876MLoKTq42+/DLp415iZQ==", 100000, + comphelper::Hash::IterCount::APPEND, u"SHA-512"); + CPPUNIT_ASSERT_EQUAL(u"5l3mgNHXpWiFaBPv5Yso1Xd/UifWvQWmlDnl/hsCYbFT2sJCzorjRmBCQ/3qeDu6Q/4+GIE8a1DsdaTwYh1q2g=="_ustr, aHash); } CPPUNIT_TEST_SUITE_REGISTRATION(TestHash); diff --git a/comphelper/qa/unit/test_traceevent.cxx b/comphelper/qa/unit/test_traceevent.cxx new file mode 100644 index 000000000000..34d10f519d2b --- /dev/null +++ b/comphelper/qa/unit/test_traceevent.cxx @@ -0,0 +1,125 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <comphelper/profilezone.hxx> +#include <comphelper/traceevent.hxx> + +#include <rtl/ustring.hxx> + +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> + +class TestTraceEvent : public CppUnit::TestFixture +{ +public: + void test(); + + CPPUNIT_TEST_SUITE(TestTraceEvent); + CPPUNIT_TEST(test); + CPPUNIT_TEST_SUITE_END(); +}; + +namespace +{ +void trace_event_test() +{ + { + // When we start recording is off and this will not generate any 'X' event when we leave the scope + comphelper::ProfileZone aZone0("test0"); + + // This will not generate any 'b' and 'e' events either + auto pAsync1(std::make_shared<comphelper::AsyncEvent>("async1")); + + { + // No 'X' by this either + comphelper::ProfileZone aZone1("block1"); + + // Now we turn on recording + comphelper::TraceEvent::startRecording(); + } + + // This will generate an 'i' event for instant1 + comphelper::TraceEvent::addInstantEvent("instant1"); + + std::shared_ptr<comphelper::AsyncEvent> pAsync25; + { + comphelper::ProfileZone aZone2("block2"); + + // This does not generate any 'e' event as it was created when recording was off + // And the nested async2 object will thus not generate anything either + pAsync1.reset(); + + // This will generate 'b' event and an 'e' event when the pointer is reset or goes out of scope + pAsync25 = std::make_shared<comphelper::AsyncEvent>("async2.5"); + + // Leaving this scope will generate an 'X' event for block2 + } + + // This will generate a 'b' event for async3 + std::map<OUString, OUString> aArgsAsync3({ { "foo", "bar" }, { "tem", "42" } }); + auto pAsync3(std::make_shared<comphelper::AsyncEvent>("async3", aArgsAsync3)); + + { + comphelper::ProfileZone aZone3("block3"); + + // Leaving this scope will generate an 'X' event for block3 + } + + // This will generate an 'e' event for async2.5 + pAsync25.reset(); + + comphelper::ProfileZone aZone4("test2"); + + // This will generate an 'i' event for instant2" + std::map<OUString, OUString> aArgsInstant2({ { "foo2", "bar2" }, { "tem2", "42" } }); + comphelper::TraceEvent::addInstantEvent("instant2", aArgsInstant2); + + // Leaving this scope will generate 'X' events for test2 and a + // 'e' event for async4in3, async7in3, and async3. + } + + // This incorrect use of overlapping (not nested) ProfileZones + // will generate a SAL_WARN but should not crash + auto p1 = new comphelper::ProfileZone("error1"); + auto p2 = new comphelper::ProfileZone("error2"); + delete p1; + delete p2; +} +} + +void TestTraceEvent::test() +{ + trace_event_test(); + auto aEvents = comphelper::TraceEvent::getEventVectorAndClear(); + for (const auto& s : aEvents) + { + std::cerr << s << "\n"; + } + + CPPUNIT_ASSERT_EQUAL(9, static_cast<int>(aEvents.size())); + + CPPUNIT_ASSERT(aEvents[0].startsWith("{\"name:\"instant1\",\"ph\":\"i\",")); + CPPUNIT_ASSERT(aEvents[1].startsWith("{\"name\":\"async2.5\",\"ph\":\"S\",\"id\":1,")); + CPPUNIT_ASSERT(aEvents[2].startsWith("{\"name\":\"block2\",\"ph\":\"X\",")); + CPPUNIT_ASSERT(aEvents[3].startsWith( + "{\"name\":\"async3\",\"ph\":\"S\",\"id\":2,\"args\":{\"foo\":\"bar\",\"tem\":\"42\"},")); + CPPUNIT_ASSERT(aEvents[4].startsWith("{\"name\":\"block3\",\"ph\":\"X\",")); + CPPUNIT_ASSERT(aEvents[5].startsWith("{\"name\":\"async2.5\",\"ph\":\"F\",\"id\":1,")); + CPPUNIT_ASSERT(aEvents[6].startsWith( + "{\"name:\"instant2\",\"ph\":\"i\",\"args\":{\"foo2\":\"bar2\",\"tem2\":\"42\"},")); + CPPUNIT_ASSERT(aEvents[7].startsWith("{\"name\":\"test2\",\"ph\":\"X\"")); + CPPUNIT_ASSERT(aEvents[8].startsWith( + "{\"name\":\"async3\",\"ph\":\"F\",\"id\":2,\"args\":{\"foo\":\"bar\",\"tem\":\"42\"},")); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TestTraceEvent); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/qa/unit/threadpooltest.cxx b/comphelper/qa/unit/threadpooltest.cxx index 10fb90c3014f..13eaf210a18b 100644 --- a/comphelper/qa/unit/threadpooltest.cxx +++ b/comphelper/qa/unit/threadpooltest.cxx @@ -12,17 +12,30 @@ #include <cppunit/TestFixture.h> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/plugin/TestPlugIn.h> +#include <tools/time.hxx> +#include <osl/thread.hxx> #include <stdlib.h> +#include <atomic> +#include <cstddef> #include <thread> +#include <mutex> class ThreadPoolTest : public CppUnit::TestFixture { public: void testPreferredConcurrency(); + void testWorkerUsage(); + void testTasksInThreads(); + void testNoThreads(); + void testDedicatedPool(); CPPUNIT_TEST_SUITE(ThreadPoolTest); CPPUNIT_TEST(testPreferredConcurrency); + CPPUNIT_TEST(testWorkerUsage); + CPPUNIT_TEST(testTasksInThreads); + CPPUNIT_TEST(testNoThreads); + CPPUNIT_TEST(testDedicatedPool); CPPUNIT_TEST_SUITE_END(); }; @@ -30,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 @@ -39,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"); @@ -48,6 +61,107 @@ void ThreadPoolTest::testPreferredConcurrency() #endif } +namespace +{ +class UsageTask : public comphelper::ThreadTask +{ +public: + UsageTask(const std::shared_ptr<comphelper::ThreadTaskTag>& pTag) + : ThreadTask(pTag) + { + } + virtual void doWork() + { + ++count; + mutex.lock(); + mutex.unlock(); + } + static inline std::atomic<int> count = 0; + static inline std::mutex mutex; +}; +} // namespace + +void ThreadPoolTest::testWorkerUsage() +{ + // Create tasks for each available worker. Lock a shared mutex before that to make all + // tasks block on it. And check that all workers have started, i.e. that the full + // thread pool capacity is used. + comphelper::ThreadPool& rSharedPool = comphelper::ThreadPool::getSharedOptimalPool(); + std::shared_ptr<comphelper::ThreadTaskTag> pTag = comphelper::ThreadPool::createThreadTaskTag(); + UsageTask::mutex.lock(); + for (int i = 0; i < rSharedPool.getWorkerCount(); ++i) + { + rSharedPool.pushTask(std::make_unique<UsageTask>(pTag)); + osl::Thread::wait(std::chrono::milliseconds(10)); // give it a time to start + } + sal_uInt64 startTicks = tools::Time::GetSystemTicks(); + while (UsageTask::count != rSharedPool.getWorkerCount()) + { + // Wait at most 5 seconds, that should do even on slow systems. + CPPUNIT_ASSERT_MESSAGE("Thread pool does not use all worker threads.", + startTicks + 5000 > tools::Time::GetSystemTicks()); + osl::Thread::wait(std::chrono::milliseconds(10)); + } + UsageTask::mutex.unlock(); + rSharedPool.waitUntilDone(pTag); +} + +namespace +{ +class CheckThreadTask : public comphelper::ThreadTask +{ + oslThreadIdentifier mThreadId; + bool mCheckEqual; + +public: + CheckThreadTask(oslThreadIdentifier threadId, bool checkEqual, + const std::shared_ptr<comphelper::ThreadTaskTag>& pTag) + : ThreadTask(pTag) + , mThreadId(threadId) + , mCheckEqual(checkEqual) + { + } + virtual void doWork() + { + CPPUNIT_ASSERT(mCheckEqual ? osl::Thread::getCurrentIdentifier() == mThreadId + : osl::Thread::getCurrentIdentifier() != mThreadId); + } +}; +} // namespace + +void ThreadPoolTest::testTasksInThreads() +{ + // Check that all tasks are run in worker threads, not this thread. + comphelper::ThreadPool& pool = comphelper::ThreadPool::getSharedOptimalPool(); + std::shared_ptr<comphelper::ThreadTaskTag> pTag = comphelper::ThreadPool::createThreadTaskTag(); + for (int i = 0; i < 8; ++i) + pool.pushTask( + std::make_unique<CheckThreadTask>(osl::Thread::getCurrentIdentifier(), false, pTag)); + pool.waitUntilDone(pTag); +} + +void ThreadPoolTest::testNoThreads() +{ + // No worker threads, tasks will be run in this thread. + comphelper::ThreadPool pool(0); + std::shared_ptr<comphelper::ThreadTaskTag> pTag = comphelper::ThreadPool::createThreadTaskTag(); + for (int i = 0; i < 8; ++i) + pool.pushTask( + std::make_unique<CheckThreadTask>(osl::Thread::getCurrentIdentifier(), true, pTag)); + pool.waitUntilDone(pTag); +} + +void ThreadPoolTest::testDedicatedPool() +{ + // Test that a separate thread pool works. The tasks themselves do not matter. + comphelper::ThreadPool pool(4); + std::shared_ptr<comphelper::ThreadTaskTag> pTag = comphelper::ThreadPool::createThreadTaskTag(); + for (int i = 0; i < 8; ++i) + pool.pushTask( + std::make_unique<CheckThreadTask>(osl::Thread::getCurrentIdentifier(), false, pTag)); + pool.waitUntilDone(pTag); +} + CPPUNIT_TEST_SUITE_REGISTRATION(ThreadPoolTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/comphelper/qa/unit/types_test.cxx b/comphelper/qa/unit/types_test.cxx index 89ad6cae870f..d647748e06be 100644 --- a/comphelper/qa/unit/types_test.cxx +++ b/comphelper/qa/unit/types_test.cxx @@ -13,7 +13,6 @@ #include <cppunit/TestAssert.h> #include <cppunit/TestFixture.h> #include <cppunit/extensions/HelperMacros.h> -#include <cppunit/plugin/TestPlugIn.h> using namespace css; @@ -43,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)); @@ -51,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)); @@ -59,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)); @@ -67,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)); @@ -76,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)); @@ -84,10 +83,10 @@ void TypesTest::testGetFloat() void TypesTest::testGetString() { - CPPUNIT_ASSERT_EQUAL(OUString("1337"), ::comphelper::getString(uno::makeAny(OUString("1337")))); + CPPUNIT_ASSERT_EQUAL(u"1337"_ustr, ::comphelper::getString(uno::Any(u"1337"_ustr))); uno::Any aValue; - CPPUNIT_ASSERT_EQUAL(OUString(""), ::comphelper::getString(aValue)); + CPPUNIT_ASSERT_EQUAL(u""_ustr, ::comphelper::getString(aValue)); } CPPUNIT_TEST_SUITE_REGISTRATION(TypesTest); diff --git a/comphelper/qa/unit/variadictemplates.cxx b/comphelper/qa/unit/variadictemplates.cxx index e729d76b24ed..48ed59faab78 100644 --- a/comphelper/qa/unit/variadictemplates.cxx +++ b/comphelper/qa/unit/variadictemplates.cxx @@ -40,7 +40,7 @@ void extract( { if (nArg >= seq.getLength()) { throw ::com::sun::star::lang::IllegalArgumentException( - "No such argument available!", + u"No such argument available!"_ustr, xErrorContext, static_cast<sal_Int16>(nArg) ); } if (! fromAny(seq[nArg], &v)) { @@ -87,26 +87,26 @@ void unwrapArgsBaseline( } void VariadicTemplatesTest::testUnwrapArgs() { - OUString tmp1 = "Test1"; + OUString tmp1 = u"Test1"_ustr; 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") ) + u"Test2"_ustr ); ::std::optional< ::com::sun::star::uno::Any > tmp10( - ::com::sun::star::uno::makeAny( OUString("Test3") ) + u"Test3"_ustr ); ::std::optional< ::com::sun::star::uno::Any > tmp11( - ::com::sun::star::uno::makeAny( tmp1 ) + tmp1 ); // test equality with the baseline and template specialization with @@ -147,11 +147,11 @@ void VariadicTemplatesTest::testUnwrapArgs() { CPPUNIT_ASSERT_EQUAL( static_cast< short >( 5 ), err.ArgumentPosition ); } - OUString test1( "Test2" ); - OUString test2( "Test2" ); - OUString test3( "Test3" ); - OUString test4( "Test4" ); - OUString test5( "Test5" ); + OUString test1( u"Test2"_ustr ); + OUString test2( u"Test2"_ustr ); + OUString test3( u"Test3"_ustr ); + OUString test4( u"Test4"_ustr ); + OUString test5( u"Test5"_ustr ); try { ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > seq( 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 d58c12501633..10e10cd7da85 100644 --- a/comphelper/qa/weakbag/test_weakbag.cxx +++ b/comphelper/qa/weakbag/test_weakbag.cxx @@ -26,15 +26,20 @@ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/plugin/TestPlugIn.h> -namespace { - -class Test: public CppUnit::TestFixture { +namespace +{ +// Tests the behaviour of comphelper::WeakBag +class WeakBagTest : public CppUnit::TestFixture +{ public: - void test() { - 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; + void test() + { + 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); @@ -42,19 +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/compare/AnyCompareFactory.cxx b/comphelper/source/compare/AnyCompareFactory.cxx index 40e5f0806a95..785fc9005707 100644 --- a/comphelper/source/compare/AnyCompareFactory.cxx +++ b/comphelper/source/compare/AnyCompareFactory.cxx @@ -112,7 +112,7 @@ void SAL_CALL AnyCompareFactory::initialize( const Sequence< Any >& aArguments ) OUString SAL_CALL AnyCompareFactory::getImplementationName( ) { - return "AnyCompareFactory"; + return u"AnyCompareFactory"_ustr; } sal_Bool SAL_CALL AnyCompareFactory::supportsService( const OUString& ServiceName ) @@ -122,7 +122,7 @@ sal_Bool SAL_CALL AnyCompareFactory::supportsService( const OUString& ServiceNam Sequence< OUString > SAL_CALL AnyCompareFactory::getSupportedServiceNames( ) { - return { "com.sun.star.ucb.AnyCompareFactory" }; + return { u"com.sun.star.ucb.AnyCompareFactory"_ustr }; } extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * diff --git a/comphelper/source/container/IndexedPropertyValuesContainer.cxx b/comphelper/source/container/IndexedPropertyValuesContainer.cxx index fe4ba0cff91a..9642b5098aa9 100644 --- a/comphelper/source/container/IndexedPropertyValuesContainer.cxx +++ b/comphelper/source/container/IndexedPropertyValuesContainer.cxx @@ -17,57 +17,21 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include <com/sun/star/container/XIndexContainer.hpp> -#include <com/sun/star/uno/Sequence.h> -#include <com/sun/star/beans/PropertyValue.hpp> -#include <cppuhelper/implbase.hxx> #include <com/sun/star/lang/IllegalArgumentException.hpp> #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> -#include <com/sun/star/lang/XServiceInfo.hpp> +#include <comphelper/indexedpropertyvalues.hxx> #include <cppuhelper/supportsservice.hxx> - -#include <vector> +#include <o3tl/safeint.hxx> namespace com::sun::star::uno { class XComponentContext; } using namespace com::sun::star; -typedef std::vector < uno::Sequence< beans::PropertyValue > > IndexedPropertyValues; - -namespace { - -class IndexedPropertyValuesContainer : public cppu::WeakImplHelper< container::XIndexContainer, lang::XServiceInfo > -{ -public: - IndexedPropertyValuesContainer() throw(); - - // XIndexContainer - virtual void SAL_CALL insertByIndex( sal_Int32 nIndex, const css::uno::Any& aElement ) override; - virtual void SAL_CALL removeByIndex( sal_Int32 nIndex ) override; - - // XIndexReplace - virtual void SAL_CALL replaceByIndex( sal_Int32 nIndex, const css::uno::Any& aElement ) override; - // XIndexAccess - virtual sal_Int32 SAL_CALL getCount( ) override; - virtual css::uno::Any SAL_CALL getByIndex( sal_Int32 nIndex ) override; +namespace comphelper { - // XElementAccess - virtual css::uno::Type SAL_CALL getElementType( ) override; - virtual sal_Bool SAL_CALL hasElements( ) override; - //XServiceInfo - virtual OUString SAL_CALL getImplementationName( ) override; - virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; - virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; - -private: - IndexedPropertyValues maProperties; -}; - -} - -IndexedPropertyValuesContainer::IndexedPropertyValuesContainer() throw() +IndexedPropertyValuesContainer::IndexedPropertyValuesContainer() noexcept { } @@ -80,7 +44,7 @@ void SAL_CALL IndexedPropertyValuesContainer::insertByIndex( sal_Int32 nIndex, c uno::Sequence<beans::PropertyValue> aProps; if (!(aElement >>= aProps)) - throw lang::IllegalArgumentException(); + throw lang::IllegalArgumentException(u"element is not beans::PropertyValue"_ustr, static_cast<cppu::OWeakObject*>(this), 2); if (nSize == nIndex) maProperties.push_back(aProps); else @@ -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); @@ -104,7 +68,7 @@ void SAL_CALL IndexedPropertyValuesContainer::replaceByIndex( sal_Int32 nIndex, uno::Sequence<beans::PropertyValue> aProps; if (!(aElement >>= aProps)) - throw lang::IllegalArgumentException(); + throw lang::IllegalArgumentException(u"element is not beans::PropertyValue"_ustr, static_cast<cppu::OWeakObject*>(this), 2); maProperties[nIndex] = aProps; } @@ -137,7 +101,7 @@ sal_Bool SAL_CALL IndexedPropertyValuesContainer::hasElements( ) //XServiceInfo OUString SAL_CALL IndexedPropertyValuesContainer::getImplementationName( ) { - return "IndexedPropertyValuesContainer"; + return u"IndexedPropertyValuesContainer"_ustr; } sal_Bool SAL_CALL IndexedPropertyValuesContainer::supportsService( const OUString& ServiceName ) @@ -147,15 +111,17 @@ sal_Bool SAL_CALL IndexedPropertyValuesContainer::supportsService( const OUStrin css::uno::Sequence< OUString > SAL_CALL IndexedPropertyValuesContainer::getSupportedServiceNames( ) { - return { "com.sun.star.document.IndexedPropertyValues" }; + return { u"com.sun.star.document.IndexedPropertyValues"_ustr }; } +} // namespace comphelper + extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * IndexedPropertyValuesContainer_get_implementation( css::uno::XComponentContext *, css::uno::Sequence<css::uno::Any> const &) { - return cppu::acquire(new IndexedPropertyValuesContainer()); + return cppu::acquire(new comphelper::IndexedPropertyValuesContainer()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/container/NamedPropertyValuesContainer.cxx b/comphelper/source/container/NamedPropertyValuesContainer.cxx index 79a7d714b5e6..510931cf57dd 100644 --- a/comphelper/source/container/NamedPropertyValuesContainer.cxx +++ b/comphelper/source/container/NamedPropertyValuesContainer.cxx @@ -37,7 +37,7 @@ namespace { class NamedPropertyValuesContainer : public cppu::WeakImplHelper< container::XNameContainer, lang::XServiceInfo > { public: - NamedPropertyValuesContainer() throw(); + NamedPropertyValuesContainer() noexcept; // XNameContainer virtual void SAL_CALL insertByName( const OUString& aName, const css::uno::Any& aElement ) override; @@ -66,7 +66,7 @@ private: } -NamedPropertyValuesContainer::NamedPropertyValuesContainer() throw() +NamedPropertyValuesContainer::NamedPropertyValuesContainer() noexcept { } @@ -78,7 +78,7 @@ void SAL_CALL NamedPropertyValuesContainer::insertByName( const OUString& aName, uno::Sequence<beans::PropertyValue> aProps; if( !(aElement >>= aProps ) ) - throw lang::IllegalArgumentException(); + throw lang::IllegalArgumentException(u"element is not beans::PropertyValue"_ustr, static_cast<cppu::OWeakObject*>(this), 2); maProperties.emplace( aName, aProps ); } @@ -101,7 +101,7 @@ void SAL_CALL NamedPropertyValuesContainer::replaceByName( const OUString& aName uno::Sequence<beans::PropertyValue> aProps; if( !(aElement >>= aProps) ) - throw lang::IllegalArgumentException(); + throw lang::IllegalArgumentException(u"element is not beans::PropertyValue"_ustr, static_cast<cppu::OWeakObject*>(this), 2); (*aIter).second = aProps; } @@ -145,7 +145,7 @@ sal_Bool SAL_CALL NamedPropertyValuesContainer::hasElements( ) //XServiceInfo OUString SAL_CALL NamedPropertyValuesContainer::getImplementationName( ) { - return "NamedPropertyValuesContainer"; + return u"NamedPropertyValuesContainer"_ustr; } sal_Bool SAL_CALL NamedPropertyValuesContainer::supportsService( const OUString& ServiceName ) @@ -155,7 +155,7 @@ sal_Bool SAL_CALL NamedPropertyValuesContainer::supportsService( const OUString& css::uno::Sequence< OUString > SAL_CALL NamedPropertyValuesContainer::getSupportedServiceNames( ) { - return { "com.sun.star.document.NamedPropertyValues" }; + return { u"com.sun.star.document.NamedPropertyValues"_ustr }; } extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * 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 2c3a6f937652..1bbf7b847fe4 100644 --- a/comphelper/source/container/embeddedobjectcontainer.cxx +++ b/comphelper/source/container/embeddedobjectcontainer.cxx @@ -42,9 +42,12 @@ #include <comphelper/embeddedobjectcontainer.hxx> #include <comphelper/sequence.hxx> #include <comphelper/propertysequence.hxx> +#include <comphelper/propertyvalue.hxx> #include <cppuhelper/weakref.hxx> #include <sal/log.hxx> +#include <officecfg/Office/Common.hxx> + #include <algorithm> #include <unordered_map> @@ -78,17 +81,17 @@ const uno::Reference < embed::XStorage >& EmbedImpl::GetReplacements() try { mxImageStorage = mxStorage->openStorageElement( - "ObjectReplacements", embed::ElementModes::READWRITE ); + u"ObjectReplacements"_ustr, embed::ElementModes::READWRITE ); } catch (const uno::Exception&) { mxImageStorage = mxStorage->openStorageElement( - "ObjectReplacements", embed::ElementModes::READ ); + u"ObjectReplacements"_ustr, embed::ElementModes::READ ); } } if ( !mxImageStorage.is() ) - throw io::IOException(); + throw io::IOException(u"No ObjectReplacements"_ustr); return mxImageStorage; } @@ -134,31 +137,31 @@ void EmbeddedObjectContainer::SwitchPersistence( const uno::Reference < embed::X bool EmbeddedObjectContainer::CommitImageSubStorage() { - if ( pImpl->mxImageStorage.is() ) + if ( !pImpl->mxImageStorage ) + return true; + + try { - try + bool bReadOnlyMode = true; + uno::Reference < beans::XPropertySet > xSet(pImpl->mxImageStorage,uno::UNO_QUERY); + if ( xSet.is() ) { - bool bReadOnlyMode = true; - uno::Reference < beans::XPropertySet > xSet(pImpl->mxImageStorage,uno::UNO_QUERY); - if ( xSet.is() ) - { - // get the open mode from the parent storage - sal_Int32 nMode = 0; - uno::Any aAny = xSet->getPropertyValue("OpenMode"); - if ( aAny >>= nMode ) - bReadOnlyMode = !(nMode & embed::ElementModes::WRITE ); - } // if ( xSet.is() ) - if ( !bReadOnlyMode ) - { - uno::Reference< embed::XTransactedObject > xTransact( pImpl->mxImageStorage, uno::UNO_QUERY_THROW ); - xTransact->commit(); - } - } - catch (const uno::Exception&) + // get the open mode from the parent storage + sal_Int32 nMode = 0; + uno::Any aAny = xSet->getPropertyValue(u"OpenMode"_ustr); + if ( aAny >>= nMode ) + bReadOnlyMode = !(nMode & embed::ElementModes::WRITE ); + } // if ( xSet.is() ) + if ( !bReadOnlyMode ) { - return false; + uno::Reference< embed::XTransactedObject > xTransact( pImpl->mxImageStorage, uno::UNO_QUERY_THROW ); + xTransact->commit(); } } + catch (const uno::Exception&) + { + return false; + } return true; } @@ -235,8 +238,7 @@ bool EmbeddedObjectContainer::HasEmbeddedObjects() const bool EmbeddedObjectContainer::HasEmbeddedObject( const OUString& rName ) { - auto aIt = pImpl->maNameToObjectMap.find( rName ); - if (aIt != pImpl->maNameToObjectMap.end()) + if (pImpl->maNameToObjectMap.contains(rName)) return true; if (!pImpl->mxStorage.is()) return false; @@ -245,7 +247,7 @@ bool EmbeddedObjectContainer::HasEmbeddedObject( const OUString& rName ) bool EmbeddedObjectContainer::HasEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj ) const { - return pImpl->maObjectToNameMap.find(xObj) != pImpl->maObjectToNameMap.end(); + return pImpl->maObjectToNameMap.contains(xObj); } bool EmbeddedObjectContainer::HasInstantiatedEmbeddedObject( const OUString& rName ) @@ -253,8 +255,7 @@ bool EmbeddedObjectContainer::HasInstantiatedEmbeddedObject( const OUString& rNa // allows to detect whether the object was already instantiated // currently the filter instantiate it on loading, so this method allows // to avoid objects pointing to the same persistence - auto aIt = pImpl->maNameToObjectMap.find( rName ); - return ( aIt != pImpl->maNameToObjectMap.end() ); + return pImpl->maNameToObjectMap.contains(rName); } OUString EmbeddedObjectContainer::GetEmbeddedObjectName( const css::uno::Reference < css::embed::XEmbeddedObject >& xObj ) const @@ -313,7 +314,7 @@ uno::Reference<embed::XEmbeddedObject> EmbeddedObjectContainer::Get_Impl( { // get the open mode from the parent storage sal_Int32 nMode = 0; - uno::Any aAny = xSet->getPropertyValue("OpenMode"); + uno::Any aAny = xSet->getPropertyValue(u"OpenMode"_ustr); if ( aAny >>= nMode ) bReadOnlyMode = !(nMode & embed::ElementModes::WRITE ); } @@ -322,24 +323,24 @@ uno::Reference<embed::XEmbeddedObject> EmbeddedObjectContainer::Get_Impl( //TODO/LATER: it would be good to detect an error when an object should be created already, but isn't (not an "inside" call) uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() ); uno::Sequence< beans::PropertyValue > aObjDescr(1 + (xCopy.is() ? 1 : 0) + (pBaseURL ? 1 : 0)); - aObjDescr[0].Name = "Parent"; - aObjDescr[0].Value <<= pImpl->m_xModel.get(); - sal_Int32 i = 1; + auto itObjDescr = aObjDescr.getArray(); + itObjDescr->Name = "Parent"; + itObjDescr->Value <<= pImpl->m_xModel.get(); if (pBaseURL) { - aObjDescr[i].Name = "DefaultParentBaseURL"; - aObjDescr[i].Value <<= *pBaseURL; - ++i; + ++itObjDescr; + itObjDescr->Name = "DefaultParentBaseURL"; + itObjDescr->Value <<= *pBaseURL; } if ( xCopy.is() ) { - aObjDescr[i].Name = "CloneFrom"; - aObjDescr[i].Value <<= xCopy; + ++itObjDescr; + itObjDescr->Name = "CloneFrom"; + itObjDescr->Value <<= xCopy; } - uno::Sequence< beans::PropertyValue > aMediaDescr( 1 ); - aMediaDescr[0].Name = "ReadOnly"; - aMediaDescr[0].Value <<= bReadOnlyMode; + uno::Sequence< beans::PropertyValue > aMediaDescr{ comphelper::makePropertyValue( + u"ReadOnly"_ustr, bReadOnlyMode) }; xObj.set( xFactory->createInstanceInitFromEntry( pImpl->mxStorage, rName, aMediaDescr, aObjDescr ), uno::UNO_QUERY ); @@ -371,14 +372,15 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CreateEmbedde const size_t nExtraArgs = pBaseURL ? 2 : 1; uno::Sequence< beans::PropertyValue > aObjDescr( rArgs.getLength() + nExtraArgs ); - aObjDescr[0].Name = "Parent"; - aObjDescr[0].Value <<= pImpl->m_xModel.get(); + auto pObjDescr = aObjDescr.getArray(); + pObjDescr[0].Name = "Parent"; + pObjDescr[0].Value <<= pImpl->m_xModel.get(); if (pBaseURL) { - aObjDescr[1].Name = "DefaultParentBaseURL"; - aObjDescr[1].Value <<= *pBaseURL; + pObjDescr[1].Name = "DefaultParentBaseURL"; + pObjDescr[1].Value <<= *pBaseURL; } - std::copy( rArgs.begin(), rArgs.end(), aObjDescr.getArray() + nExtraArgs ); + std::copy( rArgs.begin(), rArgs.end(), pObjDescr + nExtraArgs ); xObj.set( xFactory->createInstanceInitNew( rClassId, OUString(), pImpl->mxStorage, rNewName, aObjDescr ), uno::UNO_QUERY ); @@ -555,8 +557,8 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbedde // it is correct so for now, but what if somebody introduces a new stream based embedded object? // Probably introducing of such an object must be restricted ( a storage must be used! ). uno::Reference< beans::XPropertySet > xProps( xNewStream, uno::UNO_QUERY_THROW ); - xProps->setPropertyValue("MediaType", - uno::Any( OUString( "application/vnd.sun.star.oleobject" ) ) ); + xProps->setPropertyValue(u"MediaType"_ustr, + uno::Any( u"application/vnd.sun.star.oleobject"_ustr ) ); } catch (uno::Exception const& e) { @@ -591,12 +593,13 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbedde { uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() ); uno::Sequence< beans::PropertyValue > aObjDescr(pBaseURL ? 2 : 1); - aObjDescr[0].Name = "Parent"; - aObjDescr[0].Value <<= pImpl->m_xModel.get(); + auto pObjDescr = aObjDescr.getArray(); + pObjDescr[0].Name = "Parent"; + pObjDescr[0].Value <<= pImpl->m_xModel.get(); if (pBaseURL) { - aObjDescr[1].Name = "DefaultParentBaseURL"; - aObjDescr[1].Value <<= *pBaseURL; + pObjDescr[1].Name = "DefaultParentBaseURL"; + pObjDescr[1].Value <<= *pBaseURL; } xObj.set( xFactory->createInstanceInitFromMediaDescriptor( pImpl->mxStorage, rNewName, aMedium, aObjDescr ), uno::UNO_QUERY ); @@ -627,9 +630,8 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::InsertEmbedde try { uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create(::comphelper::getProcessComponentContext()); - uno::Sequence< beans::PropertyValue > aObjDescr( 1 ); - aObjDescr[0].Name = "Parent"; - aObjDescr[0].Value <<= pImpl->m_xModel.get(); + uno::Sequence< beans::PropertyValue > aObjDescr{ comphelper::makePropertyValue( + u"Parent"_ustr, pImpl->m_xModel.get()) }; xObj.set( xFactory->createInstanceLink( pImpl->mxStorage, rNewName, aMedium, aObjDescr ), uno::UNO_QUERY ); uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); @@ -714,12 +716,10 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CopyAndGetEmb uno::Reference < embed::XEmbeddedObjectCreator > xCreator = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() ); - uno::Sequence< beans::PropertyValue > aMediaDescr( 1 ); - aMediaDescr[0].Name = "URL"; - aMediaDescr[0].Value <<= aURL; - uno::Sequence< beans::PropertyValue > aObjDescr( 1 ); - aObjDescr[0].Name = "Parent"; - aObjDescr[0].Value <<= pImpl->m_xModel.get(); + uno::Sequence< beans::PropertyValue > aMediaDescr{ comphelper::makePropertyValue( + u"URL"_ustr, aURL) }; + uno::Sequence< beans::PropertyValue > aObjDescr{ comphelper::makePropertyValue( + u"Parent"_ustr, pImpl->m_xModel.get()) }; xResult.set(xCreator->createInstanceLink( pImpl->mxStorage, rName, @@ -740,9 +740,8 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::CopyAndGetEmb uno::Reference < embed::XEmbeddedObjectCreator > xCreator = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() ); - uno::Sequence< beans::PropertyValue > aObjDescr( 1 ); - aObjDescr[0].Name = "Parent"; - aObjDescr[0].Value <<= pImpl->m_xModel.get(); + uno::Sequence< beans::PropertyValue > aObjDescr{ comphelper::makePropertyValue( + u"Parent"_ustr, pImpl->m_xModel.get()) }; xResult.set(xCreator->createInstanceInitNew( xObj->getClassID(), xObj->getClassName(), @@ -914,7 +913,7 @@ bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed // the media type will be provided with object insertion OUString aOrigStorMediaType; uno::Reference< beans::XPropertySet > xStorProps( pImpl->mxStorage, uno::UNO_QUERY_THROW ); - static const OUStringLiteral s_sMediaType("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!" ); @@ -931,6 +930,14 @@ bool EmbeddedObjectContainer::RemoveEmbeddedObject( const uno::Reference < embed } OUString aTempName, aMediaType; + /* Do not create a new name for a removed object, in the pImpl->mpTempObjectContainer, + because the original m_aEntryName of xObj will be overwritten by InsertEmbeddedObject(), + so uno::Reference < embed::XEmbeddedObject >& xObj will misbehave in + EmbeddedObjectContainer::StoreAsChildren and SfxObjectShell::SaveCompletedChildren + and will throw an exception because of objects with the same names! */ + if( !pImpl->mpTempObjectContainer->HasEmbeddedObject(aName) ) + aTempName = aName; + pImpl->mpTempObjectContainer->InsertEmbeddedObject( xObj, aTempName ); uno::Reference < io::XInputStream > xStream = GetGraphicStream( xObj, &aMediaType ); @@ -962,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; @@ -1027,7 +1034,7 @@ uno::Reference < io::XInputStream > EmbeddedObjectContainer::GetGraphicStream( c uno::Reference < beans::XPropertySet > xSet( xStream, uno::UNO_QUERY ); if ( xSet.is() ) { - uno::Any aAny = xSet->getPropertyValue("MediaType"); + uno::Any aAny = xSet->getPropertyValue(u"MediaType"_ustr); aAny >>= *pMediaType; } } @@ -1064,11 +1071,11 @@ bool EmbeddedObjectContainer::InsertGraphicStream( const css::uno::Reference < c uno::Reference< beans::XPropertySet > xPropSet( xGraphicStream, uno::UNO_QUERY_THROW ); - xPropSet->setPropertyValue("UseCommonStoragePasswordEncryption", + xPropSet->setPropertyValue(u"UseCommonStoragePasswordEncryption"_ustr, uno::Any( true ) ); - xPropSet->setPropertyValue("MediaType", uno::Any(rMediaType) ); + xPropSet->setPropertyValue(u"MediaType"_ustr, uno::Any(rMediaType) ); - xPropSet->setPropertyValue("Compressed", + xPropSet->setPropertyValue(u"Compressed"_ustr, uno::Any( true ) ); } catch (const uno::Exception&) @@ -1087,13 +1094,11 @@ bool EmbeddedObjectContainer::InsertGraphicStreamDirectly( const css::uno::Refer uno::Reference < embed::XOptimizedStorage > xOptRepl( xReplacement, uno::UNO_QUERY_THROW ); // store it into the subfolder - uno::Sequence< beans::PropertyValue > aProps( 3 ); - aProps[0].Name = "MediaType"; - aProps[0].Value <<= rMediaType; - aProps[1].Name = "UseCommonStoragePasswordEncryption"; - aProps[1].Value <<= true; - aProps[2].Name = "Compressed"; - aProps[2].Value <<= true; + uno::Sequence< beans::PropertyValue > aProps{ + comphelper::makePropertyValue(u"MediaType"_ustr, rMediaType), + comphelper::makePropertyValue(u"UseCommonStoragePasswordEncryption"_ustr, true), + comphelper::makePropertyValue(u"Compressed"_ustr, true) + }; if ( xReplacement->hasByName( rObjectName ) ) xReplacement->removeElement( rObjectName ); @@ -1130,7 +1135,7 @@ namespace { try { uno::Reference< embed::XStorage > xPictures = xDocStor->openStorageElement( - "Pictures", + u"Pictures"_ustr, embed::ElementModes::READWRITE ); uno::Reference< io::XStream > xObjReplStr = xPictures->openStreamElement( aStreamName, @@ -1153,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() ) { @@ -1203,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); } } } @@ -1217,18 +1220,23 @@ bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEm uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); if ( xPersist.is() ) { - uno::Sequence< beans::PropertyValue > aArgs( _bOasisFormat ? 2 : 3 ); - aArgs[0].Name = "StoreVisualReplacement"; - aArgs[0].Value <<= !_bOasisFormat; + uno::Sequence< beans::PropertyValue > aArgs( _bOasisFormat ? 3 : 4 ); + auto pArgs = aArgs.getArray(); + pArgs[0].Name = "StoreVisualReplacement"; + pArgs[0].Value <<= !_bOasisFormat; // if it is an embedded object or the optimized inserting fails the normal inserting should be done - aArgs[1].Name = "CanTryOptimization"; - aArgs[1].Value <<= !_bCreateEmbedded; + pArgs[1].Name = "CanTryOptimization"; + pArgs[1].Value <<= !_bCreateEmbedded; + + pArgs[2].Name = "AutoSaveEvent"; + pArgs[2].Value <<= _bAutoSaveEvent; + if ( !_bOasisFormat ) { // if object has no cached replacement it will use this one - aArgs[2].Name = "VisualReplacement"; - aArgs[2].Value <<= xStream; + pArgs[3].Name = "VisualReplacement"; + pArgs[3].Value <<= xStream; } try @@ -1237,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 << "'"); } } @@ -1263,7 +1271,7 @@ bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEm try { // the substorage still can not be locked by the embedded object container - OUString aObjReplElement( "ObjectReplacements" ); + OUString aObjReplElement( u"ObjectReplacements"_ustr ); if ( _xStorage->hasByName( aObjReplElement ) && _xStorage->isStorageElement( aObjReplElement ) ) _xStorage->removeElement( aObjReplElement ); } @@ -1279,100 +1287,104 @@ 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()) { - uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObject( *pIter ); - SAL_WARN_IF( !xObj.is(), "comphelper.container", "An empty entry in the embedded objects list!" ); - if ( xObj.is() ) + try { - sal_Int32 nCurState = xObj->getCurrentState(); - if ( _bOasisFormat && nCurState != embed::EmbedStates::LOADED && nCurState != embed::EmbedStates::RUNNING ) + 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() ) { - // means that the object is active - // the image must be regenerated - OUString aMediaType; - - // TODO/LATER: another aspect could be used - uno::Reference < io::XInputStream > xStream = - GetGraphicReplacementStream( - embed::Aspects::MSOLE_CONTENT, - xObj, - &aMediaType ); - if ( xStream.is() ) + sal_Int32 nCurState = xObj->getCurrentState(); + if ( _bOasisFormat && nCurState != embed::EmbedStates::LOADED && nCurState != embed::EmbedStates::RUNNING ) { - if ( !InsertGraphicStreamDirectly( xStream, *pIter, aMediaType ) ) - InsertGraphicStream( xStream, *pIter, aMediaType ); + // means that the object is active + // the image must be regenerated + OUString aMediaType; + + // TODO/LATER: another aspect could be used + uno::Reference < io::XInputStream > xStream = + GetGraphicReplacementStream( + embed::Aspects::MSOLE_CONTENT, + xObj, + &aMediaType ); + if ( xStream.is() ) + { + if (!InsertGraphicStreamDirectly(xStream, name, aMediaType)) + InsertGraphicStream(xStream, name, aMediaType); + } } - } - // TODO/LATER: currently the object by default does not cache replacement image - // that means that if somebody loads SO7 document and store its objects using - // this method the images might be lost. - // Currently this method is only used on storing to alien formats, that means - // that SO7 documents storing does not use it, and all other filters are - // based on OASIS format. But if it changes the method must be fixed. The fix - // must be done only on demand since it can affect performance. + // TODO/LATER: currently the object by default does not cache replacement image + // that means that if somebody loads SO7 document and store its objects using + // this method the images might be lost. + // Currently this method is only used on storing to alien formats, that means + // that SO7 documents storing does not use it, and all other filters are + // based on OASIS format. But if it changes the method must be fixed. The fix + // must be done only on demand since it can affect performance. - uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); - if ( xPersist.is() ) - { - try + uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY ); + if ( xPersist.is() ) { - //TODO/LATER: only storing if changed! - //xPersist->storeOwn(); //commented, i120168 - - // begin:all charts will be persisted as xml format on disk when saving, which is time consuming. - // '_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 ) )) + try { - uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY ); - if ( xModifiable.is() && xModifiable->isModified()) + //TODO/LATER: only storing if changed! + //xPersist->storeOwn(); //commented, i120168 + + // begin:all charts will be persisted as xml format on disk when saving, which is time consuming. + // '_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(name))) { - xPersist->storeOwn(); + uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY ); + if ( xModifiable.is() && xModifiable->isModified()) + { + xPersist->storeOwn(); + } + else + { + //do nothing. Embedded model is not modified, no need to persist. + } } - else + else //the embedded object is in active status, always store back it. { - //do nothing. Embedded model is not modified, no need to persist. + xPersist->storeOwn(); } + //end i120168 } - else //the embedded object is in active status, always store back it. + catch (const uno::Exception&) { - xPersist->storeOwn(); + // TODO/LATER: error handling + bResult = false; + break; } - //end i120168 - } - catch (const uno::Exception&) - { - // TODO/LATER: error handling - bResult = false; - break; } - } - if ( !_bOasisFormat && !_bObjectsOnly ) - { - // copy replacement images for linked objects - try + if ( !_bOasisFormat && !_bObjectsOnly ) { - uno::Reference< embed::XLinkageSupport > xLink( xObj, uno::UNO_QUERY ); - if ( xLink.is() && xLink->isLink() ) + // copy replacement images for linked objects + try + { + uno::Reference< embed::XLinkageSupport > xLink( xObj, uno::UNO_QUERY ); + if ( xLink.is() && xLink->isLink() ) + { + OUString aMediaType; + uno::Reference < io::XInputStream > xInStream = GetGraphicStream( xObj, &aMediaType ); + if ( xInStream.is() ) + InsertStreamIntoPicturesStorage_Impl( pImpl->mxStorage, xInStream, name ); + } + } + catch (const uno::Exception&) { - OUString aMediaType; - uno::Reference < io::XInputStream > xInStream = GetGraphicStream( xObj, &aMediaType ); - if ( xInStream.is() ) - InsertStreamIntoPicturesStorage_Impl( pImpl->mxStorage, xInStream, *pIter ); } } - catch (const uno::Exception&) - { - } } } + catch (const uno::Exception&) + { + // TODO/LATER: error handling + } } if ( bResult && _bOasisFormat ) @@ -1383,7 +1395,7 @@ bool EmbeddedObjectContainer::StoreChildren(bool _bOasisFormat,bool _bObjectsOnl try { ReleaseImageSubStorage(); - OUString aObjReplElement( "ObjectReplacements" ); + OUString aObjReplElement( u"ObjectReplacements"_ustr ); if ( !_bOasisFormat && pImpl->mxStorage->hasByName( aObjReplElement ) && pImpl->mxStorage->isStorageElement( aObjReplElement ) ) pImpl->mxStorage->removeElement( aObjReplElement ); } @@ -1423,15 +1435,12 @@ uno::Reference< io::XInputStream > EmbeddedObjectContainer::GetGraphicReplacemen return xInStream; } -bool EmbeddedObjectContainer::SetPersistentEntries(const uno::Reference< embed::XStorage >& _xStorage,bool _bClearModifedFlag) +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() ) { @@ -1441,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 >() ); @@ -1454,7 +1463,7 @@ bool EmbeddedObjectContainer::SetPersistentEntries(const uno::Reference< embed:: break; } } - if ( _bClearModifedFlag ) + if ( _bClearModifiedFlag ) { // if this method is used as part of SaveCompleted the object must stay unmodified after execution try @@ -1474,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 55c2b9e28077..87192678fc20 100644 --- a/comphelper/source/container/enumerablemap.cxx +++ b/comphelper/source/container/enumerablemap.cxx @@ -18,7 +18,6 @@ */ -#include <comphelper_module.hxx> #include <comphelper/anytostring.hxx> #include <comphelper/anycompare.hxx> #include <comphelper/componentbase.hxx> @@ -30,15 +29,17 @@ #include <com/sun/star/beans/IllegalTypeException.hpp> #include <com/sun/star/beans/Pair.hpp> #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 <rtl/math.hxx> #include <typelib/typedescription.hxx> +#include <cmath> #include <map> #include <memory> +#include <optional> #include <utility> namespace comphelper @@ -89,7 +90,7 @@ namespace comphelper { Type m_aKeyType; Type m_aValueType; - std::unique_ptr< KeyedValues > m_pValues; + std::optional< KeyedValues > m_pValues; std::shared_ptr< IKeyPredicateLess > m_pKeyCompare; bool m_bMutable; std::vector< MapEnumerator* > m_aModListeners; @@ -102,11 +103,10 @@ namespace comphelper MapData( const MapData& _source ) :m_aKeyType( _source.m_aKeyType ) ,m_aValueType( _source.m_aValueType ) - ,m_pValues( new KeyedValues( *_source.m_pValues ) ) ,m_pKeyCompare( _source.m_pKeyCompare ) ,m_bMutable( false ) - ,m_aModListeners() { + m_pValues.emplace( *_source.m_pValues ); } private: MapData& operator=( const MapData& _source ) = delete; @@ -143,7 +143,7 @@ namespace comphelper // EnumerableMap - typedef ::cppu::WeakAggComponentImplHelper3 < XInitialization + typedef ::cppu::WeakComponentImplHelper < XInitialization , XEnumerableMap , XServiceInfo > Map_IFace; @@ -326,37 +326,37 @@ namespace comphelper sal_Int32 nArgumentCount = _arguments.getLength(); if ( ( nArgumentCount != 2 ) && ( nArgumentCount != 3 ) ) - throw IllegalArgumentException(); + throw IllegalArgumentException(u"wrong number of args"_ustr, static_cast<cppu::OWeakObject*>(this), 1); Type aKeyType, aValueType; if ( !( _arguments[0] >>= aKeyType ) ) - throw IllegalArgumentException("com.sun.star.uno.Type expected.", *this, 1 ); + throw IllegalArgumentException(u"com.sun.star.uno.Type expected."_ustr, *this, 1 ); if ( !( _arguments[1] >>= aValueType ) ) - throw IllegalArgumentException("com.sun.star.uno.Type expected.", *this, 2 ); + throw IllegalArgumentException(u"com.sun.star.uno.Type expected."_ustr, *this, 2 ); Sequence< Pair< Any, Any > > aInitialValues; bool bMutable = true; if ( nArgumentCount == 3 ) { if ( !( _arguments[2] >>= aInitialValues ) ) - throw IllegalArgumentException("[]com.sun.star.beans.Pair<any,any> expected.", *this, 2 ); + throw IllegalArgumentException(u"[]com.sun.star.beans.Pair<any,any> expected."_ustr, *this, 2 ); bMutable = false; } // for the value, anything is allowed, except VOID if ( ( aValueType.getTypeClass() == TypeClass_VOID ) || ( aValueType.getTypeClass() == TypeClass_UNKNOWN ) ) - throw IllegalTypeException("Unsupported value type.", *this ); + throw IllegalTypeException(u"Unsupported value type."_ustr, *this ); // create the comparator for the KeyType, and throw if the type is not supported std::unique_ptr< IKeyPredicateLess > pComparator( getStandardLessPredicate( aKeyType, nullptr ) ); if (!pComparator) - throw IllegalTypeException("Unsupported key type.", *this ); + throw IllegalTypeException(u"Unsupported key type."_ustr, *this ); // init members m_aData.m_aKeyType = aKeyType; m_aData.m_aValueType = aValueType; m_aData.m_pKeyCompare = std::move(pComparator); - m_aData.m_pValues.reset( new KeyedValues( *m_aData.m_pKeyCompare ) ); + m_aData.m_pValues.emplace( *m_aData.m_pKeyCompare ); m_aData.m_bMutable = bMutable; if ( aInitialValues.hasElements() ) @@ -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; } } @@ -467,7 +465,7 @@ namespace comphelper if ( _keyOrValue >>= nValue ) if ( std::isnan( nValue ) ) throw IllegalArgumentException( - "NaN (not-a-number) not supported by this implementation.", + u"NaN (not-a-number) not supported by this implementation."_ustr, *const_cast< EnumerableMap* >( this ), 0 ); // (note that the case of _key not containing a float/double value is handled in the // respective IKeyPredicateLess implementation, so there's no need to handle this here.) @@ -479,7 +477,7 @@ namespace comphelper { if ( !_key.hasValue() ) throw IllegalArgumentException( - "NULL keys not supported by this implementation.", + u"NULL keys not supported by this implementation."_ustr, *const_cast< EnumerableMap* >( this ), 0 ); impl_checkNaN_throw( _key, m_aData.m_aKeyType ); @@ -490,7 +488,7 @@ namespace comphelper { if ( !m_aData.m_bMutable ) throw NoSupportException( - "The map is immutable.", + u"The map is immutable."_ustr, *const_cast< EnumerableMap* >( this ) ); } @@ -639,7 +637,7 @@ namespace comphelper OUString SAL_CALL EnumerableMap::getImplementationName( ) { - return "org.openoffice.comp.comphelper.EnumerableMap"; + return u"org.openoffice.comp.comphelper.EnumerableMap"_ustr; } sal_Bool SAL_CALL EnumerableMap::supportsService( const OUString& _serviceName ) @@ -650,7 +648,7 @@ namespace comphelper Sequence< OUString > SAL_CALL EnumerableMap::getSupportedServiceNames( ) { - return { "com.sun.star.container.EnumerableMap" }; + return { u"com.sun.star.container.EnumerableMap"_ustr }; } bool MapEnumerator::hasMoreElements() @@ -666,7 +664,7 @@ namespace comphelper if ( m_disposed ) throw DisposedException( OUString(), m_rParent ); if ( m_mapPos == m_rMapData.m_pValues->end() ) - throw NoSuchElementException("No more elements.", m_rParent ); + throw NoSuchElementException(u"No more elements."_ustr, m_rParent ); Any aNextElement; switch ( m_eType ) diff --git a/comphelper/source/container/enumhelper.cxx b/comphelper/source/container/enumhelper.cxx index edcb03c669cc..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,28 +36,29 @@ OEnumerationByName::OEnumerationByName(const css::uno::Reference<css::container: } -OEnumerationByName::OEnumerationByName(const css::uno::Reference<css::container::XNameAccess>& _rxAccess, - const css::uno::Sequence< OUString >& _aNames ) - :m_aNames(_aNames) - ,m_xAccess(_rxAccess) +OEnumerationByName::OEnumerationByName(css::uno::Reference<css::container::XNameAccess> _xAccess, + std::vector<OUString> _aNames ) + :m_aNames(std::move(_aNames)) + ,m_xAccess(std::move(_xAccess)) ,m_nPos(0) ,m_bListening(false) { impl_startDisposeListening(); } - OEnumerationByName::~OEnumerationByName() { + std::lock_guard aLock(m_aLock); + impl_stopDisposeListening(); } sal_Bool SAL_CALL OEnumerationByName::hasMoreElements( ) { - osl::MutexGuard aLock(m_aLock); + std::lock_guard aLock(m_aLock); - if (m_xAccess.is() && m_aNames.getLength() > m_nPos) + if (m_xAccess.is() && getLength() > m_nPos) return true; if (m_xAccess.is()) @@ -71,13 +73,13 @@ sal_Bool SAL_CALL OEnumerationByName::hasMoreElements( ) css::uno::Any SAL_CALL OEnumerationByName::nextElement( ) { - osl::MutexGuard aLock(m_aLock); + std::lock_guard aLock(m_aLock); css::uno::Any aRes; - if (m_xAccess.is() && m_nPos < m_aNames.getLength()) - aRes = m_xAccess->getByName(m_aNames.getConstArray()[m_nPos++]); + if (m_xAccess.is() && m_nPos < getLength()) + aRes = m_xAccess->getByName(getElement(m_nPos++)); - if (m_xAccess.is() && m_nPos >= m_aNames.getLength()) + if (m_xAccess.is() && m_nPos >= getLength()) { impl_stopDisposeListening(); m_xAccess.clear(); @@ -89,10 +91,9 @@ css::uno::Any SAL_CALL OEnumerationByName::nextElement( ) return aRes; } - void SAL_CALL OEnumerationByName::disposing(const css::lang::EventObject& aEvent) { - osl::MutexGuard aLock(m_aLock); + std::lock_guard aLock(m_aLock); if (aEvent.Source == m_xAccess) m_xAccess.clear(); @@ -101,8 +102,6 @@ void SAL_CALL OEnumerationByName::disposing(const css::lang::EventObject& aEvent void OEnumerationByName::impl_startDisposeListening() { - osl::MutexGuard aLock(m_aLock); - if (m_bListening) return; @@ -119,8 +118,6 @@ void OEnumerationByName::impl_startDisposeListening() void OEnumerationByName::impl_stopDisposeListening() { - osl::MutexGuard aLock(m_aLock); - if (!m_bListening) return; @@ -134,8 +131,25 @@ void OEnumerationByName::impl_stopDisposeListening() osl_atomic_decrement(&m_refCount); } -OEnumerationByIndex::OEnumerationByIndex(const css::uno::Reference< css::container::XIndexAccess >& _rxAccess) - :m_xAccess(_rxAccess) +sal_Int32 OEnumerationByName::getLength() const +{ + if (m_aNames.index() == 0) + return std::get<css::uno::Sequence<OUString>>(m_aNames).getLength(); + else + return std::get<std::vector<OUString>>(m_aNames).size(); +} + +const OUString& OEnumerationByName::getElement(sal_Int32 nIndex) const +{ + if (m_aNames.index() == 0) + return std::get<css::uno::Sequence<OUString>>(m_aNames)[nIndex]; + else + return std::get<std::vector<OUString>>(m_aNames)[nIndex]; +} + + +OEnumerationByIndex::OEnumerationByIndex(css::uno::Reference< css::container::XIndexAccess > _xAccess) + :m_xAccess(std::move(_xAccess)) ,m_nPos(0) ,m_bListening(false) { @@ -145,13 +159,15 @@ OEnumerationByIndex::OEnumerationByIndex(const css::uno::Reference< css::contain OEnumerationByIndex::~OEnumerationByIndex() { + std::lock_guard aLock(m_aLock); + impl_stopDisposeListening(); } sal_Bool SAL_CALL OEnumerationByIndex::hasMoreElements( ) { - osl::MutexGuard aLock(m_aLock); + std::lock_guard aLock(m_aLock); if (m_xAccess.is() && m_xAccess->getCount() > m_nPos) return true; @@ -168,7 +184,7 @@ sal_Bool SAL_CALL OEnumerationByIndex::hasMoreElements( ) css::uno::Any SAL_CALL OEnumerationByIndex::nextElement( ) { - osl::MutexGuard aLock(m_aLock); + std::lock_guard aLock(m_aLock); css::uno::Any aRes; if (m_xAccess.is() && m_nPos < m_xAccess->getCount()) @@ -188,7 +204,7 @@ css::uno::Any SAL_CALL OEnumerationByIndex::nextElement( ) void SAL_CALL OEnumerationByIndex::disposing(const css::lang::EventObject& aEvent) { - osl::MutexGuard aLock(m_aLock); + std::lock_guard aLock(m_aLock); if (aEvent.Source == m_xAccess) m_xAccess.clear(); @@ -197,8 +213,6 @@ void SAL_CALL OEnumerationByIndex::disposing(const css::lang::EventObject& aEven void OEnumerationByIndex::impl_startDisposeListening() { - osl::MutexGuard aLock(m_aLock); - if (m_bListening) return; @@ -215,8 +229,6 @@ void OEnumerationByIndex::impl_startDisposeListening() void OEnumerationByIndex::impl_stopDisposeListening() { - osl::MutexGuard aLock(m_aLock); - if (!m_bListening) return; @@ -244,7 +256,7 @@ OAnyEnumeration::~OAnyEnumeration() sal_Bool SAL_CALL OAnyEnumeration::hasMoreElements( ) { - osl::MutexGuard aLock(m_aLock); + std::lock_guard aLock(m_aLock); return (m_lItems.getLength() > m_nPos); } @@ -255,7 +267,7 @@ css::uno::Any SAL_CALL OAnyEnumeration::nextElement( ) if ( ! hasMoreElements()) throw css::container::NoSuchElementException(); - osl::MutexGuard aLock(m_aLock); + std::lock_guard aLock(m_aLock); sal_Int32 nPos = m_nPos; ++m_nPos; return m_lItems[nPos]; diff --git a/comphelper/source/container/interfacecontainer2.cxx b/comphelper/source/container/interfacecontainer2.cxx index 1524600affd0..a2e2119be0d2 100644 --- a/comphelper/source/container/interfacecontainer2.cxx +++ b/comphelper/source/container/interfacecontainer2.cxx @@ -19,7 +19,9 @@ #include <comphelper/interfacecontainer2.hxx> +#include <comphelper/multicontainer2.hxx> +#include <o3tl/safeint.hxx> #include <osl/diagnose.h> #include <osl/mutex.hxx> @@ -36,13 +38,13 @@ namespace comphelper { OInterfaceIteratorHelper2::OInterfaceIteratorHelper2( OInterfaceContainerHelper2 & rCont_ ) - : rCont( rCont_ ), - bIsList( rCont_.bIsList ) + : rCont( rCont_ ) { MutexGuard aGuard( rCont.rMutex ); if( rCont.bInUse ) // worst case, two iterators at the same time rCont.copyAndResetInUse(); + bIsList = rCont_.bIsList; aData = rCont_.aData; if( bIsList ) { @@ -102,7 +104,7 @@ void OInterfaceIteratorHelper2::remove() if( bIsList ) { OSL_ASSERT( nRemain >= 0 && - nRemain < static_cast<sal_Int32>(aData.pAsVector->size()) ); + o3tl::make_unsigned(nRemain) < aData.pAsVector->size() ); rCont.removeInterface( (*aData.pAsVector)[nRemain] ); } else @@ -170,6 +172,9 @@ void OInterfaceContainerHelper2::copyAndResetInUse() sal_Int32 OInterfaceContainerHelper2::addInterface( const Reference<XInterface> & rListener ) { OSL_ASSERT( rListener.is() ); + if ( !rListener.is() ) + return 0; + MutexGuard aGuard( rMutex ); if( bInUse ) copyAndResetInUse(); @@ -239,6 +244,16 @@ sal_Int32 OInterfaceContainerHelper2::removeInterface( const Reference<XInterfac return aData.pAsInterface ? 1 : 0; } +Reference<XInterface> OInterfaceContainerHelper2::getInterface( sal_Int32 nIndex ) const +{ + MutexGuard aGuard( rMutex ); + + if (bIsList) + return (*aData.pAsVector)[nIndex]; + assert(aData.pAsInterface && nIndex == 0); + return aData.pAsInterface; +} + void OInterfaceContainerHelper2::disposeAndClear( const EventObject & rEvt ) { ClearableMutexGuard aGuard( rMutex ); @@ -285,6 +300,121 @@ void OInterfaceContainerHelper2::clear() } + +// specialized class for type + +OMultiTypeInterfaceContainerHelper2::OMultiTypeInterfaceContainerHelper2( Mutex & rMutex_ ) + : rMutex( rMutex_ ) +{ +} + +OMultiTypeInterfaceContainerHelper2::~OMultiTypeInterfaceContainerHelper2() +{ +} + +std::vector< css::uno::Type > OMultiTypeInterfaceContainerHelper2::getContainedTypes() const +{ + ::osl::MutexGuard aGuard( rMutex ); + std::vector< Type > aInterfaceTypes; + aInterfaceTypes.reserve( m_aMap.size() ); + for (const auto& rItem : m_aMap) + { + // are interfaces added to this container? + if( rItem.second->getLength() ) + // yes, put the type in the array + aInterfaceTypes.push_back(rItem.first); + } + return aInterfaceTypes; +} + +OMultiTypeInterfaceContainerHelper2::t_type2ptr::iterator OMultiTypeInterfaceContainerHelper2::findType(const Type & rKey ) +{ + return std::find_if(m_aMap.begin(), m_aMap.end(), + [&rKey](const t_type2ptr::value_type& rItem) { return rItem.first == rKey; }); +} + +OMultiTypeInterfaceContainerHelper2::t_type2ptr::const_iterator OMultiTypeInterfaceContainerHelper2::findType(const Type & rKey ) const +{ + return std::find_if(m_aMap.begin(), m_aMap.end(), + [&rKey](const t_type2ptr::value_type& rItem) { return rItem.first == rKey; }); +} + +OInterfaceContainerHelper2 * OMultiTypeInterfaceContainerHelper2::getContainer( const Type & rKey ) const +{ + ::osl::MutexGuard aGuard( rMutex ); + + auto iter = findType( rKey ); + if( iter != m_aMap.end() ) + return (*iter).second.get(); + return nullptr; +} + +sal_Int32 OMultiTypeInterfaceContainerHelper2::addInterface( + const Type & rKey, const Reference< XInterface > & rListener ) +{ + ::osl::MutexGuard aGuard( rMutex ); + auto iter = findType( rKey ); + if( iter == m_aMap.end() ) + { + OInterfaceContainerHelper2 * pLC = new OInterfaceContainerHelper2( rMutex ); + m_aMap.emplace_back(rKey, pLC); + return pLC->addInterface( rListener ); + } + return (*iter).second->addInterface( rListener ); +} + +sal_Int32 OMultiTypeInterfaceContainerHelper2::removeInterface( + const Type & rKey, const Reference< XInterface > & rListener ) +{ + ::osl::MutexGuard aGuard( rMutex ); + + // search container with id nUik + auto iter = findType( rKey ); + // container found? + if( iter != m_aMap.end() ) + return (*iter).second->removeInterface( rListener ); + + // no container with this id. Always return 0 + return 0; +} + +void OMultiTypeInterfaceContainerHelper2::disposeAndClear( const EventObject & rEvt ) +{ + t_type2ptr::size_type nSize = 0; + std::unique_ptr<OInterfaceContainerHelper2 *[]> ppListenerContainers; + { + ::osl::MutexGuard aGuard( rMutex ); + nSize = m_aMap.size(); + if( nSize ) + { + typedef OInterfaceContainerHelper2* ppp; + ppListenerContainers.reset(new ppp[nSize]); + + t_type2ptr::size_type i = 0; + for (const auto& rItem : m_aMap) + { + ppListenerContainers[i++] = rItem.second.get(); + } + } + } + + // create a copy, because do not fire event in a guarded section + for( t_type2ptr::size_type i = 0; i < nSize; i++ ) + { + if( ppListenerContainers[i] ) + ppListenerContainers[i]->disposeAndClear( rEvt ); + } +} + +void OMultiTypeInterfaceContainerHelper2::clear() +{ + ::osl::MutexGuard aGuard( rMutex ); + + for (auto& rItem : m_aMap) + rItem.second->clear(); +} + + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/container/namecontainer.cxx b/comphelper/source/container/namecontainer.cxx index bed257ca50c7..7e70526ec053 100644 --- a/comphelper/source/container/namecontainer.cxx +++ b/comphelper/source/container/namecontainer.cxx @@ -20,6 +20,7 @@ #include <sal/config.h> #include <map> +#include <mutex> #include <comphelper/namecontainer.hxx> #include <comphelper/sequence.hxx> @@ -58,14 +59,13 @@ namespace comphelper private: SvGenericNameContainerMapImpl maProperties; const css::uno::Type maType; - osl::Mutex maMutex; + std::mutex maMutex; }; } } using namespace ::comphelper; -using namespace ::osl; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::container; using namespace ::com::sun::star::lang; @@ -79,20 +79,20 @@ NameContainer::NameContainer( const css::uno::Type& aType ) // XNameContainer void SAL_CALL NameContainer::insertByName( const OUString& aName, const Any& aElement ) { - MutexGuard aGuard( maMutex ); + std::scoped_lock aGuard( maMutex ); if( maProperties.find( aName ) != maProperties.end() ) throw ElementExistException(); if( aElement.getValueType() != maType ) - throw IllegalArgumentException(); + throw IllegalArgumentException(u"element is wrong type"_ustr, static_cast<cppu::OWeakObject*>(this), 2); maProperties.emplace(aName,aElement); } void SAL_CALL NameContainer::removeByName( const OUString& Name ) { - MutexGuard aGuard( maMutex ); + std::scoped_lock aGuard( maMutex ); SvGenericNameContainerMapImpl::iterator aIter = maProperties.find( Name ); if( aIter == maProperties.end() ) @@ -105,14 +105,14 @@ void SAL_CALL NameContainer::removeByName( const OUString& Name ) void SAL_CALL NameContainer::replaceByName( const OUString& aName, const Any& aElement ) { - MutexGuard aGuard( maMutex ); + std::scoped_lock aGuard( maMutex ); SvGenericNameContainerMapImpl::iterator aIter( maProperties.find( aName ) ); if( aIter == maProperties.end() ) throw NoSuchElementException(); if( aElement.getValueType() != maType ) - throw IllegalArgumentException(); + throw IllegalArgumentException(u"element is wrong type"_ustr, static_cast<cppu::OWeakObject*>(this), 2); (*aIter).second = aElement; } @@ -121,7 +121,7 @@ void SAL_CALL NameContainer::replaceByName( const OUString& aName, const Any& aE Any SAL_CALL NameContainer::getByName( const OUString& aName ) { - MutexGuard aGuard( maMutex ); + std::scoped_lock aGuard( maMutex ); SvGenericNameContainerMapImpl::iterator aIter = maProperties.find( aName ); if( aIter == maProperties.end() ) @@ -132,14 +132,14 @@ Any SAL_CALL NameContainer::getByName( const OUString& aName ) Sequence< OUString > SAL_CALL NameContainer::getElementNames( ) { - MutexGuard aGuard( maMutex ); + std::scoped_lock aGuard( maMutex ); return comphelper::mapKeysToSequence(maProperties); } sal_Bool SAL_CALL NameContainer::hasByName( const OUString& aName ) { - MutexGuard aGuard( maMutex ); + std::scoped_lock aGuard( maMutex ); SvGenericNameContainerMapImpl::iterator aIter = maProperties.find( aName ); return aIter != maProperties.end(); @@ -147,7 +147,7 @@ sal_Bool SAL_CALL NameContainer::hasByName( const OUString& aName ) sal_Bool SAL_CALL NameContainer::hasElements( ) { - MutexGuard aGuard( maMutex ); + std::scoped_lock aGuard( maMutex ); return !maProperties.empty(); } diff --git a/comphelper/source/eventattachermgr/eventattachermgr.cxx b/comphelper/source/eventattachermgr/eventattachermgr.cxx index e92b7fc70e1a..4cc4dcf19d58 100644 --- a/comphelper/source/eventattachermgr/eventattachermgr.cxx +++ b/comphelper/source/eventattachermgr/eventattachermgr.cxx @@ -21,7 +21,6 @@ #include <o3tl/any.hxx> #include <o3tl/safeint.hxx> -#include <osl/mutex.hxx> #include <osl/diagnose.h> #include <comphelper/eventattachermgr.hxx> #include <comphelper/sequence.hxx> @@ -42,13 +41,15 @@ #include <com/sun/star/script/XEventAttacherManager.hpp> #include <com/sun/star/script/XScriptListener.hpp> #include <cppuhelper/weak.hxx> -#include <comphelper/interfacecontainer2.hxx> +#include <comphelper/interfacecontainer4.hxx> #include <cppuhelper/exc_hlp.hxx> #include <cppuhelper/implbase.hxx> #include <rtl/ref.hxx> #include <deque> +#include <mutex> #include <algorithm> +#include <utility> using namespace com::sun::star::uno; using namespace com::sun::star::io; @@ -57,7 +58,6 @@ using namespace com::sun::star::beans; using namespace com::sun::star::script; using namespace com::sun::star::reflection; using namespace cppu; -using namespace osl; namespace comphelper @@ -84,9 +84,9 @@ class ImplEventAttacherManager { friend class AttacherAllListener_Impl; std::deque< AttacherIndex_Impl > aIndex; - Mutex aLock; + std::mutex m_aMutex; // Container for the ScriptListener - OInterfaceContainerHelper2 aScriptListeners; + OInterfaceContainerHelper4<XScriptListener> aScriptListeners; // Instance of EventAttacher Reference< XEventAttacher2 > xAttacher; Reference< XComponentContext > mxContext; @@ -116,8 +116,14 @@ public: virtual void SAL_CALL read(const Reference< XObjectInputStream >& InStream) override; private: + void registerScriptEvent(std::unique_lock<std::mutex>&, sal_Int32 Index, const ScriptEventDescriptor& ScriptEvent); + void registerScriptEvents(std::unique_lock<std::mutex>&, sal_Int32 Index, const Sequence< ScriptEventDescriptor >& ScriptEvents); + void attach(std::unique_lock<std::mutex>&, sal_Int32 Index, const Reference< XInterface >& Object, const Any& Helper); + void detach(std::unique_lock<std::mutex>&, sal_Int32 nIndex, const Reference< XInterface >& xObject); + void insertEntry(std::unique_lock<std::mutex>&, sal_Int32 Index); + /// @throws Exception - Reference< XIdlReflection > getReflection(); + Reference< XIdlReflection > getReflection(std::unique_lock<std::mutex>&); /** checks if <arg>_nIndex</arg> is a valid index, throws an <type>IllegalArgumentException</type> if not @param _nIndex @@ -140,8 +146,8 @@ class AttacherAllListener_Impl : public WeakImplHelper< XAllListener > /// @throws CannotConvertException void convertToEventReturn( Any & rRet, const Type & rRetType ); public: - AttacherAllListener_Impl( ImplEventAttacherManager* pManager_, const OUString &rScriptType_, - const OUString & rScriptCode_ ); + AttacherAllListener_Impl( ImplEventAttacherManager* pManager_, OUString aScriptType_, + OUString aScriptCode_ ); // Methods of XAllListener virtual void SAL_CALL firing(const AllEventObject& Event) override; @@ -156,12 +162,12 @@ public: AttacherAllListener_Impl::AttacherAllListener_Impl ( ImplEventAttacherManager* pManager_, - const OUString & rScriptType_, - const OUString & rScriptCode_ + OUString aScriptType_, + OUString aScriptCode_ ) : mxManager( pManager_ ) - , aScriptType( rScriptType_ ) - , aScriptCode( rScriptCode_ ) + , aScriptType(std::move( aScriptType_ )) + , aScriptCode(std::move( aScriptCode_ )) { } @@ -179,9 +185,8 @@ void SAL_CALL AttacherAllListener_Impl::firing(const AllEventObject& Event) aScriptEvent.ScriptCode = aScriptCode; // Iterate over all listeners and pass events. - OInterfaceIteratorHelper2 aIt( mxManager->aScriptListeners ); - while( aIt.hasMoreElements() ) - static_cast<XScriptListener *>(aIt.next())->firing( aScriptEvent ); + std::unique_lock l(mxManager->m_aMutex); + mxManager->aScriptListeners.notifyEach( l, &XScriptListener::firing, aScriptEvent ); } @@ -242,13 +247,17 @@ Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Even Any aRet; // Iterate over all listeners and pass events. - OInterfaceIteratorHelper2 aIt( mxManager->aScriptListeners ); + std::unique_lock l(mxManager->m_aMutex); + OInterfaceIteratorHelper4 aIt( l, mxManager->aScriptListeners ); while( aIt.hasMoreElements() ) { - aRet = static_cast<XScriptListener *>(aIt.next())->approveFiring( aScriptEvent ); + // cannot hold lock over call to approveFiring, since it might recurse back into us + l.unlock(); + aRet = aIt.next()->approveFiring( aScriptEvent ); + l.lock(); try { - Reference< XIdlClass > xListenerType = mxManager->getReflection()-> + Reference< XIdlClass > xListenerType = mxManager->getReflection(l)-> forName( Event.ListenerType.getTypeName() ); Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName ); if( xMeth.is() ) @@ -299,7 +308,7 @@ Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Even catch (const CannotConvertException&) { // silent ignore conversions errors from a script call - Reference< XIdlClass > xListenerType = mxManager->getReflection()-> + Reference< XIdlClass > xListenerType = mxManager->getReflection(l)-> forName( Event.ListenerType.getTypeName() ); Reference< XIdlMethod > xMeth = xListenerType->getMethod( Event.MethodName ); if( xMeth.is() ) @@ -340,14 +349,13 @@ 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() ) { Reference< XInterface > xIFace( rContext->getServiceManager()->createInstanceWithContext( - "com.sun.star.script.EventAttacher", rContext) ); + u"com.sun.star.script.EventAttacher"_ustr, rContext) ); if ( xIFace.is() ) { xAttacher.set( xIFace, UNO_QUERY ); @@ -358,15 +366,12 @@ ImplEventAttacherManager::ImplEventAttacherManager( const Reference< XIntrospect Reference< XInitialization > xInit( xAttacher, UNO_QUERY ); if( xInit.is() ) { - Sequence< Any > Arguments( 1 ); - Arguments[0] <<= rIntrospection; - xInit->initialize( Arguments ); + xInit->initialize({ Any(rIntrospection) }); } } -Reference< XIdlReflection > ImplEventAttacherManager::getReflection() +Reference< XIdlReflection > ImplEventAttacherManager::getReflection(std::unique_lock<std::mutex>&) { - Guard< Mutex > aGuard( aLock ); // Do we already have a service? If not, create one. if( !mxCoreReflection.is() ) { @@ -379,7 +384,7 @@ Reference< XIdlReflection > ImplEventAttacherManager::getReflection() std::deque< AttacherIndex_Impl >::iterator ImplEventAttacherManager::implCheckIndex( sal_Int32 _nIndex ) { if ( (_nIndex < 0) || (o3tl::make_unsigned(_nIndex) >= aIndex.size()) ) - throw IllegalArgumentException(); + throw IllegalArgumentException(u"wrong index"_ustr, static_cast<cppu::OWeakObject*>(this), 1); std::deque<AttacherIndex_Impl>::iterator aIt = aIndex.begin() + _nIndex; return aIt; @@ -392,8 +397,17 @@ void SAL_CALL ImplEventAttacherManager::registerScriptEvent const ScriptEventDescriptor& ScriptEvent ) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); + registerScriptEvent(l, nIndex, ScriptEvent); +} +void ImplEventAttacherManager::registerScriptEvent +( + std::unique_lock<std::mutex>&, + sal_Int32 nIndex, + const ScriptEventDescriptor& ScriptEvent +) +{ // Examine the index and apply the array std::deque<AttacherIndex_Impl>::iterator aIt = implCheckIndex( nIndex ); @@ -427,20 +441,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 ); } @@ -452,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) { @@ -475,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(); + throw IllegalArgumentException(u"negative index"_ustr, static_cast<cppu::OWeakObject*>(this), 1); + insertEntry(l, nIndex); +} + +void ImplEventAttacherManager::insertEntry(std::unique_lock<std::mutex>&, sal_Int32 nIndex) +{ if ( o3tl::make_unsigned(nIndex) >= aIndex.size() ) aIndex.resize(nIndex+1); @@ -506,15 +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 ); } @@ -522,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); } @@ -530,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(); + throw IllegalArgumentException(u"negative index, or null object"_ustr, static_cast<cppu::OWeakObject*>(this), -1); + attach(l, nIndex, xObject, Helper); +} +void ImplEventAttacherManager::attach(std::unique_lock<std::mutex>& l, sal_Int32 nIndex, const Reference< XInterface >& xObject, const Any & Helper) +{ if( o3tl::make_unsigned(nIndex) >= aIndex.size() ) { // read older files if( nVersion != 1 ) throw IllegalArgumentException(); - insertEntry( nIndex ); - attach( nIndex, xObject, Helper ); + insertEntry( l, nIndex ); + attach( l, nIndex, xObject, Helper ); return; } @@ -586,11 +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(); + throw IllegalArgumentException(u"bad index or null object"_ustr, static_cast<cppu::OWeakObject*>(this), 1); + detach(l, nIndex, xObject); +} +void ImplEventAttacherManager::detach(std::unique_lock<std::mutex>&, sal_Int32 nIndex, const Reference< XInterface >& xObject) +{ std::deque< AttacherIndex_Impl >::iterator aCurrentPosition = aIndex.begin() + nIndex; auto aObjIt = std::find_if(aCurrentPosition->aObjList.begin(), aCurrentPosition->aObjList.end(), [&xObject](const AttachedObject_Impl& rObj) { return rObj.xTarget == xObject; }); @@ -618,26 +652,26 @@ 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 ); } // Methods of XPersistObject OUString SAL_CALL ImplEventAttacherManager::getServiceName() { - return "com.sun.star.uno.script.EventAttacherManager"; + return u"com.sun.star.uno.script.EventAttacherManager"_ustr; } void SAL_CALL ImplEventAttacherManager::write(const Reference< XObjectOutputStream >& OutStream) { - Guard< Mutex > aGuard( aLock ); + std::unique_lock l(m_aMutex); // Don't run without XMarkableStream Reference< XMarkableStream > xMarkStream( OutStream, UNO_QUERY ); if( !xMarkStream.is() ) @@ -676,7 +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() ) @@ -697,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(); @@ -713,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/inc/comphelper_module.hxx b/comphelper/source/inc/comphelper_module.hxx deleted file mode 100644 index aaa547649b8e..000000000000 --- a/comphelper/source/inc/comphelper_module.hxx +++ /dev/null @@ -1,47 +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 . - */ - -#ifndef INCLUDED_COMPHELPER_SOURCE_INC_COMPHELPER_MODULE_HXX -#define INCLUDED_COMPHELPER_SOURCE_INC_COMPHELPER_MODULE_HXX - -#include <comphelper/componentmodule.hxx> - - -namespace comphelper::module -{ - - - class ComphelperModule : public ::comphelper::OModule - { - friend struct ComphelperModuleCreator; - typedef ::comphelper::OModule BaseClass; - - public: - static ComphelperModule& getInstance(); - - private: - ComphelperModule(); - }; - -} // namespace comphelper::module - - -#endif // INCLUDED_COMPHELPER_SOURCE_INC_COMPHELPER_MODULE_HXX - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 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 5b0ffbf68465..badfe9b62d80 100644 --- a/comphelper/source/misc/DirectoryHelper.cxx +++ b/comphelper/source/misc/DirectoryHelper.cxx @@ -11,6 +11,7 @@ #include <sal/config.h> #include <osl/file.hxx> +#include <rtl/uri.hxx> #include <memory> @@ -18,24 +19,24 @@ namespace comphelper { typedef std::shared_ptr<osl::File> FileSharedPtr; -OUString DirectoryHelper::splitAtLastToken(const OUString& rSrc, sal_Unicode aToken, - OUString& rRight) +std::u16string_view DirectoryHelper::splitAtLastToken(std::u16string_view rSrc, sal_Unicode aToken, + OUString& rRight) { - const sal_Int32 nIndex(rSrc.lastIndexOf(aToken)); - OUString aRetval; + const size_t nIndex(rSrc.rfind(aToken)); + std::u16string_view aRetval; - if (-1 == nIndex) + if (std::u16string_view::npos == nIndex) { aRetval = rSrc; rRight.clear(); } else if (nIndex > 0) { - aRetval = rSrc.copy(0, nIndex); + aRetval = rSrc.substr(0, nIndex); - if (rSrc.getLength() > nIndex + 1) + if (rSrc.size() > nIndex + 1) { - rRight = rSrc.copy(nIndex + 1); + rRight = rSrc.substr(nIndex + 1); } } @@ -77,12 +78,16 @@ void DirectoryHelper::scanDirsAndFiles(const OUString& rDirURL, std::set<OUStrin if (osl::FileBase::E_None != aDirectory.open()) return; + auto lcl_encodeUriSegment = [](OUString const& rPath) { + return rtl::Uri::encode(rPath, rtl_UriCharClassUricNoSlash, rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8); + }; + osl::DirectoryItem aDirectoryItem; while (osl::FileBase::E_None == aDirectory.getNextItem(aDirectoryItem)) { - osl::FileStatus aFileStatus(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL - | osl_FileStatus_Mask_FileName); + osl::FileStatus aFileStatus(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName); if (osl::FileBase::E_None == aDirectoryItem.getFileStatus(aFileStatus)) { @@ -92,7 +97,7 @@ void DirectoryHelper::scanDirsAndFiles(const OUString& rDirURL, std::set<OUStrin if (!aFileName.isEmpty()) { - rDirs.insert(aFileName); + rDirs.insert(lcl_encodeUriSegment(aFileName)); } } else if (aFileStatus.isRegular()) @@ -103,7 +108,8 @@ void DirectoryHelper::scanDirsAndFiles(const OUString& rDirURL, std::set<OUStrin if (!aFileName.isEmpty()) { - rFiles.insert(std::pair<OUString, OUString>(aFileName, aExtension)); + rFiles.insert(std::pair<OUString, OUString>(lcl_encodeUriSegment(aFileName), + lcl_encodeUriSegment(aExtension))); } } } @@ -142,7 +148,8 @@ bool DirectoryHelper::deleteDirRecursively(const OUString& rDirURL) } // both exist, move content -bool DirectoryHelper::moveDirContent(const OUString& rSourceDirURL, const OUString& rTargetDirURL, +bool DirectoryHelper::moveDirContent(const OUString& rSourceDirURL, + std::u16string_view rTargetDirURL, const std::set<OUString>& rExcludeList) { std::set<OUString> aDirs; @@ -161,7 +168,7 @@ bool DirectoryHelper::moveDirContent(const OUString& rSourceDirURL, const OUStri if (dirExists(aNewSourceDirURL)) { - const OUString aNewTargetDirURL(rTargetDirURL + "/" + dir); + const OUString aNewTargetDirURL(OUString::Concat(rTargetDirURL) + "/" + dir); if (dirExists(aNewTargetDirURL)) { @@ -185,7 +192,7 @@ bool DirectoryHelper::moveDirContent(const OUString& rSourceDirURL, const OUStri if (fileExists(aSourceFileURL)) { - OUString aTargetFileURL(rTargetDirURL + "/" + file.first); + OUString aTargetFileURL(OUString::Concat(rTargetDirURL) + "/" + file.first); if (!file.second.isEmpty()) { @@ -203,4 +210,4 @@ bool DirectoryHelper::moveDirContent(const OUString& rSourceDirURL, const OUStri return bError; } -}
\ No newline at end of file +} diff --git a/comphelper/source/misc/SelectionMultiplex.cxx b/comphelper/source/misc/SelectionMultiplex.cxx index 267266388c71..37e4e30037b3 100644 --- a/comphelper/source/misc/SelectionMultiplex.cxx +++ b/comphelper/source/misc/SelectionMultiplex.cxx @@ -95,7 +95,20 @@ void SAL_CALL OSelectionChangeMultiplexer::selectionChanged( const EventObject& m_pListener->_selectionChanged(_rEvent); } +void OSelectionChangeMultiplexer::dispose() +{ + osl_atomic_increment(&m_refCount); + { + Reference< XSelectionChangeListener> xPreventDelete(this); + if(m_xSet.is()) + { + m_xSet->removeSelectionChangeListener(xPreventDelete); + m_xSet.clear(); + } + } + osl_atomic_decrement(&m_refCount); } +} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/accessiblecomponenthelper.cxx b/comphelper/source/misc/accessiblecomponenthelper.cxx index 2962bbac95a8..3922812b92af 100644 --- a/comphelper/source/misc/accessiblecomponenthelper.cxx +++ b/comphelper/source/misc/accessiblecomponenthelper.cxx @@ -18,6 +18,11 @@ */ #include <comphelper/accessiblecomponenthelper.hxx> +#include <comphelper/accessiblecontexthelper.hxx> +#include <osl/diagnose.h> +#include <com/sun/star/accessibility/IllegalAccessibleComponentStateException.hpp> +#include <comphelper/accessibleeventnotifier.hxx> +#include <comphelper/solarmutex.hxx> namespace comphelper @@ -30,12 +35,209 @@ namespace comphelper using namespace ::com::sun::star::accessibility; OCommonAccessibleComponent::OCommonAccessibleComponent( ) + :OCommonAccessibleComponent_Base( GetMutex() ) + ,m_nClientId( 0 ) { } OCommonAccessibleComponent::~OCommonAccessibleComponent( ) { + // this ensures that the lock, which may be already destroyed as part of the derivee, + // is not used anymore + + ensureDisposed(); + } + + + void SAL_CALL OCommonAccessibleComponent::disposing() + { + // rhbz#1001768: de facto this class is locked by SolarMutex; + // do not lock m_Mutex because it may cause deadlock + osl::Guard<SolarMutex> aGuard(SolarMutex::get()); + + if ( m_nClientId ) + { + AccessibleEventNotifier::revokeClientNotifyDisposing( m_nClientId, *this ); + m_nClientId=0; + } + } + + + void SAL_CALL OCommonAccessibleComponent::addAccessibleEventListener( const Reference< XAccessibleEventListener >& _rxListener ) + { + osl::Guard<SolarMutex> aGuard(SolarMutex::get()); + // don't use the OContextEntryGuard - it will throw an exception if we're not alive + // anymore, while the most recent specification for XComponent states that we should + // silently ignore the call in such a situation + if ( !isAlive() ) + { + if ( _rxListener.is() ) + _rxListener->disposing( EventObject( *this ) ); + return; + } + + if ( _rxListener.is() ) + { + if ( !m_nClientId ) + m_nClientId = AccessibleEventNotifier::registerClient( ); + + AccessibleEventNotifier::addEventListener( m_nClientId, _rxListener ); + } + } + + + void SAL_CALL OCommonAccessibleComponent::removeAccessibleEventListener( const Reference< XAccessibleEventListener >& _rxListener ) + { + osl::Guard<SolarMutex> aGuard(SolarMutex::get()); + // don't use the OContextEntryGuard - it will throw an exception if we're not alive + // anymore, while the most recent specification for XComponent states that we should + // silently ignore the call in such a situation + if ( !isAlive() ) + return; + + if ( !(_rxListener.is() && m_nClientId) ) + return; + + sal_Int32 nListenerCount = AccessibleEventNotifier::removeEventListener( m_nClientId, _rxListener ); + if ( !nListenerCount ) + { + // no listeners anymore + // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client), + // and at least to us not firing any events anymore, in case somebody calls + // NotifyAccessibleEvent, again + AccessibleEventNotifier::revokeClient( m_nClientId ); + m_nClientId = 0; + } + } + + + void OCommonAccessibleComponent::NotifyAccessibleEvent( const sal_Int16 _nEventId, + const Any& _rOldValue, const Any& _rNewValue, sal_Int32 nIndexHint ) + { + if ( !m_nClientId ) + // if we don't have a client id for the notifier, then we don't have listeners, then + // we don't need to notify anything + return; + + // build an event object + AccessibleEventObject aEvent(*this, _nEventId, _rNewValue, _rOldValue, nIndexHint); + + // let the notifier handle this event + AccessibleEventNotifier::addEvent( m_nClientId, aEvent ); + } + + + bool OCommonAccessibleComponent::isAlive() const + { + return !rBHelper.bDisposed && !rBHelper.bInDispose; + } + + + void OCommonAccessibleComponent::ensureAlive() const + { + if( !isAlive() ) + throw DisposedException(); + } + + + void OCommonAccessibleComponent::ensureDisposed( ) + { + if ( !rBHelper.bDisposed ) + { + OSL_ENSURE( 0 == m_refCount, "OCommonAccessibleComponent::ensureDisposed: this method _has_ to be called from without your dtor only!" ); + acquire(); + dispose(); + } + } + + + void OCommonAccessibleComponent::lateInit( const Reference< XAccessible >& _rxAccessible ) + { + m_aCreator = _rxAccessible; + } + + + Reference< XAccessible > OCommonAccessibleComponent::getAccessibleCreator( ) const + { + return m_aCreator; + } + + + OUString SAL_CALL OCommonAccessibleComponent::getAccessibleId( ) + { + return OUString(); + } + + + sal_Int64 SAL_CALL OCommonAccessibleComponent::getAccessibleIndexInParent( ) + { + OExternalLockGuard aGuard( this ); + + // -1 for child not found/no parent (according to specification) + sal_Int64 nRet = -1; + + try + { + + Reference< XAccessibleContext > xParentContext( implGetParentContext() ); + + // iterate over parent's children and search for this object + if ( xParentContext.is() ) + { + // our own XAccessible for comparing with the children of our parent + Reference< XAccessible > xCreator( m_aCreator); + + OSL_ENSURE( xCreator.is(), "OCommonAccessibleComponent::getAccessibleIndexInParent: invalid creator!" ); + // two ideas why this could be NULL: + // * nobody called our late ctor (init), so we never had a creator at all -> bad + // * the creator is already dead. In this case, we should have been disposed, and + // never survived the above OContextEntryGuard. + // in all other situations the creator should be non-NULL + + if ( xCreator.is() ) + { + sal_Int64 nChildCount = xParentContext->getAccessibleChildCount(); + for ( sal_Int64 nChild = 0; ( nChild < nChildCount ) && ( -1 == nRet ); ++nChild ) + { + Reference< XAccessible > xChild( xParentContext->getAccessibleChild( nChild ) ); + if ( xChild.get() == xCreator.get() ) + nRet = nChild; + } + } + } + } + catch( const Exception& ) + { + OSL_FAIL( "OCommonAccessibleComponent::getAccessibleIndexInParent: caught an exception!" ); + } + + return nRet; + } + + + Locale SAL_CALL OCommonAccessibleComponent::getLocale( ) + { + // simply ask the parent + Reference< XAccessible > xParent = getAccessibleParent(); + Reference< XAccessibleContext > xParentContext; + if ( xParent.is() ) + xParentContext = xParent->getAccessibleContext(); + + if ( !xParentContext.is() ) + throw IllegalAccessibleComponentStateException( OUString(), *this ); + + return xParentContext->getLocale(); + } + + + Reference< XAccessibleContext > OCommonAccessibleComponent::implGetParentContext() + { + Reference< XAccessible > xParent = getAccessibleParent(); + Reference< XAccessibleContext > xParentContext; + if ( xParent.is() ) + xParentContext = xParent->getAccessibleContext(); + return xParentContext; } @@ -97,11 +299,6 @@ namespace comphelper } - IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleComponentHelper, OCommonAccessibleComponent, OAccessibleComponentHelper_Base ) - IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleComponentHelper, OCommonAccessibleComponent, OAccessibleComponentHelper_Base ) - // (order matters: the first is the class name, the second is the class doing the ref counting) - - sal_Bool SAL_CALL OAccessibleComponentHelper::containsPoint( const awt::Point& _rPoint ) { return OCommonAccessibleComponent::containsPoint( _rPoint ); @@ -136,11 +333,6 @@ namespace comphelper } - IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleExtendedComponentHelper, OCommonAccessibleComponent, OAccessibleExtendedComponentHelper_Base ) - IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleExtendedComponentHelper, OCommonAccessibleComponent, OAccessibleExtendedComponentHelper_Base ) - // (order matters: the first is the class name, the second is the class doing the ref counting) - - sal_Bool SAL_CALL OAccessibleExtendedComponentHelper::containsPoint( const awt::Point& _rPoint ) { return OCommonAccessibleComponent::containsPoint( _rPoint ); diff --git a/comphelper/source/misc/accessiblecontexthelper.cxx b/comphelper/source/misc/accessiblecontexthelper.cxx deleted file mode 100644 index a4d11cb59c1a..000000000000 --- a/comphelper/source/misc/accessiblecontexthelper.cxx +++ /dev/null @@ -1,279 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include <comphelper/accessiblecontexthelper.hxx> -#include <osl/diagnose.h> -#include <cppuhelper/weakref.hxx> -#include <com/sun/star/accessibility/IllegalAccessibleComponentStateException.hpp> -#include <comphelper/accessibleeventnotifier.hxx> -#include <comphelper/solarmutex.hxx> - - -namespace comphelper -{ - using namespace ::com::sun::star::uno; - using namespace ::com::sun::star::lang; - using namespace ::com::sun::star::accessibility; - - /** implementation class for OAccessibleContextHelper. No own thread safety! - */ - class OContextHelper_Impl - { - private: - WeakReference< XAccessible > m_aCreator; // the XAccessible which created our XAccessibleContext - - AccessibleEventNotifier::TClientId m_nClientId; - - public: - Reference< XAccessible > getCreator( ) const { return m_aCreator; } - inline void setCreator( const Reference< XAccessible >& _rAcc ); - - AccessibleEventNotifier::TClientId - getClientId() const { return m_nClientId; } - void setClientId( const AccessibleEventNotifier::TClientId _nId ) - { m_nClientId = _nId; } - - public: - OContextHelper_Impl() - :m_nClientId( 0 ) - { - } - }; - - - inline void OContextHelper_Impl::setCreator( const Reference< XAccessible >& _rAcc ) - { - m_aCreator = _rAcc; - } - - OAccessibleContextHelper::OAccessibleContextHelper( ) - :OAccessibleContextHelper_Base( GetMutex() ) - ,m_pImpl(new OContextHelper_Impl) - { - } - - - OAccessibleContextHelper::~OAccessibleContextHelper( ) - { - // this ensures that the lock, which may be already destroyed as part of the derivee, - // is not used anymore - - ensureDisposed(); - } - - - void SAL_CALL OAccessibleContextHelper::disposing() - { - // rhbz#1001768: de facto this class is locked by SolarMutex; - // do not lock m_Mutex because it may cause deadlock - osl::Guard<SolarMutex> aGuard(SolarMutex::get()); - - if ( m_pImpl->getClientId( ) ) - { - AccessibleEventNotifier::revokeClientNotifyDisposing( m_pImpl->getClientId( ), *this ); - m_pImpl->setClientId( 0 ); - } - } - - - void SAL_CALL OAccessibleContextHelper::addAccessibleEventListener( const Reference< XAccessibleEventListener >& _rxListener ) - { - osl::Guard<SolarMutex> aGuard(SolarMutex::get()); - // don't use the OContextEntryGuard - it will throw an exception if we're not alive - // anymore, while the most recent specification for XComponent states that we should - // silently ignore the call in such a situation - if ( !isAlive() ) - { - if ( _rxListener.is() ) - _rxListener->disposing( EventObject( *this ) ); - return; - } - - if ( _rxListener.is() ) - { - if ( !m_pImpl->getClientId( ) ) - m_pImpl->setClientId( AccessibleEventNotifier::registerClient( ) ); - - AccessibleEventNotifier::addEventListener( m_pImpl->getClientId( ), _rxListener ); - } - } - - - void SAL_CALL OAccessibleContextHelper::removeAccessibleEventListener( const Reference< XAccessibleEventListener >& _rxListener ) - { - osl::Guard<SolarMutex> aGuard(SolarMutex::get()); - // don't use the OContextEntryGuard - it will throw an exception if we're not alive - // anymore, while the most recent specification for XComponent states that we should - // silently ignore the call in such a situation - if ( !isAlive() ) - return; - - if ( !(_rxListener.is() && m_pImpl->getClientId()) ) - return; - - sal_Int32 nListenerCount = AccessibleEventNotifier::removeEventListener( m_pImpl->getClientId( ), _rxListener ); - if ( !nListenerCount ) - { - // no listeners anymore - // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client), - // and at least to us not firing any events anymore, in case somebody calls - // NotifyAccessibleEvent, again - AccessibleEventNotifier::revokeClient( m_pImpl->getClientId( ) ); - m_pImpl->setClientId( 0 ); - } - } - - - void OAccessibleContextHelper::NotifyAccessibleEvent( const sal_Int16 _nEventId, - const Any& _rOldValue, const Any& _rNewValue ) - { - if ( !m_pImpl->getClientId( ) ) - // if we don't have a client id for the notifier, then we don't have listeners, then - // we don't need to notify anything - return; - - // build an event object - AccessibleEventObject aEvent; - aEvent.Source = *this; - aEvent.EventId = _nEventId; - aEvent.OldValue = _rOldValue; - aEvent.NewValue = _rNewValue; - - // let the notifier handle this event - AccessibleEventNotifier::addEvent( m_pImpl->getClientId( ), aEvent ); - } - - - bool OAccessibleContextHelper::isAlive() const - { - return !rBHelper.bDisposed && !rBHelper.bInDispose; - } - - - void OAccessibleContextHelper::ensureAlive() const - { - if( !isAlive() ) - throw DisposedException(); - } - - - void OAccessibleContextHelper::ensureDisposed( ) - { - if ( !rBHelper.bDisposed ) - { - OSL_ENSURE( 0 == m_refCount, "OAccessibleContextHelper::ensureDisposed: this method _has_ to be called from without your dtor only!" ); - acquire(); - dispose(); - } - } - - - void OAccessibleContextHelper::lateInit( const Reference< XAccessible >& _rxAccessible ) - { - m_pImpl->setCreator( _rxAccessible ); - } - - - Reference< XAccessible > OAccessibleContextHelper::getAccessibleCreator( ) const - { - return m_pImpl->getCreator(); - } - - - OUString SAL_CALL OAccessibleContextHelper::getAccessibleId( ) - { - return OUString(); - } - - - sal_Int32 SAL_CALL OAccessibleContextHelper::getAccessibleIndexInParent( ) - { - OExternalLockGuard aGuard( this ); - - // -1 for child not found/no parent (according to specification) - sal_Int32 nRet = -1; - - try - { - - Reference< XAccessibleContext > xParentContext( implGetParentContext() ); - - // iterate over parent's children and search for this object - if ( xParentContext.is() ) - { - // our own XAccessible for comparing with the children of our parent - Reference< XAccessible > xCreator( m_pImpl->getCreator() ); - - OSL_ENSURE( xCreator.is(), "OAccessibleContextHelper::getAccessibleIndexInParent: invalid creator!" ); - // two ideas why this could be NULL: - // * nobody called our late ctor (init), so we never had a creator at all -> bad - // * the creator is already dead. In this case, we should have been disposed, and - // never survived the above OContextEntryGuard. - // in all other situations the creator should be non-NULL - - if ( xCreator.is() ) - { - sal_Int32 nChildCount = xParentContext->getAccessibleChildCount(); - for ( sal_Int32 nChild = 0; ( nChild < nChildCount ) && ( -1 == nRet ); ++nChild ) - { - Reference< XAccessible > xChild( xParentContext->getAccessibleChild( nChild ) ); - if ( xChild.get() == xCreator.get() ) - nRet = nChild; - } - } - } - } - catch( const Exception& ) - { - OSL_FAIL( "OAccessibleContextHelper::getAccessibleIndexInParent: caught an exception!" ); - } - - return nRet; - } - - - Locale SAL_CALL OAccessibleContextHelper::getLocale( ) - { - // simply ask the parent - Reference< XAccessible > xParent = getAccessibleParent(); - Reference< XAccessibleContext > xParentContext; - if ( xParent.is() ) - xParentContext = xParent->getAccessibleContext(); - - if ( !xParentContext.is() ) - throw IllegalAccessibleComponentStateException( OUString(), *this ); - - return xParentContext->getLocale(); - } - - - Reference< XAccessibleContext > OAccessibleContextHelper::implGetParentContext() - { - Reference< XAccessible > xParent = getAccessibleParent(); - Reference< XAccessibleContext > xParentContext; - if ( xParent.is() ) - xParentContext = xParent->getAccessibleContext(); - return xParentContext; - } - - -} // namespace comphelper - - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/accessibleeventnotifier.cxx b/comphelper/source/misc/accessibleeventnotifier.cxx index f14176a03528..9c3b55126bc6 100644 --- a/comphelper/source/misc/accessibleeventnotifier.cxx +++ b/comphelper/source/misc/accessibleeventnotifier.cxx @@ -19,12 +19,12 @@ #include <comphelper/accessibleeventnotifier.hxx> #include <com/sun/star/accessibility/XAccessibleEventListener.hpp> -#include <rtl/instance.hxx> -#include <comphelper/interfacecontainer2.hxx> +#include <comphelper/interfacecontainer4.hxx> +#include <limits> #include <map> #include <memory> -#include <limits> +#include <unordered_map> using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; @@ -36,31 +36,37 @@ namespace { typedef std::pair< AccessibleEventNotifier::TClientId, AccessibleEventObject > ClientEvent; -typedef std::map< AccessibleEventNotifier::TClientId, - ::comphelper::OInterfaceContainerHelper2* > ClientMap; +typedef ::comphelper::OInterfaceContainerHelper4<XAccessibleEventListener> ListenerContainer; +typedef std::unordered_map< AccessibleEventNotifier::TClientId, ListenerContainer > ClientMap; /// key is the end of the interval, value is the start of the interval typedef std::map<AccessibleEventNotifier::TClientId, AccessibleEventNotifier::TClientId> IntervalMap; -struct lclMutex : public rtl::Static< ::osl::Mutex, lclMutex > {}; +std::mutex& GetLocalMutex() +{ + static std::mutex MUTEX; + return MUTEX; +} -struct Clients : public rtl::Static< ClientMap, Clients > {}; +ClientMap gaClients; -struct FreeIntervals : public rtl::StaticWithInit<IntervalMap, FreeIntervals> +IntervalMap& GetFreeIntervals() { - IntervalMap operator() () + static IntervalMap MAP = + []() { IntervalMap map; map.insert(std::make_pair( std::numeric_limits<AccessibleEventNotifier::TClientId>::max(), 1)); return map; - } -}; + }(); + return MAP; +} void releaseId(AccessibleEventNotifier::TClientId const nId) { - IntervalMap & rFreeIntervals(FreeIntervals::get()); + IntervalMap & rFreeIntervals(GetFreeIntervals()); IntervalMap::iterator const upper(rFreeIntervals.upper_bound(nId)); assert(upper != rFreeIntervals.end()); assert(nId < upper->second); // second is start of the interval! @@ -89,7 +95,7 @@ void releaseId(AccessibleEventNotifier::TClientId const nId) /// generates a new client id AccessibleEventNotifier::TClientId generateId() { - IntervalMap & rFreeIntervals(FreeIntervals::get()); + IntervalMap & rFreeIntervals(GetFreeIntervals()); assert(!rFreeIntervals.empty()); IntervalMap::iterator const iter(rFreeIntervals.begin()); AccessibleEventNotifier::TClientId const nFirst = iter->first; @@ -104,7 +110,7 @@ AccessibleEventNotifier::TClientId generateId() rFreeIntervals.erase(iter); // remove 1-element interval } - assert(Clients::get().end() == Clients::get().find(nFreeId)); + assert(gaClients.end() == gaClients.find(nFreeId)); return nFreeId; } @@ -129,7 +135,7 @@ bool implLookupClient( ClientMap::iterator& rPos ) { // look up this client - ClientMap &rClients = Clients::get(); + ClientMap &rClients = gaClients; rPos = rClients.find( nClient ); assert( rClients.end() != rPos && "AccessibleEventNotifier::implLookupClient: invalid client id " @@ -144,21 +150,13 @@ namespace comphelper { AccessibleEventNotifier::TClientId AccessibleEventNotifier::registerClient() { - ::osl::MutexGuard aGuard( lclMutex::get() ); + std::scoped_lock aGuard( GetLocalMutex() ); // generate a new client id TClientId nNewClientId = generateId( ); - // the event listeners for the new client - ::comphelper::OInterfaceContainerHelper2 *const pNewListeners = - new ::comphelper::OInterfaceContainerHelper2( lclMutex::get() ); - // note that we're using our own mutex here, so the listener containers for all - // our clients share this same mutex. - // this is a reminiscence to the days where the notifier was asynchronous. Today this is - // completely nonsense, and potentially slowing down the Office me thinks... - // add the client - Clients::get().emplace( nNewClientId, pNewListeners ); + gaClients.emplace( nNewClientId, ListenerContainer{} ); // outta here return nNewClientId; @@ -166,7 +164,7 @@ AccessibleEventNotifier::TClientId AccessibleEventNotifier::registerClient() void AccessibleEventNotifier::revokeClient( const TClientId _nClient ) { - ::osl::MutexGuard aGuard( lclMutex::get() ); + std::scoped_lock aGuard( GetLocalMutex() ); ClientMap::iterator aClientPos; if ( !implLookupClient( _nClient, aClientPos ) ) @@ -174,48 +172,42 @@ void AccessibleEventNotifier::revokeClient( const TClientId _nClient ) return; // remove it from the clients map - delete aClientPos->second; - Clients::get().erase( aClientPos ); + gaClients.erase( aClientPos ); releaseId(_nClient); } void AccessibleEventNotifier::revokeClientNotifyDisposing( const TClientId _nClient, const Reference< XInterface >& _rxEventSource ) { - std::unique_ptr<::comphelper::OInterfaceContainerHelper2> pListeners; + std::unique_lock aGuard( GetLocalMutex() ); - { - // rhbz#1001768 drop the mutex before calling disposeAndClear - ::osl::MutexGuard aGuard( lclMutex::get() ); - - ClientMap::iterator aClientPos; - if (!implLookupClient(_nClient, aClientPos)) - // already asserted in implLookupClient - return; - - // notify the listeners - pListeners.reset(aClientPos->second); - - // we do not need the entry in the clients map anymore - // (do this before actually notifying, because some client - // implementations have re-entrance problems and call into - // revokeClient while we are notifying from here) - Clients::get().erase(aClientPos); - releaseId(_nClient); - } + ClientMap::iterator aClientPos; + if (!implLookupClient(_nClient, aClientPos)) + // already asserted in implLookupClient + return; + + // notify the listeners + ListenerContainer aListeners(std::move(aClientPos->second)); + + // we do not need the entry in the clients map anymore + // (do this before actually notifying, because some client + // implementations have re-entrance problems and call into + // revokeClient while we are notifying from here) + gaClients.erase(aClientPos); + releaseId(_nClient); // notify the "disposing" event for this client EventObject aDisposalEvent; aDisposalEvent.Source = _rxEventSource; // now really do the notification - pListeners->disposeAndClear( aDisposalEvent ); + aListeners.disposeAndClear( aGuard, aDisposalEvent ); } sal_Int32 AccessibleEventNotifier::addEventListener( const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) { - ::osl::MutexGuard aGuard( lclMutex::get() ); + std::unique_lock aGuard( GetLocalMutex() ); ClientMap::iterator aClientPos; if ( !implLookupClient( _nClient, aClientPos ) ) @@ -223,15 +215,15 @@ sal_Int32 AccessibleEventNotifier::addEventListener( return 0; if ( _rxListener.is() ) - aClientPos->second->addInterface( _rxListener ); + aClientPos->second.addInterface( aGuard, _rxListener ); - return aClientPos->second->getLength(); + return aClientPos->second.getLength(aGuard); } sal_Int32 AccessibleEventNotifier::removeEventListener( const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) { - ::osl::MutexGuard aGuard( lclMutex::get() ); + std::unique_lock aGuard( GetLocalMutex() ); ClientMap::iterator aClientPos; if ( !implLookupClient( _nClient, aClientPos ) ) @@ -239,35 +231,31 @@ sal_Int32 AccessibleEventNotifier::removeEventListener( return 0; if ( _rxListener.is() ) - aClientPos->second->removeInterface( _rxListener ); + aClientPos->second.removeInterface( aGuard, _rxListener ); - return aClientPos->second->getLength(); + return aClientPos->second.getLength(aGuard); } void AccessibleEventNotifier::addEvent( const TClientId _nClient, const AccessibleEventObject& _rEvent ) { - std::vector< Reference< XInterface > > aListeners; - - { - ::osl::MutexGuard aGuard( lclMutex::get() ); + std::unique_lock aGuard( GetLocalMutex() ); - ClientMap::iterator aClientPos; - if ( !implLookupClient( _nClient, aClientPos ) ) - // already asserted in implLookupClient - return; - - // since we're synchronous, again, we want to notify immediately - aListeners = aClientPos->second->getElements(); - } + ClientMap::iterator aClientPos; + if ( !implLookupClient( _nClient, aClientPos ) ) + // already asserted in implLookupClient + return; - // default handling: loop through all listeners, and notify them - for ( const auto& rListener : aListeners ) + // since we're synchronous, again, we want to notify immediately + OInterfaceIteratorHelper4 aIt(aGuard, aClientPos->second); + // no need to hold lock here, and we don't want to hold lock while calling listeners + aGuard.unlock(); + while (aIt.hasMoreElements()) { try { - static_cast< XAccessibleEventListener* >( rListener.get() )->notifyEvent( _rEvent ); + aIt.next()->notifyEvent(_rEvent); } - catch( const Exception& ) + catch (Exception&) { // no assertion, because a broken access remote bridge or something like this // can cause this exception @@ -275,6 +263,11 @@ void AccessibleEventNotifier::addEvent( const TClientId _nClient, const Accessib } } +void AccessibleEventNotifier::shutdown() +{ + gaClients.clear(); +} + } // namespace comphelper /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/accessiblekeybindinghelper.cxx b/comphelper/source/misc/accessiblekeybindinghelper.cxx index 8028464aff2b..d1db69b98fa8 100644 --- a/comphelper/source/misc/accessiblekeybindinghelper.cxx +++ b/comphelper/source/misc/accessiblekeybindinghelper.cxx @@ -21,6 +21,7 @@ #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> #include <comphelper/accessiblekeybindinghelper.hxx> +#include <o3tl/safeint.hxx> namespace comphelper @@ -55,7 +56,7 @@ namespace comphelper void OAccessibleKeyBindingHelper::AddKeyBinding( const Sequence< awt::KeyStroke >& rKeyBinding ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); m_aKeyBindings.push_back( rKeyBinding ); } @@ -63,11 +64,8 @@ namespace comphelper void OAccessibleKeyBindingHelper::AddKeyBinding( const awt::KeyStroke& rKeyStroke ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - Sequence< awt::KeyStroke > aSeq(1); - aSeq[0] = rKeyStroke; - m_aKeyBindings.push_back( aSeq ); + std::scoped_lock aGuard( m_aMutex ); + m_aKeyBindings.push_back( { rKeyStroke } ); } @@ -76,7 +74,7 @@ namespace comphelper sal_Int32 OAccessibleKeyBindingHelper::getAccessibleKeyBindingCount() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); return m_aKeyBindings.size(); } @@ -84,9 +82,9 @@ namespace comphelper Sequence< awt::KeyStroke > OAccessibleKeyBindingHelper::getAccessibleKeyBinding( sal_Int32 nIndex ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); - if ( nIndex < 0 || nIndex >= static_cast<sal_Int32>(m_aKeyBindings.size()) ) + if ( nIndex < 0 || o3tl::make_unsigned(nIndex) >= m_aKeyBindings.size() ) throw IndexOutOfBoundsException(); return m_aKeyBindings[nIndex]; diff --git a/comphelper/source/misc/accessibleselectionhelper.cxx b/comphelper/source/misc/accessibleselectionhelper.cxx index 967c1b079e48..ff880a76ee98 100644 --- a/comphelper/source/misc/accessibleselectionhelper.cxx +++ b/comphelper/source/misc/accessibleselectionhelper.cxx @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <comphelper/accessiblecontexthelper.hxx> #include <comphelper/accessibleselectionhelper.hxx> @@ -25,8 +26,6 @@ namespace comphelper using namespace ::com::sun::star::uno; - using namespace ::com::sun::star::awt; - using namespace ::com::sun::star::lang; using namespace ::com::sun::star::accessibility; OCommonAccessibleSelection::OCommonAccessibleSelection( ) @@ -36,13 +35,13 @@ namespace comphelper OCommonAccessibleSelection::~OCommonAccessibleSelection() {} - void OCommonAccessibleSelection::selectAccessibleChild( sal_Int32 nChildIndex ) + void OCommonAccessibleSelection::selectAccessibleChild( sal_Int64 nChildIndex ) { implSelect( nChildIndex, true ); } - bool OCommonAccessibleSelection::isAccessibleChildSelected( sal_Int32 nChildIndex ) + bool OCommonAccessibleSelection::isAccessibleChildSelected( sal_Int64 nChildIndex ) { return implIsSelected( nChildIndex ); } @@ -60,16 +59,16 @@ namespace comphelper } - sal_Int32 OCommonAccessibleSelection::getSelectedAccessibleChildCount( ) + sal_Int64 OCommonAccessibleSelection::getSelectedAccessibleChildCount( ) { - sal_Int32 nRet = 0; + sal_Int64 nRet = 0; Reference< XAccessibleContext > xParentContext( implGetAccessibleContext() ); OSL_ENSURE( xParentContext.is(), "OCommonAccessibleSelection::getSelectedAccessibleChildCount: no parent context!" ); if( xParentContext.is() ) { - for( sal_Int32 i = 0, nChildCount = xParentContext->getAccessibleChildCount(); i < nChildCount; i++ ) + for( sal_Int64 i = 0, nChildCount = xParentContext->getAccessibleChildCount(); i < nChildCount; i++ ) if( implIsSelected( i ) ) ++nRet; } @@ -78,7 +77,7 @@ namespace comphelper } - Reference< XAccessible > OCommonAccessibleSelection::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) + Reference< XAccessible > OCommonAccessibleSelection::getSelectedAccessibleChild( sal_Int64 nSelectedChildIndex ) { Reference< XAccessible > xRet; Reference< XAccessibleContext > xParentContext( implGetAccessibleContext() ); @@ -87,7 +86,7 @@ namespace comphelper if( xParentContext.is() ) { - for( sal_Int32 i = 0, nChildCount = xParentContext->getAccessibleChildCount(), nPos = 0; ( i < nChildCount ) && !xRet.is(); i++ ) + for( sal_Int64 i = 0, nChildCount = xParentContext->getAccessibleChildCount(), nPos = 0; ( i < nChildCount ) && !xRet.is(); i++ ) if( implIsSelected( i ) && ( nPos++ == nSelectedChildIndex ) ) xRet = xParentContext->getAccessibleChild( i ); } @@ -96,7 +95,7 @@ namespace comphelper } - void OCommonAccessibleSelection::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) + void OCommonAccessibleSelection::deselectAccessibleChild( sal_Int64 nSelectedChildIndex ) { implSelect( nSelectedChildIndex, false ); } @@ -106,25 +105,20 @@ namespace comphelper } - IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleSelectionHelper, OAccessibleComponentHelper, OAccessibleSelectionHelper_Base ) - IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleSelectionHelper, OAccessibleComponentHelper, OAccessibleSelectionHelper_Base ) - // (order matters: the first is the class name, the second is the class doing the ref counting) - - Reference< XAccessibleContext > OAccessibleSelectionHelper::implGetAccessibleContext() { return this; } - void SAL_CALL OAccessibleSelectionHelper::selectAccessibleChild( sal_Int32 nChildIndex ) + void SAL_CALL OAccessibleSelectionHelper::selectAccessibleChild( sal_Int64 nChildIndex ) { OExternalLockGuard aGuard( this ); OCommonAccessibleSelection::selectAccessibleChild( nChildIndex ); } - sal_Bool SAL_CALL OAccessibleSelectionHelper::isAccessibleChildSelected( sal_Int32 nChildIndex ) + sal_Bool SAL_CALL OAccessibleSelectionHelper::isAccessibleChildSelected( sal_Int64 nChildIndex ) { OExternalLockGuard aGuard( this ); return OCommonAccessibleSelection::isAccessibleChildSelected( nChildIndex ); @@ -145,21 +139,21 @@ namespace comphelper } - sal_Int32 SAL_CALL OAccessibleSelectionHelper::getSelectedAccessibleChildCount( ) + sal_Int64 SAL_CALL OAccessibleSelectionHelper::getSelectedAccessibleChildCount( ) { OExternalLockGuard aGuard( this ); return OCommonAccessibleSelection::getSelectedAccessibleChildCount(); } - Reference< XAccessible > SAL_CALL OAccessibleSelectionHelper::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) + Reference< XAccessible > SAL_CALL OAccessibleSelectionHelper::getSelectedAccessibleChild( sal_Int64 nSelectedChildIndex ) { OExternalLockGuard aGuard( this ); return OCommonAccessibleSelection::getSelectedAccessibleChild( nSelectedChildIndex ); } - void SAL_CALL OAccessibleSelectionHelper::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) + void SAL_CALL OAccessibleSelectionHelper::deselectAccessibleChild( sal_Int64 nSelectedChildIndex ) { OExternalLockGuard aGuard( this ); OCommonAccessibleSelection::deselectAccessibleChild( nSelectedChildIndex ); diff --git a/comphelper/source/misc/accessibletexthelper.cxx b/comphelper/source/misc/accessibletexthelper.cxx index 35fe769c1700..02cd77fc766d 100644 --- a/comphelper/source/misc/accessibletexthelper.cxx +++ b/comphelper/source/misc/accessibletexthelper.cxx @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <comphelper/accessiblecontexthelper.hxx> #include <comphelper/accessibletexthelper.hxx> #include <com/sun/star/accessibility/AccessibleTextType.hpp> #include <com/sun/star/i18n/BreakIterator.hpp> @@ -38,7 +39,6 @@ namespace comphelper using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; - using namespace ::com::sun::star::beans; using namespace ::com::sun::star::accessibility; @@ -215,9 +215,9 @@ namespace comphelper } - sal_Unicode OCommonAccessibleText::implGetCharacter( const OUString& rText, sal_Int32 nIndex ) + sal_Unicode OCommonAccessibleText::implGetCharacter( std::u16string_view rText, sal_Int32 nIndex ) { - if ( !implIsValidIndex( nIndex, rText.getLength() ) ) + if ( !implIsValidIndex( nIndex, rText.size() ) ) throw IndexOutOfBoundsException(); return rText[nIndex]; @@ -265,16 +265,16 @@ namespace comphelper } - OUString OCommonAccessibleText::implGetTextRange( const OUString& rText, sal_Int32 nStartIndex, sal_Int32 nEndIndex ) + OUString OCommonAccessibleText::implGetTextRange( std::u16string_view rText, sal_Int32 nStartIndex, sal_Int32 nEndIndex ) { - if ( !implIsValidRange( nStartIndex, nEndIndex, rText.getLength() ) ) + if ( !implIsValidRange( nStartIndex, nEndIndex, rText.size() ) ) throw IndexOutOfBoundsException(); sal_Int32 nMinIndex = std::min( nStartIndex, nEndIndex ); sal_Int32 nMaxIndex = std::max( nStartIndex, nEndIndex ); - return rText.copy( nMinIndex, nMaxIndex - nMinIndex ); + return OUString(rText.substr( nMinIndex, nMaxIndex - nMinIndex )); } TextSegment OCommonAccessibleText::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) @@ -296,9 +296,12 @@ namespace comphelper { if ( implIsValidIndex( nIndex, nLength ) ) { - aResult.SegmentText = sText.copy( nIndex, 1 ); + auto nIndexEnd = nIndex; + sText.iterateCodePoints(&nIndexEnd); + + aResult.SegmentText = sText.copy( nIndex, nIndexEnd - nIndex ); aResult.SegmentStart = nIndex; - aResult.SegmentEnd = nIndex+1; + aResult.SegmentEnd = nIndexEnd; } } break; @@ -400,9 +403,12 @@ namespace comphelper { if ( implIsValidIndex( nIndex - 1, nLength ) ) { - aResult.SegmentText = sText.copy( nIndex - 1, 1 ); - aResult.SegmentStart = nIndex-1; - aResult.SegmentEnd = nIndex; + sText.iterateCodePoints(&nIndex, -1); + auto nIndexEnd = nIndex; + sText.iterateCodePoints(&nIndexEnd); + aResult.SegmentText = sText.copy(nIndex, nIndexEnd - nIndex); + aResult.SegmentStart = nIndex; + aResult.SegmentEnd = nIndexEnd; } } break; @@ -524,9 +530,12 @@ namespace comphelper { if ( implIsValidIndex( nIndex + 1, nLength ) ) { - aResult.SegmentText = sText.copy( nIndex + 1, 1 ); - aResult.SegmentStart = nIndex+1; - aResult.SegmentEnd = nIndex+2; + sText.iterateCodePoints(&nIndex); + auto nIndexEnd = nIndex; + sText.iterateCodePoints(&nIndexEnd); + aResult.SegmentText = sText.copy(nIndex, nIndexEnd - nIndex); + aResult.SegmentStart = nIndex; + aResult.SegmentEnd = nIndexEnd; } } break; @@ -634,13 +643,13 @@ namespace comphelper bool OCommonAccessibleText::implInitTextChangedEvent( - const OUString& rOldString, - const OUString& rNewString, + std::u16string_view rOldString, + std::u16string_view rNewString, css::uno::Any& rDeleted, css::uno::Any& rInserted) // throw() { - sal_uInt32 nLenOld = rOldString.getLength(); - sal_uInt32 nLenNew = rNewString.getLength(); + size_t nLenOld = rOldString.size(); + size_t nLenNew = rNewString.size(); // equal if ((0 == nLenOld) && (0 == nLenNew)) @@ -659,7 +668,7 @@ namespace comphelper { aInsertedText.SegmentStart = 0; aInsertedText.SegmentEnd = nLenNew; - aInsertedText.SegmentText = rNewString.copy( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart ); + aInsertedText.SegmentText = rNewString.substr( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart ); rInserted <<= aInsertedText; return true; @@ -670,28 +679,27 @@ namespace comphelper { aDeletedText.SegmentStart = 0; aDeletedText.SegmentEnd = nLenOld; - aDeletedText.SegmentText = rOldString.copy( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart ); + aDeletedText.SegmentText = rOldString.substr( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart ); rDeleted <<= aDeletedText; return true; } - const sal_Unicode* pFirstDiffOld = rOldString.getStr(); - const sal_Unicode* pLastDiffOld = rOldString.getStr() + nLenOld; - const sal_Unicode* pFirstDiffNew = rNewString.getStr(); - const sal_Unicode* pLastDiffNew = rNewString.getStr() + nLenNew; + auto pFirstDiffOld = rOldString.begin(); + auto pLastDiffOld = rOldString.end(); + auto pFirstDiffNew = rNewString.begin(); + auto pLastDiffNew = rNewString.end(); // find first difference - while ((*pFirstDiffOld == *pFirstDiffNew) && - (pFirstDiffOld < pLastDiffOld) && - (pFirstDiffNew < pLastDiffNew)) + while ((pFirstDiffOld < pLastDiffOld) && (pFirstDiffNew < pLastDiffNew) + && (*pFirstDiffOld == *pFirstDiffNew)) { pFirstDiffOld++; pFirstDiffNew++; } // equality test - if ((0 == *pFirstDiffOld) && (0 == *pFirstDiffNew)) + if (pFirstDiffOld == pLastDiffOld && pFirstDiffNew == pLastDiffNew) return false; // find last difference @@ -705,18 +713,18 @@ namespace comphelper if (pFirstDiffOld < pLastDiffOld) { - aDeletedText.SegmentStart = pFirstDiffOld - rOldString.getStr(); - aDeletedText.SegmentEnd = pLastDiffOld - rOldString.getStr(); - aDeletedText.SegmentText = rOldString.copy( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart ); + aDeletedText.SegmentStart = pFirstDiffOld - rOldString.begin(); + aDeletedText.SegmentEnd = pLastDiffOld - rOldString.begin(); + aDeletedText.SegmentText = rOldString.substr( aDeletedText.SegmentStart, aDeletedText.SegmentEnd - aDeletedText.SegmentStart ); rDeleted <<= aDeletedText; } if (pFirstDiffNew < pLastDiffNew) { - aInsertedText.SegmentStart = pFirstDiffNew - rNewString.getStr(); - aInsertedText.SegmentEnd = pLastDiffNew - rNewString.getStr(); - aInsertedText.SegmentText = rNewString.copy( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart ); + aInsertedText.SegmentStart = pFirstDiffNew - rNewString.begin(); + aInsertedText.SegmentEnd = pLastDiffNew - rNewString.begin(); + aInsertedText.SegmentText = rNewString.substr( aInsertedText.SegmentStart, aInsertedText.SegmentEnd - aInsertedText.SegmentStart ); rInserted <<= aInsertedText; } @@ -732,18 +740,6 @@ namespace comphelper } - // XInterface - - - IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleTextHelper, OAccessibleExtendedComponentHelper, OAccessibleTextHelper_Base ) - - - // XTypeProvider - - - IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleTextHelper, OAccessibleExtendedComponentHelper, OAccessibleTextHelper_Base ) - - // XAccessibleText diff --git a/comphelper/source/misc/accessiblewrapper.cxx b/comphelper/source/misc/accessiblewrapper.cxx index 4d4edb1393dc..3e356f434faa 100644 --- a/comphelper/source/misc/accessiblewrapper.cxx +++ b/comphelper/source/misc/accessiblewrapper.cxx @@ -79,15 +79,14 @@ namespace comphelper xComp->removeEventListener( this ); } // clear the map - AccessibleMap aMap; - m_aChildrenMap.swap( aMap ); + m_aChildrenMap.clear(); } Reference< XAccessible > OWrappedAccessibleChildrenManager::getAccessibleWrapperFor( const Reference< XAccessible >& _rxKey ) { - Reference< XAccessible > xValue; + rtl::Reference< OAccessibleWrapper > xValue; if( !_rxKey.is() ) { @@ -141,15 +140,14 @@ namespace comphelper Reference< XComponent > xContextComponent; if( rChild.second.is() ) - xContextComponent.set( rChild.second->getAccessibleContext(), + xContextComponent.set( rChild.second->getContextNoCreate(), ::css::uno::UNO_QUERY ); if( xContextComponent.is() ) xContextComponent->dispose(); } // clear our children - AccessibleMap aMap; - m_aChildrenMap.swap( aMap ); + m_aChildrenMap.clear(); } @@ -308,7 +306,7 @@ namespace comphelper } - OAccessibleContextWrapper* OAccessibleWrapper::createAccessibleContext( const Reference< XAccessibleContext >& _rxInnerContext ) + rtl::Reference<OAccessibleContextWrapper> OAccessibleWrapper::createAccessibleContext( const Reference< XAccessibleContext >& _rxInnerContext ) { return new OAccessibleContextWrapper( getComponentContext(), _rxInnerContext, this, m_xParentAccessible ); } @@ -347,9 +345,8 @@ namespace comphelper ,m_xChildMapper( new OWrappedAccessibleChildrenManager( getComponentContext() ) ) { // determine if we're allowed to cache children - Reference< XAccessibleStateSet > xStates( m_xInnerContext->getAccessibleStateSet( ) ); - OSL_ENSURE( xStates.is(), "OAccessibleContextWrapperHelper::OAccessibleContextWrapperHelper: no inner state set!" ); - m_xChildMapper->setTransientChildren( !xStates.is() || xStates->contains( AccessibleStateType::MANAGES_DESCENDANTS) ); + sal_Int64 aStates = m_xInnerContext->getAccessibleStateSet( ); + m_xChildMapper->setTransientChildren( aStates & AccessibleStateType::MANAGES_DESCENDANTS ); m_xChildMapper->setOwningAccessible( m_xOwningAccessible ); } @@ -391,13 +388,13 @@ namespace comphelper IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleContextWrapperHelper, OComponentProxyAggregationHelper, OAccessibleContextWrapperHelper_Base ) - sal_Int32 OAccessibleContextWrapperHelper::baseGetAccessibleChildCount( ) + sal_Int64 OAccessibleContextWrapperHelper::baseGetAccessibleChildCount( ) { return m_xInnerContext->getAccessibleChildCount(); } - Reference< XAccessible > OAccessibleContextWrapperHelper::baseGetAccessibleChild( sal_Int32 i ) + Reference< XAccessible > OAccessibleContextWrapperHelper::baseGetAccessibleChild( sal_Int64 i ) { // get the child of the wrapped component Reference< XAccessible > xInnerChild = m_xInnerContext->getAccessibleChild( i ); @@ -419,7 +416,7 @@ namespace comphelper if ( AccessibleEventId::STATE_CHANGED == _rEvent.EventId ) { bool bChildTransienceChanged = false; - sal_Int16 nChangeState = 0; + sal_Int64 nChangeState = 0; if ( _rEvent.OldValue >>= nChangeState ) bChildTransienceChanged = bChildTransienceChanged || AccessibleStateType::MANAGES_DESCENDANTS == nChangeState; if ( _rEvent.NewValue >>= nChangeState ) @@ -497,13 +494,13 @@ namespace comphelper } - sal_Int32 SAL_CALL OAccessibleContextWrapper::getAccessibleChildCount( ) + sal_Int64 SAL_CALL OAccessibleContextWrapper::getAccessibleChildCount( ) { return baseGetAccessibleChildCount(); } - Reference< XAccessible > SAL_CALL OAccessibleContextWrapper::getAccessibleChild( sal_Int32 i ) + Reference< XAccessible > SAL_CALL OAccessibleContextWrapper::getAccessibleChild( sal_Int64 i ) { return baseGetAccessibleChild( i ); } @@ -515,7 +512,7 @@ namespace comphelper } - sal_Int32 SAL_CALL OAccessibleContextWrapper::getAccessibleIndexInParent( ) + sal_Int64 SAL_CALL OAccessibleContextWrapper::getAccessibleIndexInParent( ) { return m_xInnerContext->getAccessibleIndexInParent(); } @@ -545,7 +542,7 @@ namespace comphelper } - Reference< XAccessibleStateSet > SAL_CALL OAccessibleContextWrapper::getAccessibleStateSet( ) + sal_Int64 SAL_CALL OAccessibleContextWrapper::getAccessibleStateSet( ) { return m_xInnerContext->getAccessibleStateSet(); } @@ -588,7 +585,7 @@ namespace comphelper } - void SAL_CALL OAccessibleContextWrapper::disposing() + void OAccessibleContextWrapper::implDisposing(const css::lang::EventObject* pEvent) { AccessibleEventNotifier::TClientId nClientId( 0 ); @@ -606,12 +603,29 @@ namespace comphelper // --- </mutex lock> ----------------------------------------- // let the base class do - OAccessibleContextWrapperHelper::dispose(); + if (pEvent) + OAccessibleContextWrapperHelper::disposing(*pEvent); + else + OAccessibleContextWrapperHelper::dispose(); // notify the disposal if ( nClientId ) AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, *this ); } + + void SAL_CALL OAccessibleContextWrapper::disposing() + { + implDisposing(nullptr); + } + + void SAL_CALL OAccessibleContextWrapper::disposing(const css::lang::EventObject& rEvent) + { + assert(rEvent.Source == Reference<XInterface>(m_xInnerContext, UNO_QUERY) + && "OAccessibleContextWrapper::disposing called with event source that's not the " + "wrapped a11y context"); + + implDisposing(&rEvent); + } } // namespace accessibility diff --git a/comphelper/source/misc/accimplaccess.cxx b/comphelper/source/misc/accimplaccess.cxx deleted file mode 100644 index 71a12c8a7e98..000000000000 --- a/comphelper/source/misc/accimplaccess.cxx +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include <comphelper/accimplaccess.hxx> -#include <cppuhelper/typeprovider.hxx> - -#include <string.h> - - -namespace comphelper -{ - - - using ::com::sun::star::uno::Sequence; - - OAccessibleImplementationAccess::OAccessibleImplementationAccess( ) - { - } - - - OAccessibleImplementationAccess::~OAccessibleImplementationAccess( ) - { - } - - Sequence< sal_Int8 > OAccessibleImplementationAccess::getUnoTunnelImplementationId() - { - static cppu::OImplementationId implID; - - return implID.getImplementationId(); - } - - - sal_Int64 SAL_CALL OAccessibleImplementationAccess::getSomething( const Sequence< sal_Int8 >& _rIdentifier ) - { - sal_Int64 nReturn( 0 ); - - if ( ( _rIdentifier.getLength() == 16 ) - && ( 0 == memcmp( getUnoTunnelImplementationId().getConstArray(), _rIdentifier.getConstArray(), 16 ) ) - ) - nReturn = reinterpret_cast< sal_Int64 >( this ); - - return nReturn; - } - -} // namespace comphelper - - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/anycompare.cxx b/comphelper/source/misc/anycompare.cxx index bb77544c957e..79d3864535c0 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 { @@ -60,7 +66,7 @@ namespace comphelper if ( !( _lhs >>= lhs ) || !( _rhs >>= rhs ) ) - throw css::lang::IllegalArgumentException(); + throw css::lang::IllegalArgumentException(u"bad ordering"_ustr, css::uno::Reference<css::uno::XInterface>(), -1); // FIXME Timezone? if ( lhs.Year < rhs.Year ) @@ -88,7 +94,7 @@ namespace comphelper if ( !( _lhs >>= lhs ) || !( _rhs >>= rhs ) ) - throw css::lang::IllegalArgumentException(); + throw css::lang::IllegalArgumentException(u"bad ordering"_ustr, css::uno::Reference<css::uno::XInterface>(), -1); // FIXME Timezone? if ( lhs.Hours < rhs.Hours ) @@ -121,7 +127,7 @@ namespace comphelper if ( !( _lhs >>= lhs ) || !( _rhs >>= rhs ) ) - throw css::lang::IllegalArgumentException(); + throw css::lang::IllegalArgumentException(u"bad ordering"_ustr, css::uno::Reference<css::uno::XInterface>(), -1); // FIXME Timezone? if ( lhs.Year < rhs.Year ) @@ -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(u"bad ordering"_ustr, css::uno::Reference<css::uno::XInterface>(), -1); + TypeDescription rhsTypeDescr( rhsType ); + if (!rhsTypeDescr.is()) + rhsTypeDescr.makeComplete(); + if (!rhsTypeDescr.is()) + throw css::lang::IllegalArgumentException(u"bad ordering"_ustr, 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(u"bad ordering"_ustr, 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(u"bad ordering"_ustr, css::uno::Reference<css::uno::XInterface>(), -1); + TypeDescriptionRef rhsTypeDescr( rhsType ); + if (!rhsTypeDescr.is()) + throw css::lang::IllegalArgumentException(u"bad ordering"_ustr, 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(u"bad ordering"_ustr, 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(u"bad ordering"_ustr, css::uno::Reference<css::uno::XInterface>(), -1); + TypeDescription rhsTypeDescr( rhsType ); + if (!rhsTypeDescr.is()) + rhsTypeDescr.makeComplete(); + if (!rhsTypeDescr.is()) + throw css::lang::IllegalArgumentException(u"bad ordering"_ustr, 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,14 +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; - std::unique_ptr< IKeyPredicateLess > pred = getStandardLessPredicate( lhs.getValueType(), Reference< XCollator >() ); - if (!pred) // type==VOID - return false; - return pred->isLess(lhs, rhs); + return anyLess( lhs.getValue(), lhs.getValueTypeRef(), rhs.getValue(), rhs.getValueTypeRef()); } } // namespace comphelper diff --git a/comphelper/source/misc/anytohash.cxx b/comphelper/source/misc/anytohash.cxx new file mode 100644 index 000000000000..4e97ea124d41 --- /dev/null +++ b/comphelper/source/misc/anytohash.cxx @@ -0,0 +1,210 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <comphelper/anytohash.hxx> + +#include <o3tl/hash_combine.hxx> +#include <typelib/typedescription.hxx> + +#include <com/sun/star/uno/Sequence.hxx> + +#include "typedescriptionref.hxx" + +using namespace ::com::sun::star; +using ::com::sun::star::uno::TypeDescription; +using ::comphelper::detail::TypeDescriptionRef; + +namespace comphelper { +namespace { + +std::optional<size_t> hashValue( size_t hash, + void const * val, typelib_TypeDescriptionReference * typeRef ) +{ + o3tl::hash_combine( hash, typeRef->eTypeClass ); + if (typeRef->eTypeClass == typelib_TypeClass_VOID) { + return hash; + } + assert(val != nullptr); + + switch (typeRef->eTypeClass) { + case typelib_TypeClass_INTERFACE: { + return std::nullopt; // not implemented + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: { + TypeDescription typeDescr( typeRef ); + if (!typeDescr.is()) + typeDescr.makeComplete(); + if (!typeDescr.is()) + return std::nullopt; + + typelib_CompoundTypeDescription * compType = + reinterpret_cast< typelib_CompoundTypeDescription * >( + typeDescr.get() ); + sal_Int32 nDescr = compType->nMembers; + + if (compType->pBaseTypeDescription) { + std::optional<size_t> tmpHash = hashValue( + hash, val, reinterpret_cast< + typelib_TypeDescription * >( + compType->pBaseTypeDescription)->pWeakRef); + if(!tmpHash.has_value()) + return std::nullopt; + hash = *tmpHash; + } + + typelib_TypeDescriptionReference ** ppTypeRefs = + compType->ppTypeRefs; + sal_Int32 * memberOffsets = compType->pMemberOffsets; + + for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos ) + { + TypeDescriptionRef memberType( ppTypeRefs[ nPos ] ); + if (!memberType.is()) + return std::nullopt; + + std::optional<size_t> tmpHash = hashValue( hash, + static_cast< char const * >( + val ) + memberOffsets[ nPos ], + memberType->pWeakRef ); + if(!tmpHash.has_value()) + return std::nullopt; + hash = *tmpHash; + } + break; + } + case typelib_TypeClass_SEQUENCE: { + TypeDescriptionRef typeDescr( typeRef ); + if (!typeDescr.is()) + return std::nullopt; + + typelib_TypeDescriptionReference * elementTypeRef = + reinterpret_cast< + typelib_IndirectTypeDescription * >(typeDescr.get())->pType; + TypeDescriptionRef elementTypeDescr( elementTypeRef ); + if (!elementTypeDescr.is()) + return std::nullopt; + + sal_Int32 nElementSize = elementTypeDescr->nSize; + uno_Sequence * seq = + *static_cast< uno_Sequence * const * >(val); + sal_Int32 nElements = seq->nElements; + + if (nElements > 0) + { + char const * pElements = seq->elements; + for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) + { + std::optional<size_t> tmpHash = hashValue( hash, + pElements + (nElementSize * nPos), + elementTypeDescr->pWeakRef ); + if(!tmpHash.has_value()) + return std::nullopt; + hash = *tmpHash; + } + } + break; + } + case typelib_TypeClass_ANY: { + uno_Any const * pAny = static_cast< uno_Any const * >(val); + return hashValue( hash, pAny->pData, pAny->pType ); + } + case typelib_TypeClass_TYPE: { + OUString const & str = OUString::unacquired( + &(*static_cast< + typelib_TypeDescriptionReference * const * >(val) + )->pTypeName ); + o3tl::hash_combine( hash, str.hashCode() ); + break; + } + case typelib_TypeClass_STRING: { + OUString const & str = OUString::unacquired( + static_cast< rtl_uString * const * >(val) ); + o3tl::hash_combine( hash, str.hashCode() ); + break; + } + case typelib_TypeClass_ENUM: { + TypeDescription typeDescr( typeRef ); + if (!typeDescr.is()) + typeDescr.makeComplete(); + if (!typeDescr.is()) + return std::nullopt; + + o3tl::hash_combine( hash, *static_cast< int const * >(val)); + break; + } + case typelib_TypeClass_BOOLEAN: + if (*static_cast< sal_Bool const * >(val)) + o3tl::hash_combine( hash, true ); + else + o3tl::hash_combine( hash, false ); + break; + case typelib_TypeClass_CHAR: { + o3tl::hash_combine( hash, *static_cast< sal_Unicode const * >(val)); + break; + } + case typelib_TypeClass_FLOAT: + o3tl::hash_combine( hash, *static_cast< float const * >(val) ); + break; + case typelib_TypeClass_DOUBLE: + o3tl::hash_combine( hash, *static_cast< double const * >(val) ); + break; + case typelib_TypeClass_BYTE: + o3tl::hash_combine( hash, *static_cast< sal_Int8 const * >(val) ); + break; + case typelib_TypeClass_SHORT: + o3tl::hash_combine( hash, *static_cast< sal_Int16 const * >(val) ); + break; + case typelib_TypeClass_UNSIGNED_SHORT: + o3tl::hash_combine( hash, *static_cast< sal_uInt16 const * >(val) ); + break; + case typelib_TypeClass_LONG: + o3tl::hash_combine( hash, *static_cast< sal_Int32 const * >(val) ); + break; + case typelib_TypeClass_UNSIGNED_LONG: + o3tl::hash_combine( hash, *static_cast< sal_uInt32 const * >(val) ); + break; + case typelib_TypeClass_HYPER: + o3tl::hash_combine( hash, *static_cast< sal_Int64 const * >(val) ); + break; + case typelib_TypeClass_UNSIGNED_HYPER: + o3tl::hash_combine( hash, *static_cast< sal_uInt64 const * >(val) ); + break; +// case typelib_TypeClass_UNKNOWN: +// case typelib_TypeClass_SERVICE: +// case typelib_TypeClass_MODULE: + default: + return std::nullopt; + } + return hash; +} + +} // anon namespace + + +std::optional<size_t> anyToHash( uno::Any const & value ) +{ + size_t hash = 0; + return hashValue( hash, value.getValue(), value.getValueTypeRef()); +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/anytostring.cxx b/comphelper/source/misc/anytostring.cxx index 37242356e12b..ebc338b0b4be 100644 --- a/comphelper/source/misc/anytostring.cxx +++ b/comphelper/source/misc/anytostring.cxx @@ -20,16 +20,20 @@ #include <comphelper/anytostring.hxx> #include <rtl/ustrbuf.hxx> -#include <typelib/typedescription.h> +#include <typelib/typedescription.hxx> #include <com/sun/star/lang/XServiceInfo.hpp> +#include "typedescriptionref.hxx" + using namespace ::com::sun::star; +using ::com::sun::star::uno::TypeDescription; +using ::comphelper::detail::TypeDescriptionRef; namespace comphelper { namespace { void appendTypeError( - OUStringBuffer & buf, typelib_TypeDescriptionReference * typeRef ) + OUStringBuffer & buf, const typelib_TypeDescriptionReference * typeRef ) { buf.append( "<cannot get type description of type " ); buf.append( OUString::unacquired( &typeRef->pTypeName ) ); @@ -90,15 +94,16 @@ void appendValue( OUStringBuffer & buf, case typelib_TypeClass_STRUCT: case typelib_TypeClass_EXCEPTION: { buf.append( "{ " ); - typelib_TypeDescription * typeDescr = nullptr; - typelib_typedescriptionreference_getDescription( &typeDescr, typeRef ); - if (typeDescr == nullptr || !typelib_typedescription_complete( &typeDescr )) { + TypeDescription typeDescr( typeRef ); + if (!typeDescr.is()) + typeDescr.makeComplete(); + if (!typeDescr.is()) { appendTypeError( buf, typeRef ); } else { typelib_CompoundTypeDescription * compType = reinterpret_cast< typelib_CompoundTypeDescription * >( - typeDescr ); + typeDescr.get() ); sal_Int32 nDescr = compType->nMembers; if (compType->pBaseTypeDescription) { @@ -119,9 +124,8 @@ void appendValue( OUStringBuffer & buf, { buf.append( ppMemberNames[ nPos ] ); buf.append( " = " ); - typelib_TypeDescription * memberType = nullptr; - TYPELIB_DANGER_GET( &memberType, ppTypeRefs[ nPos ] ); - if (memberType == nullptr) { + TypeDescriptionRef memberType( ppTypeRefs[ nPos ] ); + if (!memberType.is()) { appendTypeError( buf, ppTypeRefs[ nPos ] ); } else { @@ -129,30 +133,25 @@ void appendValue( OUStringBuffer & buf, static_cast< char const * >( val ) + memberOffsets[ nPos ], memberType->pWeakRef, true ); - TYPELIB_DANGER_RELEASE( memberType ); } if (nPos < (nDescr - 1)) buf.append( ", " ); } } buf.append( " }" ); - if (typeDescr != nullptr) - typelib_typedescription_release( typeDescr ); break; } case typelib_TypeClass_SEQUENCE: { - typelib_TypeDescription * typeDescr = nullptr; - TYPELIB_DANGER_GET( &typeDescr, typeRef ); - if (typeDescr == nullptr) { + TypeDescriptionRef typeDescr( typeRef ); + if (!typeDescr.is()) { appendTypeError( buf,typeRef ); } else { typelib_TypeDescriptionReference * elementTypeRef = reinterpret_cast< - typelib_IndirectTypeDescription * >(typeDescr)->pType; - typelib_TypeDescription * elementTypeDescr = nullptr; - TYPELIB_DANGER_GET( &elementTypeDescr, elementTypeRef ); - if (elementTypeDescr == nullptr) + typelib_IndirectTypeDescription * >(typeDescr.get())->pType; + TypeDescriptionRef elementTypeDescr( elementTypeRef ); + if (!elementTypeDescr.is()) { appendTypeError( buf, elementTypeRef ); } @@ -181,9 +180,7 @@ void appendValue( OUStringBuffer & buf, { buf.append( "{}" ); } - TYPELIB_DANGER_RELEASE( elementTypeDescr ); } - TYPELIB_DANGER_RELEASE( typeDescr ); } break; } @@ -218,18 +215,19 @@ void appendValue( OUStringBuffer & buf, break; } case typelib_TypeClass_ENUM: { - typelib_TypeDescription * typeDescr = nullptr; - typelib_typedescriptionreference_getDescription( &typeDescr, typeRef ); - if (typeDescr == nullptr || !typelib_typedescription_complete( &typeDescr )) { + TypeDescription typeDescr( typeRef ); + if (!typeDescr.is()) + typeDescr.makeComplete(); + if (!typeDescr.is()) { appendTypeError( buf, typeRef ); } else { sal_Int32 * pValues = reinterpret_cast< typelib_EnumTypeDescription * >( - typeDescr )->pEnumValues; + typeDescr.get() )->pEnumValues; sal_Int32 nPos = reinterpret_cast< typelib_EnumTypeDescription * >( - typeDescr )->nEnumValues; + typeDescr.get() )->nEnumValues; while (nPos--) { if (pValues[ nPos ] == *static_cast< int const * >(val)) @@ -238,15 +236,13 @@ void appendValue( OUStringBuffer & buf, if (nPos >= 0) { buf.append( reinterpret_cast< typelib_EnumTypeDescription * >( - typeDescr )->ppEnumNames[ nPos ] ); + typeDescr.get() )->ppEnumNames[ nPos ] ); } else { buf.append( "?unknown enum value?" ); } } - if (typeDescr != nullptr) - typelib_typedescription_release( typeDescr ); break; } case typelib_TypeClass_BOOLEAN: diff --git a/comphelper/source/misc/asyncnotification.cxx b/comphelper/source/misc/asyncnotification.cxx index a360b7207fe4..72c6414e7281 100644 --- a/comphelper/source/misc/asyncnotification.cxx +++ b/comphelper/source/misc/asyncnotification.cxx @@ -18,12 +18,11 @@ */ #include <comphelper/asyncnotification.hxx> -#include <osl/mutex.hxx> -#include <osl/conditn.hxx> -#include <rtl/instance.hxx> +#include <comphelper/scopeguard.hxx> +#include <mutex> +#include <condition_variable> #include <cassert> -#include <deque> #include <stdexcept> #include <vector> #include <algorithm> @@ -44,24 +43,8 @@ namespace comphelper { AnyEventRef aEvent; ::rtl::Reference< IEventProcessor > xProcessor; - - ProcessableEvent() - { - } - - ProcessableEvent( const AnyEventRef& _rEvent, const ::rtl::Reference< IEventProcessor >& _xProcessor ) - :aEvent( _rEvent ) - ,xProcessor( _xProcessor ) - { - } }; - } - - typedef std::deque< ProcessableEvent > EventQueue; - - namespace { - struct EqualProcessor { const ::rtl::Reference< IEventProcessor >& rProcessor; @@ -77,9 +60,9 @@ namespace comphelper struct EventNotifierImpl { - ::osl::Mutex aMutex; - ::osl::Condition aPendingActions; - EventQueue aEvents; + std::mutex aMutex; + std::condition_variable aPendingActions; + std::vector< ProcessableEvent > aEvents; bool bTerminate; // only used for AsyncEventNotifierAutoJoin char const* name; @@ -105,34 +88,34 @@ namespace comphelper void AsyncEventNotifierBase::removeEventsForProcessor( const ::rtl::Reference< IEventProcessor >& _xProcessor ) { - ::osl::MutexGuard aGuard( m_xImpl->aMutex ); + std::scoped_lock aGuard( m_xImpl->aMutex ); // remove all events for this processor - m_xImpl->aEvents.erase(std::remove_if( m_xImpl->aEvents.begin(), m_xImpl->aEvents.end(), EqualProcessor( _xProcessor ) ), m_xImpl->aEvents.end()); + std::erase_if( m_xImpl->aEvents, EqualProcessor( _xProcessor ) ); } void SAL_CALL AsyncEventNotifierBase::terminate() { - ::osl::MutexGuard aGuard( m_xImpl->aMutex ); + std::scoped_lock aGuard( m_xImpl->aMutex ); // remember the termination request m_xImpl->bTerminate = true; // awake the thread - m_xImpl->aPendingActions.set(); + m_xImpl->aPendingActions.notify_all(); } void AsyncEventNotifierBase::addEvent( const AnyEventRef& _rEvent, const ::rtl::Reference< IEventProcessor >& _xProcessor ) { - ::osl::MutexGuard aGuard( m_xImpl->aMutex ); + std::scoped_lock aGuard( m_xImpl->aMutex ); // remember this event - m_xImpl->aEvents.emplace_back( _rEvent, _xProcessor ); + m_xImpl->aEvents.emplace_back( ProcessableEvent {_rEvent, _xProcessor} ); // awake the thread - m_xImpl->aPendingActions.set(); + m_xImpl->aPendingActions.notify_all(); } @@ -140,28 +123,22 @@ namespace comphelper { for (;;) { - m_xImpl->aPendingActions.wait(); - ProcessableEvent aEvent; + std::vector< ProcessableEvent > aEvents; { - osl::MutexGuard aGuard(m_xImpl->aMutex); + std::unique_lock aGuard(m_xImpl->aMutex); + m_xImpl->aPendingActions.wait(aGuard, + [this] { return m_xImpl->bTerminate || !m_xImpl->aEvents.empty(); } ); if (m_xImpl->bTerminate) - { - break; - } - if (!m_xImpl->aEvents.empty()) - { - aEvent = m_xImpl->aEvents.front(); - m_xImpl->aEvents.pop_front(); - } - if (m_xImpl->aEvents.empty()) - { - m_xImpl->aPendingActions.reset(); - } + return; + else + std::swap(aEvents, m_xImpl->aEvents); } - if (aEvent.aEvent.is()) { - assert(aEvent.xProcessor.is()); - aEvent.xProcessor->processEvent(*aEvent.aEvent); + for (ProcessableEvent& rEvent : aEvents) + { + assert(rEvent.xProcessor.is()); + rEvent.xProcessor->processEvent(*rEvent.aEvent); } + aEvents.clear(); } } @@ -186,7 +163,11 @@ namespace comphelper namespace { - struct theNotifiersMutex : public rtl::Static<osl::Mutex, theNotifiersMutex> {}; + std::mutex& GetTheNotifiersMutex() + { + static std::mutex MUTEX; + return MUTEX; + } } @@ -196,7 +177,7 @@ namespace comphelper { std::vector<std::weak_ptr<AsyncEventNotifierAutoJoin>> notifiers; { - ::osl::MutexGuard g(theNotifiersMutex::get()); + std::scoped_lock g(GetTheNotifiersMutex()); notifiers = g_Notifiers; } for (std::weak_ptr<AsyncEventNotifierAutoJoin> const& wNotifier : notifiers) @@ -220,7 +201,7 @@ namespace comphelper AsyncEventNotifierAutoJoin::~AsyncEventNotifierAutoJoin() { - ::osl::MutexGuard g(theNotifiersMutex::get()); + std::scoped_lock g(GetTheNotifiersMutex()); // note: this doesn't happen atomically with the refcount // hence it's possible this deletes > 1 or 0 elements g_Notifiers.erase( @@ -236,7 +217,7 @@ namespace comphelper { std::shared_ptr<AsyncEventNotifierAutoJoin> const ret( new AsyncEventNotifierAutoJoin(name)); - ::osl::MutexGuard g(theNotifiersMutex::get()); + std::scoped_lock g(GetTheNotifiersMutex()); g_Notifiers.push_back(ret); return ret; } @@ -250,26 +231,20 @@ namespace comphelper { // see salhelper::Thread::launch xThis->m_xImpl->pKeepThisAlive = xThis; - try { - if (!xThis->create()) { - throw std::runtime_error("osl::Thread::create failed"); - } - } catch (...) { - xThis->m_xImpl->pKeepThisAlive.reset(); - throw; + comphelper::ScopeGuard g([&xThis] { xThis->m_xImpl->pKeepThisAlive.reset(); }); + if (!xThis->create()) { + throw std::runtime_error("osl::Thread::create failed"); } + g.dismiss(); } void AsyncEventNotifierAutoJoin::run() { // see salhelper::Thread::run - try { - setName(m_xImpl->name); - execute(); - } catch (...) { - onTerminated(); - throw; - } + comphelper::ScopeGuard g([this] { onTerminated(); }); + setName(m_xImpl->name); + execute(); + g.dismiss(); } void AsyncEventNotifierAutoJoin::onTerminated() diff --git a/comphelper/source/misc/asyncquithandler.cxx b/comphelper/source/misc/asyncquithandler.cxx index fd53cbd9bf4b..a04534ec92e8 100644 --- a/comphelper/source/misc/asyncquithandler.cxx +++ b/comphelper/source/misc/asyncquithandler.cxx @@ -24,10 +24,7 @@ #include <comphelper/asyncquithandler.hxx> #include <comphelper/processfactory.hxx> -AsyncQuitHandler::AsyncQuitHandler() - : mbForceQuit(false) -{ -} +AsyncQuitHandler::AsyncQuitHandler() {} AsyncQuitHandler& AsyncQuitHandler::instance() { @@ -42,10 +39,6 @@ void AsyncQuitHandler::QuitApplication() xDesktop->terminate(); } -void AsyncQuitHandler::SetForceQuit() { mbForceQuit = true; } - -bool AsyncQuitHandler::IsForceQuit() const { return mbForceQuit; } - IMPL_STATIC_LINK_NOARG(AsyncQuitHandler, OnAsyncQuit, void*, void) { QuitApplication(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx index 5d1262838011..11fa4239d2e9 100644 --- a/comphelper/source/misc/backupfilehelper.cxx +++ b/comphelper/source/misc/backupfilehelper.cxx @@ -18,6 +18,8 @@ #include <algorithm> #include <deque> #include <memory> +#include <string_view> +#include <utility> #include <vector> #include <zlib.h> @@ -40,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> @@ -172,30 +173,31 @@ namespace return osl_File_E_None == osl_writeFile(rHandle, static_cast<const void*>(rSource.getStr()), nLength, &nBaseWritten) && nLength == nBaseWritten; } - OUString createFileURL(const OUString& rURL, const OUString& rName, const OUString& rExt) + OUString createFileURL( + std::u16string_view rURL, std::u16string_view rName, std::u16string_view rExt) { OUString aRetval; - if (!rURL.isEmpty() && !rName.isEmpty()) + if (!rURL.empty() && !rName.empty()) { - aRetval = rURL + "/" + rName; + aRetval = OUString::Concat(rURL) + "/" + rName; - if (!rExt.isEmpty()) + if (!rExt.empty()) { - aRetval += "." + rExt; + aRetval += OUString::Concat(".") + rExt; } } return aRetval; } - OUString createPackURL(const OUString& rURL, const OUString& rName) + OUString createPackURL(std::u16string_view rURL, std::u16string_view rName) { OUString aRetval; - if (!rURL.isEmpty() && !rName.isEmpty()) + if (!rURL.empty() && !rName.empty()) { - aRetval = rURL + "/" + rName + ".pack"; + aRetval = OUString::Concat(rURL) + "/" + rName + ".pack"; } return aRetval; @@ -215,14 +217,13 @@ namespace public: ExtensionInfoEntry() - : maName(), - maRepository(USER), + : maRepository(USER), mbEnabled(false) { } - ExtensionInfoEntry(const OString& rName, bool bEnabled) - : maName(rName), + ExtensionInfoEntry(OString aName, bool bEnabled) + : maName(std::move(aName)), maRepository(USER), mbEnabled(bEnabled) { @@ -353,7 +354,7 @@ namespace typedef std::vector< ExtensionInfoEntry > ExtensionInfoEntryVector; - const OUStringLiteral gaRegPath { "/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 { @@ -362,7 +363,6 @@ namespace public: ExtensionInfo() - : maEntries() { } @@ -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) { @@ -439,8 +439,8 @@ namespace if (aTagName == "extension") { - OUString aAttrUrl(rElement->getAttribute("url")); - const OUString aAttrRevoked(rElement->getAttribute("revoked")); + OUString aAttrUrl(rElement->getAttribute(u"url"_ustr)); + const OUString aAttrRevoked(rElement->getAttribute(u"revoked"_ustr)); if (!aAttrUrl.isEmpty()) { @@ -479,21 +479,24 @@ namespace } public: - void createUserExtensionRegistryEntriesFromXML(const OUString& rUserConfigWorkURL) + void createUserExtensionRegistryEntriesFromXML(std::u16string_view rUserConfigWorkURL) { - const OUString aPath(rUserConfigWorkURL + "/uno_packages/cache" + gaRegPath); + const OUString aPath( + OUString::Concat(rUserConfigWorkURL) + "/uno_packages/cache" + gaRegPath); createExtensionRegistryEntriesFromXML(aPath); } - void createSharedExtensionRegistryEntriesFromXML(const OUString& rUserConfigWorkURL) + void createSharedExtensionRegistryEntriesFromXML(std::u16string_view rUserConfigWorkURL) { - const OUString aPath(rUserConfigWorkURL + "/extensions/shared" + gaRegPath); + const OUString aPath( + OUString::Concat(rUserConfigWorkURL) + "/extensions/shared" + gaRegPath); createExtensionRegistryEntriesFromXML(aPath); } - void createBundledExtensionRegistryEntriesFromXML(const OUString& rUserConfigWorkURL) + void createBundledExtensionRegistryEntriesFromXML(std::u16string_view rUserConfigWorkURL) { - const OUString aPath(rUserConfigWorkURL + "/extensions/bundled" + gaRegPath); + const OUString aPath( + OUString::Concat(rUserConfigWorkURL) + "/extensions/bundled" + gaRegPath); createExtensionRegistryEntriesFromXML(aPath); } @@ -534,8 +537,8 @@ namespace if (aTagName == rTagToSearch) { - const OString aAttrUrl(OUStringToOString(rElement->getAttribute("url"), RTL_TEXTENCODING_ASCII_US)); - const OUString aAttrRevoked(rElement->getAttribute("revoked")); + const OString aAttrUrl(OUStringToOString(rElement->getAttribute(u"url"_ustr), RTL_TEXTENCODING_ASCII_US)); + const OUString aAttrRevoked(rElement->getAttribute(u"revoked"_ustr)); const bool bEnabled(aAttrRevoked.isEmpty() || !aAttrRevoked.toBoolean()); if (!aAttrUrl.isEmpty()) @@ -547,7 +550,7 @@ namespace if (!bEnabled) { // needs to be enabled - rElement->removeAttribute("revoked"); + rElement->removeAttribute(u"revoked"_ustr); bChanged = true; } } @@ -560,7 +563,7 @@ namespace if (bEnabled) { // needs to be disabled - rElement->setAttribute("revoked", "true"); + rElement->setAttribute(u"revoked"_ustr, u"true"_ustr); bChanged = true; } } @@ -626,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 @@ -634,13 +637,10 @@ 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))) + if (aTempURL.isEmpty() || !DirectoryHelper::fileExists(aTempURL)) return; if (DirectoryHelper::fileExists(rUnoPackagReg)) @@ -657,41 +657,41 @@ namespace public: static void changeEnableDisableStateInXML( - const OUString& rUserConfigWorkURL, + std::u16string_view rUserConfigWorkURL, const ExtensionInfoEntryVector& rToBeEnabled, const ExtensionInfoEntryVector& rToBeDisabled) { - const OUString aRegPathFront("/uno_packages/cache/registry/com.sun.star.comp.deployment."); - const OUString aRegPathBack(".PackageRegistryBackend/backenddb.xml"); + static constexpr OUString aRegPathFront(u"/uno_packages/cache/registry/com.sun.star.comp.deployment."_ustr); + static constexpr OUString aRegPathBack(u".PackageRegistryBackend/backenddb.xml"_ustr); // first appearance to check { - const OUString aUnoPackagReg(rUserConfigWorkURL + aRegPathFront + "bundle" + aRegPathBack); + const OUString aUnoPackagReg(OUString::Concat(rUserConfigWorkURL) + aRegPathFront + "bundle" + aRegPathBack); visitNodesXMLChangeOneCase( aUnoPackagReg, - "extension", + u"extension"_ustr, rToBeEnabled, rToBeDisabled); } // second appearance to check { - const OUString aUnoPackagReg(rUserConfigWorkURL + aRegPathFront + "configuration" + aRegPathBack); + const OUString aUnoPackagReg(OUString::Concat(rUserConfigWorkURL) + aRegPathFront + "configuration" + aRegPathBack); visitNodesXMLChangeOneCase( aUnoPackagReg, - "configuration", + u"configuration"_ustr, rToBeEnabled, rToBeDisabled); } // third appearance to check { - const OUString aUnoPackagReg(rUserConfigWorkURL + aRegPathFront + "script" + aRegPathBack); + const OUString aUnoPackagReg(OUString::Concat(rUserConfigWorkURL) + aRegPathFront + "script" + aRegPathBack); visitNodesXMLChangeOneCase( aUnoPackagReg, - "script", + u"script"_ustr, rToBeEnabled, rToBeDisabled); } @@ -803,197 +803,191 @@ namespace bool copy_content_straight(oslFileHandle& rTargetHandle) { - if (maFile && osl::File::E_None == maFile->open(osl_File_OpenFlag_Read)) - { - sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE]; - sal_uInt64 nBytesTransfer(0); - sal_uInt64 nSize(getPackFileSize()); + if (!maFile || osl::File::E_None != maFile->open(osl_File_OpenFlag_Read)) + return false; - // set offset in source file - when this is zero, a new file is to be added - if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset()))) - { - while (nSize != 0) - { - const sal_uInt64 nToTransfer(std::min(nSize, sal_uInt64(BACKUP_FILE_HELPER_BLOCK_SIZE))); + sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE]; + sal_uInt64 nBytesTransfer(0); + sal_uInt64 nSize(getPackFileSize()); - if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer) - { - break; - } + // set offset in source file - when this is zero, a new file is to be added + if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset()))) + { + while (nSize != 0) + { + const sal_uInt64 nToTransfer(std::min(nSize, sal_uInt64(BACKUP_FILE_HELPER_BLOCK_SIZE))); - if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aArray), nToTransfer, &nBytesTransfer) || nBytesTransfer != nToTransfer) - { - break; - } + if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer) + { + break; + } - nSize -= nToTransfer; + if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aArray), nToTransfer, &nBytesTransfer) || nBytesTransfer != nToTransfer) + { + break; } - } - maFile->close(); - return (0 == nSize); + nSize -= nToTransfer; + } } - return false; + maFile->close(); + return (0 == nSize); } bool copy_content_compress(oslFileHandle& rTargetHandle) { - if (maFile && osl::File::E_None == maFile->open(osl_File_OpenFlag_Read)) - { - sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE]; - sal_uInt8 aBuffer[BACKUP_FILE_HELPER_BLOCK_SIZE]; - sal_uInt64 nBytesTransfer(0); - sal_uInt64 nSize(getPackFileSize()); - std::unique_ptr< z_stream > zstream(new z_stream); - memset(zstream.get(), 0, sizeof(*zstream)); + if (!maFile || osl::File::E_None != maFile->open(osl_File_OpenFlag_Read)) + return false; - if (Z_OK == deflateInit(zstream.get(), Z_BEST_COMPRESSION)) + sal_uInt8 aArray[BACKUP_FILE_HELPER_BLOCK_SIZE]; + sal_uInt8 aBuffer[BACKUP_FILE_HELPER_BLOCK_SIZE]; + sal_uInt64 nBytesTransfer(0); + sal_uInt64 nSize(getPackFileSize()); + z_stream zstream; + memset(&zstream, 0, sizeof(zstream)); + + if (Z_OK == deflateInit(&zstream, Z_BEST_COMPRESSION)) + { + // set offset in source file - when this is zero, a new file is to be added + if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset()))) { - // set offset in source file - when this is zero, a new file is to be added - if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset()))) + bool bOkay(true); + + while (bOkay && nSize != 0) { - bool bOkay(true); + const sal_uInt64 nToTransfer(std::min(nSize, sal_uInt64(BACKUP_FILE_HELPER_BLOCK_SIZE))); - while (bOkay && nSize != 0) + if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer) { - const sal_uInt64 nToTransfer(std::min(nSize, sal_uInt64(BACKUP_FILE_HELPER_BLOCK_SIZE))); - - if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer) - { - break; - } + break; + } - zstream->avail_in = nToTransfer; - zstream->next_in = reinterpret_cast<unsigned char*>(aArray); + zstream.avail_in = nToTransfer; + zstream.next_in = reinterpret_cast<unsigned char*>(aArray); - do { - zstream->avail_out = BACKUP_FILE_HELPER_BLOCK_SIZE; - zstream->next_out = reinterpret_cast<unsigned char*>(aBuffer); + do { + zstream.avail_out = BACKUP_FILE_HELPER_BLOCK_SIZE; + zstream.next_out = reinterpret_cast<unsigned char*>(aBuffer); #if !defined Z_PREFIX - const sal_Int64 nRetval(deflate(zstream.get(), nSize == nToTransfer ? Z_FINISH : Z_NO_FLUSH)); + const sal_Int64 nRetval(deflate(&zstream, nSize == nToTransfer ? Z_FINISH : Z_NO_FLUSH)); #else - const sal_Int64 nRetval(z_deflate(zstream.get(), nSize == nToTransfer ? Z_FINISH : Z_NO_FLUSH)); + const sal_Int64 nRetval(z_deflate(&zstream, nSize == nToTransfer ? Z_FINISH : Z_NO_FLUSH)); #endif - if (Z_STREAM_ERROR == nRetval) + if (Z_STREAM_ERROR == nRetval) + { + bOkay = false; + } + else + { + const sal_uInt64 nAvailable(BACKUP_FILE_HELPER_BLOCK_SIZE - zstream.avail_out); + + if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aBuffer), nAvailable, &nBytesTransfer) || nBytesTransfer != nAvailable) { bOkay = false; } - else - { - const sal_uInt64 nAvailable(BACKUP_FILE_HELPER_BLOCK_SIZE - zstream->avail_out); - - if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aBuffer), nAvailable, &nBytesTransfer) || nBytesTransfer != nAvailable) - { - bOkay = false; - } - } - } while (bOkay && 0 == zstream->avail_out); - - if (!bOkay) - { - break; } + } while (bOkay && 0 == zstream.avail_out); - nSize -= nToTransfer; + if (!bOkay) + { + break; } + nSize -= nToTransfer; + } + #if !defined Z_PREFIX - deflateEnd(zstream.get()); + deflateEnd(&zstream); #else - z_deflateEnd(zstream.get()); + z_deflateEnd(&zstream); #endif - } } + } - maFile->close(); - - // 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()); - std::unique_ptr< z_stream > zstream(new z_stream); - memset(zstream.get(), 0, sizeof(*zstream)); + if (!maFile || osl::File::E_None != maFile->open(osl_File_OpenFlag_Read)) + return false; + + 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.get())) + if (Z_OK == inflateInit(&zstream)) + { + // set offset in source file - when this is zero, a new file is to be added + if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset()))) { - // set offset in source file - when this is zero, a new file is to be added - if (osl::File::E_None == maFile->setPos(osl_Pos_Absolut, sal_Int64(getOffset()))) + bool bOkay(true); + + while (bOkay && nSize != 0) { - bool bOkay(true); + const sal_uInt64 nToTransfer(std::min(nSize, sal_uInt64(BACKUP_FILE_HELPER_BLOCK_SIZE))); - while (bOkay && nSize != 0) + if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer) { - const sal_uInt64 nToTransfer(std::min(nSize, sal_uInt64(BACKUP_FILE_HELPER_BLOCK_SIZE))); - - if (osl::File::E_None != maFile->read(static_cast<void*>(aArray), nToTransfer, nBytesTransfer) || nBytesTransfer != nToTransfer) - { - break; - } + break; + } - zstream->avail_in = nToTransfer; - zstream->next_in = reinterpret_cast<unsigned char*>(aArray); + zstream.avail_in = nToTransfer; + zstream.next_in = reinterpret_cast<unsigned char*>(aArray); - do { - zstream->avail_out = BACKUP_FILE_HELPER_BLOCK_SIZE; - zstream->next_out = reinterpret_cast<unsigned char*>(aBuffer); + do { + zstream.avail_out = BACKUP_FILE_HELPER_BLOCK_SIZE; + zstream.next_out = reinterpret_cast<unsigned char*>(aBuffer); #if !defined Z_PREFIX - const sal_Int64 nRetval(inflate(zstream.get(), Z_NO_FLUSH)); + const sal_Int64 nRetval(inflate(&zstream, Z_NO_FLUSH)); #else - const sal_Int64 nRetval(z_inflate(zstream.get(), Z_NO_FLUSH)); + const sal_Int64 nRetval(z_inflate(&zstream, Z_NO_FLUSH)); #endif - if (Z_STREAM_ERROR == nRetval) + if (Z_STREAM_ERROR == nRetval) + { + bOkay = false; + } + else + { + const sal_uInt64 nAvailable(BACKUP_FILE_HELPER_BLOCK_SIZE - zstream.avail_out); + + if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aBuffer), nAvailable, &nBytesTransfer) || nBytesTransfer != nAvailable) { bOkay = false; } - else - { - const sal_uInt64 nAvailable(BACKUP_FILE_HELPER_BLOCK_SIZE - zstream->avail_out); - - if (osl_File_E_None != osl_writeFile(rTargetHandle, static_cast<const void*>(aBuffer), nAvailable, &nBytesTransfer) || nBytesTransfer != nAvailable) - { - bOkay = false; - } - } - } while (bOkay && 0 == zstream->avail_out); - - if (!bOkay) - { - break; } + } while (bOkay && 0 == zstream.avail_out); - nSize -= nToTransfer; + if (!bOkay) + { + break; } + nSize -= nToTransfer; + } + #if !defined Z_PREFIX - deflateEnd(zstream.get()); + deflateEnd(&zstream); #else - z_deflateEnd(zstream.get()); + z_deflateEnd(&zstream); #endif - } } - - maFile->close(); - return (0 == nSize); } - return false; + maFile->close(); + return (0 == nSize); } @@ -1002,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) { } @@ -1019,7 +1013,6 @@ namespace mnPackFileSize(0), mnOffset(0), mnCrc32(0), - maFile(), mbDoCompress(false) { } @@ -1156,7 +1149,6 @@ namespace public: PackedFile(const OUString& rURL) : maURL(rURL), - maPackedFileEntryVector(), mbChanged(false) { FileSharedPtr aSourceFile = std::make_shared<osl::File>(rURL); @@ -1252,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 @@ -1420,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) @@ -1475,9 +1465,9 @@ namespace comphelper { // try to access user layer configuration file URL, the one that // points to registrymodifications.xcu - OUString conf("${CONFIGURATION_LAYERS}"); + OUString conf(u"${CONFIGURATION_LAYERS}"_ustr); rtl::Bootstrap::expandMacros(conf); - const OUString aTokenUser("user:"); + static constexpr OUString aTokenUser(u"user:"_ustr); sal_Int32 nStart(conf.indexOf(aTokenUser)); if (-1 != nStart) @@ -1522,15 +1512,13 @@ namespace comphelper const OUString& BackupFileHelper::getSafeModeName() { - static const OUString aSafeMode("SafeMode"); + static constexpr OUString aSafeMode(u"SafeMode"_ustr); return aSafeMode; } BackupFileHelper::BackupFileHelper() - : maDirs(), - maFiles(), - mnNumBackups(2), + : mnNumBackups(2), mnMode(1), mbActive(false), mbExtensions(true), @@ -1539,7 +1527,7 @@ namespace comphelper OUString sTokenOut; // read configuration item 'SecureUserConfig' -> bool on/off - if (rtl::Bootstrap::get("SecureUserConfig", sTokenOut)) + if (rtl::Bootstrap::get(u"SecureUserConfig"_ustr, sTokenOut)) { mbActive = sTokenOut.toBoolean(); } @@ -1553,15 +1541,15 @@ namespace comphelper mbActive = !maInitialBaseURL.isEmpty() && !maUserConfigBaseURL.isEmpty() && !maRegModName.isEmpty(); } - if (mbActive && rtl::Bootstrap::get("SecureUserConfigNumCopies", sTokenOut)) + if (mbActive && rtl::Bootstrap::get(u"SecureUserConfigNumCopies"_ustr, sTokenOut)) { const sal_uInt16 nConfigNumCopies(static_cast<sal_uInt16>(sTokenOut.toUInt32())); // limit to range [1..mnMaxAllowedBackups] - mnNumBackups = std::min(std::max(nConfigNumCopies, mnNumBackups), mnMaxAllowedBackups); + mnNumBackups = std::clamp(mnNumBackups, nConfigNumCopies, mnMaxAllowedBackups); } - if (mbActive && rtl::Bootstrap::get("SecureUserConfigMode", sTokenOut)) + if (mbActive && rtl::Bootstrap::get(u"SecureUserConfigMode"_ustr, sTokenOut)) { const sal_uInt16 nMode(static_cast<sal_uInt16>(sTokenOut.toUInt32())); @@ -1569,12 +1557,12 @@ namespace comphelper mnMode = std::min(nMode, sal_uInt16(2)); } - if (mbActive && rtl::Bootstrap::get("SecureUserConfigExtensions", sTokenOut)) + if (mbActive && rtl::Bootstrap::get(u"SecureUserConfigExtensions"_ustr, sTokenOut)) { mbExtensions = sTokenOut.toBoolean(); } - if (mbActive && rtl::Bootstrap::get("SecureUserConfigCompress", sTokenOut)) + if (mbActive && rtl::Bootstrap::get(u"SecureUserConfigCompress"_ustr, sTokenOut)) { mbCompress = sTokenOut.toBoolean(); } @@ -1643,7 +1631,7 @@ namespace comphelper // no push when SafeModeDir exists, it may be Office's exit after SafeMode // where SafeMode flag is already deleted, but SafeModeDir cleanup is not // done yet (is done at next startup) - if (!(mbActive && !mbSafeModeDirExists)) + if (!mbActive || mbSafeModeDirExists) return; const OUString aPackURL(getPackURL()); @@ -1847,12 +1835,12 @@ namespace comphelper { static std::vector< OUString > aDirNames = { - "config", // UI config stuff - "registry", // most of the registry stuff - "psprint", // not really needed, can be abandoned - "store", // not really needed, can be abandoned - "temp", // not really needed, can be abandoned - "pack" // own backup dir + u"config"_ustr, // UI config stuff + u"registry"_ustr, // most of the registry stuff + u"psprint"_ustr, // not really needed, can be abandoned + u"store"_ustr, // not really needed, can be abandoned + u"temp"_ustr, // not really needed, can be abandoned + u"pack"_ustr // own backup dir }; return aDirNames; @@ -1862,7 +1850,7 @@ namespace comphelper { static std::vector< OUString > aFileNames = { - "registrymodifications.xcu" // personal registry stuff + u"registrymodifications.xcu"_ustr // personal registry stuff }; return aFileNames; @@ -1872,14 +1860,14 @@ namespace comphelper uno::Reference<XElement> lcl_getConfigElement(const uno::Reference<XDocument>& xDocument, const OUString& rPath, const OUString& rKey, const OUString& rValue) { - uno::Reference< XElement > itemElement = xDocument->createElement("item"); - itemElement->setAttribute("oor:path", rPath); + uno::Reference< XElement > itemElement = xDocument->createElement(u"item"_ustr); + itemElement->setAttribute(u"oor:path"_ustr, rPath); - uno::Reference< XElement > propElement = xDocument->createElement("prop"); - propElement->setAttribute("oor:name", rKey); - propElement->setAttribute("oor:op", "replace"); // Replace any other options + uno::Reference< XElement > propElement = xDocument->createElement(u"prop"_ustr); + propElement->setAttribute(u"oor:name"_ustr, rKey); + propElement->setAttribute(u"oor:op"_ustr, u"replace"_ustr); // Replace any other options - uno::Reference< XElement > valueElement = xDocument->createElement("value"); + uno::Reference< XElement > valueElement = xDocument->createElement(u"value"_ustr); uno::Reference< XText > textElement = xDocument->createTextNode(rValue); valueElement->appendChild(textElement); @@ -1901,38 +1889,39 @@ namespace comphelper uno::Reference< XDocument > xDocument = xBuilder->parseURI(aRegistryModifications); uno::Reference< XElement > xRootElement = xDocument->getDocumentElement(); - xRootElement->appendChild(lcl_getConfigElement(xDocument, "/org.openoffice.Office.Common/VCL", - "UseOpenGL", "false")); - xRootElement->appendChild(lcl_getConfigElement(xDocument, "/org.openoffice.Office.Common/VCL", - "ForceOpenGL", "false")); - xRootElement->appendChild(lcl_getConfigElement(xDocument, "/org.openoffice.Office.Common/Misc", - "UseOpenCL", "false")); - // Do not disable Skia entirely, just force it's CPU-based raster mode. - xRootElement->appendChild(lcl_getConfigElement(xDocument, "/org.openoffice.Office.Common/VCL", - "ForceSkia", "false")); - xRootElement->appendChild(lcl_getConfigElement(xDocument, "/org.openoffice.Office.Common/VCL", - "ForceSkiaRaster", "true")); - - // write back - uno::Reference< xml::sax::XSAXSerializable > xSerializer(xDocument, uno::UNO_QUERY); - - if (!xSerializer.is()) - return; + xRootElement->appendChild(lcl_getConfigElement(xDocument, u"/org.openoffice.Office.Common/VCL"_ustr, + u"DisableOpenGL"_ustr, u"true"_ustr)); + xRootElement->appendChild(lcl_getConfigElement(xDocument, u"/org.openoffice.Office.Common/Misc"_ustr, + u"UseOpenCL"_ustr, u"false"_ustr)); + // Do not disable Skia entirely, just force its CPU-based raster mode. + xRootElement->appendChild(lcl_getConfigElement(xDocument, u"/org.openoffice.Office.Common/VCL"_ustr, + u"ForceSkia"_ustr, u"false"_ustr)); + xRootElement->appendChild(lcl_getConfigElement(xDocument, u"/org.openoffice.Office.Common/VCL"_ustr, + u"ForceSkiaRaster"_ustr, u"true"_ustr)); + + OUString aTempURL; + { + // use the scope to make sure that the temp file gets properly closed before move - // create a SAXWriter - uno::Reference< xml::sax::XWriter > const xSaxWriter = xml::sax::Writer::create(xContext); - uno::Reference< io::XStream > xTempFile = io::TempFile::create(xContext); - uno::Reference< io::XOutputStream > xOutStrm = xTempFile->getOutputStream(); + // write back + uno::Reference< xml::sax::XSAXSerializable > xSerializer(xDocument, uno::UNO_QUERY); - // set output stream and do the serialization - xSaxWriter->setOutputStream(xOutStrm); - xSerializer->serialize(xSaxWriter, uno::Sequence< beans::StringPair >()); + if (!xSerializer.is()) + return; - // get URL from temp file - uno::Reference < beans::XPropertySet > xTempFileProps(xTempFile, uno::UNO_QUERY); - uno::Any aUrl = xTempFileProps->getPropertyValue("Uri"); - OUString aTempURL; - aUrl >>= aTempURL; + // create a SAXWriter + uno::Reference< xml::sax::XWriter > const xSaxWriter = xml::sax::Writer::create(xContext); + uno::Reference< io::XTempFile > xTempFile = io::TempFile::create(xContext); + xTempFile->setRemoveFile(false); // avoid removal of tempfile when leaving the scope + uno::Reference< io::XOutputStream > xOutStrm = xTempFile->getOutputStream(); + + // set output stream and do the serialization + xSaxWriter->setOutputStream(xOutStrm); + xSerializer->serialize(xSaxWriter, uno::Sequence< beans::StringPair >()); + + // get URL from temp file + aTempURL = xTempFile->getUri(); + } // copy back file if (aTempURL.isEmpty() || !DirectoryHelper::fileExists(aTempURL)) @@ -2019,8 +2008,8 @@ namespace comphelper bool BackupFileHelper::tryPush_Files( const std::set< OUString >& rDirs, const std::set< std::pair< OUString, OUString > >& rFiles, - const OUString& rSourceURL, // source dir without trailing '/' - const OUString& rTargetURL // target dir without trailing '/' + std::u16string_view rSourceURL, // source dir without trailing '/' + const OUString& rTargetURL // target dir without trailing '/' ) { bool bDidPush(false); @@ -2039,7 +2028,7 @@ namespace comphelper // process dirs for (const auto& dir : rDirs) { - OUString aNewSourceURL(rSourceURL + "/" + dir); + OUString aNewSourceURL(OUString::Concat(rSourceURL) + "/" + dir); OUString aNewTargetURL(rTargetURL + "/" + dir); std::set< OUString > aNewDirs; std::set< std::pair< OUString, OUString > > aNewFiles; @@ -2069,10 +2058,10 @@ namespace comphelper } bool BackupFileHelper::tryPush_file( - const OUString& rSourceURL, // source dir without trailing '/' - const OUString& rTargetURL, // target dir without trailing '/' - const OUString& rName, // filename - const OUString& rExt // extension (or empty) + std::u16string_view rSourceURL, // source dir without trailing '/' + std::u16string_view rTargetURL, // target dir without trailing '/' + std::u16string_view rName, // filename + std::u16string_view rExt // extension (or empty) ) { const OUString aFileURL(createFileURL(rSourceURL, rName, rExt)); @@ -2101,8 +2090,8 @@ namespace comphelper bool BackupFileHelper::isPopPossible_files( const std::set< OUString >& rDirs, const std::set< std::pair< OUString, OUString > >& rFiles, - const OUString& rSourceURL, // source dir without trailing '/' - const OUString& rTargetURL // target dir without trailing '/' + std::u16string_view rSourceURL, // source dir without trailing '/' + std::u16string_view rTargetURL // target dir without trailing '/' ) { bool bPopPossible(false); @@ -2120,8 +2109,8 @@ namespace comphelper // process dirs for (const auto& dir : rDirs) { - OUString aNewSourceURL(rSourceURL + "/" + dir); - OUString aNewTargetURL(rTargetURL + "/" + dir); + OUString aNewSourceURL(OUString::Concat(rSourceURL) + "/" + dir); + OUString aNewTargetURL(OUString::Concat(rTargetURL) + "/" + dir); std::set< OUString > aNewDirs; std::set< std::pair< OUString, OUString > > aNewFiles; @@ -2144,10 +2133,10 @@ namespace comphelper } bool BackupFileHelper::isPopPossible_file( - const OUString& rSourceURL, // source dir without trailing '/' - const OUString& rTargetURL, // target dir without trailing '/' - const OUString& rName, // filename - const OUString& rExt // extension (or empty) + std::u16string_view rSourceURL, // source dir without trailing '/' + std::u16string_view rTargetURL, // target dir without trailing '/' + std::u16string_view rName, // filename + std::u16string_view rExt // extension (or empty) ) { const OUString aFileURL(createFileURL(rSourceURL, rName, rExt)); @@ -2168,7 +2157,7 @@ namespace comphelper bool BackupFileHelper::tryPop_files( const std::set< OUString >& rDirs, const std::set< std::pair< OUString, OUString > >& rFiles, - const OUString& rSourceURL, // source dir without trailing '/' + std::u16string_view rSourceURL, // source dir without trailing '/' const OUString& rTargetURL // target dir without trailing '/' ) { @@ -2187,7 +2176,7 @@ namespace comphelper // process dirs for (const auto& dir : rDirs) { - OUString aNewSourceURL(rSourceURL + "/" + dir); + OUString aNewSourceURL(OUString::Concat(rSourceURL) + "/" + dir); OUString aNewTargetURL(rTargetURL + "/" + dir); std::set< OUString > aNewDirs; std::set< std::pair< OUString, OUString > > aNewFiles; @@ -2217,60 +2206,58 @@ namespace comphelper } bool BackupFileHelper::tryPop_file( - const OUString& rSourceURL, // source dir without trailing '/' - const OUString& rTargetURL, // target dir without trailing '/' - const OUString& rName, // filename - const OUString& rExt // extension (or empty) + std::u16string_view rSourceURL, // source dir without trailing '/' + std::u16string_view rTargetURL, // target dir without trailing '/' + std::u16string_view rName, // filename + std::u16string_view rExt // extension (or empty) ) { 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 /////////////////////// bool BackupFileHelper::tryPush_extensionInfo( - const OUString& rTargetURL // target dir without trailing '/' + std::u16string_view rTargetURL // target dir without trailing '/' ) { ExtensionInfo aExtensionInfo; @@ -2280,7 +2267,7 @@ namespace comphelper // create current configuration and write to temp file - it exists until deleted if (aExtensionInfo.createTempFile(aTempURL)) { - const OUString aPackURL(createPackURL(rTargetURL, "ExtensionInfo")); + const OUString aPackURL(createPackURL(rTargetURL, u"ExtensionInfo")); PackedFile aPackedFile(aPackURL); FileSharedPtr aBaseFile = std::make_shared<osl::File>(aTempURL); @@ -2299,121 +2286,119 @@ namespace comphelper } bool BackupFileHelper::isPopPossible_extensionInfo( - const OUString& rTargetURL // target dir without trailing '/' + std::u16string_view rTargetURL // target dir without trailing '/' ) { // extensionInfo always exists internally, no test needed - const OUString aPackURL(createPackURL(rTargetURL, "ExtensionInfo")); + const OUString aPackURL(createPackURL(rTargetURL, u"ExtensionInfo")); PackedFile aPackedFile(aPackURL); return !aPackedFile.empty(); } bool BackupFileHelper::tryPop_extensionInfo( - const OUString& rTargetURL // target dir without trailing '/' + std::u16string_view rTargetURL // target dir without trailing '/' ) { // extensionInfo always exists internally, no test needed - const OUString aPackURL(createPackURL(rTargetURL, "ExtensionInfo")); + 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 /////////////////////// @@ -2450,31 +2435,31 @@ namespace comphelper maFiles.insert(std::pair< OUString, OUString >(maRegModName, maExt)); // User-defined substitution table (Tools/AutoCorrect) - maDirs.insert("autocorr"); + maDirs.insert(u"autocorr"_ustr); // User-Defined AutoText (Edit/AutoText) - maDirs.insert("autotext"); + maDirs.insert(u"autotext"_ustr); // User-defined Macros - maDirs.insert("basic"); + maDirs.insert(u"basic"_ustr); // User-adapted toolbars for modules - maDirs.insert("config"); + maDirs.insert(u"config"_ustr); // Initial and User-defined Databases - maDirs.insert("database"); + maDirs.insert(u"database"_ustr); // most part of registry files - maDirs.insert("registry"); + maDirs.insert(u"registry"_ustr); // User-Defined Scripts - maDirs.insert("Scripts"); + maDirs.insert(u"Scripts"_ustr); // Template files - maDirs.insert("template"); + maDirs.insert(u"template"_ustr); // Custom Dictionaries - maDirs.insert("wordbook"); + maDirs.insert(u"wordbook"_ustr); // Questionable - where and how is Extension stuff held and how // does this interact with enabled/disabled states which are extra handled? @@ -2496,19 +2481,19 @@ namespace comphelper // should not exist, but for the case an error occurred and it got // copied somehow, avoid further recursive copying/saving - maDirs.erase("SafeMode"); + maDirs.erase(u"SafeMode"_ustr); // not really needed, can be abandoned - maDirs.erase("psprint"); + maDirs.erase(u"psprint"_ustr); // not really needed, can be abandoned - maDirs.erase("store"); + maDirs.erase(u"store"_ustr); // not really needed, can be abandoned - maDirs.erase("temp"); + maDirs.erase(u"temp"_ustr); // exclude own backup dir to avoid recursion - maDirs.erase("pack"); + maDirs.erase(u"pack"_ustr); break; } 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/componentmodule.cxx b/comphelper/source/misc/componentmodule.cxx deleted file mode 100644 index d4e23c70f48e..000000000000 --- a/comphelper/source/misc/componentmodule.cxx +++ /dev/null @@ -1,104 +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/config.h> - -#include <com/sun/star/lang/XSingleComponentFactory.hpp> -#include <comphelper/componentmodule.hxx> - -#include <vector> - -namespace comphelper -{ - - using namespace ::cppu; - using ::com::sun::star::uno::Sequence; - using ::com::sun::star::uno::RuntimeException; - using ::com::sun::star::uno::Reference; - using ::com::sun::star::uno::XInterface; - - typedef std::vector< ComponentDescription > ComponentDescriptions; - - /** implementation for <type>OModule</type>. not threadsafe, has to be guarded by its owner - */ - class OModuleImpl - { - public: - ComponentDescriptions m_aRegisteredComponents; - - OModuleImpl(); - }; - - OModuleImpl::OModuleImpl() - { - } - - OModule::OModule() - : m_pImpl(new OModuleImpl) - { - } - - OModule::~OModule() - { - } - - void OModule::registerImplementation( const ComponentDescription& _rComp ) - { - ::osl::MutexGuard aGuard( m_aMutex ); - if ( !m_pImpl ) - throw RuntimeException(); - - m_pImpl->m_aRegisteredComponents.push_back( _rComp ); - } - - void OModule::registerImplementation( const OUString& _rImplementationName, const css::uno::Sequence< OUString >& _rServiceNames, - ::cppu::ComponentFactoryFunc _pCreateFunction ) - { - ComponentDescription aComponent( _rImplementationName, _rServiceNames, _pCreateFunction, ::cppu::createSingleComponentFactory ); - registerImplementation( aComponent ); - } - - Reference< XInterface > OModule::getComponentFactory( const OUString& _rImplementationName ) - { - Reference< XInterface > xReturn; - - for (const auto& rComponent : m_pImpl->m_aRegisteredComponents) - { - if ( rComponent.sImplementationName == _rImplementationName ) - { - xReturn = rComponent.pFactoryCreationFunc( - rComponent.pComponentCreationFunc, - rComponent.sImplementationName, - rComponent.aSupportedServices, - nullptr - ); - if ( xReturn.is() ) - { - xReturn->acquire(); - return xReturn.get(); - } - } - } - - return nullptr; - } - -} // namespace comphelper - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/configuration.cxx b/comphelper/source/misc/configuration.cxx index 24657ab011f5..88e6a7c6f658 100644 --- a/comphelper/source/misc/configuration.cxx +++ b/comphelper/source/misc/configuration.cxx @@ -10,7 +10,10 @@ #include <sal/config.h> #include <cassert> +#include <map> #include <memory> +#include <mutex> +#include <string_view> #include <com/sun/star/beans/PropertyAttribute.hpp> #include <com/sun/star/configuration/ReadOnlyAccess.hpp> @@ -27,8 +30,6 @@ #include <comphelper/solarmutex.hxx> #include <comphelper/configuration.hxx> #include <comphelper/configurationlistener.hxx> -#include <rtl/instance.hxx> -#include <rtl/ustrbuf.hxx> #include <rtl/ustring.hxx> #include <sal/log.hxx> #include <i18nlangtag/languagetag.hxx> @@ -37,13 +38,6 @@ namespace com::sun::star::uno { class XComponentContext; } namespace { -struct TheConfigurationWrapper: - public rtl::StaticWithArg< - comphelper::detail::ConfigurationWrapper, - css::uno::Reference< css::uno::XComponentContext >, - TheConfigurationWrapper > -{}; - OUString getDefaultLocale( css::uno::Reference< css::uno::XComponentContext > const & context) { @@ -54,23 +48,23 @@ OUString getDefaultLocale( getLocale()).getBcp47(false); } -OUString extendLocalizedPath(OUString const & path, OUString const & locale) { +OUString extendLocalizedPath(std::u16string_view path, OUString const & locale) { SAL_WARN_IF( locale.match("*"), "comphelper", "Locale \"" << locale << "\" starts with \"*\""); assert(locale.indexOf('&') == -1); assert(locale.indexOf('"') == -1); assert(locale.indexOf('\'') == -1); - return path + "/['*" + locale + "']"; + return OUString::Concat(path) + "/['*" + locale + "']"; } } std::shared_ptr< comphelper::ConfigurationChanges > comphelper::ConfigurationChanges::create( - css::uno::Reference< css::uno::XComponentContext > const & context) + css::uno::Reference<css::uno::XComponentContext> const & context) { - return TheConfigurationWrapper::get(context).createChanges(); + return detail::ConfigurationWrapper::get(context).createChanges(); } comphelper::ConfigurationChanges::~ConfigurationChanges() {} @@ -108,15 +102,16 @@ comphelper::ConfigurationChanges::getSet(OUString const & path) const comphelper::detail::ConfigurationWrapper const & comphelper::detail::ConfigurationWrapper::get( - css::uno::Reference< css::uno::XComponentContext > const & context) + css::uno::Reference<css::uno::XComponentContext> const & context) { - return TheConfigurationWrapper::get(context); + static comphelper::detail::ConfigurationWrapper WRAPPER(context); + return WRAPPER; } comphelper::detail::ConfigurationWrapper::ConfigurationWrapper( - css::uno::Reference< css::uno::XComponentContext > const & context): - context_(context), - access_(css::configuration::ReadWriteAccess::create(context, "*")) + css::uno::Reference<css::uno::XComponentContext> const & context): + context_(context.is() ? context : comphelper::getProcessComponentContext()), + access_(css::configuration::ReadWriteAccess::create(context_, u"*"_ustr)) {} comphelper::detail::ConfigurationWrapper::~ConfigurationWrapper() {} @@ -130,10 +125,34 @@ bool comphelper::detail::ConfigurationWrapper::isReadOnly(OUString const & path) != 0; } -css::uno::Any comphelper::detail::ConfigurationWrapper::getPropertyValue( - OUString const & path) const +css::uno::Any comphelper::detail::ConfigurationWrapper::getPropertyValue(std::u16string_view path) const { - return access_->getByHierarchicalName(path); + // should be short-circuited in ConfigurationProperty::get() + assert(!comphelper::IsFuzzing()); + + // Cache the configuration access, since some of the keys are used in hot code. + // Note that this cache is only used by the officecfg:: auto-generated code, using it for anything + // else would be unwise because the cache could end up containing stale entries. + static std::mutex gMutex; + static std::map<OUString, css::uno::Reference< css::container::XNameAccess >> gAccessMap; + + sal_Int32 idx = path.rfind('/'); + assert(idx!=-1); + OUString parentPath(path.substr(0, idx)); + OUString childName(path.substr(idx+1)); + + std::scoped_lock aGuard(gMutex); + + // check cache + auto it = gAccessMap.find(parentPath); + if (it == gAccessMap.end()) + { + // not in the cache, look it up + css::uno::Reference<css::container::XNameAccess> access( + access_->getByHierarchicalName(parentPath), css::uno::UNO_QUERY_THROW); + it = gAccessMap.emplace(parentPath, access).first; + } + return it->second->getByName(childName); } void comphelper::detail::ConfigurationWrapper::setPropertyValue( @@ -146,7 +165,7 @@ void comphelper::detail::ConfigurationWrapper::setPropertyValue( css::uno::Any comphelper::detail::ConfigurationWrapper::getLocalizedPropertyValue( - OUString const & path) const + std::u16string_view path) const { return access_->getByHierarchicalName( extendLocalizedPath(path, getDefaultLocale(context_))); @@ -231,6 +250,8 @@ void comphelper::ConfigurationListener::dispose() listener->dispose(); } maListeners.clear(); + mxConfig.clear(); + mbDisposed = true; } void SAL_CALL comphelper::ConfigurationListener::disposing(css::lang::EventObject const &) @@ -262,4 +283,23 @@ void SAL_CALL comphelper::ConfigurationListener::propertyChange( } } +namespace comphelper { + +static bool bIsFuzzing = false; + +#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) +bool IsFuzzing() +{ + return bIsFuzzing; +} +#endif + +void EnableFuzzing() +{ + bIsFuzzing = true; + LanguageTag::disable_lt_tag_parse(); +} + +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/configurationhelper.cxx b/comphelper/source/misc/configurationhelper.cxx index f3853baeff81..228885e2ec5a 100644 --- a/comphelper/source/misc/configurationhelper.cxx +++ b/comphelper/source/misc/configurationhelper.cxx @@ -51,7 +51,7 @@ css::uno::Reference< css::uno::XInterface > ConfigurationHelper::openConfig(cons if (eMode & EConfigurationModes::AllLocales) { aParam.Name = "locale"; - aParam.Value <<= OUString("*"); + aParam.Value <<= u"*"_ustr; lParams.emplace_back(aParam); } @@ -61,11 +61,11 @@ css::uno::Reference< css::uno::XInterface > ConfigurationHelper::openConfig(cons bool bReadOnly(eMode & EConfigurationModes::ReadOnly); if (bReadOnly) xCFG = xConfigProvider->createInstanceWithArguments( - "com.sun.star.configuration.ConfigurationAccess", + u"com.sun.star.configuration.ConfigurationAccess"_ustr, comphelper::containerToSequence(lParams)); else xCFG = xConfigProvider->createInstanceWithArguments( - "com.sun.star.configuration.ConfigurationUpdateAccess", + u"com.sun.star.configuration.ConfigurationUpdateAccess"_ustr, comphelper::containerToSequence(lParams)); return xCFG; diff --git a/comphelper/source/misc/date.cxx b/comphelper/source/misc/date.cxx new file mode 100644 index 000000000000..b95f63f75c97 --- /dev/null +++ b/comphelper/source/misc/date.cxx @@ -0,0 +1,210 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <comphelper/date.hxx> + +#include <cassert> + +namespace comphelper::date +{ +// Once upon a time the number of days we internally handled in tools' class +// Date was limited to MAX_DAYS 3636532. That changed with a full 16-bit year. +// Assuming the first valid positive date in a proleptic Gregorian calendar is +// 0001-01-01, this resulted in an end date of 9957-06-26. +// Hence we documented that years up to and including 9956 are handled. +/* XXX: it is unclear history why this value was chosen, the representable + * 9999-12-31 would be 3652060 days from 0001-01-01. Even 9998-12-31 to + * distinguish from a maximum possible date would be 3651695. + * There is connectivity/source/commontools/dbconversion.cxx that still has the + * same value to calculate with css::util::Date */ +/* XXX can that dbconversion cope with years > 9999 or negative years at all? + * Database fields may be limited to positive 4 digits. */ + +constexpr sal_Int32 MIN_DAYS = -11968265; // -32768-01-01 +constexpr sal_Int32 MAX_DAYS = 11967900; // 32767-12-31 + +constexpr sal_Int16 kYearMax = SAL_MAX_INT16; +constexpr sal_Int16 kYearMin = SAL_MIN_INT16; + +constexpr sal_Int32 nNullDateDays = convertDateToDays(30, 12, 1899); +static_assert(nNullDateDays == 693594); + +sal_Int32 convertDateToDaysNormalizing(sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear) +{ + // Speed-up the common null-date 1899-12-30. + if (nYear == 1899 && nMonth == 12 && nDay == 30) + return nNullDateDays; + + normalize(nDay, nMonth, nYear); + return convertDateToDays(nDay, nMonth, nYear); +} + +bool isValidDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear) +{ + if (nYear == 0) + return false; + if (nMonth < 1 || 12 < nMonth) + return false; + if (nDay < 1 || (nDay > comphelper::date::getDaysInMonth(nMonth, nYear))) + return false; + return true; +} + +void convertDaysToDate(sal_Int32 nDays, sal_uInt16& rDay, sal_uInt16& rMonth, sal_Int16& rYear) +{ + if (nDays <= MIN_DAYS) + { + rDay = 1; + rMonth = 1; + rYear = kYearMin; + return; + } + if (nDays >= MAX_DAYS) + { + rDay = 31; + rMonth = 12; + rYear = kYearMax; + return; + } + + // Day 0 is -0001-12-31, day 1 is 0001-01-01 + const sal_Int16 nSign = (nDays <= 0 ? -1 : 1); + sal_Int32 nTempDays; + sal_Int32 i = 0; + bool bCalc; + + do + { + rYear = static_cast<sal_Int16>((nDays / 365) - (i * nSign)); + if (rYear == 0) + rYear = nSign; + nTempDays = nDays - YearToDays(rYear); + bCalc = false; + if (nTempDays < 1) + { + i += nSign; + bCalc = true; + } + else + { + if (nTempDays > 365) + { + if ((nTempDays != 366) || !isLeapYear(rYear)) + { + i -= nSign; + bCalc = true; + } + } + } + } while (bCalc); + + rMonth = 1; + while (nTempDays > getDaysInMonth(rMonth, rYear)) + { + nTempDays -= getDaysInMonth(rMonth, rYear); + ++rMonth; + } + + rDay = static_cast<sal_uInt16>(nTempDays); +} + +bool normalize(sal_uInt16& rDay, sal_uInt16& rMonth, sal_Int16& rYear) +{ + if (isValidDate(rDay, rMonth, rYear)) + return false; + + if (rDay == 0 && rMonth == 0 && rYear == 0) + return false; // empty date + + if (rDay == 0) + { + if (rMonth == 0) + ; // nothing, handled below + else + --rMonth; + // Last day of month is determined at the end. + } + + if (rMonth > 12) + { + rYear += rMonth / 12; + rMonth = rMonth % 12; + if (rYear == 0) + rYear = 1; + } + if (rMonth == 0) + { + --rYear; + if (rYear == 0) + rYear = -1; + rMonth = 12; + } + + if (rYear < 0) + { + sal_uInt16 nDays; + while (rDay > (nDays = getDaysInMonth(rMonth, rYear))) + { + rDay -= nDays; + if (rMonth > 1) + --rMonth; + else + { + if (rYear == kYearMin) + { + rDay = 1; + rMonth = 1; + return true; + } + --rYear; + rMonth = 12; + } + } + } + else + { + sal_uInt16 nDays; + while (rDay > (nDays = getDaysInMonth(rMonth, rYear))) + { + rDay -= nDays; + if (rMonth < 12) + ++rMonth; + else + { + if (rYear == kYearMax) + { + rDay = 31; + rMonth = 12; + return true; + } + ++rYear; + rMonth = 1; + } + } + } + + if (rDay == 0) + rDay = getDaysInMonth(rMonth, rYear); + + return true; +} + +} // namespace comphelper::date + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/comphelper/source/misc/debuggerinfo.cxx b/comphelper/source/misc/debuggerinfo.cxx index 07b2f0132fff..1e7116a55300 100644 --- a/comphelper/source/misc/debuggerinfo.cxx +++ b/comphelper/source/misc/debuggerinfo.cxx @@ -16,6 +16,10 @@ #if defined(_WIN32) #define WIN32_LEAN_AND_MEAN #include <windows.h> +#elif defined MACOSX +#include <unistd.h> +#include <sys/types.h> +#include <sys/sysctl.h> #elif defined UNX #include <unistd.h> #include <fcntl.h> @@ -28,6 +32,35 @@ bool isDebuggerAttached() { #if defined(_WIN32) return IsDebuggerPresent(); +#elif defined MACOSX + // https://developer.apple.com/library/archive/qa/qa1361/_index.html + int junk; + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0); + assert(junk == 0); + + // We're being debugged if the P_TRACED flag is set. + + return ((info.kp_proc.p_flag & P_TRACED) != 0); #elif defined LINUX char buf[4096]; int fd = open("/proc/self/status", O_RDONLY); diff --git a/comphelper/source/misc/diagnose_ex.cxx b/comphelper/source/misc/diagnose_ex.cxx new file mode 100644 index 000000000000..487f98b637a0 --- /dev/null +++ b/comphelper/source/misc/diagnose_ex.cxx @@ -0,0 +1,392 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/configuration/CorruptedConfigurationException.hpp> +#include <com/sun/star/configuration/backend/BackendSetupException.hpp> +#include <com/sun/star/configuration/backend/MalformedDataException.hpp> +#include <com/sun/star/configuration/InvalidBootstrapFileException.hpp> +#include <com/sun/star/configuration/MissingBootstrapFileException.hpp> +#include <com/sun/star/deployment/DependencyException.hpp> +#include <com/sun/star/deployment/DeploymentException.hpp> +#include <com/sun/star/document/CorruptedFilterConfigurationException.hpp> +#include <com/sun/star/document/UndoFailedException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/WrappedTargetException.hpp> +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/ldap/LdapGenericException.hpp> +#include <com/sun/star/script/BasicErrorException.hpp> +#include <com/sun/star/script/CannotConvertException.hpp> +#include <com/sun/star/script/provider/ScriptExceptionRaisedException.hpp> +#include <com/sun/star/script/provider/ScriptFrameworkErrorException.hpp> +#include <com/sun/star/sdbc/SQLException.hpp> +#include <com/sun/star/system/SystemShellExecuteException.hpp> +#include <com/sun/star/task/ErrorCodeIOException.hpp> +#include <com/sun/star/ucb/CommandFailedException.hpp> +#include <com/sun/star/ucb/ContentCreationException.hpp> +#include <com/sun/star/ucb/MissingPropertiesException.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +#include <com/sun/star/ucb/InteractiveIOException.hpp> +#include <com/sun/star/util/MalformedNumberFormatException.hpp> +#include <com/sun/star/xml/dom/DOMException.hpp> +#include <com/sun/star/xml/sax/SAXException.hpp> +#include <com/sun/star/xml/sax/SAXParseException.hpp> +#include <comphelper/anytostring.hxx> +#include <sal/log.hxx> +#include <osl/thread.h> +#include <rtl/strbuf.hxx> + +#include <comphelper/diagnose_ex.hxx> + +#if defined __GLIBCXX__ +#include <cxxabi.h> +#endif + +static void exceptionToStringImpl(OStringBuffer& sMessage, const css::uno::Any & caught) +{ + auto toOString = [](OUString const & s) { + return OUStringToOString( s, osl_getThreadTextEncoding() ); + }; + // when called recursively, we might not have any exception to print + if (!caught.hasValue()) + return; + sMessage.append(toOString(caught.getValueTypeName())); + css::uno::Exception exception; + caught >>= exception; + if ( !exception.Message.isEmpty() ) + { + sMessage.append(" message: \""); + sMessage.append(toOString(exception.Message)); + sMessage.append("\""); + } + if ( exception.Context.is() ) + { + const char* pContext = typeid( *exception.Context ).name(); +#if defined __GLIBCXX__ + // demangle the type name, not necessary under windows, we already get demangled names there + int status; + pContext = abi::__cxa_demangle( pContext, nullptr, nullptr, &status); +#endif + sMessage.append(" context: "); + sMessage.append(pContext); +#if defined __GLIBCXX__ + std::free(const_cast<char *>(pContext)); +#endif + } + { + css::configuration::CorruptedConfigurationException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" details: "); + sMessage.append(toOString(specialized.Details)); + } + } + { + css::configuration::InvalidBootstrapFileException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" BootstrapFileURL: "); + sMessage.append(toOString(specialized.BootstrapFileURL)); + } + } + { + css::configuration::MissingBootstrapFileException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" BootstrapFileURL: "); + sMessage.append(toOString(specialized.BootstrapFileURL)); + } + } + { + css::configuration::backend::MalformedDataException specialized; + if ( caught >>= specialized ) + { + sMessage.append("\n wrapped: "); + exceptionToStringImpl(sMessage, specialized.ErrorDetails); + } + } + { + css::configuration::backend::BackendSetupException specialized; + if ( caught >>= specialized ) + { + sMessage.append("\n wrapped: "); + exceptionToStringImpl(sMessage, specialized.BackendException); + } + } + { + css::deployment::DependencyException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" UnsatisfiedDependencies: "); + sMessage.append(toOString(comphelper::anyToString(css::uno::Any(specialized.UnsatisfiedDependencies)))); + } + } + { + css::deployment::DeploymentException specialized; + if ( caught >>= specialized ) + { + sMessage.append("\n wrapped: "); + exceptionToStringImpl(sMessage, specialized.Cause); + } + } + { + css::document::CorruptedFilterConfigurationException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" Details: "); + sMessage.append(toOString(specialized.Details)); + } + } + { + css::document::UndoFailedException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" Reason: "); + sMessage.append(toOString(comphelper::anyToString(specialized.Reason))); + } + } + { + css::lang::IllegalArgumentException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" ArgumentPosition: "); + sMessage.append(static_cast<sal_Int32>(specialized.ArgumentPosition)); + } + } + { + css::lang::WrappedTargetException specialized; + if ( caught >>= specialized ) + { + sMessage.append("\n wrapped: "); + exceptionToStringImpl(sMessage, specialized.TargetException); + } + } + { + css::lang::WrappedTargetRuntimeException specialized; + if ( caught >>= specialized ) + { + sMessage.append("\n wrapped: "); + exceptionToStringImpl(sMessage, specialized.TargetException); + } + } + { + css::ldap::LdapGenericException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" ErrorCode: "); + sMessage.append(specialized.ErrorCode); + } + } + { + css::script::BasicErrorException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" ErrorCode: "); + sMessage.append(specialized.ErrorCode); + sMessage.append(" ErrorMessageArgument: "); + sMessage.append(toOString(specialized.ErrorMessageArgument)); + } + } + { + css::script::CannotConvertException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" DestinationTypeClass: "); + sMessage.append(toOString(comphelper::anyToString(css::uno::Any(specialized.DestinationTypeClass)))); + sMessage.append(" Reason: "); + sMessage.append(specialized.Reason); + sMessage.append(" ArgumentIndex: "); + sMessage.append(specialized.ArgumentIndex); + } + } + { + css::script::provider::ScriptErrorRaisedException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" scriptName: "); + sMessage.append(toOString(specialized.scriptName)); + sMessage.append(" language: "); + sMessage.append(toOString(specialized.language)); + sMessage.append(" lineNum: "); + sMessage.append(specialized.lineNum); + } + } + { + css::script::provider::ScriptExceptionRaisedException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" exceptionType: "); + sMessage.append(toOString(specialized.exceptionType)); + } + } + { + css::script::provider::ScriptFrameworkErrorException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" scriptName: "); + sMessage.append(toOString(specialized.scriptName)); + sMessage.append(" language: "); + sMessage.append(toOString(specialized.language)); + sMessage.append(" errorType: "); + sMessage.append(specialized.errorType); + } + } + { + css::sdbc::SQLException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" SQLState: "); + sMessage.append(toOString(specialized.SQLState)); + sMessage.append(" ErrorCode: "); + sMessage.append(specialized.ErrorCode); + sMessage.append("\n wrapped: "); + exceptionToStringImpl(sMessage, specialized.NextException); + } + } + { + css::system::SystemShellExecuteException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" PosixError: "); + sMessage.append(specialized.PosixError); + } + } + { + css::task::ErrorCodeIOException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" errcode: "); + sMessage.append( specialized.ErrCode ); + } + } + { + css::ucb::CommandFailedException specialized; + if ( caught >>= specialized ) + { + sMessage.append("\n Reason: "); + exceptionToStringImpl( sMessage, specialized.Reason ); + } + } + { + css::ucb::ContentCreationException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" eError: "); + sMessage.append(toOString(comphelper::anyToString( css::uno::Any(specialized.eError) ))); + } + } + { + css::ucb::MissingPropertiesException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" Properties: "); + sMessage.append(toOString(comphelper::anyToString( css::uno::Any(specialized.Properties) ))); + } + } + { + css::ucb::NameClashException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" Name: "); + sMessage.append(toOString( specialized.Name )); + } + } + { + css::util::MalformedNumberFormatException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" CheckPos: "); + sMessage.append( specialized.CheckPos ); + } + } + { + css::xml::dom::DOMException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" Code: "); + sMessage.append(toOString(comphelper::anyToString( css::uno::Any(specialized.Code) ))); + } + } + { + css::xml::dom::DOMException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" Code: "); + sMessage.append(toOString(comphelper::anyToString( css::uno::Any(specialized.Code) ))); + } + } + { + css::xml::sax::SAXException specialized; + if ( caught >>= specialized ) + { + sMessage.append("\n wrapped: "); + exceptionToStringImpl( sMessage, specialized.WrappedException ); + } + } + { + css::xml::sax::SAXParseException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" PublicId: "); + sMessage.append(toOString( specialized.PublicId )); + sMessage.append(" SystemId: "); + sMessage.append(toOString( specialized.SystemId )); + sMessage.append(" LineNumber: "); + sMessage.append( specialized.LineNumber ); + sMessage.append(" ColumnNumber: "); + sMessage.append( specialized.ColumnNumber ); + } + } + { + css::ucb::InteractiveIOException specialized; + if ( caught >>= specialized ) + { + sMessage.append(" Code: "); + sMessage.append( static_cast<sal_Int32>(specialized.Code) ); + } + } +} + +OString exceptionToString(const css::uno::Any & caught) +{ + OStringBuffer sMessage(512); + exceptionToStringImpl(sMessage, caught); + return sMessage.makeStringAndClear(); +} + +void DbgUnhandledException(const css::uno::Any & caught, const char* currentFunction, const char* fileAndLineNo, + const char* area, const char* explanatory) +{ + OStringBuffer sMessage( 512 ); + sMessage.append( OString::Concat("DBG_UNHANDLED_EXCEPTION in ") + currentFunction); + if (explanatory) + { + sMessage.append(OString::Concat("\n when: ") + explanatory); + } + sMessage.append(" exception: "); + exceptionToStringImpl(sMessage, caught); + + if (area == nullptr) + area = "legacy.osl"; + + SAL_DETAIL_LOG_FORMAT( + SAL_DETAIL_ENABLE_LOG_WARN, SAL_DETAIL_LOG_LEVEL_WARN, + area, fileAndLineNo, "%s", sMessage.getStr()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/comphelper/source/misc/docpasswordhelper.cxx b/comphelper/source/misc/docpasswordhelper.cxx index 4dd9c8312bee..e4327acb8e40 100644 --- a/comphelper/source/misc/docpasswordhelper.cxx +++ b/comphelper/source/misc/docpasswordhelper.cxx @@ -20,8 +20,10 @@ #include <config_gpgme.h> #include <algorithm> +#include <string_view> #include <comphelper/docpasswordhelper.hxx> +#include <comphelper/propertyvalue.hxx> #include <comphelper/storagehelper.hxx> #include <comphelper/hash.hxx> #include <comphelper/base64.hxx> @@ -49,18 +51,17 @@ 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; namespace comphelper { -static uno::Sequence< sal_Int8 > GeneratePBKDF2Hash( const OUString& aPassword, const uno::Sequence< sal_Int8 >& aSalt, sal_Int32 nCount, sal_Int32 nHashLength ) +static uno::Sequence< sal_Int8 > GeneratePBKDF2Hash( std::u16string_view aPassword, const uno::Sequence< sal_Int8 >& aSalt, sal_Int32 nCount, sal_Int32 nHashLength ) { uno::Sequence< sal_Int8 > aResult; - if ( !aPassword.isEmpty() && aSalt.hasElements() && nCount && nHashLength ) + if ( !aPassword.empty() && aSalt.hasElements() && nCount && nHashLength ) { OString aBytePass = OUStringToOString( aPassword, RTL_TEXTENCODING_UTF8 ); // FIXME this is subject to the SHA1-bug tdf#114939 - see also @@ -84,7 +85,7 @@ IDocPasswordVerifier::~IDocPasswordVerifier() } -uno::Sequence< beans::PropertyValue > DocPasswordHelper::GenerateNewModifyPasswordInfo( const OUString& aPassword ) +uno::Sequence< beans::PropertyValue > DocPasswordHelper::GenerateNewModifyPasswordInfo( std::u16string_view aPassword ) { uno::Sequence< beans::PropertyValue > aResult; @@ -94,29 +95,111 @@ uno::Sequence< beans::PropertyValue > DocPasswordHelper::GenerateNewModifyPasswo uno::Sequence< sal_Int8 > aNewHash = GeneratePBKDF2Hash(aPassword, aSalt, nPBKDF2IterationCount, 16); if ( aNewHash.hasElements() ) { - aResult.realloc( 4 ); - aResult[0].Name = "algorithm-name"; - aResult[0].Value <<= OUString( "PBKDF2" ); - aResult[1].Name = "salt"; - aResult[1].Value <<= aSalt; - aResult[2].Name = "iteration-count"; - aResult[2].Value <<= nPBKDF2IterationCount; - aResult[3].Name = "hash"; - aResult[3].Value <<= aNewHash; + aResult = { comphelper::makePropertyValue(u"algorithm-name"_ustr, u"PBKDF2"_ustr), + comphelper::makePropertyValue(u"salt"_ustr, aSalt), + comphelper::makePropertyValue(u"iteration-count"_ustr, nPBKDF2IterationCount), + comphelper::makePropertyValue(u"hash"_ustr, aNewHash) }; } return aResult; } -bool DocPasswordHelper::IsModifyPasswordCorrect( const OUString& aPassword, const uno::Sequence< beans::PropertyValue >& aInfo ) +uno::Sequence<beans::PropertyValue> +DocPasswordHelper::GenerateNewModifyPasswordInfoOOXML(std::u16string_view aPassword) +{ + uno::Sequence<beans::PropertyValue> aResult; + + if (!aPassword.empty()) + { + uno::Sequence<sal_Int8> aSalt = GenerateRandomByteSequence(16); + OUStringBuffer aBuffer(22); + comphelper::Base64::encode(aBuffer, aSalt); + OUString sSalt = aBuffer.makeStringAndClear(); + + sal_Int32 const nIterationCount = 100000; + OUString sAlgorithm(u"SHA-512"_ustr); + + const OUString sHash(GetOoxHashAsBase64(OUString(aPassword), sSalt, nIterationCount, + comphelper::Hash::IterCount::APPEND, sAlgorithm)); + + if (!sHash.isEmpty()) + { + aResult = { comphelper::makePropertyValue(u"algorithm-name"_ustr, sAlgorithm), + comphelper::makePropertyValue(u"salt"_ustr, sSalt), + comphelper::makePropertyValue(u"iteration-count"_ustr, nIterationCount), + comphelper::makePropertyValue(u"hash"_ustr, sHash) }; + } + } + + return aResult; +} + + +uno::Sequence< beans::PropertyValue > DocPasswordHelper::ConvertPasswordInfo( const uno::Sequence< beans::PropertyValue >& aInfo ) +{ + uno::Sequence< beans::PropertyValue > aResult; + OUString sAlgorithm, sHash, sSalt, sCount; + sal_Int32 nAlgorithm = 0; + + for ( const auto & prop : aInfo ) + { + if ( prop.Name == "cryptAlgorithmSid" ) + { + prop.Value >>= sAlgorithm; + nAlgorithm = sAlgorithm.toInt32(); + } + else if ( prop.Name == "salt" ) + prop.Value >>= sSalt; + else if ( prop.Name == "cryptSpinCount" ) + prop.Value >>= sCount; + else if ( prop.Name == "hash" ) + prop.Value >>= sHash; + } + + if (nAlgorithm == 1) + sAlgorithm = "MD2"; + else if (nAlgorithm == 2) + sAlgorithm = "MD4"; + else if (nAlgorithm == 3) + sAlgorithm = "MD5"; + else if (nAlgorithm == 4) + sAlgorithm = "SHA-1"; + else if (nAlgorithm == 5) + sAlgorithm = "MAC"; + else if (nAlgorithm == 6) + sAlgorithm = "RIPEMD"; + else if (nAlgorithm == 7) + sAlgorithm = "RIPEMD-160"; + else if (nAlgorithm == 9) + sAlgorithm = "HMAC"; + else if (nAlgorithm == 12) + sAlgorithm = "SHA-256"; + else if (nAlgorithm == 13) + sAlgorithm = "SHA-384"; + else if (nAlgorithm == 14) + sAlgorithm = "SHA-512"; + + if ( !sCount.isEmpty() ) + { + sal_Int32 nCount = sCount.toInt32(); + aResult = { comphelper::makePropertyValue(u"algorithm-name"_ustr, sAlgorithm), + comphelper::makePropertyValue(u"salt"_ustr, sSalt), + comphelper::makePropertyValue(u"iteration-count"_ustr, nCount), + comphelper::makePropertyValue(u"hash"_ustr, sHash) }; + } + + return aResult; +} + + +bool DocPasswordHelper::IsModifyPasswordCorrect( std::u16string_view aPassword, const uno::Sequence< beans::PropertyValue >& aInfo ) { bool bResult = false; - if ( !aPassword.isEmpty() && aInfo.hasElements() ) + if ( !aPassword.empty() && aInfo.hasElements() ) { OUString sAlgorithm; - uno::Sequence< sal_Int8 > aSalt; - uno::Sequence< sal_Int8 > aHash; + uno::Any aSalt, aHash; sal_Int32 nCount = 0; for ( const auto & prop : aInfo ) @@ -124,20 +207,43 @@ bool DocPasswordHelper::IsModifyPasswordCorrect( const OUString& aPassword, cons if ( prop.Name == "algorithm-name" ) prop.Value >>= sAlgorithm; else if ( prop.Name == "salt" ) - prop.Value >>= aSalt; + aSalt = prop.Value; else if ( prop.Name == "iteration-count" ) prop.Value >>= nCount; else if ( prop.Name == "hash" ) - prop.Value >>= aHash; + aHash = prop.Value; } - if ( sAlgorithm == "PBKDF2" && aSalt.hasElements() && nCount > 0 && aHash.hasElements() ) + if ( sAlgorithm == "PBKDF2" ) { - uno::Sequence< sal_Int8 > aNewHash = GeneratePBKDF2Hash( aPassword, aSalt, nCount, aHash.getLength() ); - for ( sal_Int32 nInd = 0; nInd < aNewHash.getLength() && nInd < aHash.getLength() && aNewHash[nInd] == aHash[nInd]; nInd ++ ) + uno::Sequence<sal_Int8> aIntSalt, aIntHash; + aSalt >>= aIntSalt; + aHash >>= aIntHash; + if (aIntSalt.hasElements() && nCount > 0 && aIntHash.hasElements()) { - if ( nInd == aNewHash.getLength() - 1 && nInd == aHash.getLength() - 1 ) - bResult = true; + uno::Sequence<sal_Int8> aNewHash + = GeneratePBKDF2Hash(aPassword, aIntSalt, nCount, aIntHash.getLength()); + for (sal_Int32 nInd = 0; nInd < aNewHash.getLength() && nInd < aIntHash.getLength() + && aNewHash[nInd] == aIntHash[nInd]; + nInd++) + { + if (nInd == aNewHash.getLength() - 1 && nInd == aIntHash.getLength() - 1) + bResult = true; + } + } + } + else if (nCount > 0) + { + OUString sSalt, sHash; + aSalt >>= sSalt; + aHash >>= sHash; + if (!sSalt.isEmpty() && !sHash.isEmpty()) + { + const OUString aNewHash(GetOoxHashAsBase64(OUString(aPassword), sSalt, nCount, + comphelper::Hash::IterCount::APPEND, + sAlgorithm)); + if (!aNewHash.isEmpty()) + bResult = aNewHash == sHash; } } } @@ -147,7 +253,7 @@ bool DocPasswordHelper::IsModifyPasswordCorrect( const OUString& aPassword, cons sal_uInt32 DocPasswordHelper::GetWordHashAsUINT32( - const OUString& aUString ) + std::u16string_view aUString ) { static const sal_uInt16 pInitialCode[] = { 0xE1F0, // 1 @@ -186,7 +292,7 @@ sal_uInt32 DocPasswordHelper::GetWordHashAsUINT32( }; sal_uInt32 nResult = 0; - sal_uInt32 nLen = aUString.getLength(); + size_t nLen = aUString.size(); if ( nLen ) { @@ -196,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 @@ -223,7 +329,7 @@ sal_uInt32 DocPasswordHelper::GetWordHashAsUINT32( sal_uInt16 DocPasswordHelper::GetXLHashAsUINT16( - const OUString& aUString, + std::u16string_view aUString, rtl_TextEncoding nEnc ) { sal_uInt16 nResult = 0; @@ -248,7 +354,7 @@ sal_uInt16 DocPasswordHelper::GetXLHashAsUINT16( Sequence< sal_Int8 > DocPasswordHelper::GetXLHashAsSequence( - const OUString& aUString ) + std::u16string_view aUString ) { sal_uInt16 nHash = GetXLHashAsUINT16( aUString ); return {sal_Int8(nHash >> 8), sal_Int8(nHash & 0xFF)}; @@ -260,16 +366,18 @@ std::vector<unsigned char> DocPasswordHelper::GetOoxHashAsVector( const std::vector<unsigned char>& rSaltValue, sal_uInt32 nSpinCount, comphelper::Hash::IterCount eIterCount, - const OUString& rAlgorithmName) + std::u16string_view rAlgorithmName) { comphelper::HashType eType; - if (rAlgorithmName == "SHA-512" || rAlgorithmName == "SHA512") + if (rAlgorithmName == u"SHA-512" || rAlgorithmName == u"SHA512") eType = comphelper::HashType::SHA512; - else if (rAlgorithmName == "SHA-256" || rAlgorithmName == "SHA256") + else if (rAlgorithmName == u"SHA-256" || rAlgorithmName == u"SHA256") eType = comphelper::HashType::SHA256; - else if (rAlgorithmName == "SHA-1" || rAlgorithmName == "SHA1") // "SHA1" might be in the wild + 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 == "MD5") + else if (rAlgorithmName == u"MD5") eType = comphelper::HashType::MD5; else return std::vector<unsigned char>(); @@ -280,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, - const OUString& rAlgorithmName) + 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); @@ -300,10 +408,10 @@ 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, - const OUString& rAlgorithmName) + std::u16string_view rAlgorithmName) { css::uno::Sequence<sal_Int8> aSeq( GetOoxHashAsSequence( rPassword, rSaltValue, nSpinCount, eIterCount, rAlgorithmName)); @@ -319,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(u"rtl_random_getBytes failed"_ustr); + } 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 ); } @@ -493,9 +604,8 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( PasswordRequestMode eRequestMode = PasswordRequestMode_PASSWORD_ENTER; while( eResult == DocPasswordVerifierResult::WrongPassword ) { - DocPasswordRequest* pRequest = new DocPasswordRequest( eRequestType, eRequestMode, rDocumentUrl ); - Reference< XInteractionRequest > xRequest( pRequest ); - rxInteractHandler->handle( xRequest ); + rtl::Reference<DocPasswordRequest> pRequest = new DocPasswordRequest( eRequestType, eRequestMode, rDocumentUrl ); + rxInteractHandler->handle( pRequest ); if( pRequest->isPassword() ) { if( !pRequest->getPassword().isEmpty() ) @@ -516,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 @@ -534,13 +643,13 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( // 1. Prepare binary MS formats encryption data auto aUniqueID = GenerateRandomByteSequence(16); - auto aEnc97Key = GenerateStd97Key(aPassword.getStr(), aUniqueID); + auto aEnc97Key = GenerateStd97Key(aPassword, aUniqueID); // 2. Add MS binary and OOXML encryption data to result aEncData = comphelper::concatSequences( aEncData, std::initializer_list<beans::NamedValue>{ - { "STD97EncryptionKey", css::uno::Any(aEnc97Key) }, - { "STD97UniqueID", css::uno::Any(aUniqueID) }, - { "OOXPassword", css::uno::Any(aPassword) }, + { u"STD97EncryptionKey"_ustr, css::uno::Any(aEnc97Key) }, + { u"STD97UniqueID"_ustr, css::uno::Any(aUniqueID) }, + { u"OOXPassword"_ustr, css::uno::Any(aPassword) }, }); } } @@ -556,31 +665,28 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( if ( !rGpgProperties.hasElements() ) return uno::Sequence< beans::NamedValue >(); - uno::Sequence< beans::NamedValue > aEncryptionData(1); + uno::Sequence< beans::NamedValue > aEncryptionData; std::unique_ptr<GpgME::Context> ctx; GpgME::initializeLibrary(); GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP); if (err) - throw uno::RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + throw uno::RuntimeException(u"The GpgME library failed to initialize for the OpenPGP protocol."_ustr); ctx.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP) ); if (ctx == nullptr) - throw uno::RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + throw uno::RuntimeException(u"The GpgME library failed to initialize for the OpenPGP protocol."_ustr); 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()), @@ -607,23 +713,20 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( result = plain.seek(0,SEEK_SET); assert(result == 0); if( plain.read(aKeyValue.getArray(), len) != len ) - throw uno::RuntimeException("The GpgME library failed to read the encrypted value."); + throw uno::RuntimeException(u"The GpgME library failed to read the encrypted value."_ustr); SAL_INFO("comphelper.crypto", "Extracted gpg session key of length: " << len); - aEncryptionData[0].Name = PACKAGE_ENCRYPTIONDATA_SHA256UTF8; - aEncryptionData[0].Value <<= aKeyValue; + aEncryptionData = { { PACKAGE_ENCRYPTIONDATA_SHA256UTF8, uno::Any(aKeyValue) } }; break; } } - if ( aEncryptionData[0].Value.hasValue() ) + if ( aEncryptionData.hasElements() ) { - uno::Sequence< beans::NamedValue > aContainer(2); - aContainer[0].Name = "GpgInfos"; - aContainer[0].Value <<= rGpgProperties; - aContainer[1].Name = "EncryptionKey"; - aContainer[1].Value <<= aEncryptionData; + uno::Sequence< beans::NamedValue > aContainer{ + { u"GpgInfos"_ustr, uno::Any(rGpgProperties) }, { u"EncryptionKey"_ustr, uno::Any(aEncryptionData) } + }; return aContainer; } diff --git a/comphelper/source/misc/docpasswordrequest.cxx b/comphelper/source/misc/docpasswordrequest.cxx index 56644d4d6e59..6f644336e1e2 100644 --- a/comphelper/source/misc/docpasswordrequest.cxx +++ b/comphelper/source/misc/docpasswordrequest.cxx @@ -108,7 +108,7 @@ Any SAL_CALL SimplePasswordRequest::getRequest() Sequence< Reference< XInteractionContinuation > > SAL_CALL SimplePasswordRequest::getContinuations() { - return { mxAbort.get(), mxPassword.get() }; + return { mxAbort, mxPassword }; } @@ -170,7 +170,7 @@ Any SAL_CALL DocPasswordRequest::getRequest() Sequence< Reference< XInteractionContinuation > > SAL_CALL DocPasswordRequest::getContinuations() { - return { mxAbort.get(), mxPassword.get() }; + return { mxAbort, mxPassword }; } diff --git a/comphelper/source/misc/documentinfo.cxx b/comphelper/source/misc/documentinfo.cxx index 102766778f95..21425524e64e 100644 --- a/comphelper/source/misc/documentinfo.cxx +++ b/comphelper/source/misc/documentinfo.cxx @@ -29,7 +29,6 @@ #include <cppuhelper/exc_hlp.hxx> -#include <osl/diagnose.h> #include <sal/log.hxx> namespace comphelper { @@ -66,7 +65,6 @@ namespace comphelper { if ( !_rxDocument.is() ) return sTitle; - OUString sDocURL; try { // 1. ask the model and the controller for their XTitle::getTitle @@ -81,7 +79,7 @@ namespace comphelper { // work around a problem with embedded objects, which sometimes return // private:object as URL - sDocURL = _rxDocument->getURL(); + OUString sDocURL = _rxDocument->getURL(); if ( sDocURL.startsWithIgnoreAsciiCase( "private:" ) ) sDocURL.clear(); @@ -108,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; @@ -152,7 +149,7 @@ namespace comphelper { caught >>= exception; SAL_WARN( "comphelper", "caught an exception!\ntype : " << caught.getValueTypeName() << "\nmessage: " << exception - << "\nin function:\n" << OSL_THIS_FUNC); + << "\nin function:\n" << __func__); } return sTitle; @@ -168,8 +165,9 @@ namespace comphelper { css::uno::Sequence<css::beans::PropertyValue> aMedDescr = rModel->getArgs(); sal_Int32 nNewLen = aMedDescr.getLength() + 1; aMedDescr.realloc(nNewLen); - aMedDescr[nNewLen-1].Name = "MacroEventRead"; - aMedDescr[nNewLen-1].Value <<= true; + auto pMedDescr = aMedDescr.getArray(); + pMedDescr[nNewLen-1].Name = "MacroEventRead"; + pMedDescr[nNewLen-1].Value <<= true; rModel->attachResource(rModel->getURL(), aMedDescr); } diff --git a/comphelper/source/misc/errcode.cxx b/comphelper/source/misc/errcode.cxx new file mode 100644 index 000000000000..716daab1793e --- /dev/null +++ b/comphelper/source/misc/errcode.cxx @@ -0,0 +1,174 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <comphelper/errcode.hxx> +#include <rtl/ustrbuf.hxx> +#include <o3tl/runtimetooustring.hxx> + +UNLESS_MERGELIBS(COMPHELPER_DLLPUBLIC) OUString ErrCode::toString() const +{ + std::u16string_view pWarningError; + if (IsWarning()) + pWarningError = u"Warning"; + else + pWarningError = u"Error"; + + std::u16string_view pArea; + switch (GetArea()) + { + case ErrCodeArea::Io: + pArea = u"Io"; + break; + case ErrCodeArea::Sfx: + pArea = u"Sfx"; + break; + case ErrCodeArea::Inet: + pArea = u"Inet"; + break; + case ErrCodeArea::Vcl: + pArea = u"Vcl"; + break; + case ErrCodeArea::Svx: + pArea = u"Svx"; + break; + case ErrCodeArea::So: + pArea = u"So"; + break; + case ErrCodeArea::Sbx: + pArea = u"Sbx"; + break; + case ErrCodeArea::Uui: + pArea = u"Uui"; + break; + case ErrCodeArea::Sc: + pArea = u"Sc"; + break; + case ErrCodeArea::Sd: + pArea = u"Sd"; + break; + case ErrCodeArea::Sw: + pArea = u"Sw"; + break; + } + + std::u16string_view pClass; + switch (GetClass()) + { + case ErrCodeClass::NONE: + pClass = u"NONE"; + break; + case ErrCodeClass::Abort: + pClass = u"Abort"; + break; + case ErrCodeClass::General: + pClass = u"General"; + break; + case ErrCodeClass::NotExists: + pClass = u"NotExists"; + break; + case ErrCodeClass::AlreadyExists: + pClass = u"AlreadyExists"; + break; + case ErrCodeClass::Access: + pClass = u"Access"; + break; + case ErrCodeClass::Path: + pClass = u"Path"; + break; + case ErrCodeClass::Locking: + pClass = u"Locking"; + break; + case ErrCodeClass::Parameter: + pClass = u"Parameter"; + break; + case ErrCodeClass::Space: + pClass = u"Space"; + break; + case ErrCodeClass::NotSupported: + pClass = u"NotSupported"; + break; + case ErrCodeClass::Read: + pClass = u"Read"; + break; + case ErrCodeClass::Write: + pClass = u"Write"; + break; + case ErrCodeClass::Unknown: + pClass = u"Unknown"; + break; + case ErrCodeClass::Version: + pClass = u"Version"; + break; + case ErrCodeClass::Format: + pClass = u"Format"; + break; + case ErrCodeClass::Create: + pClass = u"Create"; + break; + case ErrCodeClass::Import: + pClass = u"Import"; + break; + case ErrCodeClass::Export: + pClass = u"Export"; + break; + case ErrCodeClass::So: + pClass = u"So"; + break; + case ErrCodeClass::Sbx: + pClass = u"Sbx"; + break; + case ErrCodeClass::Runtime: + pClass = u"Runtime"; + break; + case ErrCodeClass::Compiler: + pClass = u"Compiler"; + break; + } + return toHexString() + "(" + pWarningError + " Area:" + pArea + " Class:" + pClass + + " Code:" + OUString::number(GetCode()) + ")"; +} + +COMPHELPER_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const ErrCode& err) +{ + os << err.toString(); + return os; +} + +UNLESS_MERGELIBS(COMPHELPER_DLLPUBLIC) OUString ErrCodeMsg::toString() const +{ + OUString s = mnCode.toString(); + if (!maArg1.isEmpty()) + s += " arg1=" + maArg1; + if (!maArg2.isEmpty()) + s += " arg2=" + maArg2; +#ifdef LIBO_ERRMSG_USE_SOURCE_LOCATION + if (!moLoc) + s += OUString::Concat(" func=") + o3tl::runtimeToOUString(moLoc->function_name()) + " src=" + + o3tl::runtimeToOUString(moLoc->file_name()) + ":" + OUString::number(moLoc->line()); +#endif + return s; +} + +COMPHELPER_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const ErrCodeMsg& err) +{ + os << err.toString(); + return os; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/fileurl.cxx b/comphelper/source/misc/fileurl.cxx index 9abf1a97f62d..2515b28c5b30 100644 --- a/comphelper/source/misc/fileurl.cxx +++ b/comphelper/source/misc/fileurl.cxx @@ -21,9 +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 4286c92f7a96..a9bc0e504ea5 100644 --- a/comphelper/source/misc/graphicmimetype.cxx +++ b/comphelper/source/misc/graphicmimetype.cxx @@ -18,6 +18,10 @@ */ #include <comphelper/graphicmimetype.hxx> +#include <comphelper/mediamimetype.hxx> + +#include <map> +#include <set> #include <com/sun/star/beans/PropertyValue.hpp> #include <com/sun/star/beans/XPropertySet.hpp> @@ -27,6 +31,7 @@ #include <com/sun/star/uno/Reference.hxx> #include <comphelper/processfactory.hxx> +#include <comphelper/propertyvalue.hxx> using namespace css; using namespace css::beans; @@ -36,7 +41,7 @@ using namespace css::uno; namespace comphelper { -OUString GraphicMimeTypeHelper::GetMimeTypeForExtension(const OString& rExt) +OUString GraphicMimeTypeHelper::GetMimeTypeForExtension(std::string_view rExt) { struct XMLGraphicMimeTypeMapper { @@ -52,8 +57,8 @@ OUString GraphicMimeTypeHelper::GetMimeTypeForExtension(const OString& rExt) OUString aMimeType; - long const nCount = SAL_N_ELEMENTS(aMapper); - for (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), @@ -68,11 +73,11 @@ OUString GraphicMimeTypeHelper::GetMimeTypeForXGraphic(const Reference<XGraphic> OUString aSourceMimeType; Reference<XPropertySet> const xGraphicPropertySet(xGraphic, UNO_QUERY); if (xGraphicPropertySet.is() && // it's null if it's an external link - (xGraphicPropertySet->getPropertyValue("MimeType") >>= aSourceMimeType)) + (xGraphicPropertySet->getPropertyValue(u"MimeType"_ustr) >>= aSourceMimeType)) { return aSourceMimeType; } - return ""; + return u""_ustr; } OUString @@ -81,9 +86,8 @@ GraphicMimeTypeHelper::GetMimeTypeForImageStream(const Reference<XInputStream>& // Create the graphic to retrieve the mimetype from it Reference<XGraphicProvider> xProvider = css::graphic::GraphicProvider::create(comphelper::getProcessComponentContext()); - Sequence<PropertyValue> aMediaProperties(1); - aMediaProperties[0].Name = "InputStream"; - aMediaProperties[0].Value <<= xInputStream; + Sequence<PropertyValue> aMediaProperties{ comphelper::makePropertyValue(u"InputStream"_ustr, + xInputStream) }; Reference<XGraphic> xGraphic(xProvider->queryGraphic(aMediaProperties)); return GetMimeTypeForXGraphic(xGraphic); @@ -94,30 +98,142 @@ OUString GraphicMimeTypeHelper::GetMimeTypeForConvertDataFormat(ConvertDataForma switch (convertDataFormat) { case ConvertDataFormat::BMP: - return "image/bmp"; + return u"image/bmp"_ustr; case ConvertDataFormat::GIF: - return "image/gif"; + return u"image/gif"_ustr; case ConvertDataFormat::JPG: - return "image/jpeg"; + return u"image/jpeg"_ustr; case ConvertDataFormat::PCT: - return "image/x-pict"; + return u"image/x-pict"_ustr; case ConvertDataFormat::PNG: - return "image/png"; + return u"image/png"_ustr; case ConvertDataFormat::SVM: - return "image/x-svm"; + return u"image/x-svm"_ustr; case ConvertDataFormat::TIF: - return "image/tiff"; + return u"image/tiff"_ustr; case ConvertDataFormat::WMF: - return "image/x-wmf"; + return u"image/x-wmf"_ustr; case ConvertDataFormat::EMF: - return "image/x-emf"; + return u"image/x-emf"_ustr; case ConvertDataFormat::SVG: - return "image/svg+xml"; + return u"image/svg+xml"_ustr; case ConvertDataFormat::MET: // What is this? case ConvertDataFormat::Unknown: default: - return ""; + return u""_ustr; + } +} + +char const* GraphicMimeTypeHelper::GetExtensionForConvertDataFormat(ConvertDataFormat nFormat) +{ + char const* pExt = nullptr; + // create extension + if (nFormat != ConvertDataFormat::Unknown) + { + switch (nFormat) + { + case ConvertDataFormat::BMP: + pExt = ".bmp"; + break; + case ConvertDataFormat::GIF: + pExt = ".gif"; + break; + case ConvertDataFormat::JPG: + pExt = ".jpg"; + break; + case ConvertDataFormat::MET: + pExt = ".met"; + break; + case ConvertDataFormat::PCT: + pExt = ".pct"; + break; + case ConvertDataFormat::PNG: + pExt = ".png"; + break; + case ConvertDataFormat::SVM: + pExt = ".svm"; + break; + case ConvertDataFormat::TIF: + pExt = ".tif"; + break; + case ConvertDataFormat::WMF: + pExt = ".wmf"; + break; + case ConvertDataFormat::EMF: + pExt = ".emf"; + break; + + default: + pExt = ".grf"; + break; + } } + 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 6b54ed0a2452..25b93ad87e54 100644 --- a/comphelper/source/misc/hash.cxx +++ b/comphelper/source/misc/hash.cxx @@ -9,7 +9,7 @@ #include <sal/config.h> -#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/RuntimeException.hpp> #include <comphelper/hash.hxx> #include <rtl/ustring.hxx> #include <rtl/alloc.h> @@ -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,15 +81,21 @@ 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); #elif USE_TLS_OPENSSL mpContext = EVP_MD_CTX_create(); - EVP_DigestInit_ex(mpContext, getOpenSSLType(), NULL); + EVP_DigestInit_ex(mpContext, getOpenSSLType(), nullptr); #endif } @@ -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 c32747e26514..ebb0983ace17 100644 --- a/comphelper/source/misc/instancelocker.cxx +++ b/comphelper/source/misc/instancelocker.cxx @@ -19,7 +19,6 @@ #include <cppuhelper/supportsservice.hxx> -#include <comphelper/interfacecontainer2.hxx> #include <com/sun/star/util/CloseVetoException.hpp> #include <com/sun/star/util/XCloseBroadcaster.hpp> @@ -31,6 +30,7 @@ #include <com/sun/star/frame/DoubleInitializationException.hpp> #include <com/sun/star/embed/Actions.hpp> #include <com/sun/star/embed/XActionsApproval.hpp> +#include <utility> #include "instancelocker.hxx" @@ -66,19 +66,19 @@ OInstanceLocker::~OInstanceLocker() void SAL_CALL OInstanceLocker::dispose() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) ); - if ( m_pListenersContainer ) - m_pListenersContainer->disposeAndClear( aSource ); - + m_aListenersContainer.disposeAndClear( aGuard, aSource ); if ( m_xLockListener.is() ) { - m_xLockListener->Dispose(); - m_xLockListener.clear(); + auto tmp = std::move(m_xLockListener); + aGuard.unlock(); + tmp->Dispose(); + aGuard.lock(); } m_bDisposed = true; @@ -87,29 +87,25 @@ void SAL_CALL OInstanceLocker::dispose() void SAL_CALL OInstanceLocker::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); // TODO - if ( !m_pListenersContainer ) - m_pListenersContainer.reset( new ::comphelper::OInterfaceContainerHelper2( m_aMutex ) ); - - m_pListenersContainer->addInterface( xListener ); + m_aListenersContainer.addInterface( aGuard, xListener ); } void SAL_CALL OInstanceLocker::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) { - ::osl::MutexGuard aGuard( m_aMutex ); - if ( m_pListenersContainer ) - m_pListenersContainer->removeInterface( xListener ); + std::unique_lock aGuard( m_aMutex ); + m_aListenersContainer.removeInterface( aGuard, xListener ); } // XInitialization void SAL_CALL OInstanceLocker::initialize( const uno::Sequence< uno::Any >& aArguments ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( m_bInitialized ) throw frame::DoubleInitializationException(); @@ -121,23 +117,23 @@ void SAL_CALL OInstanceLocker::initialize( const uno::Sequence< uno::Any >& aArg uno::Reference< uno::XInterface > xInstance; uno::Reference< embed::XActionsApproval > xApproval; - sal_Int32 nModes = 0; try { sal_Int32 nLen = aArguments.getLength(); if ( nLen < 2 || nLen > 3 ) throw lang::IllegalArgumentException( - "Wrong count of parameters!", + u"Wrong count of parameters!"_ustr, uno::Reference< uno::XInterface >(), 0 ); if ( !( aArguments[0] >>= xInstance ) || !xInstance.is() ) throw lang::IllegalArgumentException( - "Nonempty reference is expected as the first argument!", + u"Nonempty reference is expected as the first argument!"_ustr, uno::Reference< uno::XInterface >(), 0 ); + sal_Int32 nModes = 0; if ( !( aArguments[1] >>= nModes ) || ( @@ -147,14 +143,14 @@ void SAL_CALL OInstanceLocker::initialize( const uno::Sequence< uno::Any >& aArg ) { throw lang::IllegalArgumentException( - "The correct modes set is expected as the second argument!", + u"The correct modes set is expected as the second argument!"_ustr, uno::Reference< uno::XInterface >(), 0 ); } if ( nLen == 3 && !( aArguments[2] >>= xApproval ) ) throw lang::IllegalArgumentException( - "If the third argument is provided, it must be XActionsApproval implementation!", + u"If the third argument is provided, it must be XActionsApproval implementation!"_ustr, uno::Reference< uno::XInterface >(), 0 ); @@ -166,6 +162,7 @@ void SAL_CALL OInstanceLocker::initialize( const uno::Sequence< uno::Any >& aArg } catch( uno::Exception& ) { + aGuard.unlock(); dispose(); throw; } @@ -176,7 +173,7 @@ void SAL_CALL OInstanceLocker::initialize( const uno::Sequence< uno::Any >& aArg // XServiceInfo OUString SAL_CALL OInstanceLocker::getImplementationName( ) { - return "com.sun.star.comp.embed.InstanceLocker"; + return u"com.sun.star.comp.embed.InstanceLocker"_ustr; } sal_Bool SAL_CALL OInstanceLocker::supportsService( const OUString& ServiceName ) @@ -186,19 +183,19 @@ sal_Bool SAL_CALL OInstanceLocker::supportsService( const OUString& ServiceName uno::Sequence< OUString > SAL_CALL OInstanceLocker::getSupportedServiceNames() { - return { "com.sun.star.embed.InstanceLocker" }; + return { u"com.sun.star.embed.InstanceLocker"_ustr }; } // OLockListener -OLockListener::OLockListener( const uno::WeakReference< lang::XComponent >& xWrapper, - const uno::Reference< uno::XInterface >& xInstance, +OLockListener::OLockListener( uno::WeakReference< lang::XComponent > xWrapper, + uno::Reference< uno::XInterface > xInstance, sal_Int32 nMode, - const uno::Reference< embed::XActionsApproval >& rApproval ) -: m_xInstance( xInstance ) -, m_xApproval( rApproval ) -, m_xWrapper( xWrapper ) + uno::Reference< embed::XActionsApproval > xApproval ) +: m_xInstance(std::move( xInstance )) +, m_xApproval(std::move( xApproval )) +, m_xWrapper(std::move( xWrapper )) , m_bDisposed( false ) , m_bInitialized( false ) , m_nMode( nMode ) @@ -213,20 +210,26 @@ OLockListener::~OLockListener() void OLockListener::Dispose() { - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( m_bDisposed ) return; - if ( m_nMode & embed::Actions::PREVENT_CLOSE ) + auto xInstance = std::move(m_xInstance); + auto xApproval = std::move(m_xApproval); + auto nMode = m_nMode; + m_bDisposed = true; + aGuard.unlock(); + + if ( nMode & embed::Actions::PREVENT_CLOSE ) { try { - uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xInstance, uno::UNO_QUERY ); + uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( xInstance, uno::UNO_QUERY ); if ( xCloseBroadcaster.is() ) xCloseBroadcaster->removeCloseListener( static_cast< util::XCloseListener* >( this ) ); - uno::Reference< util::XCloseable > xCloseable( m_xInstance, uno::UNO_QUERY ); + uno::Reference< util::XCloseable > xCloseable( xInstance, uno::UNO_QUERY ); if ( xCloseable.is() ) xCloseable->close( true ); } @@ -234,26 +237,23 @@ void OLockListener::Dispose() {} } - if ( m_nMode & embed::Actions::PREVENT_TERMINATION ) + if ( nMode & embed::Actions::PREVENT_TERMINATION ) { try { - uno::Reference< frame::XDesktop > xDesktop( m_xInstance, uno::UNO_QUERY_THROW ); + uno::Reference< frame::XDesktop > xDesktop( xInstance, uno::UNO_QUERY_THROW ); xDesktop->removeTerminateListener( static_cast< frame::XTerminateListener* >( this ) ); } catch( uno::Exception& ) {} } - - m_xInstance.clear(); - m_bDisposed = true; } // XEventListener void SAL_CALL OLockListener::disposing( const lang::EventObject& aEvent ) { - osl::ClearableMutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); // object is disposed if ( aEvent.Source != m_xInstance ) @@ -264,7 +264,7 @@ void SAL_CALL OLockListener::disposing( const lang::EventObject& aEvent ) // dispose the wrapper; uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY ); - aGuard.clear(); + aGuard.unlock(); if ( xComponent.is() ) { try { xComponent->dispose(); } @@ -278,7 +278,7 @@ void SAL_CALL OLockListener::disposing( const lang::EventObject& aEvent ) void SAL_CALL OLockListener::queryClosing( const lang::EventObject& aEvent, sal_Bool ) { // GetsOwnership parameter is always ignored, the user of the service must close the object always - osl::ClearableMutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( !(!m_bDisposed && aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_CLOSE )) ) return; @@ -287,7 +287,7 @@ void SAL_CALL OLockListener::queryClosing( const lang::EventObject& aEvent, sal_ uno::Reference< embed::XActionsApproval > xApprove = m_xApproval; // unlock the mutex here - aGuard.clear(); + aGuard.unlock(); if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_CLOSE ) ) throw util::CloseVetoException(); @@ -306,7 +306,7 @@ void SAL_CALL OLockListener::queryClosing( const lang::EventObject& aEvent, sal_ void SAL_CALL OLockListener::notifyClosing( const lang::EventObject& aEvent ) { - osl::ClearableMutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); // object is closed, no reason to listen if ( aEvent.Source != m_xInstance ) @@ -322,7 +322,7 @@ void SAL_CALL OLockListener::notifyClosing( const lang::EventObject& aEvent ) { // dispose the wrapper; uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY ); - aGuard.clear(); + aGuard.unlock(); if ( xComponent.is() ) { try { xComponent->dispose(); } @@ -336,7 +336,7 @@ void SAL_CALL OLockListener::notifyClosing( const lang::EventObject& aEvent ) void SAL_CALL OLockListener::queryTermination( const lang::EventObject& aEvent ) { - osl::ClearableMutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( !(aEvent.Source == m_xInstance && ( m_nMode & embed::Actions::PREVENT_TERMINATION )) ) return; @@ -345,7 +345,7 @@ void SAL_CALL OLockListener::queryTermination( const lang::EventObject& aEvent ) uno::Reference< embed::XActionsApproval > xApprove = m_xApproval; // unlock the mutex here - aGuard.clear(); + aGuard.unlock(); if ( xApprove.is() && xApprove->approveAction( embed::Actions::PREVENT_TERMINATION ) ) throw frame::TerminationVetoException(); @@ -364,7 +364,7 @@ void SAL_CALL OLockListener::queryTermination( const lang::EventObject& aEvent ) void SAL_CALL OLockListener::notifyTermination( const lang::EventObject& aEvent ) { - osl::ClearableMutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); // object is terminated, no reason to listen if ( aEvent.Source != m_xInstance ) @@ -382,7 +382,7 @@ void SAL_CALL OLockListener::notifyTermination( const lang::EventObject& aEvent { // dispose the wrapper; uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY ); - aGuard.clear(); + aGuard.unlock(); if ( xComponent.is() ) { try { xComponent->dispose(); } @@ -399,7 +399,7 @@ void SAL_CALL OLockListener::notifyTermination( const lang::EventObject& aEvent void OLockListener::Init() { - osl::ClearableMutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( m_bDisposed || m_bInitialized ) return; @@ -422,7 +422,7 @@ void OLockListener::Init() { // dispose the wrapper; uno::Reference< lang::XComponent > xComponent( m_xWrapper.get(), uno::UNO_QUERY ); - aGuard.clear(); + aGuard.unlock(); if ( xComponent.is() ) { try { xComponent->dispose(); } diff --git a/comphelper/source/misc/instancelocker.hxx b/comphelper/source/misc/instancelocker.hxx index ff5cee4f4775..6a050c7f437c 100644 --- a/comphelper/source/misc/instancelocker.hxx +++ b/comphelper/source/misc/instancelocker.hxx @@ -17,22 +17,20 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_COMPHELPER_SOURCE_MISC_INSTANCELOCKER_HXX -#define INCLUDED_COMPHELPER_SOURCE_MISC_INSTANCELOCKER_HXX +#pragma once #include <com/sun/star/lang/XComponent.hpp> #include <com/sun/star/util/XCloseListener.hpp> #include <com/sun/star/frame/XTerminateListener.hpp> #include <com/sun/star/lang/XInitialization.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> +#include <comphelper/interfacecontainer4.hxx> #include <cppuhelper/weakref.hxx> -#include <osl/mutex.hxx> #include <cppuhelper/implbase.hxx> #include <rtl/ref.hxx> -#include <memory> +#include <mutex> namespace com::sun::star::embed { class XActionsApproval; } -namespace comphelper { class OInterfaceContainerHelper2; } class OLockListener; @@ -43,11 +41,11 @@ class OInstanceLocker : public ::cppu::WeakImplHelper< css::lang::XComponent, css::lang::XInitialization, css::lang::XServiceInfo > { - ::osl::Mutex m_aMutex; + std::mutex m_aMutex; rtl::Reference< OLockListener > m_xLockListener; - std::unique_ptr<::comphelper::OInterfaceContainerHelper2> m_pListenersContainer; // list of listeners + comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aListenersContainer; // list of listeners bool m_bDisposed; bool m_bInitialized; @@ -75,7 +73,7 @@ public: class OLockListener : public ::cppu::WeakImplHelper< css::util::XCloseListener, css::frame::XTerminateListener > { - ::osl::Mutex m_aMutex; + std::mutex m_aMutex; css::uno::Reference< css::uno::XInterface > m_xInstance; css::uno::Reference< css::embed::XActionsApproval > m_xApproval; @@ -87,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; @@ -110,6 +108,4 @@ public: }; -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/interaction.cxx b/comphelper/source/misc/interaction.cxx index 5a24075504b7..9e7b1706d111 100644 --- a/comphelper/source/misc/interaction.cxx +++ b/comphelper/source/misc/interaction.cxx @@ -20,6 +20,7 @@ #include <comphelper/interaction.hxx> #include <comphelper/sequence.hxx> +#include <utility> #include <osl/diagnose.h> @@ -30,15 +31,15 @@ namespace comphelper using namespace ::com::sun::star::uno; using namespace ::com::sun::star::task; - OInteractionRequest::OInteractionRequest(const Any& _rRequestDescription) - :m_aRequest(_rRequestDescription) + OInteractionRequest::OInteractionRequest(Any _aRequestDescription) + :m_aRequest(std::move(_aRequestDescription)) { } - OInteractionRequest::OInteractionRequest(const Any& rRequestDescription, - std::vector<Reference<XInteractionContinuation>> const& rContinuations) - : m_aRequest(rRequestDescription) - , m_aContinuations(rContinuations) + OInteractionRequest::OInteractionRequest(Any aRequestDescription, + std::vector<Reference<XInteractionContinuation>>&& rContinuations) + : m_aRequest(std::move(aRequestDescription)) + , m_aContinuations(std::move(rContinuations)) { } diff --git a/comphelper/source/misc/listenernotification.cxx b/comphelper/source/misc/listenernotification.cxx deleted file mode 100644 index 4bb4e7f619a0..000000000000 --- a/comphelper/source/misc/listenernotification.cxx +++ /dev/null @@ -1,114 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include <comphelper/listenernotification.hxx> - -#include <com/sun/star/lang/XEventListener.hpp> -#include <com/sun/star/lang/DisposedException.hpp> -#include <osl/diagnose.h> - - -namespace comphelper -{ - - - using namespace ::com::sun::star::uno; - using namespace ::com::sun::star::lang; - - OListenerContainer::OListenerContainer( ::osl::Mutex& _rMutex ) - :m_aListeners( _rMutex ) - { - } - - OListenerContainer::~OListenerContainer() {} - - - void OListenerContainer::impl_addListener( const Reference< XEventListener >& _rxListener ) - { - OSL_PRECOND( _rxListener.is(), "OListenerContainer::impl_addListener: a NULL listener?!" ); - if ( _rxListener.is() ) - m_aListeners.addInterface( _rxListener ); - } - - - void OListenerContainer::impl_removeListener( const Reference< XEventListener >& _rxListener ) - { -#if OSL_DEBUG_LEVEL > 0 - ::comphelper::OInterfaceIteratorHelper2 aIter( m_aListeners ); - bool bFound = false; - while ( aIter.hasMoreElements() && !bFound ) - { - bFound = ( Reference< XInterface >( aIter.next() ) == _rxListener ); - } - OSL_ENSURE( bFound, "OListenerContainer::impl_removeListener: sure your listener handling is correct? The given listener is not registered!" ); -#endif - m_aListeners.removeInterface( _rxListener ); - } - - - void OListenerContainer::disposing( const EventObject& _rEventSource ) - { - m_aListeners.disposeAndClear( _rEventSource ); - } - - - void OListenerContainer::clear() - { - m_aListeners.clear(); - } - - - bool OListenerContainer::impl_notify( const EventObject& _rEvent ) - { - ::comphelper::OInterfaceIteratorHelper2 aIter( m_aListeners ); - bool bCancelled = false; - while ( aIter.hasMoreElements() && !bCancelled ) - { - Reference< XEventListener > xListener( static_cast< XEventListener* >( aIter.next() ) ); - if ( !xListener.is() ) - continue; - - try - { - bCancelled = !implNotify( xListener, _rEvent ); - } - catch( const DisposedException& e ) - { - // DisposedExceptions from the listener might indicate a - // broken connection to a different environment. - - OSL_ENSURE( e.Context.is(), "OListenerContainer::impl_notify: caught dispose exception with empty Context field" ); - - // If the exception stems from the listener then remove it - // from the list of listeners. If the Context field of the - // exception is empty this is interpreted to indicate the - // listener as well. - if ( e.Context == xListener || !e.Context.is() ) - aIter.remove(); - } - } - - return !bCancelled; - } - - -} // namespace comphelper - - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/logging.cxx b/comphelper/source/misc/logging.cxx index 405a4acaeb68..a7785d46a747 100644 --- a/comphelper/source/misc/logging.cxx +++ b/comphelper/source/misc/logging.cxx @@ -22,6 +22,7 @@ #include <com/sun/star/logging/LoggerPool.hpp> +#include <comphelper/diagnose_ex.hxx> #include <osl/diagnose.h> @@ -37,7 +38,6 @@ namespace comphelper class EventLogger_Impl { private: - Reference< XComponentContext > m_aContext; Reference< XLogger > m_xLogger; public: @@ -47,23 +47,32 @@ namespace comphelper const Reference< XLogger >& getLogger() const { return m_xLogger; } }; - EventLogger_Impl::EventLogger_Impl( const Reference< XComponentContext >& _rxContext, const OUString& _rLoggerName ) - :m_aContext( _rxContext ) + namespace { - try + Reference<XLogger> createLogger(const Reference<XComponentContext>& rxContext, const OUString& rLoggerName) { - Reference< XLoggerPool > xPool( LoggerPool::get( m_aContext ) ); - if ( !_rLoggerName.isEmpty() ) - m_xLogger = xPool->getNamedLogger( _rLoggerName ); - else - m_xLogger = xPool->getDefaultLogger(); - } - catch( const Exception& ) - { - OSL_FAIL( "EventLogger_Impl::impl_createLogger_nothrow: caught an exception!" ); + try + { + Reference<XLoggerPool> xPool(LoggerPool::get(rxContext)); + if (!rLoggerName.isEmpty()) + return xPool->getNamedLogger(rLoggerName); + else + return xPool->getDefaultLogger(); + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION( + "comphelper", "EventLogger_Impl::impl_createLogger_nothrow: caught an exception!" ); + } + return Reference<XLogger>(); } } + EventLogger_Impl::EventLogger_Impl(const Reference< XComponentContext >& _rxContext, const OUString& rLoggerName) + : m_xLogger(createLogger(_rxContext, rLoggerName)) + { + } + EventLogger::EventLogger( const Reference< XComponentContext >& _rxContext, const char* _pAsciiLoggerName ) :m_pImpl( std::make_shared<EventLogger_Impl>( _rxContext, OUString::createFromAscii( _pAsciiLoggerName ) ) ) { @@ -80,7 +89,7 @@ namespace comphelper } catch( const Exception& ) { - OSL_FAIL( "EventLogger::isLoggable: caught an exception!" ); + TOOLS_WARN_EXCEPTION( "comphelper", "EventLogger::isLoggable: caught an exception!" ); } return false; @@ -94,7 +103,7 @@ namespace comphelper namespace { - void lcl_replaceParameter( OUString& _inout_Message, const char* _rPlaceHolder, const OUString& _rReplacement ) + void lcl_replaceParameter( OUString& _inout_Message, const char* _rPlaceHolder, std::u16string_view _rReplacement ) { sal_Int32 nPlaceholderPosition = _inout_Message.indexOfAsciiL( _rPlaceHolder, strlen(_rPlaceHolder) ); OSL_ENSURE( nPlaceholderPosition >= 0, "lcl_replaceParameter: placeholder not found!" ); @@ -151,7 +160,7 @@ namespace comphelper } catch( const Exception& ) { - OSL_FAIL( "EventLogger::impl_log: caught an exception!" ); + TOOLS_WARN_EXCEPTION( "comphelper", "EventLogger::impl_log: caught an exception!" ); } } } // namespace comphelper diff --git a/comphelper/source/misc/lok.cxx b/comphelper/source/misc/lok.cxx index 8f26be08c49d..36898debc22e 100644 --- a/comphelper/source/misc/lok.cxx +++ b/comphelper/source/misc/lok.cxx @@ -8,17 +8,19 @@ */ #include <comphelper/lok.hxx> +#include <osl/process.h> #include <i18nlangtag/languagetag.hxx> #include <sal/log.hxx> #include <iostream> -#include <map> namespace comphelper::LibreOfficeKit { static bool g_bActive(false); +static bool g_bForkedChild(false); + static bool g_bPartInInvalidation(false); static bool g_bTiledPainting(false); @@ -51,7 +53,7 @@ public: , maLocaleLanguageTag(LANGUAGE_NONE) {} - const LanguageTag& getLanguage() + const LanguageTag& getLanguage() const { return maLanguageTag; } @@ -65,7 +67,7 @@ public: } } - const LanguageTag& getLocale() + const LanguageTag& getLocale() const { return maLocaleLanguageTag; } @@ -74,7 +76,7 @@ public: { if (maLocaleLanguageTag != rLocaleLanguageTag) { - SAL_INFO("comphelper.lok", "Setting locale from " << maLanguageTag.getBcp47() << " to " << rLocaleLanguageTag.getBcp47()); + SAL_INFO("comphelper.lok", "Setting locale from " << maLocaleLanguageTag.getBcp47() << " to " << rLocaleLanguageTag.getBcp47()); maLocaleLanguageTag = rLocaleLanguageTag; } } @@ -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); @@ -211,14 +225,12 @@ bool isAllowlistedLanguage(const OUString& lang) if (!isActive()) return true; -#ifdef ANDROID +#if defined ANDROID || defined IOS (void) lang; return true; #else - static bool bInitialized = false; - static std::vector<OUString> aAllowlist; - if (!bInitialized) - { + static const std::vector<OUString> aAllowlist = [] { + std::vector<OUString> aList; // coverity[tainted_data] - we trust the contents of this variable const char* pAllowlist = getenv("LOK_ALLOWLIST_LANGUAGES"); if (pAllowlist) @@ -232,16 +244,16 @@ bool isAllowlistedLanguage(const OUString& lang) continue; std::cerr << s << " "; - aAllowlist.emplace_back(OStringToOUString(s.c_str(), RTL_TEXTENCODING_UTF8)); + aList.emplace_back(OStringToOUString(s, RTL_TEXTENCODING_UTF8)); } std::cerr << std::endl; } - if (aAllowlist.empty()) + if (aList.empty()) std::cerr << "No language allowlisted, turning off the language support." << std::endl; - bInitialized = true; - } + return aList; + }(); if (aAllowlist.empty()) return false; @@ -258,31 +270,49 @@ bool isAllowlistedLanguage(const OUString& lang) #endif } -static void (*pStatusIndicatorCallback)(void *data, statusIndicatorCallbackType type, int percent)(nullptr); +void setTimezone(bool isSet, const OUString& rTimezone) +{ + if (isSet) + { + // Set the given timezone, even if empty. + osl_setEnvironment(u"TZ"_ustr.pData, rTimezone.pData); + } + else + { + // Unset and empty aren't the same. + // When unset, it means default to the system configured timezone. + osl_clearEnvironment(u"TZ"_ustr.pData); + } + + // Update the timezone data. + ::tzset(); +} + +static void (*pStatusIndicatorCallback)(void *data, statusIndicatorCallbackType type, int percent, const char* pText)(nullptr); static void *pStatusIndicatorCallbackData(nullptr); -void setStatusIndicatorCallback(void (*callback)(void *data, statusIndicatorCallbackType type, int percent), void *data) +void setStatusIndicatorCallback(void (*callback)(void *data, statusIndicatorCallbackType type, int percent, const char* pText), void *data) { pStatusIndicatorCallback = callback; pStatusIndicatorCallbackData = data; } -void statusIndicatorStart() +void statusIndicatorStart(const OUString& sText) { if (pStatusIndicatorCallback) - pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::Start, 0); + pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::Start, 0, sText.toUtf8().getStr()); } void statusIndicatorSetValue(int percent) { if (pStatusIndicatorCallback) - pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::SetValue, percent); + pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::SetValue, percent, nullptr); } void statusIndicatorFinish() { if (pStatusIndicatorCallback) - pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::Finish, 0); + pStatusIndicatorCallback(pStatusIndicatorCallbackData, statusIndicatorCallbackType::Finish, 0, nullptr); } } // namespace diff --git a/comphelper/source/misc/mimeconfighelper.cxx b/comphelper/source/misc/mimeconfighelper.cxx index b41b1d3850c7..dfd7fa53f677 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(u"MimeConfigurationHelper:: empty component context"_ustr); } @@ -60,7 +61,7 @@ OUString MimeConfigurationHelper::GetStringClassIDRepresentation( const uno::Seq sal_Int32 nDigit1 = static_cast<sal_Int32>( static_cast<sal_uInt8>(aClassID[nInd]) / 16 ); sal_Int32 nDigit2 = static_cast<sal_uInt8>(aClassID[nInd]) % 16; - aResult.append(OUString::number( nDigit1, 16 )).append(OUString::number( nDigit2, 16 )); + aResult.append( OUString::number(nDigit1, 16) + OUString::number( nDigit2, 16 ) ); } } @@ -81,17 +82,18 @@ static sal_uInt8 GetDigit_Impl( char aChar ) } -uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassIDRepresentation( const OUString& aClassID ) +uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassIDRepresentation( std::u16string_view aClassID ) { - sal_Int32 nLength = aClassID.getLength(); + size_t nLength = aClassID.size(); if ( nLength == 36 ) { OString aCharClassID = OUStringToOString( aClassID, RTL_TEXTENCODING_ASCII_US ); uno::Sequence< sal_Int8 > aResult( 16 ); + auto pResult = aResult.getArray(); - sal_Int32 nStrPointer = 0; + size_t nStrPointer = 0; sal_Int32 nSeqInd = 0; - while( nSeqInd < 16 && nStrPointer + 1 < nLength ) + while( nSeqInd < 16 && nStrPointer + 1U < nLength ) { sal_uInt8 nDigit1 = GetDigit_Impl( aCharClassID[nStrPointer++] ); sal_uInt8 nDigit2 = GetDigit_Impl( aCharClassID[nStrPointer++] ); @@ -99,7 +101,7 @@ uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassIDRepresentat if ( nDigit1 > 15 || nDigit2 > 15 ) break; - aResult[nSeqInd++] = static_cast<sal_Int8>( nDigit1 * 16 + nDigit2 ); + pResult[nSeqInd++] = static_cast<sal_Int8>( nDigit1 * 16 + nDigit2 ); if ( nStrPointer < nLength && aCharClassID[nStrPointer] == '-' ) nStrPointer++; @@ -113,10 +115,8 @@ uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassIDRepresentat } -uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetConfigurationByPath( const OUString& aPath ) +uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetConfigurationByPathImpl( const OUString& aPath ) { - osl::MutexGuard aGuard( m_aMutex ); - uno::Reference< container::XNameAccess > xConfig; try @@ -129,7 +129,7 @@ uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetConfigurati {"nodepath", uno::Any(aPath)} })); xConfig.set( m_xConfigProvider->createInstanceWithArguments( - "com.sun.star.configuration.ConfigurationAccess", + u"com.sun.star.configuration.ConfigurationAccess"_ustr, aArgs ), uno::UNO_QUERY ); } @@ -142,11 +142,11 @@ uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetConfigurati uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetObjConfiguration() { - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( !m_xObjectConfig.is() ) - m_xObjectConfig = GetConfigurationByPath( - "/org.openoffice.Office.Embedding/Objects" ); + m_xObjectConfig = GetConfigurationByPathImpl( + u"/org.openoffice.Office.Embedding/Objects"_ustr ); return m_xObjectConfig; } @@ -154,11 +154,11 @@ uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetObjConfigur uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetVerbsConfiguration() { - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( !m_xVerbsConfig.is() ) - m_xVerbsConfig = GetConfigurationByPath( - "/org.openoffice.Office.Embedding/Verbs"); + m_xVerbsConfig = GetConfigurationByPathImpl( + u"/org.openoffice.Office.Embedding/Verbs"_ustr); return m_xVerbsConfig; } @@ -166,11 +166,11 @@ uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetVerbsConfig uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetMediaTypeConfiguration() { - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( !m_xMediaTypeConfig.is() ) - m_xMediaTypeConfig = GetConfigurationByPath( - "/org.openoffice.Office.Embedding/MimeTypeClassIDRelations"); + m_xMediaTypeConfig = GetConfigurationByPathImpl( + u"/org.openoffice.Office.Embedding/MimeTypeClassIDRelations"_ustr); return m_xMediaTypeConfig; } @@ -178,11 +178,11 @@ uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetMediaTypeCo uno::Reference< container::XNameAccess > MimeConfigurationHelper::GetFilterFactory() { - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( !m_xFilterFactory.is() ) m_xFilterFactory.set( - m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", m_xContext), + m_xContext->getServiceManager()->createInstanceWithContext(u"com.sun.star.document.FilterFactory"_ustr, m_xContext), uno::UNO_QUERY ); return m_xFilterFactory; @@ -203,7 +203,7 @@ OUString MimeConfigurationHelper::GetDocServiceNameFromFilter( const OUString& a uno::Sequence< beans::PropertyValue > aFilterData; if ( aFilterAnyData >>= aFilterData ) { - for ( const auto & prop : std::as_const(aFilterData) ) + for (const auto& prop : aFilterData) if ( prop.Name == "DocumentService" ) prop.Value >>= aDocServiceName; } @@ -218,7 +218,7 @@ OUString MimeConfigurationHelper::GetDocServiceNameFromFilter( const OUString& a OUString MimeConfigurationHelper::GetDocServiceNameFromMediaType( const OUString& aMediaType ) { uno::Reference< container::XContainerQuery > xTypeCFG( - m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", m_xContext), + m_xContext->getServiceManager()->createInstanceWithContext(u"com.sun.star.document.TypeDetection"_ustr, m_xContext), uno::UNO_QUERY ); if ( xTypeCFG.is() ) @@ -226,7 +226,7 @@ OUString MimeConfigurationHelper::GetDocServiceNameFromMediaType( const OUString try { // make query for all types matching the properties - uno::Sequence < beans::NamedValue > aSeq { { "MediaType", css::uno::Any(aMediaType) } }; + uno::Sequence < beans::NamedValue > aSeq { { u"MediaType"_ustr, css::uno::Any(aMediaType) } }; uno::Reference < container::XEnumeration > xEnum = xTypeCFG->createSubSetEnumerationByProperties( aSeq ); while ( xEnum->hasMoreElements() ) @@ -234,7 +234,7 @@ OUString MimeConfigurationHelper::GetDocServiceNameFromMediaType( const OUString uno::Sequence< beans::PropertyValue > aType; if ( xEnum->nextElement() >>= aType ) { - for ( const auto & prop : std::as_const(aType) ) + for (const auto& prop : aType) { OUString aFilterName; if ( prop.Name == "PreferredFilter" @@ -268,10 +268,14 @@ bool MimeConfigurationHelper::GetVerbByShortcut( const OUString& aVerbShortcut, if ( xVerbsConfig.is() && ( xVerbsConfig->getByName( aVerbShortcut ) >>= xVerbsProps ) && xVerbsProps.is() ) { embed::VerbDescriptor aTempDescr; - if ( ( xVerbsProps->getByName("VerbID") >>= aTempDescr.VerbID ) - && ( xVerbsProps->getByName("VerbUIName") >>= aTempDescr.VerbName ) - && ( xVerbsProps->getByName("VerbFlags") >>= aTempDescr.VerbFlags ) - && ( xVerbsProps->getByName("VerbAttributes") >>= aTempDescr.VerbAttributes ) ) + static constexpr OUStringLiteral sVerbID = u"VerbID"; + static constexpr OUStringLiteral sVerbUIName = u"VerbUIName"; + static constexpr OUStringLiteral sVerbFlags = u"VerbFlags"; + static constexpr OUStringLiteral sVerbAttributes = u"VerbAttributes"; + if ( ( xVerbsProps->getByName(sVerbID) >>= aTempDescr.VerbID ) + && ( xVerbsProps->getByName(sVerbUIName) >>= aTempDescr.VerbName ) + && ( xVerbsProps->getByName(sVerbFlags) >>= aTempDescr.VerbFlags ) + && ( xVerbsProps->getByName(sVerbAttributes) >>= aTempDescr.VerbAttributes ) ) { aDescriptor = aTempDescr; bResult = true; @@ -296,30 +300,32 @@ uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjPropsFromConfi { try { - uno::Sequence< OUString > aObjPropNames = xObjectProps->getElementNames(); + const uno::Sequence< OUString > aObjPropNames = xObjectProps->getElementNames(); aResult.realloc( aObjPropNames.getLength() + 1 ); - aResult[0].Name = "ClassID"; - aResult[0].Value <<= aClassID; + auto pResult = aResult.getArray(); + pResult[0].Name = "ClassID"; + pResult[0].Value <<= aClassID; for ( sal_Int32 nInd = 0; nInd < aObjPropNames.getLength(); nInd++ ) { - aResult[nInd + 1].Name = aObjPropNames[nInd]; + pResult[nInd + 1].Name = aObjPropNames[nInd]; if ( aObjPropNames[nInd] == "ObjectVerbs" ) { uno::Sequence< OUString > aVerbShortcuts; if ( !(xObjectProps->getByName( aObjPropNames[nInd] ) >>= aVerbShortcuts) ) - throw uno::RuntimeException(); + throw uno::RuntimeException(u"Failed to get verb shortcuts from object properties"_ustr); uno::Sequence< embed::VerbDescriptor > aVerbDescriptors( aVerbShortcuts.getLength() ); + auto aVerbDescriptorsRange = asNonConstRange(aVerbDescriptors); for ( sal_Int32 nVerbI = 0; nVerbI < aVerbShortcuts.getLength(); nVerbI++ ) - if ( !GetVerbByShortcut( aVerbShortcuts[nVerbI], aVerbDescriptors[nVerbI] ) ) - throw uno::RuntimeException(); + if ( !GetVerbByShortcut( aVerbShortcuts[nVerbI], aVerbDescriptorsRange[nVerbI] ) ) + throw uno::RuntimeException(u"Failed to get verb descriptor by shortcut"_ustr); - aResult[nInd+1].Value <<= aVerbDescriptors; + pResult[nInd+1].Value <<= aVerbDescriptors; } else - aResult[nInd+1].Value = xObjectProps->getByName( aObjPropNames[nInd] ); + pResult[nInd+1].Value = xObjectProps->getByName( aObjPropNames[nInd] ); } } catch( uno::Exception& ) @@ -359,11 +365,9 @@ uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByStri uno::Sequence< sal_Int8 > aClassID = GetSequenceClassIDRepresentation( aStringClassID ); if ( ClassIDsEqual( aClassID, GetSequenceClassID( SO3_DUMMY_CLASSID ) ) ) { - aObjProps.realloc(2); - aObjProps[0].Name = "ObjectFactory"; - aObjProps[0].Value <<= OUString( "com.sun.star.embed.OOoSpecialEmbeddedObjectFactory" ); - aObjProps[1].Name = "ClassID"; - aObjProps[1].Value <<= aClassID; + aObjProps = { { u"ObjectFactory"_ustr, + uno::Any(u"com.sun.star.embed.OOoSpecialEmbeddedObjectFactory"_ustr) }, + { u"ClassID"_ustr, uno::Any(aClassID) } }; return aObjProps; } @@ -392,11 +396,9 @@ uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByClas uno::Sequence< beans::NamedValue > aObjProps; if ( ClassIDsEqual( aClassID, GetSequenceClassID( SO3_DUMMY_CLASSID ) ) ) { - aObjProps.realloc(2); - aObjProps[0].Name = "ObjectFactory"; - aObjProps[0].Value <<= OUString( "com.sun.star.embed.OOoSpecialEmbeddedObjectFactory" ); - aObjProps[1].Name = "ClassID"; - aObjProps[1].Value <<= aClassID; + aObjProps = { { u"ObjectFactory"_ustr, + uno::Any(u"com.sun.star.embed.OOoSpecialEmbeddedObjectFactory"_ustr) }, + { u"ClassID"_ustr, uno::Any(aClassID) } }; } OUString aStringClassID = GetStringClassIDRepresentation( aClassID ); @@ -443,9 +445,9 @@ uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByFilt } -uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByDocumentName( const OUString& aDocName ) +uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByDocumentName( std::u16string_view aDocName ) { - if ( !aDocName.isEmpty() ) + if ( !aDocName.empty() ) { uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration(); if ( xObjConfig.is() ) @@ -459,7 +461,7 @@ uno::Sequence< beans::NamedValue > MimeConfigurationHelper::GetObjectPropsByDocu OUString aEntryDocName; if ( ( xObjConfig->getByName( id ) >>= xObjectProps ) && xObjectProps.is() - && ( xObjectProps->getByName("ObjectDocumentServiceName") >>= aEntryDocName ) + && ( xObjectProps->getByName(u"ObjectDocumentServiceName"_ustr) >>= aEntryDocName ) && aEntryDocName == aDocName ) { return GetObjPropsFromConfigEntry( GetSequenceClassIDRepresentation( id ), @@ -493,13 +495,13 @@ OUString MimeConfigurationHelper::GetFactoryNameByStringClassID( const OUString& try { if ( xObjConfig.is() && ( xObjConfig->getByName( aStringClassID.toAsciiUpperCase() ) >>= xObjectProps ) && xObjectProps.is() ) - xObjectProps->getByName("ObjectFactory") >>= aResult; + xObjectProps->getByName(u"ObjectFactory"_ustr) >>= aResult; } catch( uno::Exception& ) { uno::Sequence< sal_Int8 > aClassID = GetSequenceClassIDRepresentation( aStringClassID ); if ( ClassIDsEqual( aClassID, GetSequenceClassID( SO3_DUMMY_CLASSID ) ) ) - return "com.sun.star.embed.OOoSpecialEmbeddedObjectFactory"; + return u"com.sun.star.embed.OOoSpecialEmbeddedObjectFactory"_ustr; } } @@ -507,11 +509,11 @@ OUString MimeConfigurationHelper::GetFactoryNameByStringClassID( const OUString& } -OUString MimeConfigurationHelper::GetFactoryNameByDocumentName( const OUString& aDocName ) +OUString MimeConfigurationHelper::GetFactoryNameByDocumentName( std::u16string_view aDocName ) { OUString aResult; - if ( !aDocName.isEmpty() ) + if ( !aDocName.empty() ) { uno::Reference< container::XNameAccess > xObjConfig = GetObjConfiguration(); if ( xObjConfig.is() ) @@ -525,10 +527,10 @@ OUString MimeConfigurationHelper::GetFactoryNameByDocumentName( const OUString& OUString aEntryDocName; if ( ( xObjConfig->getByName( id ) >>= xObjectProps ) && xObjectProps.is() - && ( xObjectProps->getByName( "ObjectDocumentServiceName" ) >>= aEntryDocName ) + && ( xObjectProps->getByName( u"ObjectDocumentServiceName"_ustr ) >>= aEntryDocName ) && aEntryDocName == aDocName ) { - xObjectProps->getByName("ObjectFactory") >>= aResult; + xObjectProps->getByName(u"ObjectFactory"_ustr) >>= aResult; break; } } @@ -563,7 +565,7 @@ OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName( { OUString aFilterName; - for ( const auto & prop : std::as_const(aMediaDescr) ) + for (const auto& prop : aMediaDescr) if ( prop.Name == "FilterName" ) prop.Value >>= aFilterName; @@ -572,17 +574,17 @@ OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName( // filter name is not specified, so type detection should be done uno::Reference< document::XTypeDetection > xTypeDetection( - m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", m_xContext), + m_xContext->getServiceManager()->createInstanceWithContext(u"com.sun.star.document.TypeDetection"_ustr, m_xContext), uno::UNO_QUERY_THROW ); // typedetection can change the mode, add a stream and so on, thus a copy should be used uno::Sequence< beans::PropertyValue > aTempMD( aMediaDescr ); // get TypeName - OUString aTypeName = xTypeDetection->queryTypeByDescriptor( aTempMD, true ); + OUString aTypeName = xTypeDetection->queryTypeByDescriptor(aTempMD, /*bAllowDeepDetection*/true); // get FilterName - for ( const auto & prop : std::as_const(aTempMD) ) + for (const auto& prop : aTempMD) if ( prop.Name == "FilterName" ) prop.Value >>= aFilterName; @@ -590,8 +592,9 @@ OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName( { sal_Int32 nOldLen = aMediaDescr.getLength(); aMediaDescr.realloc( nOldLen + 1 ); - aMediaDescr[nOldLen].Name = "FilterName"; - aMediaDescr[ nOldLen ].Value <<= aFilterName; + auto pMediaDescr = aMediaDescr.getArray(); + pMediaDescr[nOldLen].Name = "FilterName"; + pMediaDescr[ nOldLen ].Value <<= aFilterName; } else if ( !aTypeName.isEmpty() && !bIgnoreType ) @@ -601,14 +604,15 @@ OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName( if ( xNameAccess.is() && ( xNameAccess->getByName( aTypeName ) >>= aTypes ) ) { - for ( const auto & prop : std::as_const(aTypes) ) + for (const auto& prop : aTypes) { if ( prop.Name == "PreferredFilter" && ( prop.Value >>= aFilterName ) ) { sal_Int32 nOldLen = aMediaDescr.getLength(); aMediaDescr.realloc( nOldLen + 1 ); - aMediaDescr[nOldLen].Name = "FilterName"; - aMediaDescr[ nOldLen ].Value = prop.Value; + auto pMediaDescr = aMediaDescr.getArray(); + pMediaDescr[nOldLen].Name = "FilterName"; + pMediaDescr[ nOldLen ].Value = prop.Value; break; } } @@ -624,7 +628,7 @@ OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName( uno::Sequence< beans::NamedValue >& aObject ) { OUString aDocName; - for ( const auto & nv : std::as_const(aObject) ) + for (const auto& nv : aObject) if ( nv.Name == "ObjectDocumentServiceName" ) { nv.Value >>= aDocName; @@ -638,7 +642,7 @@ OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName( for ( sal_Int32 nMedInd = 0; nMedInd < aMediaDescr.getLength(); nMedInd++ ) if ( aMediaDescr[nMedInd].Name == "DocumentService" ) { - aMediaDescr[nMedInd].Value <<= aDocName; + aMediaDescr.getArray()[nMedInd].Value <<= aDocName; bNeedsAddition = false; break; } @@ -647,8 +651,9 @@ OUString MimeConfigurationHelper::UpdateMediaDescriptorWithFilterName( { sal_Int32 nOldLen = aMediaDescr.getLength(); aMediaDescr.realloc( nOldLen + 1 ); - aMediaDescr[nOldLen].Name = "DocumentService"; - aMediaDescr[nOldLen].Value <<= aDocName; + auto pMediaDescr = aMediaDescr.getArray(); + pMediaDescr[nOldLen].Name = "DocumentService"; + pMediaDescr[nOldLen].Value <<= aDocName; } return UpdateMediaDescriptorWithFilterName( aMediaDescr, true ); @@ -710,8 +715,8 @@ OUString MimeConfigurationHelper::GetDefaultFilterFromServiceName( const OUStrin uno::Sequence< beans::NamedValue > aSearchRequest { - { "DocumentService", css::uno::Any(aServiceName) }, - { "FileFormatVersion", css::uno::Any(nVersion) } + { u"DocumentService"_ustr, css::uno::Any(aServiceName) }, + { u"FileFormatVersion"_ustr, css::uno::Any(nVersion) } }; uno::Reference< container::XEnumeration > xFilterEnum = @@ -724,8 +729,19 @@ OUString MimeConfigurationHelper::GetDefaultFilterFromServiceName( const OUStrin uno::Sequence< beans::PropertyValue > aProps; if ( xFilterEnum->nextElement() >>= aProps ) { - SequenceAsHashMap aPropsHM( aProps ); - SfxFilterFlags nFlags = static_cast<SfxFilterFlags>(aPropsHM.getUnpackedValueOrDefault( "Flags", sal_Int32(0) )); + SfxFilterFlags nFlags = SfxFilterFlags::NONE; + OUString sName; + for (const auto & rPropVal : aProps) + { + if (rPropVal.Name == "Flags") + { + sal_Int32 nTmp(0); + if (rPropVal.Value >>= nTmp) + nFlags = static_cast<SfxFilterFlags>(nTmp); + } + else if (rPropVal.Name == "Name") + rPropVal.Value >>= sName; + } // that should be import, export, own filter and not a template filter ( TemplatePath flag ) SfxFilterFlags const nRequired = SfxFilterFlags::OWN @@ -739,7 +755,7 @@ OUString MimeConfigurationHelper::GetDefaultFilterFromServiceName( const OUStrin // if there are more than one filter the preferred one should be used // if there is no preferred filter the first one will be used if ( aResult.isEmpty() || ( nFlags & SfxFilterFlags::PREFERED ) ) - aResult = aPropsHM.getUnpackedValueOrDefault( "Name", OUString() ); + aResult = sName; if ( nFlags & SfxFilterFlags::PREFERED ) break; // the preferred filter was found } @@ -770,12 +786,12 @@ OUString MimeConfigurationHelper::GetExportFilterFromImportFilter( const OUStrin if ( aImpFilterAny >>= aImpData ) { SequenceAsHashMap aImpFilterHM( aImpData ); - SfxFilterFlags nFlags = static_cast<SfxFilterFlags>(aImpFilterHM.getUnpackedValueOrDefault( "Flags", sal_Int32(0) )); + SfxFilterFlags nFlags = static_cast<SfxFilterFlags>(aImpFilterHM.getUnpackedValueOrDefault( u"Flags"_ustr, sal_Int32(0) )); if ( !( nFlags & SfxFilterFlags::IMPORT ) ) { OSL_FAIL( "This is no import filter!" ); - throw uno::Exception("this is no import filter", nullptr); + throw uno::Exception(u"this is no import filter"_ustr, nullptr); } if ( nFlags & SfxFilterFlags::EXPORT ) @@ -784,16 +800,16 @@ OUString MimeConfigurationHelper::GetExportFilterFromImportFilter( const OUStrin } else { - OUString aDocumentServiceName = aImpFilterHM.getUnpackedValueOrDefault( "DocumentService", OUString() ); - OUString aTypeName = aImpFilterHM.getUnpackedValueOrDefault( "Type", OUString() ); + OUString aDocumentServiceName = aImpFilterHM.getUnpackedValueOrDefault( u"DocumentService"_ustr, OUString() ); + OUString aTypeName = aImpFilterHM.getUnpackedValueOrDefault( u"Type"_ustr, OUString() ); OSL_ENSURE( !aDocumentServiceName.isEmpty() && !aTypeName.isEmpty(), "Incomplete filter data!" ); if ( !(aDocumentServiceName.isEmpty() || aTypeName.isEmpty()) ) { uno::Sequence< beans::NamedValue > aSearchRequest { - { "Type", css::uno::Any(aTypeName) }, - { "DocumentService", css::uno::Any(aDocumentServiceName) } + { u"Type"_ustr, css::uno::Any(aTypeName) }, + { u"DocumentService"_ustr, css::uno::Any(aDocumentServiceName) } }; uno::Sequence< beans::PropertyValue > aExportFilterProps = SearchForFilter( @@ -805,7 +821,7 @@ OUString MimeConfigurationHelper::GetExportFilterFromImportFilter( const OUStrin if ( aExportFilterProps.hasElements() ) { SequenceAsHashMap aExpPropsHM( aExportFilterProps ); - aExportFilterName = aExpPropsHM.getUnpackedValueOrDefault( "Name", OUString() ); + aExportFilterName = aExpPropsHM.getUnpackedValueOrDefault( u"Name"_ustr, OUString() ); } } } @@ -840,7 +856,7 @@ uno::Sequence< beans::PropertyValue > MimeConfigurationHelper::SearchForFilter( if ( xFilterEnum->nextElement() >>= aProps ) { SequenceAsHashMap aPropsHM( aProps ); - SfxFilterFlags nFlags = static_cast<SfxFilterFlags>(aPropsHM.getUnpackedValueOrDefault("Flags", + SfxFilterFlags nFlags = static_cast<SfxFilterFlags>(aPropsHM.getUnpackedValueOrDefault(u"Flags"_ustr, sal_Int32(0) )); if ( ( ( nFlags & nMustFlags ) == nMustFlags ) && !( nFlags & nDontFlags ) ) { @@ -870,23 +886,22 @@ uno::Sequence< sal_Int8 > MimeConfigurationHelper::GetSequenceClassID( sal_uInt3 sal_uInt8 b8, sal_uInt8 b9, sal_uInt8 b10, sal_uInt8 b11, sal_uInt8 b12, sal_uInt8 b13, sal_uInt8 b14, sal_uInt8 b15 ) { - uno::Sequence< sal_Int8 > aResult( 16 ); - aResult[0] = static_cast<sal_Int8>( n1 >> 24 ); - aResult[1] = static_cast<sal_Int8>( ( n1 << 8 ) >> 24 ); - aResult[2] = static_cast<sal_Int8>( ( n1 << 16 ) >> 24 ); - aResult[3] = static_cast<sal_Int8>( ( n1 << 24 ) >> 24 ); - aResult[4] = static_cast<sal_Int8>( n2 >> 8 ); - aResult[5] = static_cast<sal_Int8>( ( n2 << 8 ) >> 8 ); - aResult[6] = static_cast<sal_Int8>( n3 >> 8 ); - aResult[7] = static_cast<sal_Int8>( ( n3 << 8 ) >> 8 ); - aResult[8] = b8; - aResult[9] = b9; - aResult[10] = b10; - aResult[11] = b11; - aResult[12] = b12; - aResult[13] = b13; - aResult[14] = b14; - aResult[15] = b15; + uno::Sequence< sal_Int8 > aResult{ /* [ 0] */ static_cast<sal_Int8>( n1 >> 24 ), + /* [ 1] */ static_cast<sal_Int8>( ( n1 << 8 ) >> 24 ), + /* [ 2] */ static_cast<sal_Int8>( ( n1 << 16 ) >> 24 ), + /* [ 3] */ static_cast<sal_Int8>( ( n1 << 24 ) >> 24 ), + /* [ 4] */ static_cast<sal_Int8>( n2 >> 8 ), + /* [ 5] */ static_cast<sal_Int8>( ( n2 << 8 ) >> 8 ), + /* [ 6] */ static_cast<sal_Int8>( n3 >> 8 ), + /* [ 7] */ static_cast<sal_Int8>( ( n3 << 8 ) >> 8 ), + /* [ 8] */ static_cast<sal_Int8>( b8 ), + /* [ 9] */ static_cast<sal_Int8>( b9 ), + /* [10] */ static_cast<sal_Int8>( b10 ), + /* [11] */ static_cast<sal_Int8>( b11 ), + /* [12] */ static_cast<sal_Int8>( b12 ), + /* [13] */ static_cast<sal_Int8>( b13 ), + /* [14] */ static_cast<sal_Int8>( b14 ), + /* [15] */ static_cast<sal_Int8>( b15 ) }; return aResult; } diff --git a/comphelper/source/misc/namedvaluecollection.cxx b/comphelper/source/misc/namedvaluecollection.cxx index 768f1f610e5d..11ef15b30854 100644 --- a/comphelper/source/misc/namedvaluecollection.cxx +++ b/comphelper/source/misc/namedvaluecollection.cxx @@ -24,7 +24,6 @@ #include <com/sun/star/beans/PropertyState.hpp> #include <com/sun/star/beans/PropertyValue.hpp> -#include <rtl/instance.hxx> #include <sal/log.hxx> #include <algorithm> @@ -45,75 +44,30 @@ namespace comphelper using ::com::sun::star::lang::IllegalArgumentException; using ::com::sun::star::beans::PropertyState_DIRECT_VALUE; - typedef std::unordered_map< OUString, Any > NamedValueRepository; - - struct NamedValueCollection_Impl - { - NamedValueRepository aValues; - }; - - NamedValueCollection::NamedValueCollection() - :m_pImpl( new NamedValueCollection_Impl ) - { - } - - - NamedValueCollection::NamedValueCollection( const NamedValueCollection& _rCopySource ) - :m_pImpl( new NamedValueCollection_Impl ) - { - *this = _rCopySource; - } - - NamedValueCollection::NamedValueCollection(NamedValueCollection&& _rCopySource) noexcept - :m_pImpl( std::move(_rCopySource.m_pImpl) ) - { - } - - NamedValueCollection& NamedValueCollection::operator=( const NamedValueCollection& i_rCopySource ) - { - m_pImpl->aValues = i_rCopySource.m_pImpl->aValues; - return *this; - } - - NamedValueCollection& NamedValueCollection::operator=(NamedValueCollection&& i_rCopySource) noexcept - { - m_pImpl = std::move(i_rCopySource.m_pImpl); - return *this; - } - NamedValueCollection::NamedValueCollection( const Any& _rElements ) - :m_pImpl( new NamedValueCollection_Impl ) { impl_assign( _rElements ); } NamedValueCollection::NamedValueCollection( const Sequence< Any >& _rArguments ) - :m_pImpl( new NamedValueCollection_Impl ) { impl_assign( _rArguments ); } NamedValueCollection::NamedValueCollection( const Sequence< PropertyValue >& _rArguments ) - :m_pImpl( new NamedValueCollection_Impl ) { impl_assign( _rArguments ); } NamedValueCollection::NamedValueCollection( const Sequence< NamedValue >& _rArguments ) - :m_pImpl( new NamedValueCollection_Impl ) { impl_assign( _rArguments ); } - NamedValueCollection::~NamedValueCollection() - { - } - - bool NamedValueCollection::canExtractFrom( css::uno::Any const & i_value ) { Type const & aValueType = i_value.getValueType(); @@ -126,7 +80,7 @@ namespace comphelper NamedValueCollection& NamedValueCollection::merge( const NamedValueCollection& _rAdditionalValues, bool _bOverwriteExisting ) { - for (auto const& value : _rAdditionalValues.m_pImpl->aValues) + for (auto const& value : _rAdditionalValues.maValues) { if ( _bOverwriteExisting || !impl_has( value.first ) ) impl_put( value.first, value.second ); @@ -138,20 +92,20 @@ namespace comphelper size_t NamedValueCollection::size() const { - return m_pImpl->aValues.size(); + return maValues.size(); } bool NamedValueCollection::empty() const { - return m_pImpl->aValues.empty(); + return maValues.empty(); } std::vector< OUString > NamedValueCollection::getNames() const { std::vector< OUString > aNames; - for (auto const& value : m_pImpl->aValues) + for (auto const& value : maValues) { aNames.push_back( value.first ); } @@ -181,10 +135,7 @@ namespace comphelper void NamedValueCollection::impl_assign( const Sequence< Any >& _rArguments ) { - { - NamedValueRepository aEmpty; - m_pImpl->aValues.swap( aEmpty ); - } + maValues.clear(); PropertyValue aPropertyValue; NamedValue aNamedValue; @@ -192,9 +143,9 @@ namespace comphelper for ( auto const & argument : _rArguments ) { if ( argument >>= aPropertyValue ) - m_pImpl->aValues[ aPropertyValue.Name ] = aPropertyValue.Value; + maValues[ aPropertyValue.Name ] = aPropertyValue.Value; else if ( argument >>= aNamedValue ) - m_pImpl->aValues[ aNamedValue.Name ] = aNamedValue.Value; + maValues[ aNamedValue.Name ] = aNamedValue.Value; else { SAL_WARN_IF( @@ -209,101 +160,133 @@ namespace comphelper void NamedValueCollection::impl_assign( const Sequence< PropertyValue >& _rArguments ) { - { - NamedValueRepository aEmpty; - m_pImpl->aValues.swap( aEmpty ); - } + maValues.clear(); for ( auto const & argument : _rArguments ) - m_pImpl->aValues[ argument.Name ] = argument.Value; + maValues[ argument.Name ] = argument.Value; } void NamedValueCollection::impl_assign( const Sequence< NamedValue >& _rArguments ) { - { - NamedValueRepository aEmpty; - m_pImpl->aValues.swap( aEmpty ); - } + maValues.clear(); for ( auto const & argument : _rArguments ) - m_pImpl->aValues[ argument.Name ] = argument.Value; + maValues[ argument.Name ] = argument.Value; } bool NamedValueCollection::get_ensureType( const OUString& _rValueName, void* _pValueLocation, const Type& _rExpectedValueType ) const { - NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName ); - if ( pos != m_pImpl->aValues.end() ) + auto pos = maValues.find( _rValueName ); + if ( pos == maValues.end() ) + // argument does not exist + return false; + + if ( uno_type_assignData( + _pValueLocation, _rExpectedValueType.getTypeLibType(), + const_cast< void* >( pos->second.getValue() ), pos->second.getValueType().getTypeLibType(), + reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ), + reinterpret_cast< uno_AcquireFunc >( cpp_acquire ), + reinterpret_cast< uno_ReleaseFunc >( cpp_release ) + ) ) + // argument exists, and could be extracted + return true; + + // argument exists, but is of wrong type + throw IllegalArgumentException( + "Invalid value type for '" + _rValueName + + "'.\nExpected: " + _rExpectedValueType.getTypeName() + + "\nFound: " + pos->second.getValueType().getTypeName(), + nullptr, 0 ); + } + + // static + bool NamedValueCollection::get_ensureType( const css::uno::Sequence<css::beans::PropertyValue>& rPropSeq, + std::u16string_view _rValueName, void* _pValueLocation, const Type& _rExpectedValueType ) + { + for (const css::beans::PropertyValue& rPropVal : rPropSeq) { - if ( uno_type_assignData( - _pValueLocation, _rExpectedValueType.getTypeLibType(), - const_cast< void* >( pos->second.getValue() ), pos->second.getValueType().getTypeLibType(), - reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ), - reinterpret_cast< uno_AcquireFunc >( cpp_acquire ), - reinterpret_cast< uno_ReleaseFunc >( cpp_release ) - ) ) - // argument exists, and could be extracted - return true; - - // argument exists, but is of wrong type - throw IllegalArgumentException( - "Invalid value type for '" + _rValueName - + "'.\nExpected: " + _rExpectedValueType.getTypeName() - + "\nFound: " + pos->second.getValueType().getTypeName(), - nullptr, 0 ); + if (rPropVal.Name == _rValueName) + { + if ( uno_type_assignData( + _pValueLocation, _rExpectedValueType.getTypeLibType(), + const_cast< void* >( rPropVal.Value.getValue() ), rPropVal.Value.getValueType().getTypeLibType(), + reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ), + reinterpret_cast< uno_AcquireFunc >( cpp_acquire ), + reinterpret_cast< uno_ReleaseFunc >( cpp_release ) + ) ) + // argument exists, and could be extracted + return true; + + // argument exists, but is of wrong type + throw IllegalArgumentException( + OUString::Concat("Invalid value type for '") + _rValueName + + "'.\nExpected: " + _rExpectedValueType.getTypeName() + + "\nFound: " + rPropVal.Value.getValueType().getTypeName(), + nullptr, 0 ); + } } - // argument does not exist return false; } - namespace + // static + const css::uno::Any& NamedValueCollection::get( const css::uno::Sequence<css::beans::PropertyValue>& rPropSeq, + std::u16string_view _rValueName ) { - class theEmptyDefault : public rtl::Static<Any, theEmptyDefault> {}; + static const Any theEmptyDefault; + for (const css::beans::PropertyValue& rPropVal : rPropSeq) + { + if (rPropVal.Name == _rValueName) + { + return rPropVal.Value; + } + } + return theEmptyDefault; } - const Any& NamedValueCollection::impl_get( const OUString& _rValueName ) const { - NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName ); - if ( pos != m_pImpl->aValues.end() ) + static const Any theEmptyDefault; + auto pos = maValues.find( _rValueName ); + if ( pos != maValues.end() ) return pos->second; - return theEmptyDefault::get(); + return theEmptyDefault; } bool NamedValueCollection::impl_has( const OUString& _rValueName ) const { - NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName ); - return ( pos != m_pImpl->aValues.end() ); + auto pos = maValues.find( _rValueName ); + return ( pos != maValues.end() ); } bool NamedValueCollection::impl_put( const OUString& _rValueName, const Any& _rValue ) { bool bHas = impl_has( _rValueName ); - m_pImpl->aValues[ _rValueName ] = _rValue; + maValues[ _rValueName ] = _rValue; return bHas; } bool NamedValueCollection::impl_remove( const OUString& _rValueName ) { - NamedValueRepository::iterator pos = m_pImpl->aValues.find( _rValueName ); - if ( pos == m_pImpl->aValues.end() ) + auto pos = maValues.find( _rValueName ); + if ( pos == maValues.end() ) return false; - m_pImpl->aValues.erase( pos ); + maValues.erase( pos ); return true; } sal_Int32 NamedValueCollection::operator >>= ( Sequence< PropertyValue >& _out_rValues ) const { - _out_rValues.realloc( m_pImpl->aValues.size() ); - std::transform( m_pImpl->aValues.begin(), m_pImpl->aValues.end(), _out_rValues.getArray(), - [](const NamedValueRepository::value_type& _rValue) + _out_rValues.realloc( maValues.size() ); + std::transform( maValues.begin(), maValues.end(), _out_rValues.getArray(), + [](const std::pair< OUString, css::uno::Any >& _rValue) { return PropertyValue( _rValue.first, 0, _rValue.second, PropertyState_DIRECT_VALUE ); } ); return _out_rValues.getLength(); } @@ -311,9 +294,9 @@ namespace comphelper sal_Int32 NamedValueCollection::operator >>= ( Sequence< NamedValue >& _out_rValues ) const { - _out_rValues.realloc( m_pImpl->aValues.size() ); - std::transform( m_pImpl->aValues.begin(), m_pImpl->aValues.end(), _out_rValues.getArray(), - [](const NamedValueRepository::value_type& _rValue) + _out_rValues.realloc( maValues.size() ); + std::transform( maValues.begin(), maValues.end(), _out_rValues.getArray(), + [](const std::pair< OUString, css::uno::Any >& _rValue) { return NamedValue( _rValue.first, _rValue.second ); } ); return _out_rValues.getLength(); } diff --git a/comphelper/source/misc/numberedcollection.cxx b/comphelper/source/misc/numberedcollection.cxx index c4ed3319d5c2..e47c30ee0a32 100644 --- a/comphelper/source/misc/numberedcollection.cxx +++ b/comphelper/source/misc/numberedcollection.cxx @@ -24,14 +24,10 @@ namespace comphelper{ -const char ERRMSG_INVALID_COMPONENT_PARAM[] = "NULL as component reference not allowed."; +constexpr OUString ERRMSG_INVALID_COMPONENT_PARAM = u"NULL as component reference not allowed."_ustr; NumberedCollection::NumberedCollection() - : ::cppu::BaseMutex () - , m_sUntitledPrefix () - , m_lComponents () - , m_xOwner () { } @@ -44,7 +40,7 @@ NumberedCollection::~NumberedCollection() void NumberedCollection::setOwner(const css::uno::Reference< css::uno::XInterface >& xOwner) { // SYNCHRONIZED -> - osl::MutexGuard aLock(m_aMutex); + std::scoped_lock aLock(m_aMutex); m_xOwner = xOwner; @@ -55,7 +51,7 @@ void NumberedCollection::setOwner(const css::uno::Reference< css::uno::XInterfac void NumberedCollection::setUntitledPrefix(const OUString& sPrefix) { // SYNCHRONIZED -> - osl::MutexGuard aLock(m_aMutex); + std::scoped_lock aLock(m_aMutex); m_sUntitledPrefix = sPrefix; @@ -66,7 +62,7 @@ void NumberedCollection::setUntitledPrefix(const OUString& sPrefix) ::sal_Int32 SAL_CALL NumberedCollection::leaseNumber(const css::uno::Reference< css::uno::XInterface >& xComponent) { // SYNCHRONIZED -> - osl::MutexGuard aLock(m_aMutex); + std::scoped_lock aLock(m_aMutex); if ( ! xComponent.is ()) throw css::lang::IllegalArgumentException(ERRMSG_INVALID_COMPONENT_PARAM, m_xOwner.get(), 1); @@ -101,10 +97,10 @@ void NumberedCollection::setUntitledPrefix(const OUString& sPrefix) void SAL_CALL NumberedCollection::releaseNumber(::sal_Int32 nNumber) { // SYNCHRONIZED -> - osl::MutexGuard aLock(m_aMutex); + std::scoped_lock aLock(m_aMutex); if (nNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER) - throw css::lang::IllegalArgumentException ("Special valkud INVALID_NUMBER not allowed as input parameter.", m_xOwner.get(), 1); + throw css::lang::IllegalArgumentException (u"Special value INVALID_NUMBER not allowed as input parameter."_ustr, m_xOwner.get(), 1); TDeadItemList lDeadItems; TNumberedItemHash::iterator pComponent; @@ -138,7 +134,7 @@ void SAL_CALL NumberedCollection::releaseNumber(::sal_Int32 nNumber) void SAL_CALL NumberedCollection::releaseNumberForComponent(const css::uno::Reference< css::uno::XInterface >& xComponent) { // SYNCHRONIZED -> - osl::MutexGuard aLock(m_aMutex); + std::scoped_lock aLock(m_aMutex); if ( ! xComponent.is ()) throw css::lang::IllegalArgumentException(ERRMSG_INVALID_COMPONENT_PARAM, m_xOwner.get(), 1); @@ -160,7 +156,7 @@ void SAL_CALL NumberedCollection::releaseNumberForComponent(const css::uno::Refe OUString SAL_CALL NumberedCollection::getUntitledPrefix() { // SYNCHRONIZED -> - osl::MutexGuard aLock(m_aMutex); + std::scoped_lock aLock(m_aMutex); return m_sUntitledPrefix; @@ -182,54 +178,31 @@ 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 , const TDeadItemList& lDeadItems) { - for (const long& rDeadItem : lDeadItems) + for (const sal_IntPtr& rDeadItem : lDeadItems) { lItems.erase(rDeadItem); } diff --git a/comphelper/source/misc/numbers.cxx b/comphelper/source/misc/numbers.cxx index f3b609392ceb..9bff08c79ae7 100644 --- a/comphelper/source/misc/numbers.cxx +++ b/comphelper/source/misc/numbers.cxx @@ -37,7 +37,7 @@ sal_Int16 getNumberFormatType(const css::uno::Reference<css::util::XNumberFormat { css::uno::Reference<css::beans::XPropertySet> xFormat(xFormats->getByKey(nKey)); if (xFormat.is()) - xFormat->getPropertyValue("Type") >>= nReturn; + xFormat->getPropertyValue(u"Type"_ustr) >>= nReturn; } catch(...) { @@ -67,7 +67,7 @@ css::uno::Any getNumberFormatDecimals(const css::uno::Reference<css::util::XNumb css::uno::Reference<css::beans::XPropertySet> xFormat( xFormats->getByKey(nKey)); if (xFormat.is()) { - return xFormat->getPropertyValue( "Decimals" ); + return xFormat->getPropertyValue( u"Decimals"_ustr ); } } catch(...) diff --git a/comphelper/source/misc/officerestartmanager.cxx b/comphelper/source/misc/officerestartmanager.cxx index f56486858522..95110c75a7ab 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(u"no component context"_ustr); { - ::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 ) @@ -61,7 +60,7 @@ void SAL_CALL OOfficeRestartManager::requestRestart( const uno::Reference< task: uno::Reference< awt::XRequestCallback > xRequestCallback( xFactory->createInstanceWithContext( - "com.sun.star.awt.AsyncCallback", + u"com.sun.star.awt.AsyncCallback"_ustr, m_xContext ), uno::UNO_QUERY_THROW ); @@ -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; @@ -99,7 +98,7 @@ void SAL_CALL OOfficeRestartManager::notify( const uno::Any& /* aData */ ) // Turn Quickstarter veto off uno::Reference< beans::XPropertySet > xPropertySet( xDesktop, uno::UNO_QUERY_THROW ); - OUString aVetoPropName( "SuspendQuickstartVeto" ); + OUString aVetoPropName( u"SuspendQuickstartVeto"_ustr ); uno::Any aValue; aValue <<= true; xPropertySet->setPropertyValue( aVetoPropName, aValue ); @@ -131,7 +130,7 @@ void SAL_CALL OOfficeRestartManager::notify( const uno::Any& /* aData */ ) OUString SAL_CALL OOfficeRestartManager::getImplementationName() { - return "com.sun.star.comp.task.OfficeRestartManager"; + return u"com.sun.star.comp.task.OfficeRestartManager"_ustr; } sal_Bool SAL_CALL OOfficeRestartManager::supportsService( const OUString& aServiceName ) @@ -141,36 +140,18 @@ sal_Bool SAL_CALL OOfficeRestartManager::supportsService( const OUString& aServi uno::Sequence< OUString > SAL_CALL OOfficeRestartManager::getSupportedServiceNames() { - return { "com.sun.star.comp.task.OfficeRestartManager" }; + return { u"com.sun.star.comp.task.OfficeRestartManager"_ustr }; } } // namespace comphelper -namespace { - -struct Instance { - explicit Instance( - css::uno::Reference<css::uno::XComponentContext> const & context): - instance(static_cast<cppu::OWeakObject *>(new comphelper::OOfficeRestartManager(context))) - {} - - rtl::Reference<css::uno::XInterface> instance; -}; - -struct Singleton: - public rtl::StaticWithArg< - Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton> -{}; - -} extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_task_OfficeRestartManager( css::uno::XComponentContext *context, css::uno::Sequence<css::uno::Any> const &) { - return cppu::acquire(static_cast<cppu::OWeakObject *>( - Singleton::get(context).instance.get())); + return cppu::acquire(new comphelper::OOfficeRestartManager(context)); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/officerestartmanager.hxx b/comphelper/source/misc/officerestartmanager.hxx index 865fc29b23b3..ecf59c543270 100644 --- a/comphelper/source/misc/officerestartmanager.hxx +++ b/comphelper/source/misc/officerestartmanager.hxx @@ -17,15 +17,16 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_COMPHELPER_SOURCE_MISC_OFFICERESTARTMANAGER_HXX -#define INCLUDED_COMPHELPER_SOURCE_MISC_OFFICERESTARTMANAGER_HXX +#pragma once #include <com/sun/star/task/XRestartManager.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> #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 ) {} @@ -63,6 +64,4 @@ public: } // namespace comphelper -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/profilezone.cxx b/comphelper/source/misc/profilezone.cxx deleted file mode 100644 index 5abcca8a80b3..000000000000 --- a/comphelper/source/misc/profilezone.cxx +++ /dev/null @@ -1,113 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include <sal/config.h> - -#include <atomic> -#include <iostream> - -#include <comphelper/sequence.hxx> -#include <comphelper/profilezone.hxx> -#include <osl/time.h> -#include <osl/thread.h> - -namespace comphelper -{ - -std::atomic<bool> ProfileZone::g_bRecording(false); - -namespace ProfileRecording -{ - -static std::vector<OUString> g_aRecording; // recorded data -static long long g_aSumTime(0); // overall zone time in microsec -static int g_aNesting; // level of overlapped zones -static long long g_aStartTime; // start time of recording -static ::osl::Mutex g_aMutex; - -void startRecording(bool bStartRecording) -{ - if (bStartRecording) - { - TimeValue systemTime; - osl_getSystemTime( &systemTime ); - ::osl::MutexGuard aGuard( g_aMutex ); - g_aStartTime = static_cast<long long>(systemTime.Seconds) * 1000000 + systemTime.Nanosec/1000; - g_aNesting = 0; - } - ProfileZone::g_bRecording = bStartRecording; -} - -long long addRecording(const char * aProfileId, long long aCreateTime) -{ - assert( ProfileZone::g_bRecording ); - - TimeValue systemTime; - osl_getSystemTime( &systemTime ); - long long aTime = static_cast<long long>(systemTime.Seconds) * 1000000 + systemTime.Nanosec/1000; - - if (!aProfileId) - aProfileId = "(null)"; - OUString aString(aProfileId, strlen(aProfileId), RTL_TEXTENCODING_UTF8); - - OUString sRecordingData(OUString::number(osl_getThreadIdentifier(nullptr)) + " " + - OUString::number(aTime/1000000.0) + " " + aString + ": " + - (aCreateTime == 0 ? OUStringLiteral("start") : OUStringLiteral("stop")) + - (aCreateTime != 0 ? (" " + OUString::number((aTime - aCreateTime)/1000.0) + " ms") : OUString(""))); - - ::osl::MutexGuard aGuard( g_aMutex ); - - g_aRecording.emplace_back(sRecordingData); - if (aCreateTime == 0) - { - g_aNesting++; - return aTime; - } - // neglect ProfileZones created before startRecording - else if (aCreateTime >= g_aStartTime) - { - if (g_aNesting > 0) - g_aNesting--; - if (g_aNesting == 0) - g_aSumTime += aTime - aCreateTime; - } - return 0; -} - -css::uno::Sequence<OUString> getRecordingAndClear() -{ - bool bRecording; - std::vector<OUString> aRecording; - { - ::osl::MutexGuard aGuard( g_aMutex ); - bRecording = ProfileZone::g_bRecording; - startRecording(false); - aRecording.swap(g_aRecording); - long long aSumTime = g_aSumTime; - aRecording.insert(aRecording.begin(), OUString::number(aSumTime/1000000.0)); - } - // reset start time and nesting level - startRecording(bRecording); - return ::comphelper::containerToSequence(aRecording); -} - -} // namespace ProfileRecording - -void ProfileZone::startConsole() { m_aCreateTime = osl_getGlobalTimer(); } - -void ProfileZone::stopConsole() -{ - sal_uInt32 nEndTime = osl_getGlobalTimer(); - std::cerr << "comphelper::ProfileZone: " << m_sProfileId << " finished in " - << nEndTime - m_aCreateTime << " ms" << std::endl; -} - -} // namespace comphelper - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/proxyaggregation.cxx b/comphelper/source/misc/proxyaggregation.cxx index 5efb0f211f76..db580bea496c 100644 --- a/comphelper/source/misc/proxyaggregation.cxx +++ b/comphelper/source/misc/proxyaggregation.cxx @@ -110,7 +110,7 @@ namespace comphelper m_xInner = _rxComponent; // aggregate a proxy for the object - baseAggregateProxyFor( m_xInner.get(), _rRefCount, _rDelegator ); + baseAggregateProxyFor( m_xInner, _rRefCount, _rDelegator ); // add as event listener to the inner context, because we want to be notified of disposals osl_atomic_increment( &_rRefCount ); diff --git a/comphelper/source/misc/random.cxx b/comphelper/source/misc/random.cxx index 260db3a544ca..96d466641dfb 100644 --- a/comphelper/source/misc/random.cxx +++ b/comphelper/source/misc/random.cxx @@ -11,7 +11,6 @@ */ #include <comphelper/random.hxx> -#include <rtl/instance.hxx> #include <sal/log.hxx> #include <assert.h> #include <time.h> @@ -27,24 +26,24 @@ namespace comphelper::rng { - // underlying random number generator // std::mt19937 implements the Mersenne twister algorithm which // is fast and has good statistical properties, it produces integers // in the range of [0, 2^32-1] internally // memory requirement: 625*sizeof(uint32_t) // http://en.wikipedia.org/wiki/Mersenne_twister -#define STD_RNG_ALGO std::mt19937 - -namespace { +#define STD_RNG_ALGO std::mt19937 +namespace +{ struct RandomNumberGenerator { std::mutex mutex; STD_RNG_ALGO global_rng; RandomNumberGenerator() { - bool bRepeatable = (getenv("SAL_RAND_REPEATABLE") != nullptr); + // make RR easier to use, breaks easily without the RNG being repeatable + bool bRepeatable = (getenv("SAL_RAND_REPEATABLE") != nullptr) || (getenv("RR") != nullptr); // valgrind on some platforms (e.g.Ubuntu16.04) does not support the new Intel RDRAND instructions, // which leads to "Illegal Opcode" errors, so just turn off randomness. #if defined HAVE_VALGRIND_HEADERS @@ -75,15 +74,18 @@ struct RandomNumberGenerator } }; -class theRandomNumberGenerator : public rtl::Static<RandomNumberGenerator, theRandomNumberGenerator> {}; - +RandomNumberGenerator& GetTheRandomNumberGenerator() +{ + static RandomNumberGenerator RANDOM; + return RANDOM; +} } // uniform ints [a,b] distribution int uniform_int_distribution(int a, int b) { std::uniform_int_distribution<int> dist(a, b); - auto & gen = theRandomNumberGenerator::get(); + auto& gen = GetTheRandomNumberGenerator(); std::scoped_lock<std::mutex> g(gen.mutex); return dist(gen.global_rng); } @@ -92,7 +94,7 @@ int uniform_int_distribution(int a, int b) unsigned int uniform_uint_distribution(unsigned int a, unsigned int b) { std::uniform_int_distribution<unsigned int> dist(a, b); - auto & gen = theRandomNumberGenerator::get(); + auto& gen = GetTheRandomNumberGenerator(); std::scoped_lock<std::mutex> g(gen.mutex); return dist(gen.global_rng); } @@ -101,7 +103,7 @@ unsigned int uniform_uint_distribution(unsigned int a, unsigned int b) size_t uniform_size_distribution(size_t a, size_t b) { std::uniform_int_distribution<size_t> dist(a, b); - auto & gen = theRandomNumberGenerator::get(); + auto& gen = GetTheRandomNumberGenerator(); std::scoped_lock<std::mutex> g(gen.mutex); return dist(gen.global_rng); } @@ -111,7 +113,7 @@ double uniform_real_distribution(double a, double b) { assert(a < b); std::uniform_real_distribution<double> dist(a, b); - auto & gen = theRandomNumberGenerator::get(); + auto& gen = GetTheRandomNumberGenerator(); std::scoped_lock<std::mutex> g(gen.mutex); return dist(gen.global_rng); } diff --git a/comphelper/source/misc/sequenceashashmap.cxx b/comphelper/source/misc/sequenceashashmap.cxx index eb78e60c55d2..ba4955e09780 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{ @@ -76,7 +149,7 @@ void SequenceAsHashMap::operator<<(const css::uno::Any& aSource) } throw css::lang::IllegalArgumentException( - "Any contains wrong type.", css::uno::Reference<css::uno::XInterface>(), + u"Any contains wrong type."_ustr, css::uno::Reference<css::uno::XInterface>(), -1); } @@ -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; @@ -96,7 +170,7 @@ void SequenceAsHashMap::operator<<(const css::uno::Sequence< css::uno::Any >& lS (!lP.Value.hasValue()) ) throw css::lang::IllegalArgumentException( - "PropertyValue struct contains no useful information.", + u"PropertyValue struct contains no useful information."_ustr, css::uno::Reference<css::uno::XInterface>(), -1); (*this)[lP.Name] = lP.Value; continue; @@ -110,7 +184,7 @@ void SequenceAsHashMap::operator<<(const css::uno::Sequence< css::uno::Any >& lS (!lN.Value.hasValue()) ) throw css::lang::IllegalArgumentException( - "NamedValue struct contains no useful information.", + u"NamedValue struct contains no useful information."_ustr, css::uno::Reference<css::uno::XInterface>(), -1); (*this)[lN.Name] = lN.Value; continue; @@ -119,7 +193,7 @@ void SequenceAsHashMap::operator<<(const css::uno::Sequence< css::uno::Any >& lS // ignore VOID Any ... but reject wrong filled ones! if (lSource[i].hasValue()) throw css::lang::IllegalArgumentException( - "Any contains wrong type.", + u"Any contains wrong type."_ustr, css::uno::Reference<css::uno::XInterface>(), -1); } } @@ -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 aaf9d280e7b7..8cd77af7d693 100644 --- a/comphelper/source/misc/simplefileaccessinteraction.cxx +++ b/comphelper/source/misc/simplefileaccessinteraction.cxx @@ -16,8 +16,8 @@ #include <com/sun/star/ucb/InteractiveNetworkException.hpp> #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> -namespace comphelper { - +namespace comphelper +{ /// Will handle com::sun::star::ucb::InteractiveIOException and derived classes const sal_Int32 HANDLE_INTERACTIVEIOEXCEPTION = 0; /// Will handle com::sun::star::ucb::UnsupportedDataSinkException @@ -30,55 +30,41 @@ const sal_Int32 HANDLE_CERTIFICATEREQUEST = 3; const sal_Int32 HANDLE_AUTHENTICATIONREQUEST = 4; SimpleFileAccessInteraction::SimpleFileAccessInteraction( - const css::uno::Reference< css::task::XInteractionHandler >& xHandler ) + const css::uno::Reference<css::task::XInteractionHandler>& xHandler) { - std::vector< ::ucbhelper::InterceptedInteraction::InterceptedRequest > lInterceptions; - ::ucbhelper::InterceptedInteraction::InterceptedRequest aInterceptedRequest; - - //intercept standard IO error exception (local file and WebDAV) - aInterceptedRequest.Handle = HANDLE_INTERACTIVEIOEXCEPTION; - aInterceptedRequest.Request <<= css::ucb::InteractiveIOException(); - aInterceptedRequest.Continuation = cppu::UnoType<css::task::XInteractionAbort>::get(); - lInterceptions.push_back(aInterceptedRequest); - - //intercept internal error - aInterceptedRequest.Handle = HANDLE_UNSUPPORTEDDATASINKEXCEPTION; - aInterceptedRequest.Request <<= css::ucb::UnsupportedDataSinkException(); - aInterceptedRequest.Continuation = cppu::UnoType<css::task::XInteractionAbort>::get(); - lInterceptions.push_back(aInterceptedRequest); - - //intercept network error exception (WebDAV ucp provider) - aInterceptedRequest.Handle = HANDLE_INTERACTIVENETWORKEXCEPTION; - aInterceptedRequest.Request <<= css::ucb::InteractiveNetworkException(); - aInterceptedRequest.Continuation = cppu::UnoType<css::task::XInteractionAbort>::get(); - lInterceptions.push_back(aInterceptedRequest); - - //intercept certificate validation request (WebDAV ucp provider) - aInterceptedRequest.Handle = HANDLE_CERTIFICATEREQUEST; - aInterceptedRequest.Request <<= css::ucb::CertificateValidationRequest(); - aInterceptedRequest.Continuation = cppu::UnoType<css::task::XInteractionAbort>::get(); - lInterceptions.push_back(aInterceptedRequest); - - //intercept authentication request (WebDAV ucp provider) - aInterceptedRequest.Handle = HANDLE_AUTHENTICATIONREQUEST; - aInterceptedRequest.Request <<= css::ucb::AuthenticationRequest(); - aInterceptedRequest.Continuation = cppu::UnoType<css::task::XInteractionApprove>::get(); - lInterceptions.push_back(aInterceptedRequest); + std::vector<::ucbhelper::InterceptedInteraction::InterceptedRequest> lInterceptions{ + { //intercept standard IO error exception (local file and WebDAV) + css::uno::Any(css::ucb::InteractiveIOException()), + cppu::UnoType<css::task::XInteractionAbort>::get(), HANDLE_INTERACTIVEIOEXCEPTION }, + { //intercept internal error + css::uno::Any(css::ucb::UnsupportedDataSinkException()), + cppu::UnoType<css::task::XInteractionAbort>::get(), HANDLE_UNSUPPORTEDDATASINKEXCEPTION }, + { + //intercept network error exception (WebDAV ucp provider) + css::uno::Any(css::ucb::InteractiveNetworkException()), + cppu::UnoType<css::task::XInteractionAbort>::get(), + HANDLE_INTERACTIVENETWORKEXCEPTION, + }, + { //intercept certificate validation request (WebDAV ucp provider) + css::uno::Any(css::ucb::CertificateValidationRequest()), + cppu::UnoType<css::task::XInteractionAbort>::get(), HANDLE_CERTIFICATEREQUEST }, + { //intercept authentication request (WebDAV ucp provider) + css::uno::Any(css::ucb::AuthenticationRequest()), + cppu::UnoType<css::task::XInteractionApprove>::get(), HANDLE_AUTHENTICATIONREQUEST } + }; setInterceptedHandler(xHandler); - setInterceptions(lInterceptions); + setInterceptions(std::move(lInterceptions)); } -SimpleFileAccessInteraction::~SimpleFileAccessInteraction() -{ -} +SimpleFileAccessInteraction::~SimpleFileAccessInteraction() {} ucbhelper::InterceptedInteraction::EInterceptionState SimpleFileAccessInteraction::intercepted( const ::ucbhelper::InterceptedInteraction::InterceptedRequest& aRequest, - const css::uno::Reference< css::task::XInteractionRequest >& xRequest) + const css::uno::Reference<css::task::XInteractionRequest>& xRequest) { bool bAbort = false; - switch(aRequest.Handle) + switch (aRequest.Handle) { case HANDLE_UNSUPPORTEDDATASINKEXCEPTION: case HANDLE_INTERACTIVENETWORKEXCEPTION: @@ -119,10 +105,9 @@ ucbhelper::InterceptedInteraction::EInterceptionState SimpleFileAccessInteractio // any selection... if (bAbort) { - css::uno::Reference< css::task::XInteractionContinuation > xAbort = - ::ucbhelper::InterceptedInteraction::extractContinuation( - xRequest->getContinuations(), - cppu::UnoType<css::task::XInteractionAbort>::get() ); + css::uno::Reference<css::task::XInteractionContinuation> xAbort + = ::ucbhelper::InterceptedInteraction::extractContinuation( + xRequest->getContinuations(), cppu::UnoType<css::task::XInteractionAbort>::get()); if (!xAbort.is()) return ::ucbhelper::InterceptedInteraction::E_NO_CONTINUATION_FOUND; return ::ucbhelper::InterceptedInteraction::E_INTERCEPTED; diff --git a/comphelper/source/misc/solarmutex.cxx b/comphelper/source/misc/solarmutex.cxx index 5d1052327154..3e45ae14582d 100644 --- a/comphelper/source/misc/solarmutex.cxx +++ b/comphelper/source/misc/solarmutex.cxx @@ -38,7 +38,6 @@ SolarMutex *SolarMutex::get() SolarMutex::SolarMutex() : m_nCount( 0 ) - , m_nThreadId( 0 ) , m_aBeforeReleaseHandler( nullptr ) { assert(!g_pSolarMutex); @@ -54,7 +53,7 @@ void SolarMutex::doAcquire( const sal_uInt32 nLockCount ) { for ( sal_uInt32 n = nLockCount; n ; --n ) m_aMutex.acquire(); - m_nThreadId = osl::Thread::getCurrentIdentifier(); + m_nThreadId = std::this_thread::get_id(); m_nCount += nLockCount; } @@ -72,7 +71,7 @@ sal_uInt32 SolarMutex::doRelease( bool bUnlockAll ) { if ( m_aBeforeReleaseHandler ) m_aBeforeReleaseHandler(); - m_nThreadId = 0; + m_nThreadId = std::thread::id(); } for ( sal_uInt32 n = nCount ; n ; --n ) @@ -83,14 +82,14 @@ sal_uInt32 SolarMutex::doRelease( bool bUnlockAll ) bool SolarMutex::IsCurrentThread() const { - return m_nThreadId == osl::Thread::getCurrentIdentifier(); + return m_nThreadId == std::this_thread::get_id(); } bool SolarMutex::tryToAcquire() { if ( m_aMutex.tryToAcquire() ) { - m_nThreadId = osl::Thread::getCurrentIdentifier(); + m_nThreadId = std::this_thread::get_id(); m_nCount++; return true; } diff --git a/comphelper/source/misc/stillreadwriteinteraction.cxx b/comphelper/source/misc/stillreadwriteinteraction.cxx index 0efec31b160b..88bc25bc46cb 100644 --- a/comphelper/source/misc/stillreadwriteinteraction.cxx +++ b/comphelper/source/misc/stillreadwriteinteraction.cxx @@ -30,16 +30,18 @@ #include <com/sun/star/ucb/AuthenticationRequest.hpp> #include <com/sun/star/ucb/CertificateValidationRequest.hpp> +#include <utility> namespace comphelper{ StillReadWriteInteraction::StillReadWriteInteraction(const css::uno::Reference< css::task::XInteractionHandler >& xHandler, - const css::uno::Reference< css::task::XInteractionHandler >& xAuxiliaryHandler) + css::uno::Reference< css::task::XInteractionHandler > xAuxiliaryHandler) : m_bUsed (false) , m_bHandledByMySelf (false) - , m_xAuxiliaryHandler(xAuxiliaryHandler) + , m_xAuxiliaryHandler(std::move(xAuxiliaryHandler)) { std::vector< ::ucbhelper::InterceptedInteraction::InterceptedRequest > lInterceptions; + lInterceptions.reserve(4); ::ucbhelper::InterceptedInteraction::InterceptedRequest aInterceptedRequest; aInterceptedRequest.Handle = HANDLE_INTERACTIVEIOEXCEPTION; @@ -63,7 +65,7 @@ StillReadWriteInteraction::StillReadWriteInteraction(const css::uno::Reference< lInterceptions.push_back(aInterceptedRequest); setInterceptedHandler(xHandler); - setInterceptions(lInterceptions); + setInterceptions(std::move(lInterceptions)); } void StillReadWriteInteraction::resetInterceptions() diff --git a/comphelper/source/misc/storagehelper.cxx b/comphelper/source/misc/storagehelper.cxx index 01cec5831223..ab6f71c7c734 100644 --- a/comphelper/source/misc/storagehelper.cxx +++ b/comphelper/source/misc/storagehelper.cxx @@ -27,15 +27,13 @@ #include <com/sun/star/embed/FileSystemStorageFactory.hpp> #include <com/sun/star/io/IOException.hpp> #include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> #include <com/sun/star/ucb/SimpleFileAccess.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/beans/PropertyValue.hpp> #include <com/sun/star/beans/NamedValue.hpp> #include <com/sun/star/beans/IllegalTypeException.hpp> -#include <com/sun/star/xml/crypto/NSSInitializer.hpp> -#include <com/sun/star/xml/crypto/XDigestContext.hpp> -#include <com/sun/star/xml/crypto/DigestID.hpp> #include <com/sun/star/security/DocumentDigitalSignatures.hpp> #include <com/sun/star/security/XCertificate.hpp> @@ -48,13 +46,17 @@ #include <ucbhelper/content.hxx> +#include <comphelper/bytereader.hxx> +#include <comphelper/diagnose_ex.hxx> #include <comphelper/fileformat.h> #include <comphelper/hash.hxx> #include <comphelper/processfactory.hxx> #include <comphelper/documentconstants.hxx> +#include <comphelper/propertyvalue.hxx> #include <comphelper/storagehelper.hxx> #include <comphelper/sequence.hxx> #include <cppuhelper/exc_hlp.hxx> +#include <o3tl/string_view.hxx> #if HAVE_FEATURE_GPGME # include <context.h> @@ -98,10 +100,7 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromURL( sal_Int32 nStorageMode, const uno::Reference< uno::XComponentContext >& rxContext ) { - uno::Sequence< uno::Any > aArgs( 2 ); - aArgs[0] <<= aURL; - aArgs[1] <<= nStorageMode; - + uno::Sequence< uno::Any > aArgs{ uno::Any(aURL), uno::Any(nStorageMode) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; @@ -113,9 +112,7 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromURL2( sal_Int32 nStorageMode, const uno::Reference< uno::XComponentContext >& rxContext ) { - uno::Sequence< uno::Any > aArgs( 2 ); - aArgs[0] <<= aURL; - aArgs[1] <<= nStorageMode; + uno::Sequence< uno::Any > aArgs{ uno::Any(aURL), uno::Any(nStorageMode) }; uno::Reference< lang::XSingleServiceFactory > xFact; css::uno::Any anyEx; @@ -136,7 +133,7 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromURL2( if (!xFact.is()) { if (anyEx.hasValue()) - throw css::lang::WrappedTargetRuntimeException( "", nullptr, anyEx ); + throw css::lang::WrappedTargetRuntimeException( u""_ustr, nullptr, anyEx ); else throw uno::RuntimeException(); } @@ -151,10 +148,7 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromInputStream( const uno::Reference < io::XInputStream >& xStream, const uno::Reference< uno::XComponentContext >& rxContext ) { - uno::Sequence< uno::Any > aArgs( 2 ); - aArgs[0] <<= xStream; - aArgs[1] <<= embed::ElementModes::READ; - + uno::Sequence< uno::Any > aArgs{ uno::Any(xStream), uno::Any(embed::ElementModes::READ) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; @@ -166,10 +160,7 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageFromStream( sal_Int32 nStorageMode, const uno::Reference< uno::XComponentContext >& rxContext ) { - uno::Sequence< uno::Any > aArgs( 2 ); - aArgs[0] <<= xStream; - aArgs[1] <<= nStorageMode; - + uno::Sequence< uno::Any > aArgs{ uno::Any(xStream), uno::Any(nStorageMode) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; @@ -182,19 +173,30 @@ void OStorageHelper::CopyInputToOutput( { static const sal_Int32 nConstBufferSize = 32000; + if (auto pByteReader = dynamic_cast< comphelper::ByteReader* >( xInput.get() )) + { + if (auto pByteWriter = dynamic_cast< comphelper::ByteWriter* >( xOutput.get() )) + { + sal_Int32 nRead; + sal_Int8 aTempBuf[ nConstBufferSize ]; + do + { + nRead = pByteReader->readSomeBytes ( aTempBuf, nConstBufferSize ); + pByteWriter->writeBytes ( aTempBuf, nRead ); + } + while ( nRead == nConstBufferSize ); + return; + } + } + sal_Int32 nRead; uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize ); - do { nRead = xInput->readBytes ( aSequence, nConstBufferSize ); if ( nRead < nConstBufferSize ) - { - uno::Sequence < sal_Int8 > aTempBuf ( aSequence.getConstArray(), nRead ); - xOutput->writeBytes ( aTempBuf ); - } - else - xOutput->writeBytes ( aSequence ); + aSequence.realloc( nRead ); + xOutput->writeBytes ( aSequence ); } while ( nRead == nConstBufferSize ); } @@ -218,7 +220,7 @@ void OStorageHelper::SetCommonStorageEncryptionData( { uno::Reference< embed::XEncryptionProtectedStorage > xEncrSet( xStorage, uno::UNO_QUERY ); if ( !xEncrSet.is() ) - throw io::IOException(); // TODO + throw io::IOException(u"no XEncryptionProtectedStorage"_ustr); // TODO if ( aEncryptionData.getLength() == 2 && aEncryptionData[0].Name == "GpgInfos" && @@ -240,7 +242,7 @@ sal_Int32 OStorageHelper::GetXStorageFormat( uno::Reference< beans::XPropertySet > xStorProps( xStorage, uno::UNO_QUERY_THROW ); OUString aMediaType; - xStorProps->getPropertyValue("MediaType") >>= aMediaType; + xStorProps->getPropertyValue(u"MediaType"_ustr) >>= aMediaType; sal_Int32 nResult = 0; @@ -284,8 +286,8 @@ sal_Int32 OStorageHelper::GetXStorageFormat( else { // the mediatype is not known - OUString aMsg = OUStringLiteral(OSL_THIS_FUNC) - + ":" + OUString aMsg = __func__ + + OUString::Concat(u":") + OUString::number(__LINE__) + ": unknown media type '" + aMediaType @@ -303,15 +305,10 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromURL( sal_Int32 nStorageMode, const uno::Reference< uno::XComponentContext >& rxContext ) { - uno::Sequence< beans::PropertyValue > aProps( 1 ); - aProps[0].Name = "StorageFormat"; - aProps[0].Value <<= aFormat; - - uno::Sequence< uno::Any > aArgs( 3 ); - aArgs[0] <<= aURL; - aArgs[1] <<= nStorageMode; - aArgs[2] <<= aProps; + uno::Sequence< beans::PropertyValue > aProps{ comphelper::makePropertyValue(u"StorageFormat"_ustr, + aFormat) }; + uno::Sequence< uno::Any > aArgs{ uno::Any(aURL), uno::Any(nStorageMode), uno::Any(aProps) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; @@ -324,24 +321,17 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromInputStr const uno::Reference< uno::XComponentContext >& rxContext, bool bRepairStorage ) { - uno::Sequence< beans::PropertyValue > aProps( 1 ); - sal_Int32 nPos = 0; - aProps[nPos].Name = "StorageFormat"; - aProps[nPos].Value <<= aFormat; - ++nPos; + uno::Sequence< beans::PropertyValue > aProps( bRepairStorage ? 2 : 1 ); + auto pProps = aProps.getArray(); + pProps[0].Name = "StorageFormat"; + pProps[0].Value <<= aFormat; if ( bRepairStorage ) { - aProps.realloc(nPos+1); - aProps[nPos].Name = "RepairPackage"; - aProps[nPos].Value <<= bRepairStorage; - ++nPos; + pProps[1].Name = "RepairPackage"; + pProps[1].Value <<= bRepairStorage; } - uno::Sequence< uno::Any > aArgs( 3 ); - aArgs[0] <<= xStream; - aArgs[1] <<= embed::ElementModes::READ; - aArgs[2] <<= aProps; - + uno::Sequence< uno::Any > aArgs{ uno::Any(xStream), uno::Any(embed::ElementModes::READ), uno::Any(aProps) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; @@ -355,65 +345,56 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromStream( const uno::Reference< uno::XComponentContext >& rxContext, bool bRepairStorage ) { - uno::Sequence< beans::PropertyValue > aProps( 1 ); - sal_Int32 nPos = 0; - aProps[nPos].Name = "StorageFormat"; - aProps[nPos].Value <<= aFormat; - ++nPos; + uno::Sequence< beans::PropertyValue > aProps( bRepairStorage ? 2 : 1 ); + auto pProps = aProps.getArray(); + pProps[0].Name = "StorageFormat"; + pProps[0].Value <<= aFormat; if ( bRepairStorage ) { - aProps.realloc(nPos+1); - aProps[nPos].Name = "RepairPackage"; - aProps[nPos].Value <<= bRepairStorage; - ++nPos; + pProps[1].Name = "RepairPackage"; + pProps[1].Value <<= bRepairStorage; } - uno::Sequence< uno::Any > aArgs( 3 ); - aArgs[0] <<= xStream; - aArgs[1] <<= nStorageMode; - aArgs[2] <<= aProps; - + uno::Sequence< uno::Any > aArgs{ uno::Any(xStream), uno::Any(nStorageMode), uno::Any(aProps) }; uno::Reference< embed::XStorage > xTempStorage( GetStorageFactory( rxContext )->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW ); return xTempStorage; } -uno::Sequence< beans::NamedValue > OStorageHelper::CreatePackageEncryptionData( const OUString& aPassword ) +uno::Sequence< beans::NamedValue > OStorageHelper::CreatePackageEncryptionData( std::u16string_view aPassword ) { // TODO/LATER: Should not the method be part of DocPasswordHelper? uno::Sequence< beans::NamedValue > aEncryptionData; - if ( !aPassword.isEmpty() ) + if ( !aPassword.empty() ) { sal_Int32 nSha1Ind = 0; // generate SHA256 start key try { - uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext(); - - uno::Reference< css::xml::crypto::XNSSInitializer > xDigestContextSupplier = css::xml::crypto::NSSInitializer::create(xContext); - uno::Reference< css::xml::crypto::XDigestContext > xDigestContext( xDigestContextSupplier->getDigestContext( css::xml::crypto::DigestID::SHA256, uno::Sequence< beans::NamedValue >() ), uno::UNO_SET_THROW ); - OString aUTF8Password( OUStringToOString( aPassword, RTL_TEXTENCODING_UTF8 ) ); - xDigestContext->updateDigest( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aUTF8Password.getStr() ), aUTF8Password.getLength() ) ); - uno::Sequence< sal_Int8 > aDigest = xDigestContext->finalizeDigestAndDispose(); + std::vector<unsigned char> const hash(comphelper::Hash::calculateHash( + reinterpret_cast<unsigned char const*>(aUTF8Password.getStr()), aUTF8Password.getLength(), + comphelper::HashType::SHA256)); + uno::Sequence<sal_Int8> aDigest(reinterpret_cast<const sal_Int8*>(hash.data()), hash.size()); - aEncryptionData.realloc( ++nSha1Ind ); - aEncryptionData[0].Name = PACKAGE_ENCRYPTIONDATA_SHA256UTF8; - aEncryptionData[0].Value <<= aDigest; + ++nSha1Ind; + aEncryptionData = { { PACKAGE_ENCRYPTIONDATA_SHA256UTF8, uno::Any(aDigest) } }; } catch ( uno::Exception& ) { - OSL_ENSURE( false, "Can not create SHA256 digest!" ); + TOOLS_WARN_EXCEPTION("comphelper", "Can not create SHA256 digest!" ); + throw; // tdf#159519 DO NOT RETURN SUCCESS } // MS_1252 encoding was used for SO60 document format password encoding, // this encoding supports only a minor subset of nonascii characters, // but for compatibility reasons it has to be used for old document formats aEncryptionData.realloc( nSha1Ind + 3 ); + auto pEncryptionData = aEncryptionData.getArray(); // these are StarOffice not-quite-SHA1 - aEncryptionData[nSha1Ind].Name = PACKAGE_ENCRYPTIONDATA_SHA1UTF8; - aEncryptionData[nSha1Ind + 1].Name = PACKAGE_ENCRYPTIONDATA_SHA1MS1252; + pEncryptionData[nSha1Ind].Name = PACKAGE_ENCRYPTIONDATA_SHA1UTF8; + pEncryptionData[nSha1Ind + 1].Name = PACKAGE_ENCRYPTIONDATA_SHA1MS1252; rtl_TextEncoding const pEncoding[2] = { RTL_TEXTENCODING_UTF8, RTL_TEXTENCODING_MS_1252 }; @@ -430,19 +411,20 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreatePackageEncryptionData( if ( nError != rtl_Digest_E_None ) { aEncryptionData.realloc( nSha1Ind ); - break; + return aEncryptionData; } - aEncryptionData[nSha1Ind+nInd].Value <<= uno::Sequence< sal_Int8 >( reinterpret_cast<sal_Int8*>(pBuffer), RTL_DIGEST_LENGTH_SHA1 ); + // coverity[overrun-buffer-arg : FALSE] - coverity has difficulty with css::uno::Sequence + pEncryptionData[nSha1Ind+nInd].Value <<= uno::Sequence< sal_Int8 >( reinterpret_cast<sal_Int8*>(pBuffer), RTL_DIGEST_LENGTH_SHA1 ); } // actual SHA1 - aEncryptionData[nSha1Ind + 2].Name = PACKAGE_ENCRYPTIONDATA_SHA1CORRECT; + pEncryptionData[nSha1Ind + 2].Name = PACKAGE_ENCRYPTIONDATA_SHA1CORRECT; OString aByteStrPass = OUStringToOString(aPassword, RTL_TEXTENCODING_UTF8); std::vector<unsigned char> const sha1(::comphelper::Hash::calculateHash( reinterpret_cast<unsigned char const*>(aByteStrPass.getStr()), aByteStrPass.getLength(), ::comphelper::HashType::SHA1)); - aEncryptionData[nSha1Ind + 2].Value <<= uno::Sequence<sal_Int8>( + pEncryptionData[nSha1Ind + 2].Value <<= uno::Sequence<sal_Int8>( reinterpret_cast<sal_Int8 const*>(sha1.data()), sha1.size()); } @@ -459,14 +441,14 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat // get 32 random chars out of it uno::Sequence < sal_Int8 > aVector(32); - rtl_random_getBytes( aRandomPool, aVector.getArray(), aVector.getLength() ); + if (rtl_random_getBytes(aRandomPool, aVector.getArray(), aVector.getLength()) != rtl_Random_E_None) + { + throw uno::RuntimeException(u"rtl_random_getBytes failed"_ustr); + } rtl_random_destroyPool(aRandomPool); - uno::Sequence< beans::NamedValue > aContainer(2); std::vector< uno::Sequence< beans::NamedValue > > aGpgEncryptions; - uno::Sequence< beans::NamedValue > aGpgEncryptionEntry(3); - uno::Sequence< beans::NamedValue > aEncryptionData(1); uno::Reference< security::XDocumentDigitalSignatures > xSigner( // here none of the version-dependent methods are called @@ -486,24 +468,30 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat std::unique_ptr<GpgME::Context> ctx; GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP); 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); + throw uno::RuntimeException(u"The GpgME library failed to initialize for the OpenPGP protocol."_ustr); + 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(u"The GpgME library failed to initialize for the OpenPGP protocol."_ustr); + ctx->setArmor(false); + } + uno::Sequence < sal_Int8 > aKeyID; if (cert.is()) aKeyID = cert->getSHA1Thumbprint(); - std::vector<GpgME::Key> keys; - keys.push_back( + std::vector<GpgME::Key> keys + { ctx->key( reinterpret_cast<const char*>(aKeyID.getConstArray()), - err, false)); + err, false) + }; // ctx is setup now, let's encrypt the lot! GpgME::Data plain( @@ -515,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); @@ -524,34 +535,32 @@ uno::Sequence< beans::NamedValue > OStorageHelper::CreateGpgPackageEncryptionDat if(crypt_res.error() || !len) throw lang::IllegalArgumentException( - "Not a suitable key, or failed to encrypt.", + u"Not a suitable key, or failed to encrypt."_ustr, css::uno::Reference<css::uno::XInterface>(), -1); uno::Sequence < sal_Int8 > aCipherValue(len); result = cipher.seek(0,SEEK_SET); assert(result == 0); if( cipher.read(aCipherValue.getArray(), len) != len ) - throw uno::RuntimeException("The GpgME library failed to read the encrypted value."); + throw uno::RuntimeException(u"The GpgME library failed to read the encrypted value."_ustr); SAL_INFO("comphelper.crypto", "Generated gpg crypto of length: " << len); - aGpgEncryptionEntry[0].Name = "KeyId"; - aGpgEncryptionEntry[0].Value <<= aKeyID; - aGpgEncryptionEntry[1].Name = "KeyPacket"; - aGpgEncryptionEntry[1].Value <<= aKeyID; - aGpgEncryptionEntry[2].Name = "CipherValue"; - aGpgEncryptionEntry[2].Value <<= aCipherValue; + uno::Sequence< beans::NamedValue > aGpgEncryptionEntry{ + { u"KeyId"_ustr, uno::Any(aKeyID) }, + { u"KeyPacket"_ustr, uno::Any(aKeyID) }, + { u"CipherValue"_ustr, uno::Any(aCipherValue) } + }; aGpgEncryptions.push_back(aGpgEncryptionEntry); } - aEncryptionData[0].Name = PACKAGE_ENCRYPTIONDATA_SHA256UTF8; - aEncryptionData[0].Value <<= aVector; + uno::Sequence<beans::NamedValue> aEncryptionData + = { { PACKAGE_ENCRYPTIONDATA_SHA256UTF8, uno::Any(aVector) } }; - aContainer[0].Name = "GpgInfos"; - aContainer[0].Value <<= comphelper::containerToSequence(aGpgEncryptions); - aContainer[1].Name = "EncryptionKey"; - aContainer[1].Value <<= aEncryptionData; + uno::Sequence<beans::NamedValue> aContainer + = { { u"GpgInfos"_ustr, uno::Any(comphelper::containerToSequence(aGpgEncryptions)) }, + { u"EncryptionKey"_ustr, uno::Any(aEncryptionData) } }; return aContainer; #else @@ -559,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 '?': @@ -585,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; } } @@ -593,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.copy( nPathLen - nSegLen - 1, nSegLen + 1 ) == aEndSegment ) + if ( !bResult && nPathLen > nSegLen && aPath.substr( nPathLen - nSegLen - 1, nSegLen + 1 ) == aEndSegment ) bResult = true; } @@ -638,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( @@ -662,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; @@ -672,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; @@ -705,7 +706,7 @@ OUString OStorageHelper::GetODFVersionFromStorage(const uno::Reference<embed::XS try { uno::Reference<beans::XPropertySet> xPropSet(xStorage, uno::UNO_QUERY_THROW); - xPropSet->getPropertyValue("Version") >>= aODFVersion; + xPropSet->getPropertyValue(u"Version"_ustr) >>= aODFVersion; } catch (uno::Exception&) { diff --git a/comphelper/source/misc/string.cxx b/comphelper/source/misc/string.cxx index ba84ff032b66..8b72ad5f34a5 100644 --- a/comphelper/source/misc/string.cxx +++ b/comphelper/source/misc/string.cxx @@ -19,16 +19,21 @@ #include <sal/config.h> +#include <cassert> #include <cstddef> #include <string_view> +#include <utility> #include <vector> #include <algorithm> +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> #include <rtl/character.hxx> #include <rtl/ustring.hxx> #include <rtl/ustrbuf.hxx> #include <rtl/string.hxx> #include <rtl/strbuf.hxx> +#include <sal/log.hxx> #include <sal/types.h> #include <comphelper/string.hxx> @@ -47,6 +52,23 @@ namespace template <typename T, typename C> T tmpl_stripStart(const T &rIn, const C cRemove) { + if (rIn.empty()) + return rIn; + + typename T::size_type i = 0; + + while (i < rIn.size()) + { + if (rIn[i] != cRemove) + break; + ++i; + } + + return rIn.substr(i); + } + template <typename T, typename C> T tmpl_stripStartString(const T &rIn, + const C cRemove) + { if (rIn.isEmpty()) return rIn; @@ -63,14 +85,24 @@ namespace } } -OString stripStart(const OString &rIn, char c) +OString stripStart(const OString& rIn, char c) { - return tmpl_stripStart<OString, char>(rIn, c); + return tmpl_stripStartString<OString, char>(rIn, c); } -OUString stripStart(const OUString &rIn, sal_Unicode c) +std::string_view stripStart(std::string_view rIn, char c) { - return tmpl_stripStart<OUString, sal_Unicode>(rIn, c); + return tmpl_stripStart<std::string_view, char>(rIn, c); +} + +OUString stripStart(const OUString& rIn, sal_Unicode c) +{ + return tmpl_stripStartString<OUString, sal_Unicode>(rIn, c); +} + +std::u16string_view stripStart(std::u16string_view rIn, sal_Unicode c) +{ + return tmpl_stripStart<std::u16string_view, sal_Unicode>(rIn, c); } namespace @@ -78,6 +110,23 @@ namespace template <typename T, typename C> T tmpl_stripEnd(const T &rIn, const C cRemove) { + if (rIn.empty()) + return rIn; + + typename T::size_type i = rIn.size(); + + while (i > 0) + { + if (rIn[i-1] != cRemove) + break; + --i; + } + + return rIn.substr(0, i); + } + template <typename T, typename C> T tmpl_stripEndString(const T &rIn, + const C cRemove) + { if (rIn.isEmpty()) return rIn; @@ -94,37 +143,108 @@ namespace } } -OString stripEnd(const OString &rIn, char c) +OString stripEnd(const OString& rIn, char c) +{ + return tmpl_stripEndString<OString, char>(rIn, c); +} + +std::string_view stripEnd(std::string_view rIn, char c) +{ + return tmpl_stripEnd<std::string_view, char>(rIn, c); +} + +OUString stripEnd(const OUString& rIn, sal_Unicode c) +{ + return tmpl_stripEndString<OUString, sal_Unicode>(rIn, c); +} + +std::u16string_view stripEnd(std::u16string_view rIn, sal_Unicode c) +{ + return tmpl_stripEnd<std::u16string_view, sal_Unicode>(rIn, c); +} + +namespace +{ + template <typename T, typename C> T tmpl_strip(const T &rIn, + const C cRemove) + { + if (rIn.empty()) + return rIn; + + typename T::size_type end = rIn.size(); + while (end > 0) + { + if (rIn[end-1] != cRemove) + break; + --end; + } + + typename T::size_type start = 0; + while (start < end) + { + if (rIn[start] != cRemove) + break; + ++start; + } + + return rIn.substr(start, end - start); + } + template <typename T, typename C> T tmpl_stripString(const T &rIn, + const C cRemove) + { + if (rIn.isEmpty()) + return rIn; + + sal_Int32 end = rIn.getLength(); + while (end > 0) + { + if (rIn[end-1] != cRemove) + break; + --end; + } + sal_Int32 start = 0; + while (start < end) + { + if (rIn[start] != cRemove) + break; + ++start; + } + + return rIn.copy(start, end - start); + } +} + +OString strip(const OString& rIn, char c) { - return tmpl_stripEnd<OString, char>(rIn, c); + return tmpl_stripString<OString, char>(rIn, c); } -OUString stripEnd(const OUString &rIn, sal_Unicode c) +std::string_view strip(std::string_view rIn, char c) { - return tmpl_stripEnd<OUString, sal_Unicode>(rIn, c); + return tmpl_strip<std::string_view, char>(rIn, c); } -OString strip(const OString &rIn, char c) +OUString strip(const OUString& rIn, sal_Unicode c) { - return stripEnd(stripStart(rIn, c), c); + return tmpl_stripString<OUString, sal_Unicode>(rIn, c); } -OUString strip(const OUString &rIn, sal_Unicode c) +std::u16string_view strip(std::u16string_view rIn, sal_Unicode c) { - return stripEnd(stripStart(rIn, c), c); + return tmpl_strip<std::u16string_view, sal_Unicode>(rIn, c); } namespace { - template <typename T, typename C> sal_Int32 tmpl_getTokenCount(const T &rIn, + template <typename T, typename C> sal_Int32 tmpl_getTokenCount( T rIn, C cTok) { // Empty String: TokenCount by Definition is 0 - if (rIn.isEmpty()) + if (rIn.empty()) return 0; sal_Int32 nTokCount = 1; - for (sal_Int32 i = 0; i < rIn.getLength(); ++i) + for (typename T::size_type i = 0; i < rIn.size(); ++i) { if (rIn[i] == cTok) ++nTokCount; @@ -133,23 +253,22 @@ namespace } } -sal_Int32 getTokenCount(const OString &rIn, char cTok) +sal_Int32 getTokenCount(std::string_view rIn, char cTok) { - return tmpl_getTokenCount<OString, char>(rIn, cTok); + return tmpl_getTokenCount<std::string_view, char>(rIn, cTok); } -sal_Int32 getTokenCount(const OUString &rIn, sal_Unicode cTok) +sal_Int32 getTokenCount(std::u16string_view rIn, sal_Unicode cTok) { - return tmpl_getTokenCount<OUString, sal_Unicode>(rIn, cTok); + return tmpl_getTokenCount<std::u16string_view, sal_Unicode>(rIn, cTok); } -static sal_uInt32 decimalStringToNumber( - OUString const & str, sal_Int32 nStart, sal_Int32 nLength ) +sal_uInt32 decimalStringToNumber(std::u16string_view str) { sal_uInt32 result = 0; - for( sal_Int32 i = nStart; i < nStart + nLength; ) + for( std::size_t i = 0; i < str.size(); ) { - sal_uInt32 c = str.iterateCodePoints(&i); + sal_uInt32 c = o3tl::iterateCodePoints(str, &i); sal_uInt32 value = 0; if( c <= 0x0039) // ASCII decimal digits, most common value = c - 0x0030; @@ -240,12 +359,6 @@ static sal_uInt32 decimalStringToNumber( return result; } -sal_uInt32 decimalStringToNumber( - OUString const & str ) -{ - return decimalStringToNumber(str, 0, str.getLength()); -} - using namespace ::com::sun::star; // convert between sequence of string and comma separated string @@ -255,38 +368,37 @@ OUString convertCommaSeparated( { OUStringBuffer buf; ::comphelper::intersperse( - i_rSeq.begin(), i_rSeq.end(), ::comphelper::OUStringBufferAppender(buf), OUString( ", " )); + i_rSeq.begin(), i_rSeq.end(), ::comphelper::OUStringBufferAppender(buf), u", "_ustr); return buf.makeStringAndClear(); } std::vector<OUString> - split(const OUString& rStr, sal_Unicode cSeparator) + split(std::u16string_view rStr, sal_Unicode cSeparator) { std::vector< OUString > vec; - sal_Int32 idx = 0; + std::size_t idx = 0; do { - OUString kw = - rStr.getToken(0, cSeparator, idx); - kw = kw.trim(); - if (!kw.isEmpty()) + std::u16string_view kw = o3tl::getToken(rStr, cSeparator, idx); + kw = o3tl::trim(kw); + if (!kw.empty()) { - vec.push_back(kw); + vec.push_back(OUString(kw)); } - } while (idx >= 0); + } while (idx != std::u16string_view::npos); return vec; } uno::Sequence< OUString > - convertCommaSeparated( OUString const& i_rString ) + convertCommaSeparated( std::u16string_view i_rString ) { std::vector< OUString > vec = split(i_rString, ','); return comphelper::containerToSequence(vec); } -OString join(const OString& rSeparator, const std::vector<OString>& rSequence) +OString join(std::string_view rSeparator, const std::vector<OString>& rSequence) { OStringBuffer aBuffer; for (size_t i = 0; i < rSequence.size(); ++i) @@ -310,33 +422,50 @@ sal_Int32 compareNatural( const OUString & rLHS, const OUString & rRHS, sal_Int32 nLHSFirstDigitPos = 0; sal_Int32 nRHSFirstDigitPos = 0; + // Check if the string starts with a digit + sal_Int32 nStartsDigitLHS = rBI->endOfCharBlock(rLHS, nLHSFirstDigitPos, rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + sal_Int32 nStartsDigitRHS = rBI->endOfCharBlock(rRHS, nRHSFirstDigitPos, rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + + if (nStartsDigitLHS > 0 && nStartsDigitRHS > 0) + { + sal_uInt32 nLHS = comphelper::string::decimalStringToNumber(rLHS.subView(0, nStartsDigitLHS)); + sal_uInt32 nRHS = comphelper::string::decimalStringToNumber(rRHS.subView(0, nStartsDigitRHS)); + + if (nLHS != nRHS) + return nLHS < nRHS ? -1 : 1; + nLHSLastNonDigitPos = nStartsDigitLHS; + nRHSLastNonDigitPos = nStartsDigitRHS; + } + else if (nStartsDigitLHS > 0) + return -1; + else if (nStartsDigitRHS > 0) + return 1; + while (nLHSFirstDigitPos < rLHS.getLength() || nRHSFirstDigitPos < rRHS.getLength()) { sal_Int32 nLHSChunkLen; sal_Int32 nRHSChunkLen; //Compare non digit block as normal strings - nLHSFirstDigitPos = rBI->nextCharBlock(rLHS, nLHSLastNonDigitPos, - rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); - nRHSFirstDigitPos = rBI->nextCharBlock(rRHS, nRHSLastNonDigitPos, - rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + nLHSFirstDigitPos = rBI->nextCharBlock(rLHS, nLHSLastNonDigitPos, rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + nRHSFirstDigitPos = rBI->nextCharBlock(rRHS, nRHSLastNonDigitPos, rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + if (nLHSFirstDigitPos == -1) nLHSFirstDigitPos = rLHS.getLength(); + if (nRHSFirstDigitPos == -1) nRHSFirstDigitPos = rRHS.getLength(); + nLHSChunkLen = nLHSFirstDigitPos - nLHSLastNonDigitPos; nRHSChunkLen = nRHSFirstDigitPos - nRHSLastNonDigitPos; - nRet = rCollator->compareSubstring(rLHS, nLHSLastNonDigitPos, - nLHSChunkLen, rRHS, nRHSLastNonDigitPos, nRHSChunkLen); + nRet = rCollator->compareSubstring(rLHS, nLHSLastNonDigitPos, nLHSChunkLen, rRHS, nRHSLastNonDigitPos, nRHSChunkLen); if (nRet != 0) break; //Compare digit block as one number vs another - nLHSLastNonDigitPos = rBI->endOfCharBlock(rLHS, nLHSFirstDigitPos, - rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); - nRHSLastNonDigitPos = rBI->endOfCharBlock(rRHS, nRHSFirstDigitPos, - rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + nLHSLastNonDigitPos = rBI->endOfCharBlock(rLHS, nLHSFirstDigitPos, rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); + nRHSLastNonDigitPos = rBI->endOfCharBlock(rRHS, nRHSFirstDigitPos, rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER); if (nLHSLastNonDigitPos == -1) nLHSLastNonDigitPos = rLHS.getLength(); if (nRHSLastNonDigitPos == -1) @@ -348,8 +477,8 @@ sal_Int32 compareNatural( const OUString & rLHS, const OUString & rRHS, //numbers outside of the normal 0-9 range, e.g. see GetLocalizedChar in //vcl - sal_uInt32 nLHS = comphelper::string::decimalStringToNumber(rLHS, nLHSFirstDigitPos, nLHSChunkLen); - sal_uInt32 nRHS = comphelper::string::decimalStringToNumber(rRHS, nRHSFirstDigitPos, nRHSChunkLen); + sal_uInt32 nLHS = comphelper::string::decimalStringToNumber(rLHS.subView(nLHSFirstDigitPos, nLHSChunkLen)); + sal_uInt32 nRHS = comphelper::string::decimalStringToNumber(rRHS.subView(nRHSFirstDigitPos, nRHSChunkLen)); if (nLHS != nRHS) { @@ -363,56 +492,52 @@ sal_Int32 compareNatural( const OUString & rLHS, const OUString & rRHS, NaturalStringSorter::NaturalStringSorter( const uno::Reference< uno::XComponentContext > &rContext, - const lang::Locale &rLocale) : m_aLocale(rLocale) + lang::Locale aLocale) : m_aLocale(std::move(aLocale)) { m_xCollator = i18n::Collator::create( rContext ); m_xCollator->loadDefaultCollator(m_aLocale, 0); m_xBI = i18n::BreakIterator::create( rContext ); } -bool isdigitAsciiString(const OString &rString) +bool isdigitAsciiString(std::string_view rString) { return std::all_of( - rString.getStr(), rString.getStr() + rString.getLength(), + rString.data(), rString.data() + rString.size(), [](unsigned char c){ return rtl::isAsciiDigit(c); }); } -bool isdigitAsciiString(const OUString &rString) +bool isdigitAsciiString(std::u16string_view rString) { return std::all_of( - rString.getStr(), rString.getStr() + rString.getLength(), + rString.data(), rString.data() + rString.size(), [](sal_Unicode c){ return rtl::isAsciiDigit(c); }); } -namespace +OUString reverseString(std::u16string_view rStr) { - template <typename T, typename O> T tmpl_reverseString(const T &rIn) - { - if (rIn.isEmpty()) - return rIn; - - sal_Int32 i = rIn.getLength(); - O sBuf(i); - while (i) - sBuf.append(rIn[--i]); - return sBuf.makeStringAndClear(); - } -} - -OUString reverseString(const OUString &rStr) -{ - return tmpl_reverseString<OUString, OUStringBuffer>(rStr); + if (rStr.empty()) + return OUString(); + + std::size_t i = rStr.size(); + OUStringBuffer sBuf(static_cast<sal_Int32>(i)); + while (i) + sBuf.append(rStr[--i]); + return sBuf.makeStringAndClear(); } -OString reverseString(const OString &rStr) -{ - return tmpl_reverseString<OString, OStringBuffer>(rStr); +OUString reverseCodePoints(std::u16string_view str) { + auto const len = str.size(); + OUStringBuffer buf(len); + for (sal_Int32 i = len; i != 0;) { + buf.appendUtf32(o3tl::iterateCodePoints(str, &i, -1)); + } + return buf.makeStringAndClear(); } -sal_Int32 indexOfAny(OUString const& rIn, +sal_Int32 indexOfAny(std::u16string_view rIn, sal_Unicode const*const pChars, sal_Int32 const nPos) { - for (sal_Int32 i = nPos; i < rIn.getLength(); ++i) + for (std::u16string_view::size_type i = nPos; i < rIn.size(); ++i) { sal_Unicode const c = rIn[i]; for (sal_Unicode const* pChar = pChars; *pChar; ++pChar) @@ -426,12 +551,12 @@ sal_Int32 indexOfAny(OUString const& rIn, return -1; } -OUString removeAny(OUString const& rIn, +OUString removeAny(std::u16string_view rIn, sal_Unicode const*const pChars) { OUStringBuffer buf; bool isFound(false); - for (sal_Int32 i = 0; i < rIn.getLength(); ++i) + for (std::u16string_view::size_type i = 0; i < rIn.size(); ++i) { sal_Unicode const c = rIn[i]; bool removeC(false); @@ -449,7 +574,7 @@ OUString removeAny(OUString const& rIn, { if (i > 0) { - buf.append(std::u16string_view(rIn).substr(0, i)); + buf.append(rIn.substr(0, i)); } isFound = true; } @@ -459,11 +584,11 @@ OUString removeAny(OUString const& rIn, buf.append(c); } } - return isFound ? buf.makeStringAndClear() : rIn; + return isFound ? buf.makeStringAndClear() : OUString(rIn); } OUString setToken(const OUString& rIn, sal_Int32 nToken, sal_Unicode cTok, - const OUString& rNewToken) + std::u16string_view rNewToken) { sal_Int32 nLen = rIn.getLength(); sal_Int32 nTok = 0; @@ -492,6 +617,62 @@ OUString setToken(const OUString& rIn, sal_Int32 nToken, sal_Unicode cTok, return rIn; } +/** Similar to OUString::replaceAt, but for an OUStringBuffer. + + Replace n = count characters + from position index in this string with newStr. + */ +void replaceAt(OUStringBuffer& rIn, sal_Int32 nIndex, sal_Int32 nCount, std::u16string_view newStr ) +{ + assert(nIndex >= 0 && nIndex <= rIn.getLength()); + assert(nCount >= 0); + assert(nCount <= rIn.getLength() - nIndex); + + /* Append? */ + const sal_Int32 nOldLength = rIn.getLength(); + if ( nIndex == nOldLength ) + { + rIn.append(newStr); + return; + } + + sal_Int32 nNewLength = nOldLength + newStr.size() - nCount; + if (newStr.size() > o3tl::make_unsigned(nCount)) + rIn.ensureCapacity(nOldLength + newStr.size() - nCount); + + sal_Unicode* pStr = const_cast<sal_Unicode*>(rIn.getStr()); + memmove(pStr + nIndex + newStr.size(), pStr + nIndex + nCount, nOldLength - nIndex + nCount); + memcpy(pStr + nIndex, newStr.data(), newStr.size()); + + rIn.setLength(nNewLength); +} + +OUString sanitizeStringSurrogates(const OUString& rString) +{ + sal_Int32 i=0; + while (i < rString.getLength()) + { + sal_Unicode c = rString[i]; + if (rtl::isHighSurrogate(c)) + { + if (i+1 == rString.getLength() + || !rtl::isLowSurrogate(rString[i+1])) + { + SAL_WARN("comphelper", "Surrogate error: high without low"); + return rString.copy(0, i); + } + ++i; //skip correct low + } + if (rtl::isLowSurrogate(c)) //bare low without preceding high + { + SAL_WARN("comphelper", "Surrogate error: low without high"); + return rString.copy(0, i); + } + ++i; + } + return rString; +} + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/synchronousdispatch.cxx b/comphelper/source/misc/synchronousdispatch.cxx index a09f05db8331..1602c8963fb1 100644 --- a/comphelper/source/misc/synchronousdispatch.cxx +++ b/comphelper/source/misc/synchronousdispatch.cxx @@ -65,7 +65,9 @@ uno::Reference< lang::XComponent > SynchronousDispatch::dispatch( } catch ( uno::Exception& ) { - SAL_WARN("comphelper","SynchronousDispatch::dispatch() Error while dispatching!"); + // can't use TOOLS_WARN_EXCEPTION, as comphelper is used by libtl! + SAL_WARN("comphelper", "SynchronousDispatch::dispatch(): error while dispatching '" + << sURL << "' for '" << sTarget << "'!"); } } diff --git a/comphelper/source/misc/syntaxhighlight.cxx b/comphelper/source/misc/syntaxhighlight.cxx index 60ecc7b97c94..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,31 +432,31 @@ 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; } + else + reType = TokenType::Operator; } 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; } + else + reType = TokenType::Operator; } else { @@ -455,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; @@ -476,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; } @@ -493,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 @@ -527,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++; @@ -547,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; @@ -579,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; } @@ -672,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); } } @@ -699,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 @@ -712,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 f93400d96f9f..f0a71eb05168 100644 --- a/comphelper/source/misc/threadpool.cxx +++ b/comphelper/source/misc/threadpool.cxx @@ -11,15 +11,17 @@ #include <com/sun/star/uno/Exception.hpp> #include <config_options.h> +#include <o3tl/safeint.hxx> #include <sal/config.h> #include <sal/log.hxx> -#include <rtl/instance.hxx> #include <salhelper/thread.hxx> #include <algorithm> #include <memory> #include <thread> #include <chrono> +#include <cstddef> #include <comphelper/debuggerinfo.hxx> +#include <utility> #if defined HAVE_VALGRIND_HEADERS #include <valgrind/memcheck.h> @@ -28,9 +30,6 @@ #if defined(_WIN32) #define WIN32_LEAN_AND_MEAN #include <windows.h> -#elif defined UNX -#include <unistd.h> -#include <fcntl.h> #endif namespace comphelper { @@ -79,20 +78,25 @@ public: std::unique_ptr<ThreadTask> pTask = mpPool->popWorkLocked( aGuard, true ); if( pTask ) { + std::shared_ptr<ThreadTaskTag> pTag(pTask->mpTag); + mpPool->incBusyWorker(); aGuard.unlock(); pTask->exec(); pTask.reset(); aGuard.lock(); + mpPool->decBusyWorker(); + pTag->onTaskWorkerDone(); } } } }; -ThreadPool::ThreadPool(sal_Int32 nWorkers) +ThreadPool::ThreadPool(std::size_t nWorkers) : mbTerminate(true) - , mnWorkers(nWorkers) + , mnMaxWorkers(nWorkers) + , mnBusyWorkers(0) { } @@ -104,41 +108,45 @@ ThreadPool::~ThreadPool() // still 0, but hopefully they will be more helpful on non-WNT platforms assert(mbTerminate); assert(maTasks.empty()); + assert(mnBusyWorkers == 0); } namespace { -struct ThreadPoolStatic : public rtl::StaticWithInit< std::shared_ptr< ThreadPool >, - ThreadPoolStatic > +std::shared_ptr< ThreadPool >& GetStaticThreadPool() { - std::shared_ptr< ThreadPool > operator () () { - const sal_Int32 nThreads = ThreadPool::getPreferredConcurrency(); + static std::shared_ptr< ThreadPool > POOL = + []() + { + const std::size_t nThreads = ThreadPool::getPreferredConcurrency(); return std::make_shared< ThreadPool >( nThreads ); - }; -}; + }(); + return POOL; +} } ThreadPool& ThreadPool::getSharedOptimalPool() { - return *ThreadPoolStatic::get(); + return *GetStaticThreadPool(); } -sal_Int32 ThreadPool::getPreferredConcurrency() +std::size_t ThreadPool::getPreferredConcurrency() { - static sal_Int32 ThreadCount = [&]() + static std::size_t ThreadCount = []() { - const sal_Int32 nHardThreads = std::max(std::thread::hardware_concurrency(), 1U); - sal_Int32 nThreads = nHardThreads; + const std::size_t nHardThreads = o3tl::clamp_to_unsigned<std::size_t>( + std::max(std::thread::hardware_concurrency(), 1U)); + std::size_t nThreads = nHardThreads; const char *pEnv = getenv("MAX_CONCURRENCY"); if (pEnv != nullptr) { // Override with user/admin preference. - nThreads = rtl_str_toInt32(pEnv, 10); + nThreads = o3tl::clamp_to_unsigned<std::size_t>(rtl_str_toInt32(pEnv, 10)); } nThreads = std::min(nHardThreads, nThreads); - return std::max<sal_Int32>(nThreads, 1); + return std::max<std::size_t>(nThreads, 1); }(); return ThreadCount; @@ -161,12 +169,23 @@ void ThreadPool::shutdownLocked(std::unique_lock<std::mutex>& aGuard) { // no threads at all -> execute the work in-line std::unique_ptr<ThreadTask> pTask; while ( ( pTask = popWorkLocked(aGuard, false) ) ) + { + std::shared_ptr<ThreadTaskTag> pTag(pTask->mpTag); pTask->exec(); + pTag->onTaskWorkerDone(); + } } else { while( !maTasks.empty() ) + { maTasksChanged.wait( aGuard ); + // In the (unlikely but possible?) case pushTask() gets called meanwhile, + // its notify_one() call is meant to wake a up a thread and process the task. + // But if this code gets woken up instead, it could lead to a deadlock. + // Pass on the notification. + maTasksChanged.notify_one(); + } } assert( maTasks.empty() ); @@ -198,7 +217,8 @@ void ThreadPool::pushTask( std::unique_ptr<ThreadTask> pTask ) mbTerminate = false; - if (maWorkers.size() < mnWorkers && maWorkers.size() <= maTasks.size()) + // Worked on tasks are already removed from maTasks, so include the count of busy workers. + if (maWorkers.size() < mnMaxWorkers && maWorkers.size() <= maTasks.size() + mnBusyWorkers) { maWorkers.push_back( new ThreadWorker( this ) ); maWorkers.back()->launch(); @@ -230,7 +250,18 @@ std::unique_ptr<ThreadTask> ThreadPool::popWorkLocked( std::unique_lock< std::mu return nullptr; } -void ThreadPool::waitUntilDone(const std::shared_ptr<ThreadTaskTag>& rTag, bool bJoinAll) +void ThreadPool::incBusyWorker() +{ + ++mnBusyWorkers; +} + +void ThreadPool::decBusyWorker() +{ + assert(mnBusyWorkers >= 1); + --mnBusyWorkers; +} + +void ThreadPool::waitUntilDone(const std::shared_ptr<ThreadTaskTag>& rTag, bool bJoin) { #if defined DBG_UTIL && (defined LINUX || defined _WIN32) assert(!gbIsWorkerThread && "cannot wait for tasks from inside a task"); @@ -245,21 +276,23 @@ void ThreadPool::waitUntilDone(const std::shared_ptr<ThreadTaskTag>& rTag, bool std::unique_ptr<ThreadTask> pTask = popWorkLocked(aGuard, false); if (!pTask) break; + std::shared_ptr<ThreadTaskTag> pTag(pTask->mpTag); pTask->exec(); + pTag->onTaskWorkerDone(); } } } rTag->waitUntilDone(); - if (bJoinAll) - joinAll(); + if (bJoin) + joinThreadsIfIdle(); } -void ThreadPool::joinAll() +void ThreadPool::joinThreadsIfIdle() { std::unique_lock< std::mutex > aGuard( maMutex ); - if (maTasks.empty()) // check if there are still tasks from another tag + if (isIdle()) // check if there are still tasks from another tag { shutdownLocked(aGuard); } @@ -275,14 +308,13 @@ 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)) { } void ThreadTask::exec() { - std::shared_ptr<ThreadTaskTag> pTag(mpTag); try { doWork(); } @@ -294,8 +326,10 @@ void ThreadTask::exec() { SAL_WARN("comphelper", "exception in thread worker while calling doWork(): " << e); } - - pTag->onTaskWorkerDone(); + catch (...) + { + SAL_WARN("comphelper", "unknown exception in thread worker while calling doWork()"); + } } ThreadTaskTag::ThreadTaskTag() : mnTasksWorking(0) diff --git a/comphelper/source/misc/traceevent.cxx b/comphelper/source/misc/traceevent.cxx new file mode 100644 index 000000000000..1296404ebd32 --- /dev/null +++ b/comphelper/source/misc/traceevent.cxx @@ -0,0 +1,145 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <atomic> +#include <mutex> +#include <iostream> + +#include <comphelper/profilezone.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/traceevent.hxx> + +namespace comphelper +{ +#ifdef DBG_UTIL +std::atomic<bool> TraceEvent::s_bRecording = (getenv("TRACE_EVENT_RECORDING") != nullptr); +#else +std::atomic<bool> TraceEvent::s_bRecording = false; +#endif + +std::size_t TraceEvent::s_nBufferSize = 0; +void (*TraceEvent::s_pBufferFullCallback)() = nullptr; + +int AsyncEvent::s_nIdCounter = 0; + +static thread_local int nProfileZoneNesting = 0; // Level of Nested Profile Zones + +namespace +{ +std::vector<OUString> g_aRecording; // recorded data +std::mutex g_aMutex; +} + +void TraceEvent::addRecording(const OUString& sObject) +{ + bool bEmitCallback; + { + std::lock_guard aGuard(g_aMutex); + + g_aRecording.emplace_back(sObject); + + bEmitCallback = s_nBufferSize > 0 && g_aRecording.size() >= s_nBufferSize; + } + if (bEmitCallback && s_pBufferFullCallback != nullptr) + (*s_pBufferFullCallback)(); +} + +void TraceEvent::addInstantEvent(const char* sName, const std::map<OUString, OUString>& args) +{ + long long nNow = getNow(); + + int nPid = 0; + oslProcessInfo aProcessInfo; + aProcessInfo.Size = sizeof(oslProcessInfo); + if (osl_getProcessInfo(nullptr, osl_Process_IDENTIFIER, &aProcessInfo) == osl_Process_E_None) + nPid = aProcessInfo.Ident; + + addRecording("{" + "\"name:\"" + + OUString(sName, strlen(sName), RTL_TEXTENCODING_UTF8) + + "\"," + "\"ph\":\"i\"" + + createArgsString(args) + ",\"ts\":" + OUString::number(nNow) + + "," + "\"pid\":" + + OUString::number(nPid) + + "," + "\"tid\":" + + OUString::number(osl_getThreadIdentifier(nullptr)) + "},"); +} + +void TraceEvent::startRecording() +{ + std::lock_guard aGuard(g_aMutex); + s_bRecording = true; +} + +void TraceEvent::stopRecording() { s_bRecording = false; } + +void TraceEvent::setBufferSizeAndCallback(std::size_t bufferSize, void (*bufferFullCallback)()) +{ + s_nBufferSize = bufferSize; + s_pBufferFullCallback = bufferFullCallback; +} + +std::vector<OUString> TraceEvent::getEventVectorAndClear() +{ + bool bRecording; + std::vector<OUString> aRecording; + { + std::lock_guard aGuard(g_aMutex); + bRecording = s_bRecording; + stopRecording(); + aRecording.swap(g_aRecording); + } + // reset start time and nesting level + if (bRecording) + startRecording(); + return aRecording; +} + +css::uno::Sequence<OUString> TraceEvent::getRecordingAndClear() +{ + return comphelper::containerToSequence(getEventVectorAndClear()); +} + +void ProfileZone::addRecording() +{ + assert(s_bRecording); + + long long nNow = getNow(); + + // Generate a single "Complete Event" (type X) + TraceEvent::addRecording("{" + "\"name\":\"" + + OUString(m_sName, strlen(m_sName), RTL_TEXTENCODING_UTF8) + + "\"," + "\"ph\":\"X\"," + "\"ts\":" + + OUString::number(m_nCreateTime) + + "," + "\"dur\":" + + OUString::number(nNow - m_nCreateTime) + m_sArgs + + "," + "\"pid\":" + + OUString::number(m_nPid) + + "," + "\"tid\":" + + OUString::number(osl_getThreadIdentifier(nullptr)) + "},"); +} + +int ProfileZone::getNestingLevel() { return nProfileZoneNesting; } + +void ProfileZone::setNestingLevel(int nNestingLevel) { nProfileZoneNesting = nNestingLevel; } + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/comphelper_module.cxx b/comphelper/source/misc/typedescriptionref.hxx index 9cf32546e1be..f4580cb2e4cb 100644 --- a/comphelper/source/misc/comphelper_module.cxx +++ b/comphelper/source/misc/typedescriptionref.hxx @@ -17,35 +17,35 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#pragma once -#include <comphelper_module.hxx> +#include <typelib/typedescription.h> - -namespace comphelper::module +namespace comphelper::detail { - - - struct ComphelperModuleCreator - { - ComphelperModule m_aComphelperModule; - }; - namespace - { - class theComphelperModuleInstance : public rtl::Static<ComphelperModuleCreator, theComphelperModuleInstance> {}; - } - - ComphelperModule::ComphelperModule() - :BaseClass() +// 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) { + TYPELIB_DANGER_GET(&typeDescr, typeDef); } - - ComphelperModule& ComphelperModule::getInstance() + ~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 theComphelperModuleInstance::get().m_aComphelperModule; + return typeDescr && other.typeDescr + && typelib_typedescription_equals(typeDescr, other.typeDescr); } +private: + typelib_TypeDescription* typeDescr = nullptr; +}; -} // namespace comphelper::module - +} // namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/misc/types.cxx b/comphelper/source/misc/types.cxx index 0818dcc54bdd..8e5d42073bff 100644 --- a/comphelper/source/misc/types.cxx +++ b/comphelper/source/misc/types.cxx @@ -27,11 +27,8 @@ #include <typelib/typedescription.hxx> #include <sal/log.hxx> - namespace comphelper { - - using namespace ::com::sun::star::uno; using namespace ::com::sun::star::awt; using namespace ::com::sun::star::lang; @@ -39,57 +36,51 @@ using namespace ::com::sun::star::lang; sal_Int64 getINT64(const Any& _rAny) { sal_Int64 nReturn = 0; - if(!(_rAny >>= nReturn)) + if (!(_rAny >>= nReturn)) SAL_WARN("comphelper", "conversion from Any to sal_Int64 failed"); return nReturn; } - sal_Int32 getINT32(const Any& _rAny) { sal_Int32 nReturn = 0; - if(!(_rAny >>= nReturn)) + if (!(_rAny >>= nReturn)) SAL_WARN("comphelper", "conversion from Any to sal_Int32 failed"); return nReturn; } - sal_Int16 getINT16(const Any& _rAny) { sal_Int16 nReturn = 0; - if(!(_rAny >>= nReturn)) + if (!(_rAny >>= nReturn)) SAL_WARN("comphelper", "conversion from Any to sal_Int16 failed"); return nReturn; } - double getDouble(const Any& _rAny) { double nReturn = 0.0; - if(!(_rAny >>= nReturn)) + if (!(_rAny >>= nReturn)) SAL_WARN("comphelper", "conversion from Any to double failed"); return nReturn; } - float getFloat(const Any& _rAny) { float nReturn = 0.0; - if(!(_rAny >>= nReturn)) + if (!(_rAny >>= nReturn)) SAL_WARN("comphelper", "conversion from Any to float failed"); return nReturn; } - OUString getString(const Any& _rAny) { OUString nReturn; - if(!(_rAny >>= nReturn)) + if (!(_rAny >>= nReturn)) SAL_WARN("comphelper", "conversion from Any to OUString failed"); return nReturn; } - bool getBOOL(const Any& _rAny) { bool bReturn = false; @@ -100,17 +91,16 @@ bool getBOOL(const Any& _rAny) return bReturn; } - sal_Int32 getEnumAsINT32(const Any& _rAny) { sal_Int32 nReturn = 0; - if (! ::cppu::enum2int(nReturn,_rAny) ) - throw IllegalArgumentException(); + if (!::cppu::enum2int(nReturn, _rAny)) + throw IllegalArgumentException(u"enum2int failed"_ustr, + css::uno::Reference<css::uno::XInterface>(), -1); return nReturn; } - -FontDescriptor getDefaultFont() +FontDescriptor getDefaultFont() { FontDescriptor aReturn; aReturn.Slant = FontSlant_DONTKNOW; @@ -119,7 +109,6 @@ FontDescriptor getDefaultFont() return aReturn; } - bool isAssignableFrom(const Type& _rAssignable, const Type& _rFrom) { // get the type lib descriptions @@ -136,14 +125,14 @@ bool isAssignableFrom(const Type& _rAssignable, const Type& _rFrom) Type getSequenceElementType(const Type& _rSequenceType) { OSL_ENSURE(_rSequenceType.getTypeClass() == TypeClass_SEQUENCE, - "getSequenceElementType: must be called with a sequence type!"); + "getSequenceElementType: must be called with a sequence type!"); if (_rSequenceType.getTypeClass() != TypeClass_SEQUENCE) return Type(); TypeDescription aTD(_rSequenceType); - typelib_IndirectTypeDescription* pSequenceTD = - reinterpret_cast< typelib_IndirectTypeDescription* >(aTD.get()); + typelib_IndirectTypeDescription* pSequenceTD + = reinterpret_cast<typelib_IndirectTypeDescription*>(aTD.get()); OSL_ASSERT(pSequenceTD && pSequenceTD->pType); if (pSequenceTD && pSequenceTD->pType) @@ -152,7 +141,6 @@ Type getSequenceElementType(const Type& _rSequenceType) return Type(); } -} // namespace comphelper - +} // namespace comphelper /* 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 c01743b36615..e1bb828ba631 100644 --- a/comphelper/source/misc/xmlsechelper.cxx +++ b/comphelper/source/misc/xmlsechelper.cxx @@ -17,14 +17,14 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ - #include <comphelper/xmlsechelper.hxx> #include <rtl/ustrbuf.hxx> #include <osl/diagnose.h> -#include <vector> +#include <o3tl/string_view.hxx> -using namespace std; +#include <utility> +#include <vector> namespace comphelper::xmlsec { @@ -33,9 +33,9 @@ namespace comphelper::xmlsec switch (rKind) { case css::security::CertificateKind_X509: - return "X.509"; + return u"X.509"_ustr; case css::security::CertificateKind_OPENPGP: - return "OpenPGP"; + return u"OpenPGP"_ustr; default: return OUString(); } @@ -49,9 +49,9 @@ namespace comphelper::xmlsec The second string is for the details view at the bottom. It shows the attribute/value pairs on different lines. All escape characters ('"') are removed. */ - pair< OUString, OUString> GetDNForCertDetailsView( const OUString & rRawString) + std::pair< OUString, OUString> GetDNForCertDetailsView( std::u16string_view rRawString) { - vector< pair< OUString, OUString > > vecAttrValueOfDN = parseDN(rRawString); + std::vector< std::pair< OUString, OUString > > vecAttrValueOfDN = parseDN(rRawString); OUStringBuffer s1, s2; for (auto i = vecAttrValueOfDN.cbegin(); i < vecAttrValueOfDN.cend(); ++i) { @@ -61,9 +61,9 @@ namespace comphelper::xmlsec s2.append('\n'); } s1.append(i->second); - s2.append(i->first).append(" = ").append(i->second); + s2.append(i->first + " = " + i->second); } - return make_pair(s1.makeStringAndClear(), s2.makeStringAndClear()); + return std::make_pair(s1.makeStringAndClear(), s2.makeStringAndClear()); } /* @@ -73,18 +73,18 @@ namespace comphelper::xmlsec they are escaped with a double quote. This function removes the escape characters. */ #ifdef _WIN32 -vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) +std::vector< std::pair< OUString, OUString> > parseDN(std::u16string_view rRawString) { - vector< pair<OUString, OUString> > retVal; + std::vector< std::pair<OUString, OUString> > retVal; bool bInEscape = false; bool bInValue = false; bool bInType = true; sal_Int32 nTypeNameStart = 0; - OUString sType; + std::u16string_view sType; OUStringBuffer sbufValue; - sal_Int32 length = rRawString.getLength(); + size_t length = rRawString.size(); - for (sal_Int32 i = 0; i < length; i++) + for (size_t i = 0; i < length; i++) { sal_Unicode c = rRawString[i]; @@ -92,8 +92,8 @@ vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) { if (! bInValue) { - sType = rRawString.copy(nTypeNameStart, i - nTypeNameStart); - sType = sType.trim(); + sType = rRawString.substr(nTypeNameStart, i - nTypeNameStart); + sType = o3tl::trim(sType); bInType = false; } else @@ -129,9 +129,9 @@ vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) //then we have reached the end of the value if (!bInValue) { - OSL_ASSERT(!sType.isEmpty()); - retVal.push_back(make_pair(sType, sbufValue.makeStringAndClear())); - sType.clear(); + OSL_ASSERT(!sType.empty()); + retVal.emplace_back(OUString(sType), sbufValue.makeStringAndClear()); + sType = {}; //The next char is the start of the new type nTypeNameStart = i + 1; bInType = true; @@ -152,25 +152,25 @@ vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) } if (sbufValue.getLength()) { - OSL_ASSERT(!sType.isEmpty()); - retVal.push_back(make_pair(sType, sbufValue.makeStringAndClear())); + OSL_ASSERT(!sType.empty()); + retVal.emplace_back(OUString(sType), sbufValue.makeStringAndClear()); } return retVal; } #else -vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) +std::vector< std::pair< OUString, OUString> > parseDN(std::u16string_view rRawString) { - vector< pair<OUString, OUString> > retVal; + std::vector< std::pair<OUString, OUString> > retVal; //bInEscape == true means that the preceding character is an escape character bool bInEscape = false; bool bInValue = false; bool bInType = true; sal_Int32 nTypeNameStart = 0; - OUString sType; + std::u16string_view sType; OUStringBuffer sbufValue; - sal_Int32 length = rRawString.getLength(); + size_t length = rRawString.size(); - for (sal_Int32 i = 0; i < length; i++) + for (size_t i = 0; i < length; i++) { sal_Unicode c = rRawString[i]; @@ -178,8 +178,8 @@ vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) { if (! bInValue) { - sType = rRawString.copy(nTypeNameStart, i - nTypeNameStart); - sType = sType.trim(); + sType = rRawString.substr(nTypeNameStart, i - nTypeNameStart); + sType = o3tl::trim(sType); bInType = false; } else @@ -224,9 +224,9 @@ vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) //then we have reached the end of the value if (!bInValue) { - OSL_ASSERT(!sType.isEmpty()); + OSL_ASSERT(!sType.empty()); retVal.emplace_back(sType, sbufValue.makeStringAndClear()); - sType.clear(); + sType = {}; //The next char is the start of the new type nTypeNameStart = i + 1; bInType = true; @@ -250,7 +250,7 @@ vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) } if (!sbufValue.isEmpty()) { - OSL_ASSERT(!sType.isEmpty()); + OSL_ASSERT(!sType.empty()); retVal.emplace_back(sType, sbufValue.makeStringAndClear()); } return retVal; @@ -268,12 +268,12 @@ vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) OUString retVal; int i = 0; - vector< pair< OUString, OUString > > vecAttrValueOfDN = parseDN(_rRawString); + std::vector< std::pair< OUString, OUString > > vecAttrValueOfDN = parseDN(_rRawString); while ( aIDs[i] ) { OUString sPartId = OUString::createFromAscii( aIDs[i++] ); auto idn = std::find_if(vecAttrValueOfDN.cbegin(), vecAttrValueOfDN.cend(), - [&sPartId](const pair< OUString, OUString >& dn) { return dn.first == sPartId; }); + [&sPartId](const std::pair< OUString, OUString >& dn) { return dn.first == sPartId; }); if (idn != vecAttrValueOfDN.cend()) retVal = idn->second; if (!retVal.isEmpty()) @@ -284,18 +284,14 @@ vector< pair< OUString, OUString> > parseDN(const OUString& rRawString) OUString GetHexString( const css::uno::Sequence< sal_Int8 >& _rSeq, const char* _pSep, sal_uInt16 _nLineBreak ) { - const sal_Int8* pSerNumSeq = _rSeq.getConstArray(); - int nCnt = _rSeq.getLength(); OUStringBuffer aStr; const char pHexDigs[ 17 ] = "0123456789ABCDEF"; char pBuffer[ 3 ] = " "; - sal_uInt8 nNum; sal_uInt16 nBreakStart = _nLineBreak? _nLineBreak : 1; sal_uInt16 nBreak = nBreakStart; - for( int i = 0 ; i < nCnt ; ++i ) + for (sal_Int8 n : _rSeq) { - nNum = sal_uInt8( pSerNumSeq[ i ] ); - + sal_uInt8 nNum = static_cast<sal_uInt8>(n); // exchange the buffer[0] and buffer[1], which make it consistent with Mozilla and Windows pBuffer[ 1 ] = pHexDigs[ nNum & 0x0F ]; nNum >>= 4; diff --git a/comphelper/source/officeinstdir/officeinstallationdirectories.cxx b/comphelper/source/officeinstdir/officeinstallationdirectories.cxx index 4090fda37ada..252ba2d5231e 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 { -OUString const g_aOfficeBrandDirMacro("$(brandbaseurl)"); -OUString const g_aUserDirMacro("$(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 )) { } @@ -189,7 +189,7 @@ OfficeInstallationDirectories::makeAbsoluteURL( const OUString& URL ) OUString SAL_CALL OfficeInstallationDirectories::getImplementationName() { - return "com.sun.star.comp.util.OfficeInstallationDirectories"; + return u"com.sun.star.comp.util.OfficeInstallationDirectories"_ustr; } // virtual @@ -203,7 +203,7 @@ OfficeInstallationDirectories::supportsService( const OUString& ServiceName ) uno::Sequence< OUString > SAL_CALL OfficeInstallationDirectories::getSupportedServiceNames() { - return { "com.sun.star.util.OfficeInstallationDirectories" }; + return { u"com.sun.star.util.OfficeInstallationDirectories"_ustr }; } void OfficeInstallationDirectories::initDirs() @@ -211,13 +211,13 @@ void OfficeInstallationDirectories::initDirs() if ( m_xOfficeBrandDir) return; - osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if ( m_xOfficeBrandDir ) return; uno::Reference< util::XMacroExpander > xExpander = util::theMacroExpander::get(m_xCtx); - m_xOfficeBrandDir = xExpander->expandMacros( "$BRAND_BASE_DIR" ); + m_xOfficeBrandDir = xExpander->expandMacros( u"$BRAND_BASE_DIR"_ustr ); OSL_ENSURE( !m_xOfficeBrandDir->isEmpty(), "Unable to obtain office brand installation directory!" ); @@ -226,7 +226,7 @@ void OfficeInstallationDirectories::initDirs() m_xUserDir = xExpander->expandMacros( - "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE( "bootstrap" ) ":UserInstallation}" ); + u"${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE( "bootstrap" ) ":UserInstallation}"_ustr ); OSL_ENSURE( !m_xUserDir->isEmpty(), "Unable to obtain office user data directory!" ); @@ -236,32 +236,14 @@ void OfficeInstallationDirectories::initDirs() } -namespace { - -struct Instance { - explicit Instance( - css::uno::Reference<css::uno::XComponentContext> const & context): - instance(static_cast<cppu::OWeakObject *>( - new comphelper::OfficeInstallationDirectories(context))) - {} - - rtl::Reference<css::uno::XInterface> instance; -}; - -struct Singleton: - public rtl::StaticWithArg< - Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton> -{}; - -} extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_util_OfficeInstallationDirectories( css::uno::XComponentContext *context, css::uno::Sequence<css::uno::Any> const &) { - return cppu::acquire(static_cast<cppu::OWeakObject *>( - Singleton::get(context).instance.get())); + return cppu::acquire( + new comphelper::OfficeInstallationDirectories(context)); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/officeinstdir/officeinstallationdirectories.hxx b/comphelper/source/officeinstdir/officeinstallationdirectories.hxx index def6dcbd7e35..d0d86b76c4d5 100644 --- a/comphelper/source/officeinstdir/officeinstallationdirectories.hxx +++ b/comphelper/source/officeinstdir/officeinstallationdirectories.hxx @@ -17,15 +17,14 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_COMPHELPER_SOURCE_OFFICEINSTDIR_OFFICEINSTALLATIONDIRECTORIES_HXX -#define INCLUDED_COMPHELPER_SOURCE_OFFICEINSTDIR_OFFICEINSTALLATIONDIRECTORIES_HXX +#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; } @@ -36,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 @@ -71,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; @@ -78,6 +73,4 @@ private: } // namespace comphelper -#endif /* ! INCLUDED_COMPHELPER_SOURCE_OFFICEINSTDIR_OFFICEINSTALLATIONDIRECTORIES_HXX */ - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/processfactory/processfactory.cxx b/comphelper/source/processfactory/processfactory.cxx index 8df1e244ca19..00827434566f 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; }; @@ -75,7 +75,7 @@ Reference< XMultiServiceFactory > getProcessServiceFactory() Reference< XMultiServiceFactory> xReturn = localProcessFactory.get(); if ( !xReturn.is() ) { - throw DeploymentException( "null process service factory" ); + throw DeploymentException( u"null process service factory"_ustr ); } return xReturn; } @@ -86,8 +86,9 @@ Reference< XComponentContext > getComponentContext( Reference< XComponentContext > xRet; uno::Reference<beans::XPropertySet> const xProps( factory, uno::UNO_QUERY ); if (xProps.is()) { + static constexpr OUStringLiteral DEFAULT_CONTEXT = u"DefaultContext"; try { - xRet.set( xProps->getPropertyValue("DefaultContext"), + xRet.set( xProps->getPropertyValue(DEFAULT_CONTEXT), uno::UNO_QUERY ); } catch (beans::UnknownPropertyException & e) { @@ -99,7 +100,7 @@ Reference< XComponentContext > getComponentContext( if ( !xRet.is() ) { throw DeploymentException( - "no service factory DefaultContext", + u"no service factory DefaultContext"_ustr, Reference<XInterface>(factory, UNO_QUERY) ); } return xRet; @@ -107,7 +108,8 @@ Reference< XComponentContext > getComponentContext( Reference< XComponentContext > getProcessComponentContext() { - return getComponentContext( getProcessServiceFactory() ); + static const uno::Reference<XComponentContext> processComponentContext = getComponentContext( getProcessServiceFactory() ); + return processComponentContext; } } // namespace comphelper diff --git a/comphelper/source/property/ChainablePropertySet.cxx b/comphelper/source/property/ChainablePropertySet.cxx index c4f0d018641d..dfb5c2b3f80d 100644 --- a/comphelper/source/property/ChainablePropertySet.cxx +++ b/comphelper/source/property/ChainablePropertySet.cxx @@ -23,6 +23,7 @@ #include <memory> +#include <optional> using namespace ::comphelper; using namespace ::com::sun::star; @@ -31,29 +32,29 @@ using namespace ::com::sun::star::lang; using namespace ::com::sun::star::beans; ChainablePropertySet::ChainablePropertySet( comphelper::ChainablePropertySetInfo* pInfo, comphelper::SolarMutex* pMutex ) - throw() + noexcept : mpMutex ( pMutex ) , mxInfo ( pInfo ) { } ChainablePropertySet::~ChainablePropertySet() - throw() + noexcept { } // XPropertySet Reference< XPropertySetInfo > SAL_CALL ChainablePropertySet::getPropertySetInfo( ) { - return mxInfo.get(); + return mxInfo; } void SAL_CALL ChainablePropertySet::setPropertyValue( const OUString& rPropertyName, const Any& rValue ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); PropertyInfoHash::const_iterator aIter = mxInfo->maMap.find ( rPropertyName ); @@ -68,9 +69,9 @@ void SAL_CALL ChainablePropertySet::setPropertyValue( const OUString& rPropertyN Any SAL_CALL ChainablePropertySet::getPropertyValue( const OUString& rPropertyName ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); PropertyInfoHash::const_iterator aIter = mxInfo->maMap.find ( rPropertyName ); @@ -109,31 +110,27 @@ 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(); if( nCount != rValues.getLength() ) - throw IllegalArgumentException(); + throw IllegalArgumentException(u"lengths do not match"_ustr, static_cast<cppu::OWeakObject*>(this), -1); if( !nCount ) return; _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 26cf2f6e3d70..4515e5c4314b 100644 --- a/comphelper/source/property/ChainablePropertySetInfo.cxx +++ b/comphelper/source/property/ChainablePropertySetInfo.cxx @@ -31,14 +31,14 @@ ChainablePropertySetInfo::ChainablePropertySetInfo( PropertyInfo const * pMap ) for( ; !pMap->maName.isEmpty(); ++pMap ) { SAL_WARN_IF( - maMap.find(pMap->maName) != maMap.end(), + maMap.contains(pMap->maName), "comphelper", "Duplicate property name \"" << pMap->maName << "\""); maMap[pMap->maName] = pMap; } } ChainablePropertySetInfo::~ChainablePropertySetInfo() - throw() + noexcept { } diff --git a/comphelper/source/property/MasterPropertySet.cxx b/comphelper/source/property/MasterPropertySet.cxx index e5e94b5ad46f..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]; } }; } @@ -61,7 +62,7 @@ SlaveData::SlaveData ( ChainablePropertySet *pSlave) } MasterPropertySet::MasterPropertySet( comphelper::MasterPropertySetInfo* pInfo, comphelper::SolarMutex* pMutex ) - throw() + noexcept : mpMutex ( pMutex ) , mnLastId ( 0 ) , mxInfo ( pInfo ) @@ -69,7 +70,7 @@ MasterPropertySet::MasterPropertySet( comphelper::MasterPropertySetInfo* pInfo, } MasterPropertySet::~MasterPropertySet() - throw() + noexcept { for( const auto& rSlave : maSlaveMap ) delete rSlave.second; @@ -78,11 +79,11 @@ MasterPropertySet::~MasterPropertySet() // XPropertySet Reference< XPropertySetInfo > SAL_CALL MasterPropertySet::getPropertySetInfo( ) { - return mxInfo.get(); + return mxInfo; } void MasterPropertySet::registerSlave ( ChainablePropertySet *pNewSet ) - throw() + noexcept { maSlaveMap [ ++mnLastId ] = new SlaveData ( pNewSet ); mxInfo->add ( pNewSet->mxInfo->maMap, mnLastId ); @@ -91,9 +92,9 @@ void MasterPropertySet::registerSlave ( ChainablePropertySet *pNewSet ) void SAL_CALL MasterPropertySet::setPropertyValue( const OUString& rPropertyName, const Any& rValue ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); PropertyDataHash::const_iterator aIter = mxInfo->maMap.find ( rPropertyName ); @@ -111,9 +112,9 @@ void SAL_CALL MasterPropertySet::setPropertyValue( const OUString& rPropertyName ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mxSlave.get(); // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard2; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard2; if (pSlave->mpMutex) - xMutexGuard2.reset( new osl::Guard< comphelper::SolarMutex >(pSlave->mpMutex) ); + xMutexGuard2.emplace( pSlave->mpMutex ); pSlave->_preSetValues(); pSlave->_setSingleValue( *((*aIter).second->mpInfo), rValue ); @@ -124,9 +125,9 @@ void SAL_CALL MasterPropertySet::setPropertyValue( const OUString& rPropertyName Any SAL_CALL MasterPropertySet::getPropertyValue( const OUString& rPropertyName ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); PropertyDataHash::const_iterator aIter = mxInfo->maMap.find ( rPropertyName ); @@ -145,9 +146,9 @@ Any SAL_CALL MasterPropertySet::getPropertyValue( const OUString& rPropertyName ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mxSlave.get(); // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard2; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard2; if (pSlave->mpMutex) - xMutexGuard2.reset( new osl::Guard< comphelper::SolarMutex >(pSlave->mpMutex) ); + xMutexGuard2.emplace( pSlave->mpMutex ); pSlave->_preGetValues(); pSlave->_getSingleValue( *((*aIter).second->mpInfo), aAny ); @@ -180,9 +181,9 @@ void SAL_CALL MasterPropertySet::removeVetoableChangeListener( const OUString&, void SAL_CALL MasterPropertySet::setPropertyValues( const Sequence< OUString >& aPropertyNames, const Sequence< Any >& aValues ) { // acquire mutex in c-tor and releases it in the d-tor (exception safe!). - std::unique_ptr< osl::Guard< comphelper::SolarMutex > > xMutexGuard; + std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; if (mpMutex) - xMutexGuard.reset( new osl::Guard< comphelper::SolarMutex >(mpMutex) ); + xMutexGuard.emplace( mpMutex ); const sal_Int32 nCount = aPropertyNames.getLength(); @@ -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 1b1a2249ec08..4040b479a05c 100644 --- a/comphelper/source/property/MasterPropertySetInfo.cxx +++ b/comphelper/source/property/MasterPropertySetInfo.cxx @@ -31,14 +31,14 @@ MasterPropertySetInfo::MasterPropertySetInfo( PropertyInfo const * pMap ) for ( ; !pMap->maName.isEmpty(); ++pMap ) { SAL_WARN_IF( - maMap.find(pMap->maName) != maMap.end(), + maMap.contains(pMap->maName), "comphelper", "Duplicate property name \"" << pMap->maName << "\""); maMap[pMap->maName] = new PropertyData ( 0, pMap ); } } MasterPropertySetInfo::~MasterPropertySetInfo() - throw() + noexcept { for( const auto& rObj : maMap ) delete rObj.second; @@ -52,7 +52,7 @@ void MasterPropertySetInfo::add( PropertyInfoHash &rHash, sal_uInt8 nMapId ) for( const auto& rObj : rHash ) { SAL_WARN_IF( - maMap.find(rObj.first) != maMap.end(), + maMap.contains(rObj.first), "comphelper", "Duplicate property name \"" << rObj.first << "\""); maMap[rObj.first] = new PropertyData ( nMapId, rObj.second ); } diff --git a/comphelper/source/property/genericpropertyset.cxx b/comphelper/source/property/genericpropertyset.cxx index fd591774cdeb..c33ed391ec96 100644 --- a/comphelper/source/property/genericpropertyset.cxx +++ b/comphelper/source/property/genericpropertyset.cxx @@ -24,15 +24,14 @@ #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/lang/XTypeProvider.hpp> #include <cppuhelper/weakagg.hxx> -#include <cppuhelper/interfacecontainer.hxx> #include <cppuhelper/supportsservice.hxx> +#include <comphelper/multiinterfacecontainer4.hxx> #include <comphelper/propertysethelper.hxx> -#include <osl/mutex.hxx> +#include <mutex> #include <rtl/ref.hxx> #include <comphelper/genericpropertyset.hxx> #include <comphelper/propertysetinfo.hxx> -using namespace ::osl; using namespace ::cppu; using namespace ::comphelper; using namespace ::com::sun::star; @@ -44,33 +43,27 @@ namespace comphelper { namespace { - struct IMPL_GenericPropertySet_MutexContainer - { - Mutex maMutex; - }; - - class GenericPropertySet : public OWeakAggObject, + class GenericPropertySet : public OWeakObject, public XServiceInfo, public XTypeProvider, - public PropertySetHelper, - private IMPL_GenericPropertySet_MutexContainer + public PropertySetHelper { private: std::map<OUString, Any> maAnyMap; - cppu::OMultiTypeInterfaceContainerHelperVar<OUString> m_aListener; + std::mutex maMutex; + comphelper::OMultiTypeInterfaceContainerHelperVar4<OUString, XPropertyChangeListener> m_aListener; protected: virtual void _setPropertyValues( const PropertyMapEntry** ppEntries, const Any* pValues ) override; virtual void _getPropertyValues( const PropertyMapEntry** ppEntries, Any* pValue ) override; public: - explicit GenericPropertySet( PropertySetInfo* pInfo ) throw(); + explicit GenericPropertySet( PropertySetInfo* pInfo ) noexcept; // XInterface - virtual Any SAL_CALL queryAggregation( const Type & rType ) override; virtual Any SAL_CALL queryInterface( const Type & rType ) override; - virtual void SAL_CALL acquire() throw() override; - virtual void SAL_CALL release() throw() override; + virtual void SAL_CALL acquire() noexcept override; + virtual void SAL_CALL release() noexcept override; // XTypeProvider virtual Sequence< Type > SAL_CALL getTypes( ) override; @@ -90,9 +83,8 @@ namespace comphelper } -GenericPropertySet::GenericPropertySet( PropertySetInfo* pInfo ) throw() +GenericPropertySet::GenericPropertySet( PropertySetInfo* pInfo ) noexcept : PropertySetHelper( pInfo ) -,m_aListener(maMutex) { } @@ -102,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 ) { - OInterfaceContainerHelper * 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() throw() +void SAL_CALL GenericPropertySet::acquire() noexcept { - OWeakAggObject::acquire(); + OWeakObject::acquire(); } -void SAL_CALL GenericPropertySet::release() throw() +void SAL_CALL GenericPropertySet::release() noexcept { - OWeakAggObject::release(); + OWeakObject::release(); } uno::Sequence< uno::Type > SAL_CALL GenericPropertySet::getTypes() @@ -238,12 +217,12 @@ sal_Bool SAL_CALL GenericPropertySet::supportsService( const OUString& ServiceN OUString SAL_CALL GenericPropertySet::getImplementationName() { - return "com.sun.star.comp.comphelper.GenericPropertySet"; + return u"com.sun.star.comp.comphelper.GenericPropertySet"_ustr; } Sequence< OUString > SAL_CALL GenericPropertySet::getSupportedServiceNames( ) { - return { "com.sun.star.beans.XPropertySet" }; + return { u"com.sun.star.beans.XPropertySet"_ustr }; } css::uno::Reference< css::beans::XPropertySet > comphelper::GenericPropertySet_CreateInstance( comphelper::PropertySetInfo* pInfo ) diff --git a/comphelper/source/property/opropertybag.cxx b/comphelper/source/property/opropertybag.cxx index 5f5a1289ba31..eec379ffd761 100644 --- a/comphelper/source/property/opropertybag.cxx +++ b/comphelper/source/property/opropertybag.cxx @@ -30,7 +30,6 @@ #include <cppuhelper/exc_hlp.hxx> #include <algorithm> -#include <iterator> namespace com::sun::star::uno { class XComponentContext; } @@ -84,17 +83,17 @@ namespace comphelper && (_rArguments[1] >>= AllowEmptyPropertyName) && (_rArguments[2] >>= AutomaticAddition)) { - m_aAllowedTypes.insert(aTypes.begin(), aTypes.end()); + m_aAllowedTypes.insert(std::cbegin(aTypes), std::cend(aTypes)); m_bAutoAddProperties = AutomaticAddition; } else { ::comphelper::NamedValueCollection aArguments( _rArguments ); - if ( aArguments.get_ensureType( "AllowedTypes", aTypes ) ) - m_aAllowedTypes.insert( aTypes.begin(), aTypes.end()); + if ( aArguments.get_ensureType( u"AllowedTypes"_ustr, aTypes ) ) + m_aAllowedTypes.insert(std::cbegin(aTypes), std::cend(aTypes)); - aArguments.get_ensureType( "AutomaticAddition", m_bAutoAddProperties ); - aArguments.get_ensureType( "AllowEmptyPropertyName", + aArguments.get_ensureType( u"AutomaticAddition"_ustr, m_bAutoAddProperties ); + aArguments.get_ensureType( u"AllowEmptyPropertyName"_ustr, AllowEmptyPropertyName ); } if (AllowEmptyPropertyName) { @@ -105,7 +104,7 @@ namespace comphelper OUString SAL_CALL OPropertyBag::getImplementationName() { - return "com.sun.star.comp.comphelper.OPropertyBag"; + return u"com.sun.star.comp.comphelper.OPropertyBag"_ustr; } sal_Bool SAL_CALL OPropertyBag::supportsService( const OUString& rServiceName ) @@ -115,7 +114,7 @@ namespace comphelper Sequence< OUString > SAL_CALL OPropertyBag::getSupportedServiceNames( ) { - return { "com.sun.star.beans.PropertyBag" }; + return { u"com.sun.star.beans.PropertyBag"_ustr }; } void OPropertyBag::fireEvents( @@ -198,7 +197,7 @@ namespace comphelper // If we ever have a smarter XPropertyContainer::addProperty interface, we can remove this, ehm, well, hack. Property aProperty; if ( !( _element >>= aProperty ) ) - throw IllegalArgumentException( OUString(), *this, 1 ); + throw IllegalArgumentException( u"element is not Property"_ustr, *this, 1 ); { osl::MutexGuard g(m_aMutex); @@ -207,7 +206,7 @@ namespace comphelper // by m_aDynamicProperties if (!m_aAllowedTypes.empty() && m_aAllowedTypes.find(aProperty.Type) == m_aAllowedTypes.end()) - throw IllegalArgumentException(OUString(), *this, 1); + throw IllegalArgumentException(u"not in list of allowed types"_ustr, *this, 1); m_aDynamicProperties.addVoidProperty(aProperty.Name, aProperty.Type, findFreeHandle(), aProperty.Attributes); @@ -378,8 +377,8 @@ namespace comphelper // their names Sequence< OUString > aNames( aProperties.getLength() ); std::transform( - aProperties.begin(), - aProperties.end(), + std::cbegin(aProperties), + std::cend(aProperties), aNames.getArray(), TransformPropertyToName< Property >() ); @@ -390,7 +389,7 @@ namespace comphelper { aValues = OPropertyBag_PBase::getPropertyValues( aNames ); if ( aValues.getLength() != aNames.getLength() ) - throw RuntimeException(); + throw RuntimeException(u"property name and value counts out of sync"_ustr); } catch( const RuntimeException& ) { @@ -405,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; @@ -426,17 +422,18 @@ namespace comphelper { // sort (the XMultiPropertySet interface requires this) Sequence< PropertyValue > aProperties( _rProps ); + auto [begin, end] = asNonConstRange(aProperties); std::sort( - aProperties.begin(), - aProperties.end(), + begin, + end, ComparePropertyValueByName() ); // a sequence of names Sequence< OUString > aNames( aProperties.getLength() ); std::transform( - aProperties.begin(), - aProperties.end(), + std::cbegin(aProperties), + std::cend(aProperties), aNames.getArray(), TransformPropertyToName< PropertyValue >() ); @@ -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,24 +462,24 @@ 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 Sequence< Any > aValues( aProperties.getLength() ); std::transform( - aProperties.begin(), - aProperties.end(), + std::cbegin(aProperties), + std::cend(aProperties), aValues.getArray(), 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 57ff26b8142e..66c38d870c10 100644 --- a/comphelper/source/property/opropertybag.hxx +++ b/comphelper/source/property/opropertybag.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_COMPHELPER_SOURCE_PROPERTY_OPROPERTYBAG_HXX -#define INCLUDED_COMPHELPER_SOURCE_PROPERTY_OPROPERTYBAG_HXX +#pragma once #include <com/sun/star/lang/XInitialization.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> @@ -26,8 +25,8 @@ #include <com/sun/star/beans/XPropertyBag.hpp> #include <com/sun/star/container/XSet.hpp> -#include <cppuhelper/implbase5.hxx> -#include <comphelper/interfacecontainer2.hxx> +#include <cppuhelper/implbase.hxx> +#include <comphelper/interfacecontainer3.hxx> #include <comphelper/propstate.hxx> #include <comphelper/broadcasthelper.hxx> #include <comphelper/propertybag.hxx> @@ -56,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 @@ -81,7 +80,7 @@ namespace comphelper bool m_bAutoAddProperties; /// for notification - ::comphelper::OInterfaceContainerHelper2 m_NotifyListeners; + ::comphelper::OInterfaceContainerHelper3<css::util::XModifyListener> m_NotifyListeners; /// modify flag bool m_isModified; @@ -216,6 +215,4 @@ namespace comphelper } // namespace comphelper -#endif // INCLUDED_COMPHELPER_SOURCE_PROPERTY_OPROPERTYBAG_HXX - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/property/propagg.cxx b/comphelper/source/property/propagg.cxx index af1092c9748b..f84649b3bf19 100644 --- a/comphelper/source/property/propagg.cxx +++ b/comphelper/source/property/propagg.cxx @@ -24,10 +24,10 @@ #include <osl/diagnose.h> #include <sal/log.hxx> #include <com/sun/star/beans/PropertyAttribute.hpp> - +#include <o3tl/sorted_vector.hxx> #include <typeinfo> #include <algorithm> -#include <set> +#include <cstddef> #include <unordered_set> #include <memory> @@ -84,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 @@ -112,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; } } @@ -127,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 ) { @@ -171,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) { @@ -187,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 ]; @@ -200,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) { @@ -208,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; } @@ -227,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++; @@ -250,7 +250,7 @@ namespace internal { private: OPropertySetAggregationHelper& m_rAggregationHelper; - std::set< sal_Int32 > m_aProperties; + o3tl::sorted_vector< sal_Int32 > m_aProperties; sal_Int32 m_nCurrentlyForwarding; public: @@ -265,7 +265,7 @@ namespace internal /** checks whether the forwarder is responsible for the given property */ - bool isResponsibleFor( sal_Int32 _nHandle ); + bool isResponsibleFor( sal_Int32 _nHandle ) const; /// actually forwards a property value to the aggregate /// @@ -289,7 +289,7 @@ namespace internal } - bool PropertyForwarder::isResponsibleFor( sal_Int32 _nHandle ) + bool PropertyForwarder::isResponsibleFor( sal_Int32 _nHandle ) const { return m_aProperties.find( _nHandle ) != m_aProperties.end(); } @@ -384,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 ); @@ -587,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(u"lengths do not match"_ustr, static_cast<XPropertySet*>(this), + -1); try { setPropertyValue( _rPropertyNames[0], _rValues[0] ); @@ -629,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(u"lengths do not match"_ustr, + static_cast<XPropertySet*>(this), -1); // aggregate's names Sequence< OUString > AggPropertyNames( nAggCount ); @@ -648,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 @@ -692,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 75208c2c51b4..7d57baeb39cb 100644 --- a/comphelper/source/property/property.cxx +++ b/comphelper/source/property/property.cxx @@ -21,6 +21,7 @@ #include <comphelper/sequence.hxx> #include <osl/diagnose.h> #include <sal/log.hxx> +#include <comphelper/diagnose_ex.hxx> #if OSL_DEBUG_LEVEL > 0 #include <cppuhelper/exc_hlp.hxx> @@ -87,10 +88,12 @@ void copyProperties(const Reference<XPropertySet>& _rxSource, catch (Exception&) { #if OSL_DEBUG_LEVEL > 0 - OUStringBuffer aBuffer; - aBuffer.append( "::comphelper::copyProperties: could not copy property '" ); - aBuffer.append(rSourceProp.Name ); - aBuffer.append( "' to the destination set (a '" ); + TOOLS_WARN_EXCEPTION("comphelper", "Caught exception copying properties"); + + OUStringBuffer aBuffer( + "::comphelper::copyProperties: could not copy property '" + + rSourceProp.Name + + "' to the destination set (a '" ); Reference< XServiceInfo > xSI( _rxDest, UNO_QUERY ); if ( xSI.is() ) @@ -99,21 +102,21 @@ void copyProperties(const Reference<XPropertySet>& _rxSource, } else { - aBuffer.append( OUString::createFromAscii(typeid( *_rxDest ).name()) ); + aBuffer.appendAscii( typeid( *_rxDest ).name() ); } aBuffer.append( "' implementation).\n" ); Any aException( ::cppu::getCaughtException() ); - aBuffer.append( "Caught an exception of type '" ); - aBuffer.append( aException.getValueTypeName() ); - aBuffer.append( "'" ); + aBuffer.append( "Caught an exception of type '" + + aException.getValueTypeName() + + "'" ); Exception aBaseException; if ( ( aException >>= aBaseException ) && !aBaseException.Message.isEmpty() ) { - aBuffer.append( ", saying '" ); - aBuffer.append( aBaseException.Message ); - aBuffer.append( "'" ); + aBuffer.append( ", saying '" + + aBaseException.Message + + "'" ); } aBuffer.append( "." ); @@ -138,31 +141,25 @@ bool hasProperty(const OUString& _rName, const Reference<XPropertySet>& _rxSet) void RemoveProperty(Sequence<Property>& _rProps, const OUString& _rPropName) { - sal_Int32 nLen = _rProps.getLength(); - // binary search - const Property* pProperties = _rProps.getConstArray(); Property aNameProp(_rPropName, 0, Type(), 0); - const Property* pResult = std::lower_bound(pProperties, pProperties + nLen, aNameProp, PropertyCompareByName()); + const Property* pResult = std::lower_bound(std::cbegin(_rProps), std::cend(_rProps), aNameProp, PropertyCompareByName()); - if ( pResult != _rProps.end() && pResult->Name == _rPropName ) + if ( pResult != std::cend(_rProps) && pResult->Name == _rPropName) { - OSL_ENSURE(pResult->Name == _rPropName, "::RemoveProperty Properties not sorted"); - removeElementAt(_rProps, pResult - pProperties); + removeElementAt(_rProps, pResult - std::cbegin(_rProps)); } } void ModifyPropertyAttributes(Sequence<Property>& seqProps, const OUString& sPropName, sal_Int16 nAddAttrib, sal_Int16 nRemoveAttrib) { - sal_Int32 nLen = seqProps.getLength(); - // binary search - Property* pProperties = seqProps.getArray(); + auto [begin, end] = asNonConstRange(seqProps); Property aNameProp(sPropName, 0, Type(), 0); - Property* pResult = std::lower_bound(pProperties, pProperties + nLen, aNameProp, PropertyCompareByName()); + Property* pResult = std::lower_bound(begin, end, aNameProp, PropertyCompareByName()); - if ( (pResult != seqProps.end()) && (pResult->Name == sPropName) ) + if ( (pResult != end) && (pResult->Name == sPropName) ) { pResult->Attributes |= nAddAttrib; pResult->Attributes &= ~nRemoveAttrib; diff --git a/comphelper/source/property/propertybag.cxx b/comphelper/source/property/propertybag.cxx index ac8fc17ff1b7..b85786705cf0 100644 --- a/comphelper/source/property/propertybag.cxx +++ b/comphelper/source/property/propertybag.cxx @@ -29,7 +29,7 @@ #include <com/sun/star/beans/UnknownPropertyException.hpp> #include <map> - +#include <string_view> namespace comphelper { @@ -48,16 +48,8 @@ namespace comphelper namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute; - typedef std::map< sal_Int32, Any > MapInt2Any; - struct PropertyBag_Impl - { - PropertyBag_Impl() : m_bAllowEmptyPropertyName(false) { } - MapInt2Any aDefaults; - bool m_bAllowEmptyPropertyName; - }; - PropertyBag::PropertyBag() - :m_pImpl( new PropertyBag_Impl ) + : m_bAllowEmptyPropertyName(false) { } @@ -68,17 +60,17 @@ namespace comphelper void PropertyBag::setAllowEmptyPropertyName( bool i_isAllowed ) { - m_pImpl->m_bAllowEmptyPropertyName = i_isAllowed; + m_bAllowEmptyPropertyName = i_isAllowed; } namespace { - void lcl_checkForEmptyName( const bool _allowEmpty, const OUString& _name ) + void lcl_checkForEmptyName( const bool _allowEmpty, std::u16string_view _name ) { - if ( !_allowEmpty && _name.isEmpty() ) + if ( !_allowEmpty && _name.empty() ) throw IllegalArgumentException( - "The property name must not be empty.", + u"The property name must not be empty."_ustr, // TODO: resource nullptr, 1 @@ -89,7 +81,7 @@ namespace comphelper { if ( _container.hasPropertyByName( _name ) || _container.hasPropertyByHandle( _handle ) ) throw PropertyExistException( - "Property name or handle already used.", + u"Property name or handle already used."_ustr, nullptr ); } @@ -98,7 +90,7 @@ namespace comphelper { if ( _container.hasPropertyByName( _name ) || _container.hasPropertyByHandle( _handle ) ) throw ElementExistException( - "Property name or handle already used.", + u"Property name or handle already used."_ustr, nullptr ); } @@ -110,14 +102,14 @@ namespace comphelper { if ( _rType.getTypeClass() == TypeClass_VOID ) throw IllegalArgumentException( - "Illegal property type: VOID", + u"Illegal property type: VOID"_ustr, // TODO: resource nullptr, 1 ); // check name/handle sanity - lcl_checkForEmptyName( m_pImpl->m_bAllowEmptyPropertyName, _rName ); + lcl_checkForEmptyName( m_bAllowEmptyPropertyName, _rName ); lcl_checkNameAndHandle_ElementExistException( _rName, _nHandle, *this ); // register the property @@ -125,7 +117,7 @@ namespace comphelper registerPropertyNoMember( _rName, _nHandle, _nAttributes | PropertyAttribute::MAYBEVOID, _rType, css::uno::Any() ); // remember the default - m_pImpl->aDefaults.emplace( _nHandle, Any() ); + aDefaults.emplace( _nHandle, Any() ); } @@ -135,12 +127,12 @@ namespace comphelper const Type& aPropertyType = _rInitialValue.getValueType(); if ( aPropertyType.getTypeClass() == TypeClass_VOID ) throw IllegalTypeException( - "The initial value must be non-NULL to determine the property type.", + u"The initial value must be non-NULL to determine the property type."_ustr, // TODO: resource nullptr ); // check name/handle sanity - lcl_checkForEmptyName( m_pImpl->m_bAllowEmptyPropertyName, _rName ); + lcl_checkForEmptyName( m_bAllowEmptyPropertyName, _rName ); lcl_checkNameAndHandle_PropertyExistException( _rName, _nHandle, *this ); // register the property @@ -148,7 +140,7 @@ namespace comphelper _rInitialValue ); // remember the default - m_pImpl->aDefaults.emplace( _nHandle, _rInitialValue ); + aDefaults.emplace( _nHandle, _rInitialValue ); } @@ -162,7 +154,7 @@ namespace comphelper revokeProperty( nHandle ); - m_pImpl->aDefaults.erase( nHandle ); + aDefaults.erase( nHandle ); } @@ -199,9 +191,9 @@ namespace comphelper if ( !hasPropertyByHandle( _nHandle ) ) throw UnknownPropertyException(OUString::number(_nHandle)); - MapInt2Any::const_iterator pos = m_pImpl->aDefaults.find( _nHandle ); - OSL_ENSURE( pos != m_pImpl->aDefaults.end(), "PropertyBag::getPropertyDefaultByHandle: inconsistency!" ); - if ( pos != m_pImpl->aDefaults.end() ) + auto pos = aDefaults.find( _nHandle ); + OSL_ENSURE( pos != aDefaults.end(), "PropertyBag::getPropertyDefaultByHandle: inconsistency!" ); + if ( pos != aDefaults.end() ) _out_rValue = pos->second; else _out_rValue.clear(); diff --git a/comphelper/source/property/propertycontainer.cxx b/comphelper/source/property/propertycontainer.cxx index 2b5685405604..ad24c5f30aa7 100644 --- a/comphelper/source/property/propertycontainer.cxx +++ b/comphelper/source/property/propertycontainer.cxx @@ -26,7 +26,6 @@ namespace comphelper using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::lang; using namespace ::com::sun::star::beans; OPropertyContainer::OPropertyContainer(::cppu::OBroadcastHelper& _rBHelper) diff --git a/comphelper/source/property/propertycontainer2.cxx b/comphelper/source/property/propertycontainer2.cxx new file mode 100644 index 000000000000..5a3bfa4be285 --- /dev/null +++ b/comphelper/source/property/propertycontainer2.cxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <comphelper/propertycontainer2.hxx> +#include <cppuhelper/typeprovider.hxx> + +namespace comphelper +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; + +OPropertyContainer2::OPropertyContainer2() {} + +OPropertyContainer2::~OPropertyContainer2() {} + +Sequence<Type> OPropertyContainer2::getBaseTypes() +{ + // just the types from our one and only base class + ::cppu::OTypeCollection aTypes(cppu::UnoType<XPropertySet>::get(), + cppu::UnoType<XFastPropertySet>::get(), + cppu::UnoType<XMultiPropertySet>::get()); + return aTypes.getTypes(); +} + +bool OPropertyContainer2::convertFastPropertyValue(std::unique_lock<std::mutex>& /*rGuard*/, + Any& _rConvertedValue, Any& _rOldValue, + sal_Int32 _nHandle, const Any& _rValue) +{ + return OPropertyContainerHelper::convertFastPropertyValue(_rConvertedValue, _rOldValue, + _nHandle, _rValue); +} + +void OPropertyContainer2::setFastPropertyValue_NoBroadcast(std::unique_lock<std::mutex>& /*rGuard*/, + sal_Int32 _nHandle, const Any& _rValue) +{ + OPropertyContainerHelper::setFastPropertyValue(_nHandle, _rValue); +} + +void OPropertyContainer2::getFastPropertyValue(std::unique_lock<std::mutex>& /*rGuard*/, + Any& _rValue, sal_Int32 _nHandle) const +{ + OPropertyContainerHelper::getFastPropertyValue(_rValue, _nHandle); +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/property/propertycontainerhelper.cxx b/comphelper/source/property/propertycontainerhelper.cxx index 1ba31ec8258f..ee81100ae617 100644 --- a/comphelper/source/property/propertycontainerhelper.cxx +++ b/comphelper/source/property/propertycontainerhelper.cxx @@ -26,6 +26,7 @@ #include <com/sun/star/beans/UnknownPropertyException.hpp> #include <algorithm> +#include <utility> namespace comphelper @@ -51,7 +52,7 @@ namespace struct PropertyDescriptionNameMatch { OUString const m_rCompare; - explicit PropertyDescriptionNameMatch( const OUString& _rCompare ) : m_rCompare( _rCompare ) { } + explicit PropertyDescriptionNameMatch( OUString _aCompare ) : m_rCompare(std::move( _aCompare )) { } bool operator() (const PropertyDescription& x ) const { @@ -269,7 +270,7 @@ bool OPropertyContainerHelper::convertFastPropertyValue( if (PropertyDescription::LocationType::HoldMyself == aPos->eLocated) { - OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < static_cast<sal_Int32>(m_aHoldProperties.size()), + OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < m_aHoldProperties.size(), "OPropertyContainerHelper::convertFastPropertyValue: invalid position !"); auto aIter = m_aHoldProperties.begin() + aPos->aLocation.nOwnClassVectorIndex; pPropContainer = &(*aIter); @@ -407,7 +408,7 @@ void OPropertyContainerHelper::getFastPropertyValue(Any& _rValue, sal_Int32 _nHa switch (aPos->eLocated) { case PropertyDescription::LocationType::HoldMyself: - OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < static_cast<sal_Int32>(m_aHoldProperties.size()), + OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < m_aHoldProperties.size(), "OPropertyContainerHelper::convertFastPropertyValue: invalid position !"); _rValue = m_aHoldProperties[aPos->aLocation.nOwnClassVectorIndex]; break; @@ -469,15 +470,15 @@ void OPropertyContainerHelper::describeProperties(Sequence< Property >& _rProps) } // as our property vector is sorted by handles, not by name, we have to sort aOwnProps - std::sort(aOwnProps.begin(), aOwnProps.end(), PropertyCompareByName()); + auto [begin, end] = asNonConstRange(aOwnProps); + std::sort(begin, end, PropertyCompareByName()); // unfortunately the STL merge function does not allow the output range to overlap one of the input ranges, // so we need an extra sequence - Sequence< Property > aOutput; - aOutput.realloc(_rProps.getLength() + aOwnProps.getLength()); + Sequence< Property > aOutput(_rProps.getLength() + aOwnProps.getLength()); // do the merge - std::merge( _rProps.begin(), _rProps.end(), // input 1 - aOwnProps.begin(), aOwnProps.end(), // input 2 + std::merge( std::cbegin(_rProps), std::cend(_rProps), // input 1 + std::cbegin(aOwnProps), std::cend(aOwnProps), // input 2 aOutput.getArray(), // output PropertyCompareByName() // compare operator ); diff --git a/comphelper/source/property/propertysethelper.cxx b/comphelper/source/property/propertysethelper.cxx index f397cdc13925..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; @@ -30,52 +31,36 @@ using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::lang; -namespace comphelper -{ -class PropertySetHelperImpl -{ -public: - PropertyMapEntry const * find( const OUString& aName ) const throw(); - - rtl::Reference<PropertySetInfo> mxInfo; -}; -} - -PropertyMapEntry const * PropertySetHelperImpl::find( const OUString& aName ) const throw() +static PropertyMapEntry const * find( const rtl::Reference<PropertySetInfo>& mxInfo, const OUString& aName ) noexcept { PropertyMap::const_iterator aIter = mxInfo->getPropertyMap().find( aName ); if( mxInfo->getPropertyMap().end() != aIter ) - { return (*aIter).second; - } else - { return nullptr; - } } -PropertySetHelper::PropertySetHelper( rtl::Reference<comphelper::PropertySetInfo> const & xInfo ) throw() - : mpImpl(new PropertySetHelperImpl) +PropertySetHelper::PropertySetHelper( rtl::Reference<comphelper::PropertySetInfo> xInfo ) noexcept + : mxInfo(std::move(xInfo)) { - mpImpl->mxInfo = xInfo; } -PropertySetHelper::~PropertySetHelper() throw() +PropertySetHelper::~PropertySetHelper() noexcept { } // XPropertySet Reference< XPropertySetInfo > SAL_CALL PropertySetHelper::getPropertySetInfo( ) { - return mpImpl->mxInfo.get(); + return mxInfo; } void SAL_CALL PropertySetHelper::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) { PropertyMapEntry const * aEntries[2]; - aEntries[0] = mpImpl->find( aPropertyName ); + aEntries[0] = find( mxInfo, aPropertyName ); if( nullptr == aEntries[0] ) throw UnknownPropertyException( aPropertyName, static_cast< XPropertySet* >( this ) ); @@ -88,7 +73,7 @@ void SAL_CALL PropertySetHelper::setPropertyValue( const OUString& aPropertyName Any SAL_CALL PropertySetHelper::getPropertyValue( const OUString& PropertyName ) { PropertyMapEntry const * aEntries[2]; - aEntries[0] = mpImpl->find( PropertyName ); + aEntries[0] = find( mxInfo, PropertyName ); if( nullptr == aEntries[0] ) throw UnknownPropertyException( PropertyName, static_cast< XPropertySet* >( this ) ); @@ -127,60 +112,45 @@ void SAL_CALL PropertySetHelper::setPropertyValues( const Sequence< OUString >& const sal_Int32 nCount = rPropertyNames.getLength(); if( nCount != rValues.getLength() ) - throw IllegalArgumentException(); + 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] = mpImpl->find( *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) { const sal_Int32 nCount = rPropertyNames.getLength(); - Sequence< Any > aValues; - if( nCount ) - { - 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++ ) - { - pEntries[n] = mpImpl->find( *pNames ); - bUnknown = nullptr == pEntries[n]; - } + if( !nCount ) + return Sequence< Any >(); - if( !bUnknown ) - { - aValues.realloc(nCount); - _getPropertyValues( pEntries.get(), aValues.getArray() ); - } + std::unique_ptr<PropertyMapEntry const *[]> pEntries(new PropertyMapEntry const *[nCount+1]); - if( bUnknown ) - throw RuntimeException( *pNames, static_cast< XPropertySet* >( this ) ); + for (sal_Int32 n = 0; n < nCount; n++) + { + pEntries[n] = find(mxInfo, rPropertyNames[n]); + if (!pEntries[n]) + throw UnknownPropertyException(rPropertyNames[n], static_cast<XPropertySet*>(this)); } + pEntries[nCount] = nullptr; + Sequence< Any > aValues(nCount); + _getPropertyValues( pEntries.get(), aValues.getArray() ); return aValues; + } void SAL_CALL PropertySetHelper::addPropertiesChangeListener( const Sequence< OUString >&, const Reference< XPropertiesChangeListener >& ) @@ -203,7 +173,7 @@ PropertyState SAL_CALL PropertySetHelper::getPropertyState( const OUString& Prop { PropertyMapEntry const * aEntries[2]; - aEntries[0] = mpImpl->find( PropertyName ); + aEntries[0] = find( mxInfo, PropertyName ); if( aEntries[0] == nullptr ) throw UnknownPropertyException( PropertyName, static_cast< XPropertySet* >( this ) ); @@ -223,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] = mpImpl->find( *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; @@ -250,7 +213,7 @@ Sequence< PropertyState > SAL_CALL PropertySetHelper::getPropertyStates( const S void SAL_CALL PropertySetHelper::setPropertyToDefault( const OUString& PropertyName ) { - PropertyMapEntry const *pEntry = mpImpl->find( PropertyName ); + PropertyMapEntry const *pEntry = find(mxInfo, PropertyName ); if( nullptr == pEntry ) throw UnknownPropertyException( PropertyName, static_cast< XPropertySet* >( this ) ); @@ -259,7 +222,7 @@ void SAL_CALL PropertySetHelper::setPropertyToDefault( const OUString& PropertyN Any SAL_CALL PropertySetHelper::getPropertyDefault( const OUString& aPropertyName ) { - PropertyMapEntry const * pEntry = mpImpl->find( aPropertyName ); + PropertyMapEntry const * pEntry = find(mxInfo, aPropertyName ); if( nullptr == pEntry ) throw UnknownPropertyException( aPropertyName, static_cast< XPropertySet* >( this ) ); diff --git a/comphelper/source/property/propertysetinfo.cxx b/comphelper/source/property/propertysetinfo.cxx index a77a32799c7d..1d4ad2be8d25 100644 --- a/comphelper/source/property/propertysetinfo.cxx +++ b/comphelper/source/property/propertysetinfo.cxx @@ -20,74 +20,69 @@ #include <comphelper/propertysetinfo.hxx> #include <comphelper/sequence.hxx> -#include <vector> using namespace ::comphelper; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; -using namespace ::com::sun::star::lang; -namespace comphelper +PropertySetInfo::PropertySetInfo() noexcept { -class PropertyMapImpl final -{ -public: - PropertyMapImpl() throw(); - - void add(PropertyMapEntry const * pMap) throw(); - void remove( const OUString& aName ) throw(); - - std::vector< Property > const & getProperties() throw(); - - const PropertyMap& getPropertyMap() const throw() { return maPropertyMap;} +} - /// @throws UnknownPropertyException - Property getPropertyByName( const OUString& aName ); - bool hasPropertyByName( const OUString& aName ) throw(); +PropertySetInfo::PropertySetInfo( std::span<const PropertyMapEntry> pMap ) noexcept +{ + maPropertyMap.reserve(pMap.size()); + for (const auto & rEntry : pMap) + { + // check for duplicates + assert(maPropertyMap.find(rEntry.maName) == maPropertyMap.end()); + // Make sure there are no accidental empty entries left at the end of the array from + // when this method used to take a empty-terminated array. + assert(!rEntry.maName.isEmpty()); -private: - PropertyMap maPropertyMap; - std::vector< Property > maProperties; -}; + maPropertyMap.emplace(rEntry.maName, &rEntry); + } } -PropertyMapImpl::PropertyMapImpl() throw() +PropertySetInfo::~PropertySetInfo() noexcept { } -void PropertyMapImpl::add(PropertyMapEntry const * pMap) throw() +void PropertySetInfo::add( std::span<PropertyMapEntry const> pMap ) noexcept { - while (!pMap->maName.isEmpty()) + maPropertyMap.reserve(maPropertyMap.size() + pMap.size()); + for (const auto & rEntry : pMap) { // check for duplicates - assert(maPropertyMap.find(pMap->maName) == maPropertyMap.end()); - - maPropertyMap[pMap->maName] = pMap; + assert(maPropertyMap.find(rEntry.maName) == maPropertyMap.end()); + // Make sure there are no accidental empty entries left at the end of the array from + // when this method used to take a empty-terminated array. + assert(!rEntry.maName.isEmpty()); - maProperties.clear(); - - pMap = &pMap[1]; + maPropertyMap.emplace(rEntry.maName, &rEntry); } + + // clear cache + maProperties.realloc(0); } -void PropertyMapImpl::remove( const OUString& aName ) throw() +void PropertySetInfo::remove( const OUString& aName ) noexcept { maPropertyMap.erase( aName ); - - maProperties.clear(); + maProperties.realloc(0); } -std::vector< Property > const & PropertyMapImpl::getProperties() throw() +Sequence< css::beans::Property > SAL_CALL PropertySetInfo::getProperties() { // maybe we have to generate the properties after // a change in the property map or at first call // to getProperties if( maProperties.size() != maPropertyMap.size() ) { - maProperties.resize( maPropertyMap.size() ); - auto propIter = maProperties.begin(); + maProperties.realloc( maPropertyMap.size() ); + auto propIter = maProperties.getArray(); for( const auto& rProperty : maPropertyMap ) { @@ -101,12 +96,10 @@ std::vector< Property > const & PropertyMapImpl::getProperties() throw() ++propIter; } } - return maProperties; } - -Property PropertyMapImpl::getPropertyByName( const OUString& aName ) +Property SAL_CALL PropertySetInfo::getPropertyByName( const OUString& aName ) { PropertyMap::iterator aIter = maPropertyMap.find( aName ); @@ -118,73 +111,9 @@ Property PropertyMapImpl::getPropertyByName( const OUString& aName ) return Property( aName, pEntry->mnHandle, pEntry->maType, pEntry->mnAttributes ); } -bool PropertyMapImpl::hasPropertyByName( const OUString& aName ) throw() -{ - return maPropertyMap.find( aName ) != maPropertyMap.end(); -} - - -PropertySetInfo::PropertySetInfo() throw() - : mpImpl(new PropertyMapImpl) -{ -} - -PropertySetInfo::PropertySetInfo( PropertyMapEntry const * pMap ) throw() - : mpImpl(new PropertyMapImpl) -{ - mpImpl->add( pMap ); -} - -PropertySetInfo::PropertySetInfo(uno::Sequence<beans::Property> const& rProps) throw() - : mpImpl(new PropertyMapImpl) -{ - PropertyMapEntry * pEntries(new PropertyMapEntry[rProps.getLength() + 1]); - PropertyMapEntry * pEntry(&pEntries[0]); - for (auto const& it : rProps) - { - pEntry->maName = it.Name; - pEntry->mnHandle = it.Handle; - pEntry->maType = it.Type; - pEntry->mnAttributes = it.Attributes; - pEntry->mnMemberId = 0; - ++pEntry; - } - pEntry->maName = OUString(); - mpImpl->add(pEntries); -} - -PropertySetInfo::~PropertySetInfo() throw() -{ -} - -void PropertySetInfo::add( PropertyMapEntry const * pMap ) throw() -{ - mpImpl->add( pMap ); -} - -void PropertySetInfo::remove( const OUString& aName ) throw() -{ - mpImpl->remove( aName ); -} - -Sequence< css::beans::Property > SAL_CALL PropertySetInfo::getProperties() -{ - return comphelper::containerToSequence(mpImpl->getProperties()); -} - -Property SAL_CALL PropertySetInfo::getPropertyByName( const OUString& aName ) -{ - return mpImpl->getPropertyByName( aName ); -} - -sal_Bool SAL_CALL PropertySetInfo::hasPropertyByName( const OUString& Name ) -{ - return mpImpl->hasPropertyByName( Name ); -} - -const PropertyMap& PropertySetInfo::getPropertyMap() const throw() +sal_Bool SAL_CALL PropertySetInfo::hasPropertyByName( const OUString& aName ) { - return mpImpl->getPropertyMap(); + return maPropertyMap.contains( aName ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/property/propertystatecontainer.cxx b/comphelper/source/property/propertystatecontainer.cxx index e83d4752a57e..9ab7f534dc02 100644 --- a/comphelper/source/property/propertystatecontainer.cxx +++ b/comphelper/source/property/propertystatecontainer.cxx @@ -17,8 +17,11 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <sal/config.h> + +#include <string_view> + #include <comphelper/propertystatecontainer.hxx> -#include <rtl/ustrbuf.hxx> namespace comphelper @@ -27,17 +30,16 @@ namespace comphelper using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; - using namespace ::com::sun::star::lang; namespace { - OUString lcl_getUnknownPropertyErrorMessage( const OUString& _rPropertyName ) + OUString lcl_getUnknownPropertyErrorMessage( std::u16string_view _rPropertyName ) { // TODO: perhaps it's time to think about resources in the comphelper module? // Would be nice to have localized exception strings (a simply resource file containing // strings only would suffice, and could be realized with a UNO service, so we do not // need the dependency to the Tools project) - return "The property \"" + _rPropertyName + "\" is unknown."; + return OUString::Concat("The property \"") + _rPropertyName + "\" is unknown."; } } @@ -87,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..b0139c747969 --- /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(u"lengths do not match"_ustr, + 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 d48a72d094cf..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; @@ -210,13 +207,13 @@ namespace comphelper } - void SAL_CALL OStatefulPropertySet::acquire() throw() + void SAL_CALL OStatefulPropertySet::acquire() noexcept { ::cppu::OWeakObject::acquire(); } - void SAL_CALL OStatefulPropertySet::release() throw() + void SAL_CALL OStatefulPropertySet::release() noexcept { ::cppu::OWeakObject::release(); } diff --git a/comphelper/source/streaming/basicio.cxx b/comphelper/source/streaming/basicio.cxx index d86427b7de81..534d8b4cd0a1 100644 --- a/comphelper/source/streaming/basicio.cxx +++ b/comphelper/source/streaming/basicio.cxx @@ -18,6 +18,8 @@ */ #include <comphelper/basicio.hxx> +#include <comphelper/bytereader.hxx> +#include <comphelper/servicehelper.hxx> #include <com/sun/star/awt/FontDescriptor.hpp> namespace comphelper @@ -157,6 +159,9 @@ const css::uno::Reference<css::io::XObjectOutputStream>& operator << (const css: return _rxOutStream; } +ByteReader::~ByteReader() {} + +ByteWriter::~ByteWriter() {} } // namespace comphelper diff --git a/comphelper/source/streaming/memorystream.cxx b/comphelper/source/streaming/memorystream.cxx index b275ac34b06e..b457f4b42ca8 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,12 +102,13 @@ private: UNOMemoryStream::UNOMemoryStream() : mnCursor(0) { + maData.reserve(1 * 1024 * 1024); } // XServiceInfo OUString SAL_CALL UNOMemoryStream::getImplementationName() { - return "com.sun.star.comp.MemoryStream"; + return u"com.sun.star.comp.MemoryStream"_ustr; } sal_Bool SAL_CALL UNOMemoryStream::supportsService(const OUString& ServiceName) @@ -106,7 +118,7 @@ sal_Bool SAL_CALL UNOMemoryStream::supportsService(const OUString& ServiceName) css::uno::Sequence<OUString> SAL_CALL UNOMemoryStream::getSupportedServiceNames() { - return { "com.sun.star.comp.MemoryStream" }; + return { u"com.sun.star.comp.MemoryStream"_ustr }; } // XStream @@ -124,7 +136,7 @@ Reference< XOutputStream > SAL_CALL UNOMemoryStream::getOutputStream( ) sal_Int32 SAL_CALL UNOMemoryStream::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) { if( nBytesToRead < 0 ) - throw IOException(); + throw IOException(u"nBytesToRead < 0"_ustr); nBytesToRead = std::min( nBytesToRead, available() ); aData.realloc( nBytesToRead ); @@ -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; } @@ -149,7 +161,7 @@ sal_Int32 SAL_CALL UNOMemoryStream::readSomeBytes( Sequence< sal_Int8 >& aData, void SAL_CALL UNOMemoryStream::skipBytes( sal_Int32 nBytesToSkip ) { if( nBytesToSkip < 0 ) - throw IOException(); + throw IOException(u"nBytesToSkip < 0"_ustr); mnCursor += std::min( nBytesToSkip, available() ); } @@ -168,10 +180,10 @@ void SAL_CALL UNOMemoryStream::closeInput() void SAL_CALL UNOMemoryStream::seek( sal_Int64 location ) { if( (location < 0) || (location > SAL_MAX_INT32) ) - throw IllegalArgumentException("this implementation does not support more than 2GB!", static_cast<OWeakObject*>(this), 0 ); + throw IllegalArgumentException(u"this implementation does not support more than 2GB!"_ustr, 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; @@ -198,15 +215,15 @@ void SAL_CALL UNOMemoryStream::writeBytes( const Sequence< sal_Int8 >& aData ) if( nNewSize > SAL_MAX_INT32 ) { OSL_ASSERT(false); - throw IOException("this implementation does not support more than 2GB!", static_cast<OWeakObject*>(this) ); + throw IOException(u"this implementation does not support more than 2GB!"_ustr, static_cast<OWeakObject*>(this) ); } - if( static_cast< sal_Int32 >( nNewSize ) > static_cast< sal_Int32 >( maData.size() ) ) + if( o3tl::make_unsigned( nNewSize ) > maData.size() ) maData.resize( nNewSize ); sal_Int8* pData = &(*maData.begin()); sal_Int8* pCursor = &(pData[mnCursor]); - memcpy( pCursor, aData.getConstArray(), nBytesToWrite ); + memcpy(pCursor, pInData, nBytesToWrite); mnCursor += nBytesToWrite; } diff --git a/comphelper/source/streaming/oslfile2streamwrap.cxx b/comphelper/source/streaming/oslfile2streamwrap.cxx index eff916a833ff..243634610c2b 100644 --- a/comphelper/source/streaming/oslfile2streamwrap.cxx +++ b/comphelper/source/streaming/oslfile2streamwrap.cxx @@ -51,10 +51,10 @@ sal_Int32 SAL_CALL OSLInputStreamWrapper::readBytes(css::uno::Sequence< sal_Int8 if (nBytesToRead < 0) throw css::io::BufferSizeExceededException(OUString(),static_cast<css::uno::XWeak*>(this)); - ::osl::MutexGuard aGuard( m_aMutex ); - aData.realloc(nBytesToRead); + std::scoped_lock aGuard( m_aMutex ); + sal_uInt64 nRead = 0; FileBase::RC eError = m_pFile->read(static_cast<void*>(aData.getArray()), nBytesToRead, nRead); if (eError != FileBase::E_None) @@ -80,7 +80,7 @@ sal_Int32 SAL_CALL OSLInputStreamWrapper::readSomeBytes(css::uno::Sequence< sal_ void SAL_CALL OSLInputStreamWrapper::skipBytes(sal_Int32 nBytesToSkip) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if (!m_pFile) throw css::io::NotConnectedException(OUString(), static_cast<css::uno::XWeak*>(this)); @@ -97,7 +97,7 @@ void SAL_CALL OSLInputStreamWrapper::skipBytes(sal_Int32 nBytesToSkip) sal_Int32 SAL_CALL OSLInputStreamWrapper::available() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if (!m_pFile) throw css::io::NotConnectedException(OUString(), static_cast<css::uno::XWeak*>(this)); diff --git a/comphelper/source/streaming/seekableinput.cxx b/comphelper/source/streaming/seekableinput.cxx index e4f654043dc7..6fd418df36ca 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(u"no component context"_ustr, *this, 1); } @@ -90,7 +92,7 @@ void OSeekableInputWrapper::PrepareCopy_Impl() if ( !m_xCopyInput.is() ) { if ( !m_xContext.is() ) - throw uno::RuntimeException(); + throw uno::RuntimeException(u"no component context"_ustr); uno::Reference< io::XOutputStream > xTempOut( io::TempFile::create(m_xContext), @@ -110,14 +112,14 @@ void OSeekableInputWrapper::PrepareCopy_Impl() } if ( !m_xCopyInput.is() ) - throw io::IOException(); + throw io::IOException(u"no m_xCopyInput"_ustr); } // XInputStream sal_Int32 SAL_CALL OSeekableInputWrapper::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOriginalStream.is() ) throw io::NotConnectedException(); @@ -130,7 +132,7 @@ sal_Int32 SAL_CALL OSeekableInputWrapper::readBytes( uno::Sequence< sal_Int8 >& sal_Int32 SAL_CALL OSeekableInputWrapper::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOriginalStream.is() ) throw io::NotConnectedException(); @@ -143,7 +145,7 @@ sal_Int32 SAL_CALL OSeekableInputWrapper::readSomeBytes( uno::Sequence< sal_Int8 void SAL_CALL OSeekableInputWrapper::skipBytes( sal_Int32 nBytesToSkip ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOriginalStream.is() ) throw io::NotConnectedException(); @@ -156,7 +158,7 @@ void SAL_CALL OSeekableInputWrapper::skipBytes( sal_Int32 nBytesToSkip ) sal_Int32 SAL_CALL OSeekableInputWrapper::available() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOriginalStream.is() ) throw io::NotConnectedException(); @@ -169,7 +171,7 @@ sal_Int32 SAL_CALL OSeekableInputWrapper::available() void SAL_CALL OSeekableInputWrapper::closeInput() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOriginalStream.is() ) throw io::NotConnectedException(); @@ -191,7 +193,7 @@ void SAL_CALL OSeekableInputWrapper::closeInput() void SAL_CALL OSeekableInputWrapper::seek( sal_Int64 location ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOriginalStream.is() ) throw io::NotConnectedException(); @@ -204,7 +206,7 @@ void SAL_CALL OSeekableInputWrapper::seek( sal_Int64 location ) sal_Int64 SAL_CALL OSeekableInputWrapper::getPosition() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOriginalStream.is() ) throw io::NotConnectedException(); @@ -217,7 +219,7 @@ sal_Int64 SAL_CALL OSeekableInputWrapper::getPosition() sal_Int64 SAL_CALL OSeekableInputWrapper::getLength() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOriginalStream.is() ) throw io::NotConnectedException(); diff --git a/comphelper/source/streaming/seqinputstreamserv.cxx b/comphelper/source/streaming/seqinputstreamserv.cxx index 2f5c21753b03..93d421f40fe6 100644 --- a/comphelper/source/streaming/seqinputstreamserv.cxx +++ b/comphelper/source/streaming/seqinputstreamserv.cxx @@ -19,7 +19,6 @@ #include <sal/config.h> -#include <osl/mutex.hxx> #include <cppuhelper/implbase.hxx> #include <cppuhelper/supportsservice.hxx> #include <comphelper/seqstream.hxx> @@ -29,6 +28,7 @@ #include <com/sun/star/io/XSeekableInputStream.hpp> #include <com/sun/star/lang/XInitialization.hpp> #include <com/sun/star/frame/DoubleInitializationException.hpp> +#include <mutex> namespace com::sun::star::uno { class XComponentContext; } @@ -73,7 +73,7 @@ private: virtual ~SequenceInputStreamService() override {} - ::osl::Mutex m_aMutex; + std::mutex m_aMutex; bool m_bInitialized; uno::Reference< io::XInputStream > m_xInputStream; uno::Reference< io::XSeekable > m_xSeekable; @@ -86,7 +86,7 @@ SequenceInputStreamService::SequenceInputStreamService() // com.sun.star.uno.XServiceInfo: OUString SAL_CALL SequenceInputStreamService::getImplementationName() { - return "com.sun.star.comp.SequenceInputStreamService"; + return u"com.sun.star.comp.SequenceInputStreamService"_ustr; } sal_Bool SAL_CALL SequenceInputStreamService::supportsService( OUString const & serviceName ) @@ -96,13 +96,13 @@ sal_Bool SAL_CALL SequenceInputStreamService::supportsService( OUString const & uno::Sequence< OUString > SAL_CALL SequenceInputStreamService::getSupportedServiceNames() { - return { "com.sun.star.io.SequenceInputStream" }; + return { u"com.sun.star.io.SequenceInputStream"_ustr }; } // css::io::XInputStream: ::sal_Int32 SAL_CALL SequenceInputStreamService::readBytes( uno::Sequence< ::sal_Int8 > & aData, ::sal_Int32 nBytesToRead ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xInputStream.is() ) throw io::NotConnectedException(); @@ -111,7 +111,7 @@ uno::Sequence< OUString > SAL_CALL SequenceInputStreamService::getSupportedServi ::sal_Int32 SAL_CALL SequenceInputStreamService::readSomeBytes( uno::Sequence< ::sal_Int8 > & aData, ::sal_Int32 nMaxBytesToRead ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xInputStream.is() ) throw io::NotConnectedException(); @@ -120,7 +120,7 @@ uno::Sequence< OUString > SAL_CALL SequenceInputStreamService::getSupportedServi void SAL_CALL SequenceInputStreamService::skipBytes( ::sal_Int32 nBytesToSkip ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xInputStream.is() ) throw io::NotConnectedException(); @@ -129,7 +129,7 @@ void SAL_CALL SequenceInputStreamService::skipBytes( ::sal_Int32 nBytesToSkip ) ::sal_Int32 SAL_CALL SequenceInputStreamService::available() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xInputStream.is() ) throw io::NotConnectedException(); @@ -138,7 +138,7 @@ void SAL_CALL SequenceInputStreamService::skipBytes( ::sal_Int32 nBytesToSkip ) void SAL_CALL SequenceInputStreamService::closeInput() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xInputStream.is() ) throw io::NotConnectedException(); @@ -150,7 +150,7 @@ void SAL_CALL SequenceInputStreamService::closeInput() // css::io::XSeekable: void SAL_CALL SequenceInputStreamService::seek( ::sal_Int64 location ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xSeekable.is() ) throw io::NotConnectedException(); @@ -159,7 +159,7 @@ void SAL_CALL SequenceInputStreamService::seek( ::sal_Int64 location ) ::sal_Int64 SAL_CALL SequenceInputStreamService::getPosition() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xSeekable.is() ) throw io::NotConnectedException(); @@ -168,7 +168,7 @@ void SAL_CALL SequenceInputStreamService::seek( ::sal_Int64 location ) ::sal_Int64 SAL_CALL SequenceInputStreamService::getLength() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xSeekable.is() ) throw io::NotConnectedException(); @@ -178,27 +178,26 @@ void SAL_CALL SequenceInputStreamService::seek( ::sal_Int64 location ) // css::lang::XInitialization: void SAL_CALL SequenceInputStreamService::initialize( const uno::Sequence< css::uno::Any > & aArguments ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( m_bInitialized ) throw frame::DoubleInitializationException(); if ( aArguments.getLength() != 1 ) - throw lang::IllegalArgumentException( "Wrong number of arguments!", + throw lang::IllegalArgumentException( u"Wrong number of arguments!"_ustr, static_cast< ::cppu::OWeakObject* >(this), 1 ); uno::Sequence< sal_Int8 > aSeq; if ( !(aArguments[0] >>= aSeq) ) - throw lang::IllegalArgumentException( "Unexpected type of argument!", + throw lang::IllegalArgumentException( u"Unexpected type of argument!"_ustr, static_cast< ::cppu::OWeakObject* >(this), 1 ); uno::Reference< io::XInputStream > xInputStream( static_cast< ::cppu::OWeakObject* >( new ::comphelper::SequenceInputStream( aSeq ) ), uno::UNO_QUERY_THROW ); - uno::Reference< io::XSeekable > xSeekable( xInputStream, uno::UNO_QUERY_THROW ); + m_xSeekable.set(xInputStream, uno::UNO_QUERY_THROW); m_xInputStream = xInputStream; - m_xSeekable = xSeekable; m_bInitialized = true; } diff --git a/comphelper/source/streaming/seqoutputstreamserv.cxx b/comphelper/source/streaming/seqoutputstreamserv.cxx index 477961397413..144ba259a37d 100644 --- a/comphelper/source/streaming/seqoutputstreamserv.cxx +++ b/comphelper/source/streaming/seqoutputstreamserv.cxx @@ -19,13 +19,13 @@ #include <sal/config.h> -#include <osl/mutex.hxx> #include <cppuhelper/implbase.hxx> #include <cppuhelper/supportsservice.hxx> #include <comphelper/seqstream.hxx> #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/io/NotConnectedException.hpp> #include <com/sun/star/io/XSequenceOutputStream.hpp> +#include <mutex> namespace com::sun::star::uno { class XComponentContext; } @@ -61,9 +61,10 @@ private: virtual ~SequenceOutputStreamService() override {}; - ::osl::Mutex m_aMutex; - uno::Reference< io::XOutputStream > m_xOutputStream; + std::mutex m_aMutex; + // WARNING: dtor of m_xOutputStream writes into m_aSequence so that must live longer! uno::Sequence< ::sal_Int8 > m_aSequence; + uno::Reference< io::XOutputStream > m_xOutputStream; }; SequenceOutputStreamService::SequenceOutputStreamService() { @@ -73,7 +74,7 @@ SequenceOutputStreamService::SequenceOutputStreamService() // com.sun.star.uno.XServiceInfo: OUString SAL_CALL SequenceOutputStreamService::getImplementationName() { - return "com.sun.star.comp.SequenceOutputStreamService"; + return u"com.sun.star.comp.SequenceOutputStreamService"_ustr; } sal_Bool SAL_CALL SequenceOutputStreamService::supportsService( OUString const & serviceName ) @@ -83,13 +84,13 @@ sal_Bool SAL_CALL SequenceOutputStreamService::supportsService( OUString const & uno::Sequence< OUString > SAL_CALL SequenceOutputStreamService::getSupportedServiceNames() { - return { "com.sun.star.io.SequenceOutputStream" }; + return { u"com.sun.star.io.SequenceOutputStream"_ustr }; } // css::io::XOutputStream: void SAL_CALL SequenceOutputStreamService::writeBytes( const uno::Sequence< ::sal_Int8 > & aData ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOutputStream.is() ) throw io::NotConnectedException(); @@ -98,7 +99,7 @@ void SAL_CALL SequenceOutputStreamService::writeBytes( const uno::Sequence< ::sa void SAL_CALL SequenceOutputStreamService::flush() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOutputStream.is() ) throw io::NotConnectedException(); @@ -107,10 +108,11 @@ void SAL_CALL SequenceOutputStreamService::flush() void SAL_CALL SequenceOutputStreamService::closeOutput() { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); if ( !m_xOutputStream.is() ) throw io::NotConnectedException(); + m_xOutputStream->flush(); m_xOutputStream->closeOutput(); m_xOutputStream.clear(); } @@ -118,11 +120,14 @@ void SAL_CALL SequenceOutputStreamService::closeOutput() // css::io::XSequenceOutputStream: uno::Sequence< ::sal_Int8 > SAL_CALL SequenceOutputStreamService::getWrittenBytes() { - ::osl::MutexGuard aGuard( m_aMutex ); - if ( !m_xOutputStream.is() ) - throw io::NotConnectedException(); + std::scoped_lock aGuard( m_aMutex ); + + if (m_xOutputStream.is()) + { + m_xOutputStream->flush(); + } + // else: no exception, just return the finished sequence - m_xOutputStream->flush(); return m_aSequence; } diff --git a/comphelper/source/streaming/seqstream.cxx b/comphelper/source/streaming/seqstream.cxx index 2837f27f5d35..03e0b7269adb 100644 --- a/comphelper/source/streaming/seqstream.cxx +++ b/comphelper/source/streaming/seqstream.cxx @@ -31,66 +31,83 @@ namespace comphelper using namespace ::com::sun::star::lang; using namespace ::com::sun::star::io; using namespace ::com::sun::star::uno; -using namespace ::osl; -SequenceInputStream::SequenceInputStream( - css::uno::Sequence<sal_Int8> const & rData) -: m_aData(rData) +MemoryInputStream::MemoryInputStream( + const sal_Int8* pData, sal_Int32 nDataLength) +: m_pMemoryData(pData) +, m_nMemoryDataLength(nDataLength) , m_nPos(0) { } // checks if closed, returns available size, not mutex-protected -inline sal_Int32 SequenceInputStream::avail() +inline sal_Int32 MemoryInputStream::avail() { if (m_nPos == -1) throw NotConnectedException(OUString(), *this); - return m_aData.getLength() - m_nPos; + return m_nMemoryDataLength - m_nPos; } // css::io::XInputStream -sal_Int32 SAL_CALL SequenceInputStream::readBytes( Sequence<sal_Int8>& aData, sal_Int32 nBytesToRead ) +sal_Int32 SAL_CALL MemoryInputStream::readBytes( Sequence<sal_Int8>& aData, sal_Int32 nBytesToRead ) { - ::osl::MutexGuard aGuard( m_aMutex ); + if (nBytesToRead < 0) + throw BufferSizeExceededException(OUString(),*this); + + std::scoped_lock aGuard( m_aMutex ); sal_Int32 nAvail = avail(); + if (nAvail < nBytesToRead) + nBytesToRead = nAvail; + + aData.realloc(nBytesToRead); + memcpy(aData.getArray(), m_pMemoryData + m_nPos, nBytesToRead); + m_nPos += nBytesToRead; + + return nBytesToRead; +} + +sal_Int32 MemoryInputStream::readSomeBytes( sal_Int8* pData, sal_Int32 nBytesToRead ) +{ if (nBytesToRead < 0) throw BufferSizeExceededException(OUString(),*this); + std::scoped_lock aGuard( m_aMutex ); + + sal_Int32 nAvail = avail(); + if (nAvail < nBytesToRead) nBytesToRead = nAvail; - aData.realloc(nBytesToRead); - memcpy(aData.getArray(), m_aData.getConstArray() + m_nPos, nBytesToRead); + memcpy(pData, m_pMemoryData + m_nPos, nBytesToRead); m_nPos += nBytesToRead; return nBytesToRead; } - -sal_Int32 SAL_CALL SequenceInputStream::readSomeBytes( Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead ) +sal_Int32 SAL_CALL MemoryInputStream::readSomeBytes( Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead ) { // all data is available at once return readBytes(aData, nMaxBytesToRead); } -void SAL_CALL SequenceInputStream::skipBytes( sal_Int32 nBytesToSkip ) +void SAL_CALL MemoryInputStream::skipBytes( sal_Int32 nBytesToSkip ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - sal_Int32 nAvail = avail(); - if (nBytesToSkip < 0) throw BufferSizeExceededException(OUString(),*this); + std::scoped_lock aGuard( m_aMutex ); + + sal_Int32 nAvail = avail(); + if (nAvail < nBytesToSkip) nBytesToSkip = nAvail; @@ -98,37 +115,49 @@ void SAL_CALL SequenceInputStream::skipBytes( sal_Int32 nBytesToSkip ) } -sal_Int32 SAL_CALL SequenceInputStream::available( ) +sal_Int32 SAL_CALL MemoryInputStream::available( ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::scoped_lock aGuard( m_aMutex ); return avail(); } -void SAL_CALL SequenceInputStream::closeInput( ) +void SAL_CALL MemoryInputStream::closeInput( ) { + std::scoped_lock aGuard( m_aMutex ); + if (m_nPos == -1) throw NotConnectedException(OUString(), *this); m_nPos = -1; } -void SAL_CALL SequenceInputStream::seek( sal_Int64 location ) +void SAL_CALL MemoryInputStream::seek( sal_Int64 location ) { - if ( location > m_aData.getLength() || location < 0 || location > SAL_MAX_INT32 ) - throw IllegalArgumentException(); + if ( location > m_nMemoryDataLength || location < 0 || location > SAL_MAX_INT32 ) + throw IllegalArgumentException(u"bad location"_ustr, static_cast<cppu::OWeakObject*>(this), 1); + std::scoped_lock aGuard( m_aMutex ); m_nPos = static_cast<sal_Int32>(location); } -sal_Int64 SAL_CALL SequenceInputStream::getPosition() +sal_Int64 SAL_CALL MemoryInputStream::getPosition() { + std::scoped_lock aGuard( m_aMutex ); return m_nPos; } -sal_Int64 SAL_CALL SequenceInputStream::getLength( ) +sal_Int64 SAL_CALL MemoryInputStream::getLength( ) +{ + return m_nMemoryDataLength; +} + + +SequenceInputStream::SequenceInputStream( + css::uno::Sequence<sal_Int8> const & rData) +: MemoryInputStream(rData.getConstArray(), rData.getLength()) +, m_aData(rData) { - return m_aData.getLength(); } @@ -148,7 +177,7 @@ OSequenceOutputStream::OSequenceOutputStream(Sequence< sal_Int8 >& _rSeq, double void SAL_CALL OSequenceOutputStream::writeBytes( const Sequence< sal_Int8 >& _rData ) { - MutexGuard aGuard(m_aMutex); + std::scoped_lock aGuard(m_aMutex); if (!m_bConnected) throw NotConnectedException(); @@ -188,7 +217,7 @@ void SAL_CALL OSequenceOutputStream::writeBytes( const Sequence< sal_Int8 >& _rD void SAL_CALL OSequenceOutputStream::flush( ) { - MutexGuard aGuard(m_aMutex); + std::scoped_lock aGuard(m_aMutex); if (!m_bConnected) throw NotConnectedException(); @@ -198,8 +227,6 @@ void SAL_CALL OSequenceOutputStream::flush( ) void OSequenceOutputStream::finalizeOutput() { - MutexGuard aGuard(m_aMutex); - // cut the sequence to the real size m_rSequence.realloc(m_nSize); // and don't allow any further accesses @@ -208,7 +235,7 @@ void OSequenceOutputStream::finalizeOutput() void SAL_CALL OSequenceOutputStream::closeOutput() { - MutexGuard aGuard(m_aMutex); + std::scoped_lock aGuard(m_aMutex); if (!m_bConnected) throw NotConnectedException(); diff --git a/comphelper/source/windows/windows_process.cxx b/comphelper/source/windows/windows_process.cxx index 7588bae027e5..8e7fd19f0b30 100644 --- a/comphelper/source/windows/windows_process.cxx +++ b/comphelper/source/windows/windows_process.cxx @@ -241,7 +241,7 @@ WinLaunchChild(const wchar_t *exePath, } else { - LPVOID lpMsgBuf = nullptr; + LPWSTR lpMsgBuf = nullptr; FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, diff --git a/comphelper/source/xml/attributelist.cxx b/comphelper/source/xml/attributelist.cxx index fa918d01da29..0b087095aa53 100644 --- a/comphelper/source/xml/attributelist.cxx +++ b/comphelper/source/xml/attributelist.cxx @@ -19,25 +19,14 @@ #include <comphelper/attributelist.hxx> -#include <vector> +#include <algorithm> +#include <cassert> -using namespace osl; 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) @@ -55,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() @@ -67,8 +58,70 @@ AttributeList::~AttributeList() css::uno::Reference< css::util::XCloneable > AttributeList::createClone() { - AttributeList *p = new AttributeList( *this ); - return css::uno::Reference< css::util::XCloneable > ( static_cast<css::util::XCloneable *>(p) ); + return new AttributeList( *this ); +} + +void AttributeList::AddAttribute(const OUString& sName, const OUString& sValue) +{ + assert(!sName.isEmpty() && "empty attribute name is invalid"); + // Either it's 'namespace_prefix:attribute_name', + // or as in XMLNamespaces::applyNSToAttributeName, it's 'namespace:full:uri^attribute_name'. + assert((std::count(sName.getStr(), sName.getStr() + sName.getLength(), u':') <= 1 + || std::count(sName.getStr(), sName.getStr() + sName.getLength(), u'^') == 1) + && "too many colons"); + // TODO: this assertion fails in tests! +// assert(std::none_of(mAttributes.begin(), mAttributes.end(), +// [&sName](const TagAttribute& a) { return a.sName == sName; })); + mAttributes.push_back({ sName, sValue }); +} + +void AttributeList::RemoveAttribute(const OUString& sName) +{ + auto ii = std::find_if(mAttributes.begin(), mAttributes.end(), + [&sName](const TagAttribute& rAttr) { return rAttr.sName == sName; }); + + if (ii != mAttributes.end()) + mAttributes.erase(ii); +} + +void AttributeList::AppendAttributeList(const uno::Reference<css::xml::sax::XAttributeList>& r) +{ + assert(r.is()); + + sal_Int16 nMax = r->getLength(); + sal_Int16 nTotalSize = mAttributes.size() + nMax; + mAttributes.reserve(nTotalSize); + + for (sal_Int16 i = 0; i < nMax; ++i) + AddAttribute(r->getNameByIndex(i), r->getValueByIndex(i)); + + assert(nTotalSize == getLength()); +} + +void AttributeList::SetValueByIndex(sal_Int16 i, const OUString& rValue) +{ + mAttributes[i].sValue = rValue; +} + +void AttributeList::RemoveAttributeByIndex(sal_Int16 i) +{ + mAttributes.erase(mAttributes.begin() + i); +} + +void AttributeList::RenameAttributeByIndex(sal_Int16 i, const OUString& rNewName) +{ + mAttributes[i].sName = rNewName; +} + +sal_Int16 AttributeList::GetIndexByName(const OUString& rName) const +{ + auto ii = std::find_if(mAttributes.begin(), mAttributes.end(), + [&rName](const TagAttribute& rAttr) { return rAttr.sName == rName; }); + + if (ii != mAttributes.end()) + return static_cast<sal_Int16>(std::distance(mAttributes.begin(), ii)); + + return -1; } } // namespace comphelper diff --git a/comphelper/source/xml/ofopxmlhelper.cxx b/comphelper/source/xml/ofopxmlhelper.cxx index 8045f9b767b6..c678d7841c0b 100644 --- a/comphelper/source/xml/ofopxmlhelper.cxx +++ b/comphelper/source/xml/ofopxmlhelper.cxx @@ -22,6 +22,7 @@ #include <comphelper/attributelist.hxx> #include <cppuhelper/implbase.hxx> +#include <rtl/ref.hxx> #include <com/sun/star/beans/StringPair.hpp> #include <com/sun/star/xml/sax/Parser.hpp> @@ -79,10 +80,10 @@ static uno::Sequence<uno::Sequence< beans::StringPair>> ReadSequence_Impl( uno::Sequence< uno::Sequence< beans::StringPair > > ReadRelationsInfoSequence( const uno::Reference< io::XInputStream >& xInStream, - const OUString & aStreamName, + std::u16string_view aStreamName, const uno::Reference< uno::XComponentContext >& rContext ) { - OUString aStringID = "_rels/" + aStreamName; + OUString aStringID = OUString::Concat("_rels/") + aStreamName; return ReadSequence_Impl( xInStream, aStringID, RELATIONINFO_FORMAT, rContext ); } @@ -91,7 +92,7 @@ uno::Sequence< uno::Sequence< beans::StringPair > > ReadContentTypeSequence( const uno::Reference< io::XInputStream >& xInStream, const uno::Reference< uno::XComponentContext >& rContext ) { - return ReadSequence_Impl( xInStream, "[Content_Types].xml", CONTENTTYPE_FORMAT, rContext ); + return ReadSequence_Impl( xInStream, u"[Content_Types].xml"_ustr, CONTENTTYPE_FORMAT, rContext ); } OUString GetContentTypeByName( @@ -139,26 +140,22 @@ void WriteRelationsInfoSequence( xWriter->setOutputStream( xOutStream ); - OUString aRelListElement( "Relationships" ); - OUString aRelElement( "Relationship" ); - OUString aCDATAString( "CDATA" ); - OUString aWhiteSpace( " " ); + OUString aRelListElement( u"Relationships"_ustr ); + OUString aRelElement( u"Relationship"_ustr ); + OUString aWhiteSpace( u" "_ustr ); // write the namespace - AttributeList* pRootAttrList = new AttributeList; - uno::Reference< css::xml::sax::XAttributeList > xRootAttrList( pRootAttrList ); + rtl::Reference<AttributeList> pRootAttrList = new AttributeList; pRootAttrList->AddAttribute( - "xmlns", - aCDATAString, - "http://schemas.openxmlformats.org/package/2006/relationships" ); + u"xmlns"_ustr, + u"http://schemas.openxmlformats.org/package/2006/relationships"_ustr ); xWriter->startDocument(); - xWriter->startElement( aRelListElement, xRootAttrList ); + xWriter->startElement( aRelListElement, pRootAttrList ); for ( const auto & i : aSequence ) { - AttributeList *pAttrList = new AttributeList; - uno::Reference< css::xml::sax::XAttributeList > xAttrList( pAttrList ); + rtl::Reference<AttributeList> pAttrList = new AttributeList; for( const beans::StringPair & pair : i ) { if ( !(pair.First == "Id" @@ -169,10 +166,10 @@ void WriteRelationsInfoSequence( // TODO/LATER: should the extensions be allowed? throw lang::IllegalArgumentException(); } - pAttrList->AddAttribute( pair.First, aCDATAString, pair.Second ); + pAttrList->AddAttribute( pair.First, pair.Second ); } - xWriter->startElement( aRelElement, xAttrList ); + xWriter->startElement( aRelElement, pAttrList ); xWriter->ignorableWhitespace( aWhiteSpace ); xWriter->endElement( aRelElement ); } @@ -196,44 +193,39 @@ void WriteContentSequence( xWriter->setOutputStream( xOutStream ); - static const OUString aTypesElement("Types"); - static const OUString aDefaultElement("Default"); - static const OUString aOverrideElement("Override"); - static const OUString aContentTypeAttr("ContentType"); - static const OUString aCDATAString("CDATA"); - static const OUString aWhiteSpace(" "); + static constexpr OUString aTypesElement(u"Types"_ustr); + static constexpr OUString aDefaultElement(u"Default"_ustr); + static constexpr OUString aOverrideElement(u"Override"_ustr); + static constexpr OUString aContentTypeAttr(u"ContentType"_ustr); + static constexpr OUString aWhiteSpace(u" "_ustr); // write the namespace - AttributeList* pRootAttrList = new AttributeList; - uno::Reference< css::xml::sax::XAttributeList > xRootAttrList( pRootAttrList ); + rtl::Reference<AttributeList> pRootAttrList = new AttributeList; pRootAttrList->AddAttribute( - "xmlns", - aCDATAString, - "http://schemas.openxmlformats.org/package/2006/content-types" ); + u"xmlns"_ustr, + u"http://schemas.openxmlformats.org/package/2006/content-types"_ustr ); xWriter->startDocument(); - xWriter->startElement( aTypesElement, xRootAttrList ); + xWriter->startElement( aTypesElement, pRootAttrList ); for ( const beans::StringPair & pair : aDefaultsSequence ) { - AttributeList *pAttrList = new AttributeList; - uno::Reference< css::xml::sax::XAttributeList > xAttrList( pAttrList ); - pAttrList->AddAttribute( "Extension", aCDATAString, pair.First ); - pAttrList->AddAttribute( aContentTypeAttr, aCDATAString, pair.Second ); + rtl::Reference<AttributeList> pAttrList = new AttributeList; + pAttrList->AddAttribute( u"Extension"_ustr, pair.First ); + pAttrList->AddAttribute( aContentTypeAttr, pair.Second ); - xWriter->startElement( aDefaultElement, xAttrList ); + xWriter->startElement( aDefaultElement, pAttrList ); xWriter->ignorableWhitespace( aWhiteSpace ); xWriter->endElement( aDefaultElement ); } for ( const beans::StringPair & pair : aOverridesSequence ) { - AttributeList *pAttrList = new AttributeList; - uno::Reference< css::xml::sax::XAttributeList > xAttrList( pAttrList ); - pAttrList->AddAttribute( "PartName", aCDATAString, pair.First ); - pAttrList->AddAttribute( aContentTypeAttr, aCDATAString, pair.Second ); + rtl::Reference<AttributeList> pAttrList = new AttributeList; + pAttrList->AddAttribute( u"PartName"_ustr, pair.First ); + pAttrList->AddAttribute( aContentTypeAttr, pair.Second ); - xWriter->startElement( aOverrideElement, xAttrList ); + xWriter->startElement( aOverrideElement, pAttrList ); xWriter->ignorableWhitespace( aWhiteSpace ); xWriter->endElement( aOverrideElement ); } @@ -254,12 +246,11 @@ uno::Sequence< uno::Sequence< beans::StringPair > > ReadSequence_Impl( uno::Reference< css::xml::sax::XParser > xParser = css::xml::sax::Parser::create( rContext ); - OFOPXMLHelper_Impl *const pHelper = new OFOPXMLHelper_Impl( nFormat ); - uno::Reference< css::xml::sax::XDocumentHandler > xHelper( static_cast< css::xml::sax::XDocumentHandler* >( pHelper ) ); + rtl::Reference<OFOPXMLHelper_Impl> pHelper = new OFOPXMLHelper_Impl( nFormat ); css::xml::sax::InputSource aParserInput; aParserInput.aInputStream = xInStream; aParserInput.sSystemId = aStringID; - xParser->setDocumentHandler( xHelper ); + xParser->setDocumentHandler( pHelper ); xParser->parseStream( aParserInput ); xParser->setDocumentHandler( uno::Reference < css::xml::sax::XDocumentHandler > () ); @@ -269,20 +260,20 @@ uno::Sequence< uno::Sequence< beans::StringPair > > ReadSequence_Impl( } // namespace OFOPXMLHelper // Relations info related strings -OUString const g_aRelListElement("Relationships"); -OUString const g_aRelElement( "Relationship" ); -OUString const g_aIDAttr( "Id" ); -OUString const g_aTypeAttr( "Type" ); -OUString const g_aTargetModeAttr( "TargetMode" ); -OUString const g_aTargetAttr( "Target" ); +constexpr OUStringLiteral g_aRelListElement(u"Relationships"); +constexpr OUStringLiteral g_aRelElement( u"Relationship" ); +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 -OUString const g_aTypesElement( "Types" ); -OUString const g_aDefaultElement( "Default" ); -OUString const g_aOverrideElement( "Override" ); -OUString const g_aExtensionAttr( "Extension" ); -OUString const g_aPartNameAttr( "PartName" ); -OUString const g_aContentTypeAttr( "ContentType" ); +constexpr OUStringLiteral g_aTypesElement( u"Types" ); +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 OUString g_aContentTypeAttr( u"ContentType"_ustr ); OFOPXMLHelper_Impl::OFOPXMLHelper_Impl( sal_uInt16 nFormat ) : m_nFormat( nFormat ) @@ -333,8 +324,10 @@ void SAL_CALL OFOPXMLHelper_Impl::startElement( const OUString& aName, const uno sal_Int32 nNewEntryNum = m_aResultSeq.getLength() + 1; m_aResultSeq.realloc( nNewEntryNum ); + auto pResultSeq = m_aResultSeq.getArray(); sal_Int32 nAttrNum = 0; - m_aResultSeq[nNewEntryNum-1].realloc( 4 ); // the maximal expected number of arguments is 4 + pResultSeq[nNewEntryNum-1].realloc( 4 ); // the maximal expected number of arguments is 4 + auto pAttrs = pResultSeq[nNewEntryNum-1].getArray(); OUString aIDValue = xAttribs->getValueByName( g_aIDAttr ); if ( aIDValue.isEmpty() ) @@ -344,28 +337,28 @@ void SAL_CALL OFOPXMLHelper_Impl::startElement( const OUString& aName, const uno OUString aTargetValue = xAttribs->getValueByName( g_aTargetAttr ); OUString aTargetModeValue = xAttribs->getValueByName( g_aTargetModeAttr ); - m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = g_aIDAttr; - m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aIDValue; + pAttrs[++nAttrNum - 1].First = g_aIDAttr; + pAttrs[nAttrNum - 1].Second = aIDValue; if ( !aTypeValue.isEmpty() ) { - m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = g_aTypeAttr; - m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTypeValue; + pAttrs[++nAttrNum - 1].First = g_aTypeAttr; + pAttrs[nAttrNum - 1].Second = aTypeValue; } if ( !aTargetValue.isEmpty() ) { - m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = g_aTargetAttr; - m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTargetValue; + pAttrs[++nAttrNum - 1].First = g_aTargetAttr; + pAttrs[nAttrNum - 1].Second = aTargetValue; } if ( !aTargetModeValue.isEmpty() ) { - m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = g_aTargetModeAttr; - m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTargetModeValue; + pAttrs[++nAttrNum - 1].First = g_aTargetModeAttr; + pAttrs[nAttrNum - 1].Second = aTargetModeValue; } - m_aResultSeq[nNewEntryNum-1].realloc( nAttrNum ); + pResultSeq[nNewEntryNum-1].realloc( nAttrNum ); } else throw css::xml::sax::SAXException(); // TODO: no other elements expected! @@ -400,6 +393,8 @@ void SAL_CALL OFOPXMLHelper_Impl::startElement( const OUString& aName, const uno if ( m_aResultSeq.getLength() != 2 ) throw uno::RuntimeException(); + auto pResultSeq = m_aResultSeq.getArray(); + const OUString aExtensionValue = xAttribs->getValueByName( g_aExtensionAttr ); if ( aExtensionValue.isEmpty() ) throw css::xml::sax::SAXException(); // TODO: the Extension value must present @@ -409,10 +404,11 @@ void SAL_CALL OFOPXMLHelper_Impl::startElement( const OUString& aName, const uno throw css::xml::sax::SAXException(); // TODO: the ContentType value must present const sal_Int32 nNewResultLen = m_aResultSeq[0].getLength() + 1; - m_aResultSeq[0].realloc( nNewResultLen ); + pResultSeq[0].realloc( nNewResultLen ); + auto pSeq = pResultSeq[0].getArray(); - m_aResultSeq[0][nNewResultLen-1].First = aExtensionValue; - m_aResultSeq[0][nNewResultLen-1].Second = aContentTypeValue; + pSeq[nNewResultLen-1].First = aExtensionValue; + pSeq[nNewResultLen-1].Second = aContentTypeValue; } else if ( aName == g_aOverrideElement ) { @@ -428,6 +424,8 @@ void SAL_CALL OFOPXMLHelper_Impl::startElement( const OUString& aName, const uno if ( m_aResultSeq.getLength() != 2 ) throw uno::RuntimeException(); + auto pResultSeq = m_aResultSeq.getArray(); + OUString aPartNameValue = xAttribs->getValueByName( g_aPartNameAttr ); if ( aPartNameValue.isEmpty() ) throw css::xml::sax::SAXException(); // TODO: the PartName value must present @@ -437,10 +435,11 @@ void SAL_CALL OFOPXMLHelper_Impl::startElement( const OUString& aName, const uno throw css::xml::sax::SAXException(); // TODO: the ContentType value must present sal_Int32 nNewResultLen = m_aResultSeq[1].getLength() + 1; - m_aResultSeq[1].realloc( nNewResultLen ); + pResultSeq[1].realloc( nNewResultLen ); + auto pSeq = pResultSeq[1].getArray(); - m_aResultSeq[1][nNewResultLen-1].First = aPartNameValue; - m_aResultSeq[1][nNewResultLen-1].Second = aContentTypeValue; + pSeq[nNewResultLen-1].First = aPartNameValue; + pSeq[nNewResultLen-1].Second = aContentTypeValue; } else throw css::xml::sax::SAXException(); // TODO: no other elements expected! diff --git a/comphelper/source/xml/xmltools.cxx b/comphelper/source/xml/xmltools.cxx index 74ad5faa67e7..6ae8fceed5b9 100644 --- a/comphelper/source/xml/xmltools.cxx +++ b/comphelper/source/xml/xmltools.cxx @@ -9,7 +9,7 @@ #include <comphelper/xmltools.hxx> #include <rtl/random.h> -#include <rtl/uuid.h> +#include <tools/Guid.hxx> #include <vector> using namespace com::sun::star; @@ -71,17 +71,21 @@ namespace namespace comphelper::xml { + // Generate some 'chaff' of varying length to be the body of an + // XML comment to put at the start of encrypted content to make + // document content a little less predictable. + // See SvXMLExport::addChaffWhenEncryptedStorage OString makeXMLChaff() { rtlRandomPool pool = rtl_random_createPool(); sal_Int8 n; - rtl_random_getBytes(pool, &n, 1); + (void)rtl_random_getBytes(pool, &n, 1); sal_Int32 nLength = 1024+n; // coverity[tainted_data] - 1024 deliberate random minus max -127/plus max 128 std::vector<sal_uInt8> aChaff(nLength); - rtl_random_getBytes(pool, aChaff.data(), nLength); + (void)rtl_random_getBytes(pool, aChaff.data(), nLength); rtl_random_destroyPool(pool); @@ -92,15 +96,8 @@ namespace comphelper::xml OString generateGUIDString() { - sal_uInt8 aSeq[16]; - rtl_createUuid(aSeq, nullptr, true); - - char str[39]; - sprintf(str, "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", - aSeq[0], aSeq[1], aSeq[2], aSeq[3], aSeq[4], aSeq[5], aSeq[6], aSeq[7], aSeq[8], - aSeq[9], aSeq[10], aSeq[11], aSeq[12], aSeq[13], aSeq[14], aSeq[15]); - - return str; + tools::Guid aGuid(tools::Guid::Generate); + return aGuid.getString(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/util/comphelp.component b/comphelper/util/comphelp.component index 705e870eb5e0..1e4e0c8fbf8e 100644 --- a/comphelper/util/comphelp.component +++ b/comphelper/util/comphelp.component @@ -52,12 +52,14 @@ <service name="com.sun.star.embed.InstanceLocker"/> </implementation> <implementation name="com.sun.star.comp.task.OfficeRestartManager" - constructor="com_sun_star_comp_task_OfficeRestartManager"> + constructor="com_sun_star_comp_task_OfficeRestartManager" + single-instance="true"> <service name="com.sun.star.comp.task.OfficeRestartManager"/> <singleton name="com.sun.star.task.OfficeRestartManager"/> </implementation> <implementation name="com.sun.star.comp.util.OfficeInstallationDirectories" - constructor="com_sun_star_comp_util_OfficeInstallationDirectories"> + constructor="com_sun_star_comp_util_OfficeInstallationDirectories" + single-instance="true"> <service name="com.sun.star.util.OfficeInstallationDirectories"/> <singleton name="com.sun.star.util.theOfficeInstallationDirectories"/> </implementation> |